diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc')
64 files changed, 1927 insertions, 543 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/basics/Makefile b/drivers/gpu/drm/amd/display/dc/basics/Makefile index 7ad0cad0f4ef..01b99e0d788e 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/Makefile +++ b/drivers/gpu/drm/amd/display/dc/basics/Makefile @@ -24,8 +24,7 @@ # It provides the general basic services required by other DAL # subcomponents. -BASICS = conversion.o fixpt31_32.o \ - log_helpers.o vector.o dc_common.o +BASICS = conversion.o fixpt31_32.o vector.o dc_common.o AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS)) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index 8ec2dfe45d40..a5c2114e4292 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -90,7 +90,7 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m dc->hwss.exit_optimized_pwr_state(dc, dc->current_state); if (edp_link) { - clk_mgr->psr_allow_active_cache = edp_link->psr_allow_active; + clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active; dc_link_set_psr_allow_active(edp_link, false, false); } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c index 26db1c5d4e4d..b210f8e9d592 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c @@ -131,7 +131,7 @@ int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); int dprefclk_wdivider; int dprefclk_src_sel; - int dp_ref_clk_khz = 600000; + int dp_ref_clk_khz; int target_div; /* ASSERT DP Reference Clock source is from DFS*/ diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c index 97b7f32294fd..c320b7af7d34 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c @@ -97,9 +97,6 @@ int rv1_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_di VBIOSSMC_MSG_SetDispclkFreq, requested_dispclk_khz / 1000); - /* Actual dispclk set is returned in the parameter register */ - actual_dispclk_set_mhz = REG_READ(MP1_SMN_C2PMSG_83) * 1000; - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) { if (clk_mgr->dfs_bypass_disp_clk != actual_dispclk_set_mhz) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8489f1e56892..0f7810571be3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -66,6 +66,8 @@ #include "dce/dce_i2c.h" +#include "dmub/inc/dmub_cmd_dal.h" + #define CTX \ dc->ctx @@ -348,7 +350,7 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream, for (i = 0; i < MAX_PIPES; i++) { pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe->stream == stream) + if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe) break; } /* Stream not found */ @@ -365,6 +367,9 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream, param.windowb_x_end = pipe->stream->timing.h_addressable; param.windowb_y_end = pipe->stream->timing.v_addressable; + param.dsc_mode = pipe->stream->timing.flags.DSC ? 1:0; + param.odm_mode = pipe->next_odm_pipe ? 1:0; + /* Default to the union of both windows */ param.selection = UNION_WINDOW_A_B; param.continuous_mode = continuous; @@ -2641,33 +2646,12 @@ void dc_set_power_state( void dc_resume(struct dc *dc) { - uint32_t i; for (i = 0; i < dc->link_count; i++) core_link_resume(dc->links[i]); } -unsigned int dc_get_current_backlight_pwm(struct dc *dc) -{ - struct abm *abm = dc->res_pool->abm; - - if (abm) - return abm->funcs->get_current_backlight(abm); - - return 0; -} - -unsigned int dc_get_target_backlight_pwm(struct dc *dc) -{ - struct abm *abm = dc->res_pool->abm; - - if (abm) - return abm->funcs->get_target_backlight(abm); - - return 0; -} - bool dc_is_dmcu_initialized(struct dc *dc) { struct dmcu *dmcu = dc->res_pool->dmcu; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 67cfff1586e9..9c4686edcf3e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -46,10 +46,11 @@ #include "dmcu.h" #include "hw/clk_mgr.h" #include "dce/dmub_psr.h" +#include "dmub/inc/dmub_cmd_dal.h" +#include "inc/hw/panel_cntl.h" #define DC_LOGGER_INIT(logger) - #define LINK_INFO(...) \ DC_LOG_HW_HOTPLUG( \ __VA_ARGS__) @@ -64,11 +65,11 @@ enum { PEAK_FACTOR_X1000 = 1006, /* - * Some receivers fail to train on first try and are good - * on subsequent tries. 2 retries should be plenty. If we - * don't have a successful training then we don't expect to - * ever get one. - */ + * Some receivers fail to train on first try and are good + * on subsequent tries. 2 retries should be plenty. If we + * don't have a successful training then we don't expect to + * ever get one. + */ LINK_TRAINING_MAX_VERIFY_RETRY = 2 }; @@ -79,7 +80,7 @@ static void dc_link_destruct(struct dc_link *link) { int i; - if (link->hpd_gpio != NULL) { + if (link->hpd_gpio) { dal_gpio_destroy_irq(&link->hpd_gpio); link->hpd_gpio = NULL; } @@ -87,7 +88,10 @@ static void dc_link_destruct(struct dc_link *link) if (link->ddc) dal_ddc_service_destroy(&link->ddc); - if(link->link_enc) + if (link->panel_cntl) + link->panel_cntl->funcs->destroy(&link->panel_cntl); + + if (link->link_enc) link->link_enc->funcs->destroy(&link->link_enc); if (link->local_sink) @@ -98,8 +102,8 @@ static void dc_link_destruct(struct dc_link *link) } struct gpio *get_hpd_gpio(struct dc_bios *dcb, - struct graphics_object_id link_id, - struct gpio_service *gpio_service) + struct graphics_object_id link_id, + struct gpio_service *gpio_service) { enum bp_result bp_result; struct graphics_object_hpd_info hpd_info; @@ -116,10 +120,9 @@ struct gpio *get_hpd_gpio(struct dc_bios *dcb, return NULL; } - return dal_gpio_service_create_irq( - gpio_service, - pin_info.offset, - pin_info.mask); + return dal_gpio_service_create_irq(gpio_service, + pin_info.offset, + pin_info.mask); } /* @@ -134,13 +137,10 @@ struct gpio *get_hpd_gpio(struct dc_bios *dcb, * @return * true on success, false otherwise */ -static bool program_hpd_filter( - const struct dc_link *link) +static bool program_hpd_filter(const struct dc_link *link) { bool result = false; - struct gpio *hpd; - int delay_on_connect_in_ms = 0; int delay_on_disconnect_in_ms = 0; @@ -159,10 +159,10 @@ static bool program_hpd_filter( case SIGNAL_TYPE_DISPLAY_PORT_MST: /* Program hpd filter to allow DP signal to settle */ /* 500: not able to detect MST <-> SST switch as HPD is low for - * only 100ms on DELL U2413 - * 0: some passive dongle still show aux mode instead of i2c - * 20-50:not enough to hide bouncing HPD with passive dongle. - * also see intermittent i2c read issues. + * only 100ms on DELL U2413 + * 0: some passive dongle still show aux mode instead of i2c + * 20-50: not enough to hide bouncing HPD with passive dongle. + * also see intermittent i2c read issues. */ delay_on_connect_in_ms = 80; delay_on_disconnect_in_ms = 0; @@ -175,7 +175,8 @@ static bool program_hpd_filter( } /* Obtain HPD handle */ - hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); + hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, + link->ctx->gpio_service); if (!hpd) return result; @@ -226,8 +227,9 @@ bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type) } /* todo: may need to lock gpio access */ - hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); - if (hpd_pin == NULL) + hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id, + link->ctx->gpio_service); + if (!hpd_pin) goto hpd_gpio_failure; dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT); @@ -248,8 +250,7 @@ hpd_gpio_failure: return false; } -static enum ddc_transaction_type get_ddc_transaction_type( - enum signal_type sink_signal) +static enum ddc_transaction_type get_ddc_transaction_type(enum signal_type sink_signal) { enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE; @@ -270,7 +271,8 @@ static enum ddc_transaction_type get_ddc_transaction_type( case SIGNAL_TYPE_DISPLAY_PORT_MST: /* MST does not use I2COverAux, but there is the * SPECIAL use case for "immediate dwnstrm device - * access" (EPR#370830). */ + * access" (EPR#370830). + */ transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX; break; @@ -281,9 +283,8 @@ static enum ddc_transaction_type get_ddc_transaction_type( return transaction_type; } -static enum signal_type get_basic_signal_type( - struct graphics_object_id encoder, - struct graphics_object_id downstream) +static enum signal_type get_basic_signal_type(struct graphics_object_id encoder, + struct graphics_object_id downstream) { if (downstream.type == OBJECT_TYPE_CONNECTOR) { switch (downstream.id) { @@ -369,10 +370,11 @@ bool dc_link_is_dp_sink_present(struct dc_link *link) /* Open GPIO and set it to I2C mode */ /* Note: this GpioMode_Input will be converted * to GpioConfigType_I2cAuxDualMode in GPIO component, - * which indicates we need additional delay */ + * which indicates we need additional delay + */ - if (GPIO_RESULT_OK != dal_ddc_open( - ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) { + if (dal_ddc_open(ddc, GPIO_MODE_INPUT, + GPIO_DDC_CONFIG_TYPE_MODE_I2C) != GPIO_RESULT_OK) { dal_ddc_close(ddc); return present; @@ -406,25 +408,25 @@ bool dc_link_is_dp_sink_present(struct dc_link *link) * @brief * Detect output sink type */ -static enum signal_type link_detect_sink( - struct dc_link *link, - enum dc_detect_reason reason) +static enum signal_type link_detect_sink(struct dc_link *link, + enum dc_detect_reason reason) { - enum signal_type result = get_basic_signal_type( - link->link_enc->id, link->link_id); + enum signal_type result = get_basic_signal_type(link->link_enc->id, + link->link_id); /* Internal digital encoder will detect only dongles - * that require digital signal */ + * that require digital signal + */ /* Detection mechanism is different * for different native connectors. * LVDS connector supports only LVDS signal; * PCIE is a bus slot, the actual connector needs to be detected first; * eDP connector supports only eDP signal; - * HDMI should check straps for audio */ + * HDMI should check straps for audio + */ /* PCIE detects the actual connector on add-on board */ - if (link->link_id.id == CONNECTOR_ID_PCIE) { /* ZAZTODO implement PCIE add-on card detection */ } @@ -432,8 +434,10 @@ static enum signal_type link_detect_sink( switch (link->link_id.id) { case CONNECTOR_ID_HDMI_TYPE_A: { /* check audio support: - * if native HDMI is not supported, switch to DVI */ - struct audio_support *aud_support = &link->dc->res_pool->audio_support; + * if native HDMI is not supported, switch to DVI + */ + struct audio_support *aud_support = + &link->dc->res_pool->audio_support; if (!aud_support->hdmi_audio_native) if (link->link_id.id == CONNECTOR_ID_HDMI_TYPE_A) @@ -461,16 +465,15 @@ static enum signal_type link_detect_sink( return result; } -static enum signal_type decide_signal_from_strap_and_dongle_type( - enum display_dongle_type dongle_type, - struct audio_support *audio_support) +static enum signal_type decide_signal_from_strap_and_dongle_type(enum display_dongle_type dongle_type, + struct audio_support *audio_support) { enum signal_type signal = SIGNAL_TYPE_NONE; switch (dongle_type) { case DISPLAY_DONGLE_DP_HDMI_DONGLE: if (audio_support->hdmi_audio_on_dongle) - signal = SIGNAL_TYPE_HDMI_TYPE_A; + signal = SIGNAL_TYPE_HDMI_TYPE_A; else signal = SIGNAL_TYPE_DVI_SINGLE_LINK; break; @@ -491,16 +494,14 @@ static enum signal_type decide_signal_from_strap_and_dongle_type( return signal; } -static enum signal_type dp_passive_dongle_detection( - struct ddc_service *ddc, - struct display_sink_capability *sink_cap, - struct audio_support *audio_support) +static enum signal_type dp_passive_dongle_detection(struct ddc_service *ddc, + struct display_sink_capability *sink_cap, + struct audio_support *audio_support) { - dal_ddc_service_i2c_query_dp_dual_mode_adaptor( - ddc, sink_cap); - return decide_signal_from_strap_and_dongle_type( - sink_cap->dongle_type, - audio_support); + dal_ddc_service_i2c_query_dp_dual_mode_adaptor(ddc, sink_cap); + + return decide_signal_from_strap_and_dongle_type(sink_cap->dongle_type, + audio_support); } static void link_disconnect_sink(struct dc_link *link) @@ -519,6 +520,96 @@ static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *lin link->local_sink = prev_sink; } +#if defined(CONFIG_DRM_AMD_DC_HDCP) +bool dc_link_is_hdcp14(struct dc_link *link) +{ + bool ret = false; + + switch (link->connector_signal) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + ret = link->hdcp_caps.bcaps.bits.HDCP_CAPABLE; + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_HDMI_TYPE_A: + /* HDMI doesn't tell us its HDCP(1.4) capability, so assume to always be capable, + * we can poll for bksv but some displays have an issue with this. Since its so rare + * for a display to not be 1.4 capable, this assumtion is ok + */ + ret = true; + break; + default: + break; + } + return ret; +} + +bool dc_link_is_hdcp22(struct dc_link *link) +{ + bool ret = false; + + switch (link->connector_signal) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + ret = (link->hdcp_caps.bcaps.bits.HDCP_CAPABLE && + link->hdcp_caps.rx_caps.fields.byte0.hdcp_capable && + (link->hdcp_caps.rx_caps.fields.version == 0x2)) ? 1 : 0; + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_HDMI_TYPE_A: + ret = (link->hdcp_caps.rx_caps.fields.version == 0x4) ? 1:0; + break; + default: + break; + } + + return ret; +} + +static void query_hdcp_capability(enum signal_type signal, struct dc_link *link) +{ + struct hdcp_protection_message msg22; + struct hdcp_protection_message msg14; + + memset(&msg22, 0, sizeof(struct hdcp_protection_message)); + memset(&msg14, 0, sizeof(struct hdcp_protection_message)); + memset(link->hdcp_caps.rx_caps.raw, 0, + sizeof(link->hdcp_caps.rx_caps.raw)); + + if ((link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && + link->ddc->transaction_type == + DDC_TRANSACTION_TYPE_I2C_OVER_AUX) || + link->connector_signal == SIGNAL_TYPE_EDP) { + msg22.data = link->hdcp_caps.rx_caps.raw; + msg22.length = sizeof(link->hdcp_caps.rx_caps.raw); + msg22.msg_id = HDCP_MESSAGE_ID_RX_CAPS; + } else { + msg22.data = &link->hdcp_caps.rx_caps.fields.version; + msg22.length = sizeof(link->hdcp_caps.rx_caps.fields.version); + msg22.msg_id = HDCP_MESSAGE_ID_HDCP2VERSION; + } + msg22.version = HDCP_VERSION_22; + msg22.link = HDCP_LINK_PRIMARY; + msg22.max_retries = 5; + dc_process_hdcp_msg(signal, link, &msg22); + + if (signal == SIGNAL_TYPE_DISPLAY_PORT || signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + enum hdcp_message_status status = HDCP_MESSAGE_UNSUPPORTED; + + msg14.data = &link->hdcp_caps.bcaps.raw; + msg14.length = sizeof(link->hdcp_caps.bcaps.raw); + msg14.msg_id = HDCP_MESSAGE_ID_READ_BCAPS; + msg14.version = HDCP_VERSION_14; + msg14.link = HDCP_LINK_PRIMARY; + msg14.max_retries = 5; + + status = dc_process_hdcp_msg(signal, link, &msg14); + } + +} +#endif static void read_current_link_settings_on_detect(struct dc_link *link) { @@ -532,18 +623,18 @@ static void read_current_link_settings_on_detect(struct dc_link *link) // Read DPCD 00101h to find out the number of lanes currently set for (i = 0; i < read_dpcd_retry_cnt; i++) { - status = core_link_read_dpcd( - link, - DP_LANE_COUNT_SET, - &lane_count_set.raw, - sizeof(lane_count_set)); + status = core_link_read_dpcd(link, + DP_LANE_COUNT_SET, |
