summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/dce
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dce')
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_aux.c40
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_aux.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c52
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c84
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_opp.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c60
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.h33
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c19
10 files changed, 266 insertions, 42 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile
index 973be8f9fd10..0d7db132a20f 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile
@@ -30,7 +30,7 @@ DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \
dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \
dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o dce_aux.o \
dce_i2c.o dce_i2c_hw.o dce_i2c_sw.o dmub_psr.o dmub_abm.o dce_panel_cntl.o \
-dmub_hw_lock_mgr.o
+dmub_hw_lock_mgr.o dmub_outbox.o
AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE))
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
index d51b5fe91287..87d57e81de12 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
@@ -31,6 +31,8 @@
#include "dce_aux.h"
#include "dce/dce_11_0_sh_mask.h"
#include "dm_event_log.h"
+#include "dm_helpers.h"
+#include "dmub/inc/dmub_cmd.h"
#define CTX \
aux110->base.ctx
@@ -324,7 +326,7 @@ static int read_channel_reply(struct dce_aux *engine, uint32_t size,
return 0;
}
-static enum aux_channel_operation_result get_channel_status(
+static enum aux_return_code_type get_channel_status(
struct dce_aux *engine,
uint8_t *returned_bytes)
{
@@ -335,7 +337,7 @@ static enum aux_channel_operation_result get_channel_status(
if (returned_bytes == NULL) {
/*caller pass NULL pointer*/
ASSERT_CRITICAL(false);
- return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN;
+ return AUX_RET_ERROR_UNKNOWN;
}
*returned_bytes = 0;
@@ -346,7 +348,7 @@ static enum aux_channel_operation_result get_channel_status(
value = REG_READ(AUX_SW_STATUS);
/* in case HPD is LOW, exit AUX transaction */
if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
- return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
+ return AUX_RET_ERROR_HPD_DISCON;
/* Note that the following bits are set in 'status.bits'
* during CTS 4.2.1.2 (FW 3.3.1):
@@ -359,14 +361,14 @@ static enum aux_channel_operation_result get_channel_status(
if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) {
if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) ||
(value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK))
- return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
+ return AUX_RET_ERROR_TIMEOUT;
else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) ||
(value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) ||
(value &
AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) ||
(value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK))
- return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
+ return AUX_RET_ERROR_INVALID_REPLY;
*returned_bytes = get_reg_field_value(value,
AUX_SW_STATUS,
@@ -374,17 +376,17 @@ static enum aux_channel_operation_result get_channel_status(
if (*returned_bytes == 0)
return
- AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
+ AUX_RET_ERROR_INVALID_REPLY;
else {
*returned_bytes -= 1;
- return AUX_CHANNEL_OPERATION_SUCCEEDED;
+ return AUX_RET_SUCCESS;
}
} else {
/*time_elapsed >= aux_engine->timeout_period
* AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point
*/
ASSERT_CRITICAL(false);
- return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
+ return AUX_RET_ERROR_TIMEOUT;
}
}
@@ -541,7 +543,7 @@ static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payl
int dce_aux_transfer_raw(struct ddc_service *ddc,
struct aux_payload *payload,
- enum aux_channel_operation_result *operation_result)
+ enum aux_return_code_type *operation_result)
{
struct ddc *ddc_pin = ddc->ddc_pin;
struct dce_aux *aux_engine;
@@ -556,7 +558,7 @@ int dce_aux_transfer_raw(struct ddc_service *ddc,
aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
if (!acquire(aux_engine, ddc_pin)) {
- *operation_result = AUX_CHANNEL_OPERATION_FAILED_ENGINE_ACQUIRE;
+ *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
return -1;
}
@@ -575,8 +577,9 @@ int dce_aux_transfer_raw(struct ddc_service *ddc,
submit_channel_request(aux_engine, &aux_req);
*operation_result = get_channel_status(aux_engine, &returned_bytes);
- if (*operation_result == AUX_CHANNEL_OPERATION_SUCCEEDED) {
+ if (*operation_result == AUX_RET_SUCCESS) {
int __maybe_unused bytes_replied = 0;
+
bytes_replied = read_channel_reply(aux_engine, payload->length,
payload->data, payload->reply,
&status);
@@ -604,7 +607,7 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
int i, ret = 0;
uint8_t reply;
bool payload_reply = true;
- enum aux_channel_operation_result operation_result;
+ enum aux_return_code_type operation_result;
bool retry_on_defer = false;
int aux_ack_retries = 0,
@@ -620,8 +623,9 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
for (i = 0; i < AUX_MAX_RETRIES; i++) {
ret = dce_aux_transfer_raw(ddc, payload, &operation_result);
+
switch (operation_result) {
- case AUX_CHANNEL_OPERATION_SUCCEEDED:
+ case AUX_RET_SUCCESS:
aux_timeout_retries = 0;
aux_invalid_reply_retries = 0;
@@ -667,14 +671,14 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
}
break;
- case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
+ case AUX_RET_ERROR_INVALID_REPLY:
if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES)
goto fail;
else
udelay(400);
break;
- case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
+ case AUX_RET_ERROR_TIMEOUT:
// Check whether a DEFER had occurred before the timeout.
// If so, treat timeout as a DEFER.
if (retry_on_defer) {
@@ -696,9 +700,9 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
}
break;
- case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
- case AUX_CHANNEL_OPERATION_FAILED_ENGINE_ACQUIRE:
- case AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN:
+ case AUX_RET_ERROR_HPD_DISCON:
+ case AUX_RET_ERROR_ENGINE_ACQUIRE:
+ case AUX_RET_ERROR_UNKNOWN:
default:
goto fail;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h
index 277484cf853e..566b1bddd8cc 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h
@@ -29,6 +29,7 @@
#include "i2caux_interface.h"
#include "inc/hw/aux_engine.h"
+enum aux_return_code_type;
#define AUX_COMMON_REG_LIST0(id)\
SRI(AUX_CONTROL, DP_AUX, id), \
@@ -99,7 +100,6 @@ struct dce110_aux_registers {
AUX_SF(AUX_SW_CONTROL, AUX_SW_GO, mask_sh),\
AUX_SF(AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
AUX_SF(AUX_SW_DATA, AUX_SW_DATA_RW, mask_sh),\
- AUX_SF(AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
AUX_SF(AUX_SW_DATA, AUX_SW_INDEX, mask_sh),\
AUX_SF(AUX_SW_DATA, AUX_SW_DATA, mask_sh),\
AUX_SF(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, mask_sh),\
@@ -302,7 +302,7 @@ bool dce110_aux_engine_acquire(
int dce_aux_transfer_raw(struct ddc_service *ddc,
struct aux_payload *cmd,
- enum aux_channel_operation_result *operation_result);
+ enum aux_return_code_type *operation_result);
bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
struct aux_payload *cmd);
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index dec58b3c42e4..2c7eb982eabc 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -1002,15 +1002,27 @@ static bool get_pixel_clk_frequency_100hz(
{
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
unsigned int clock_hz = 0;
+ unsigned int modulo_hz = 0;
if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) {
clock_hz = REG_READ(PHASE[inst]);
- /* NOTE: There is agreement with VBIOS here that MODULO is
- * programmed equal to DPREFCLK, in which case PHASE will be
- * equivalent to pixel clock.
- */
- *pixel_clk_khz = clock_hz / 100;
+ if (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&
+ clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {
+ /* NOTE: In case VBLANK syncronization is enabled, MODULO may
+ * not be programmed equal to DPREFCLK
+ */
+ modulo_hz = REG_READ(MODULO[inst]);
+ *pixel_clk_khz = div_u64((uint64_t)clock_hz*
+ clock_source->ctx->dc->clk_mgr->dprefclk_khz*10,
+ modulo_hz);
+ } else {
+ /* NOTE: There is agreement with VBIOS here that MODULO is
+ * programmed equal to DPREFCLK, in which case PHASE will be
+ * equivalent to pixel clock.
+ */
+ *pixel_clk_khz = clock_hz / 100;
+ }
return true;
}
@@ -1074,8 +1086,35 @@ static bool dcn20_program_pix_clk(
struct pixel_clk_params *pix_clk_params,
struct pll_settings *pll_settings)
{
+ struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
+ unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
+
dce112_program_pix_clk(clock_source, pix_clk_params, pll_settings);
+ if (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&
+ clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {
+ /* NOTE: In case VBLANK syncronization is enabled,
+ * we need to set modulo to default DPREFCLK first
+ * dce112_program_pix_clk does not set default DPREFCLK
+ */
+ REG_WRITE(MODULO[inst],
+ clock_source->ctx->dc->clk_mgr->dprefclk_khz*1000);
+ }
+ return true;
+}
+
+static bool dcn20_override_dp_pix_clk(
+ struct clock_source *clock_source,
+ unsigned int inst,
+ unsigned int pixel_clk,
+ unsigned int ref_clk)
+{
+ struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
+
+ REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 0);
+ REG_WRITE(PHASE[inst], pixel_clk);
+ REG_WRITE(MODULO[inst], ref_clk);
+ REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1);
return true;
}
@@ -1083,7 +1122,8 @@ static const struct clock_source_funcs dcn20_clk_src_funcs = {
.cs_power_down = dce110_clock_source_power_down,
.program_pix_clk = dcn20_program_pix_clk,
.get_pix_clk_dividers = dce112_get_pix_clk_dividers,
- .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
+ .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz,
+ .override_dp_pix_clk = dcn20_override_dp_pix_clk
};
#if defined(CONFIG_DRM_AMD_DC_DCN)
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
index ddc789daf3b1..4f864501e046 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
@@ -57,6 +57,8 @@
#define MCP_SYNC_PHY_LOCK 0x90
#define MCP_SYNC_PHY_UNLOCK 0x91
#define MCP_BL_SET_PWM_FRAC 0x6A /* Enable or disable Fractional PWM */
+#define CRC_WIN_NOTIFY 0x92
+#define CRC_STOP_UPDATE 0x93
#define MCP_SEND_EDID_CEA 0xA0
#define EDID_CEA_CMD_ACK 1
#define EDID_CEA_CMD_NACK 2
@@ -930,6 +932,84 @@ static bool dcn10_recv_edid_cea_ack(struct dmcu *dmcu, int *offset)
#endif //(CONFIG_DRM_AMD_DC_DCN)
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+static void dcn10_forward_crc_window(struct dmcu *dmcu,
+ struct crc_region *crc_win,
+ struct otg_phy_mux *mux_mapping)
+{
+ struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
+ unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
+ unsigned int dmcu_wait_reg_ready_interval = 100;
+ unsigned int crc_start = 0, crc_end = 0, otg_phy_mux = 0;
+
+ /* If microcontroller is not running, do nothing */
+ if (dmcu->dmcu_state != DMCU_RUNNING)
+ return;
+
+ if (!crc_win)
+ return;
+
+ /* waitDMCUReadyForCmd */
+ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
+ dmcu_wait_reg_ready_interval,
+ dmcu_max_retry_on_wait_reg_ready);
+
+ /* build up nitification data */
+ crc_start = (((unsigned int) crc_win->x_start) << 16) | crc_win->y_start;
+ crc_end = (((unsigned int) crc_win->x_end) << 16) | crc_win->y_end;
+ otg_phy_mux =
+ (((unsigned int) mux_mapping->otg_output_num) << 16) | mux_mapping->phy_output_num;
+
+ dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1),
+ crc_start);
+
+ dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG2),
+ crc_end);
+
+ dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG3),
+ otg_phy_mux);
+
+ /* setDMCUParam_Cmd */
+ REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0,
+ CRC_WIN_NOTIFY);
+
+ /* notifyDMCUMsg */
+ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
+}
+
+static void dcn10_stop_crc_win_update(struct dmcu *dmcu,
+ struct otg_phy_mux *mux_mapping)
+{
+ struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
+ unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
+ unsigned int dmcu_wait_reg_ready_interval = 100;
+ unsigned int otg_phy_mux = 0;
+
+ /* If microcontroller is not running, do nothing */
+ if (dmcu->dmcu_state != DMCU_RUNNING)
+ return;
+
+ /* waitDMCUReadyForCmd */
+ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
+ dmcu_wait_reg_ready_interval,
+ dmcu_max_retry_on_wait_reg_ready);
+
+ /* build up nitification data */
+ otg_phy_mux =
+ (((unsigned int) mux_mapping->otg_output_num) << 16) | mux_mapping->phy_output_num;
+
+ dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1),
+ otg_phy_mux);
+
+ /* setDMCUParam_Cmd */
+ REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0,
+ CRC_STOP_UPDATE);
+
+ /* notifyDMCUMsg */
+ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
+}
+#endif
+
static const struct dmcu_funcs dce_funcs = {
.dmcu_init = dce_dmcu_init,
.load_iram = dce_dmcu_load_iram,
@@ -953,6 +1033,10 @@ static const struct dmcu_funcs dcn10_funcs = {
.send_edid_cea = dcn10_send_edid_cea,
.recv_amd_vsdb = dcn10_recv_amd_vsdb,
.recv_edid_cea_ack = dcn10_recv_edid_cea_ack,
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+ .forward_crc_window = dcn10_forward_crc_window,
+ .stop_crc_win_update = dcn10_stop_crc_win_update,
+#endif
.is_dmcu_initialized = dcn10_is_dmcu_initialized
};
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
index 4600231da6cb..895b015b02e8 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
@@ -216,9 +216,7 @@ static void set_spatial_dither(
REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_EN, 0);
- /* no 10bpc on DCE11*/
- if (params->flags.SPATIAL_DITHER_ENABLED == 0 ||
- params->flags.SPATIAL_DITHER_DEPTH == 2)
+ if (params->flags.SPATIAL_DITHER_ENABLED == 0)
return;
/* only use FRAME_COUNTER_MAX if frameRandom == 1*/
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
index 453aaa5757bd..eb1698d54a48 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
@@ -72,11 +72,11 @@ static void dmub_abm_init(struct abm *abm, uint32_t backlight)
{
struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
- REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x103);
- REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x101);
- REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x103);
- REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x101);
- REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x101);
+ REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x3);
+ REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x1);
+ REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x3);
+ REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x1);
+ REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x1);
REG_SET_3(DC_ABM1_HG_MISC_CTRL, 0,
ABM1_HG_NUM_OF_BINS_SEL, 0,
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c
new file mode 100644
index 000000000000..295596d1f47f
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ */
+
+#include "dmub_outbox.h"
+#include "dc_dmub_srv.h"
+#include "dmub/inc/dmub_cmd.h"
+
+/**
+ *****************************************************************************
+ * Function: dmub_enable_outbox_notification
+ *
+ * @brief
+ * Sends inbox cmd to dmub to enable outbox1 messages with interrupt.
+ * Dmub sends outbox1 message and triggers outbox1 interrupt.
+ *
+ * @param
+ * [in] dc: dc structure
+ *
+ * @return
+ * None
+ *****************************************************************************
+ */
+void dmub_enable_outbox_notification(struct dc *dc)
+{
+ union dmub_rb_cmd cmd;
+ struct dc_context *dc_ctx = dc->ctx;
+
+ memset(&cmd, 0x0, sizeof(cmd));
+ cmd.outbox1_enable.header.type = DMUB_CMD__OUTBOX1_ENABLE;
+ cmd.outbox1_enable.header.sub_type = 0;
+ cmd.outbox1_enable.header.payload_bytes =
+ sizeof(cmd.outbox1_enable) -
+ sizeof(cmd.outbox1_enable.header);
+ cmd.outbox1_enable.enable = true;
+
+ dc_dmub_srv_cmd_queue(dc_ctx->dmub_srv, &cmd);
+ dc_dmub_srv_cmd_execute(dc_ctx->dmub_srv);
+ dc_dmub_srv_wait_idle(dc_ctx->dmub_srv);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.h
new file mode 100644
index 000000000000..4e0aa0d1a2d5
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef _DMUB_OUTBOX_H_
+#define _DMUB_OUTBOX_H_
+
+#include "dc.h"
+
+void dmub_enable_outbox_notification(struct dc *dc);
+
+#endif /* _DMUB_OUTBOX_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
index 69e34bef274c..15ed09b7a452 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
@@ -81,13 +81,18 @@ static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state)
{
struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub;
uint32_t raw_state;
+ enum dmub_status status;
// Send gpint command and wait for ack
- dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30);
-
- dmub_srv_get_gpint_response(srv, &raw_state);
-
- *state = convert_psr_state(raw_state);
+ status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30);
+
+ if (status == DMUB_STATUS_OK) {
+ // GPINT was executed, get response
+ dmub_srv_get_gpint_response(srv, &raw_state);
+ *state = convert_psr_state(raw_state);
+ } else
+ // Return invalid state when GPINT times out
+ *state = 0xFF;
}
/*
@@ -216,6 +221,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
res_ctx->pipe_ctx[i].stream->link == link &&
res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) {
pipe_ctx = &res_ctx->pipe_ctx[i];
+ //TODO: refactor for multi edp support
break;
}
}
@@ -269,8 +275,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
copy_settings_data->frame_cap_ind = psr_context->psrFrameCaptureIndicationReq;
copy_settings_data->init_sdp_deadline = psr_context->sdpTransmitLineNumDeadline;
copy_settings_data->debug.u32All = 0;
- copy_settings_data->debug.bitfields.visual_confirm = dc->dc->debug.visual_confirm == VISUAL_CONFIRM_PSR ?
- true : false;
+ copy_settings_data->debug.bitfields.visual_confirm = dc->dc->debug.visual_confirm == VISUAL_CONFIRM_PSR;
copy_settings_data->debug.bitfields.use_hw_lock_mgr = 1;
dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);