diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dce')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 40 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce/dce_aux.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 52 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 84 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c | 60 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.h | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 19 |
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); |