diff options
Diffstat (limited to 'meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0321-drm-amd-display-Refactor-edid-read.patch')
-rw-r--r-- | meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0321-drm-amd-display-Refactor-edid-read.patch | 1123 |
1 files changed, 1123 insertions, 0 deletions
diff --git a/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0321-drm-amd-display-Refactor-edid-read.patch b/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0321-drm-amd-display-Refactor-edid-read.patch new file mode 100644 index 00000000..3eb40489 --- /dev/null +++ b/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0321-drm-amd-display-Refactor-edid-read.patch @@ -0,0 +1,1123 @@ +From 436dca3938da2421f7ca20ec25e1740219aee890 Mon Sep 17 00:00:00 2001 +From: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com> +Date: Tue, 28 Mar 2017 16:57:52 -0400 +Subject: [PATCH 0321/4131] drm/amd/display: Refactor edid read. + +Allow Linux to use DRM provided EDID read functioality +by moving DAL edid implementation to module hence +removing this code from DC by this cleaning up DC +code for upstream. + +v2: Removing ddc_service. No more need for it. + +Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com> +Acked-by: Harry Wentland <Harry.Wentland@amd.com> +Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 47 +++ + .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 47 ++- + .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.h | 2 +- + .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 10 +- + drivers/gpu/drm/amd/display/dc/core/dc.c | 78 +++-- + drivers/gpu/drm/amd/display/dc/core/dc_link.c | 53 +--- + drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 337 +-------------------- + drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 30 +- + drivers/gpu/drm/amd/display/dc/dc.h | 21 +- + drivers/gpu/drm/amd/display/dc/dc_types.h | 6 + + drivers/gpu/drm/amd/display/dc/dm_helpers.h | 10 + + drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 9 +- + drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h | 38 ++- + .../drm/amd/display/include/ddc_service_types.h | 28 -- + .../gpu/drm/amd/display/include/i2caux_interface.h | 3 + + 15 files changed, 254 insertions(+), 465 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +index ca4fa5c..3401780 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +@@ -434,3 +434,50 @@ bool dm_helpers_submit_i2c( + + return result; + } ++ ++enum dc_edid_status dm_helpers_read_local_edid( ++ struct dc_context *ctx, ++ struct dc_link *link, ++ struct dc_sink *sink) ++{ ++ struct amdgpu_connector *aconnector = link->priv; ++ struct i2c_adapter *ddc; ++ int retry = 3; ++ enum dc_edid_status edid_status; ++ struct edid *edid; ++ ++ if (link->aux_mode) ++ ddc = &aconnector->dm_dp_aux.aux.ddc; ++ else ++ ddc = &aconnector->i2c->base; ++ ++ /* some dongles read edid incorrectly the first time, ++ * do check sum and retry to make sure read correct edid. ++ */ ++ do { ++ ++ edid = drm_get_edid(&aconnector->base, ddc); ++ ++ if (!edid) ++ return EDID_NO_RESPONSE; ++ ++ sink->dc_edid.length = EDID_LENGTH * (edid->extensions + 1); ++ memmove(sink->dc_edid.raw_edid, (uint8_t *)edid, sink->dc_edid.length); ++ ++ /* We don't need the original edid anymore */ ++ kfree(edid); ++ ++ edid_status = dm_helpers_parse_edid_caps( ++ ctx, ++ &sink->dc_edid, ++ &sink->edid_caps); ++ ++ } while (edid_status == EDID_BAD_CHECKSUM && --retry > 0); ++ ++ if (edid_status != EDID_OK) ++ DRM_ERROR("EDID err: %d, on connector: %s", ++ edid_status, ++ aconnector->base.name); ++ ++ return edid_status; ++} +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +index cea8afb..436fa56 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +@@ -81,24 +81,43 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct amdgpu_device *adev = drm_dev->dev_private; + struct dc *dc = adev->dm.dc; ++ enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ? I2C_MOT_TRUE : I2C_MOT_FALSE; + bool res; + +- switch (msg->request) { ++ switch (msg->request & ~DP_AUX_I2C_MOT) { + case DP_AUX_NATIVE_READ: +- res = dc_read_dpcd( +- dc, +- TO_DM_AUX(aux)->link_index, +- msg->address, +- msg->buffer, +- msg->size); ++ res = dc_read_aux_dpcd( ++ dc, ++ TO_DM_AUX(aux)->link_index, ++ msg->address, ++ msg->buffer, ++ msg->size); + break; + case DP_AUX_NATIVE_WRITE: +- res = dc_write_dpcd( +- dc, +- TO_DM_AUX(aux)->link_index, +- msg->address, +- msg->buffer, +- msg->size); ++ res = dc_write_aux_dpcd( ++ dc, ++ TO_DM_AUX(aux)->link_index, ++ msg->address, ++ msg->buffer, ++ msg->size); ++ break; ++ case DP_AUX_I2C_READ: ++ res = dc_read_aux_i2c( ++ dc, ++ TO_DM_AUX(aux)->link_index, ++ mot, ++ msg->address, ++ msg->buffer, ++ msg->size); ++ break; ++ case DP_AUX_I2C_WRITE: ++ res = dc_write_aux_i2c( ++ dc, ++ TO_DM_AUX(aux)->link_index, ++ mot, ++ msg->address, ++ msg->buffer, ++ msg->size); + break; + default: + return 0; +@@ -420,7 +439,7 @@ static const struct drm_dp_mst_topology_cbs dm_mst_cbs = { + .register_connector = dm_dp_mst_register_connector + }; + +-void amdgpu_dm_initialize_mst_connector( ++void amdgpu_dm_initialize_dp_connector( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector) + { +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +index 6130d62..418061f 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +@@ -29,7 +29,7 @@ + struct amdgpu_display_manager; + struct amdgpu_connector; + +-void amdgpu_dm_initialize_mst_connector( ++void amdgpu_dm_initialize_dp_connector( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector); + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +index 4fba5ad..e9876574 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +@@ -2218,7 +2218,7 @@ int amdgpu_dm_connector_init( + + if (connector_type == DRM_MODE_CONNECTOR_DisplayPort + || connector_type == DRM_MODE_CONNECTOR_eDP) +- amdgpu_dm_initialize_mst_connector(dm, aconnector); ++ amdgpu_dm_initialize_dp_connector(dm, aconnector); + + #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) +@@ -3209,9 +3209,11 @@ static bool is_dp_capable_without_timing_msa( + uint8_t dpcd_data; + bool capable = false; + if (amdgpu_connector->dc_link && +- dc_read_dpcd(dc, amdgpu_connector->dc_link->link_index, +- DP_DOWN_STREAM_PORT_COUNT, +- &dpcd_data, sizeof(dpcd_data)) ) ++ dc_read_aux_dpcd( ++ dc, ++ amdgpu_connector->dc_link->link_index, ++ DP_DOWN_STREAM_PORT_COUNT, ++ &dpcd_data, sizeof(dpcd_data))) + capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false; + + return capable; +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index b389122..40a8001 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -1553,7 +1553,7 @@ void dc_resume(const struct dc *dc) + core_link_resume(core_dc->links[i]); + } + +-bool dc_read_dpcd( ++bool dc_read_aux_dpcd( + struct dc *dc, + uint32_t link_index, + uint32_t address, +@@ -1565,56 +1565,100 @@ bool dc_read_dpcd( + struct core_link *link = core_dc->links[link_index]; + enum ddc_result r = dal_ddc_service_read_dpcd_data( + link->ddc, ++ false, ++ I2C_MOT_UNDEF, + address, + data, + size); + return r == DDC_RESULT_SUCESSFULL; + } + +-bool dc_query_ddc_data( ++bool dc_write_aux_dpcd( + struct dc *dc, + uint32_t link_index, + uint32_t address, +- uint8_t *write_buf, +- uint32_t write_size, +- uint8_t *read_buf, +- uint32_t read_size) { +- ++ const uint8_t *data, ++ uint32_t size) ++{ + struct core_dc *core_dc = DC_TO_CORE(dc); +- + struct core_link *link = core_dc->links[link_index]; + +- bool result = dal_ddc_service_query_ddc_data( ++ enum ddc_result r = dal_ddc_service_write_dpcd_data( + link->ddc, ++ false, ++ I2C_MOT_UNDEF, + address, +- write_buf, +- write_size, +- read_buf, +- read_size); +- +- return result; ++ data, ++ size); ++ return r == DDC_RESULT_SUCESSFULL; + } + ++bool dc_read_aux_i2c( ++ struct dc *dc, ++ uint32_t link_index, ++ enum i2c_mot_mode mot, ++ uint32_t address, ++ uint8_t *data, ++ uint32_t size) ++{ ++ struct core_dc *core_dc = DC_TO_CORE(dc); + +-bool dc_write_dpcd( ++ struct core_link *link = core_dc->links[link_index]; ++ enum ddc_result r = dal_ddc_service_read_dpcd_data( ++ link->ddc, ++ true, ++ mot, ++ address, ++ data, ++ size); ++ return r == DDC_RESULT_SUCESSFULL; ++} ++ ++bool dc_write_aux_i2c( + struct dc *dc, + uint32_t link_index, ++ enum i2c_mot_mode mot, + uint32_t address, + const uint8_t *data, + uint32_t size) + { + struct core_dc *core_dc = DC_TO_CORE(dc); +- + struct core_link *link = core_dc->links[link_index]; + + enum ddc_result r = dal_ddc_service_write_dpcd_data( + link->ddc, ++ true, ++ mot, + address, + data, + size); + return r == DDC_RESULT_SUCESSFULL; + } + ++bool dc_query_ddc_data( ++ struct dc *dc, ++ uint32_t link_index, ++ uint32_t address, ++ uint8_t *write_buf, ++ uint32_t write_size, ++ uint8_t *read_buf, ++ uint32_t read_size) { ++ ++ struct core_dc *core_dc = DC_TO_CORE(dc); ++ ++ struct core_link *link = core_dc->links[link_index]; ++ ++ bool result = dal_ddc_service_query_ddc_data( ++ link->ddc, ++ address, ++ write_buf, ++ write_size, ++ read_buf, ++ read_size); ++ ++ return result; ++} ++ + bool dc_submit_i2c( + struct dc *dc, + uint32_t link_index, +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 74dd272..0f825f6 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c +@@ -464,39 +464,6 @@ static void link_disconnect_sink(struct core_link *link) + link->dpcd_sink_count = 0; + } + +-static enum dc_edid_status read_edid( +- struct core_link *link, +- struct core_sink *sink) +-{ +- uint32_t edid_retry = 3; +- enum dc_edid_status edid_status; +- +- /* some dongles read edid incorrectly the first time, +- * do check sum and retry to make sure read correct edid. +- */ +- do { +- sink->public.dc_edid.length = +- dal_ddc_service_edid_query(link->ddc); +- +- if (0 == sink->public.dc_edid.length) +- return EDID_NO_RESPONSE; +- +- dal_ddc_service_get_edid_buf(link->ddc, +- sink->public.dc_edid.raw_edid); +- edid_status = dm_helpers_parse_edid_caps( +- sink->ctx, +- &sink->public.dc_edid, +- &sink->public.edid_caps); +- --edid_retry; +- if (edid_status == EDID_BAD_CHECKSUM) +- dm_logger_write(link->ctx->logger, LOG_WARNING, +- "Bad EDID checksum, retry remain: %d\n", +- edid_retry); +- } while (edid_status == EDID_BAD_CHECKSUM && edid_retry > 0); +- +- return edid_status; +-} +- + static void detect_dp( + struct core_link *link, + struct display_sink_capability *sink_caps, +@@ -673,6 +640,9 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) + link->ddc, + sink_caps.transaction_type); + ++ link->public.aux_mode = dal_ddc_service_is_in_aux_transaction_mode( ++ link->ddc); ++ + sink_init_data.link = &link->public; + sink_init_data.sink_signal = sink_caps.signal; + +@@ -688,7 +658,10 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) + sink = DC_SINK_TO_CORE(dc_sink); + link->public.local_sink = &sink->public; + +- edid_status = read_edid(link, sink); ++ edid_status = dm_helpers_read_local_edid( ++ link->ctx, ++ &link->public, ++ &sink->public); + + switch (edid_status) { + case EDID_BAD_CHECKSUM: +@@ -1500,11 +1473,13 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, + */ + psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR = 1; + } +- dal_ddc_service_write_dpcd_data( +- link->ddc, +- 368, +- &psr_configuration.raw, +- sizeof(psr_configuration.raw)); ++ ++ dm_helpers_dp_write_dpcd( ++ link->ctx, ++ dc_link, ++ 368, ++ &psr_configuration.raw, ++ sizeof(psr_configuration.raw)); + + psr_context.channel = link->ddc->ddc_pin->hw_info.ddc_channel; + if (psr_context.channel == 0) +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +index 4e9465b..2f5a89c 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +@@ -58,30 +58,6 @@ struct dp_hdmi_dongle_signature_data { + uint8_t eot;/* end of transmition '\x4' */ + }; + +-/* Address range from 0x00 to 0x1F.*/ +-#define DP_ADAPTOR_TYPE2_SIZE 0x20 +-#define DP_ADAPTOR_TYPE2_REG_ID 0x10 +-#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D +-/* Identifies adaptor as Dual-mode adaptor */ +-#define DP_ADAPTOR_TYPE2_ID 0xA0 +-/* MHz*/ +-#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600 +-/* MHz*/ +-#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25 +-/* kHZ*/ +-#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000 +-/* kHZ*/ +-#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000 +- +-#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW +- +-enum edid_read_result { +- EDID_READ_RESULT_EDID_MATCH = 0, +- EDID_READ_RESULT_EDID_MISMATCH, +- EDID_READ_RESULT_CHECKSUM_READ_ERR, +- EDID_READ_RESULT_VENDOR_READ_ERR +-}; +- + /* SCDC Address defines (HDMI 2.0)*/ + #define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3 + #define HDMI_SCDC_ADDRESS 0x54 +@@ -392,7 +368,7 @@ static uint32_t defer_delay_converter_wa( + + #define DP_TRANSLATOR_DELAY 5 + +-static uint32_t get_defer_delay(struct ddc_service *ddc) ++uint32_t get_defer_delay(struct ddc_service *ddc) + { + uint32_t defer_delay = 0; + +@@ -451,307 +427,6 @@ static bool i2c_read( + &command); + } + +-static uint8_t aux_read_edid_block( +- struct ddc_service *ddc, +- uint8_t address, +- uint8_t index, +- uint8_t *buf) +-{ +- struct aux_command cmd = { +- .payloads = NULL, +- .number_of_payloads = 0, +- .defer_delay = get_defer_delay(ddc), +- .max_defer_write_retry = 0 }; +- +- uint8_t retrieved = 0; +- uint8_t base_offset = +- (index % DDC_EDID_BLOCKS_PER_SEGMENT) * DDC_EDID_BLOCK_SIZE; +- uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; +- +- for (retrieved = 0; retrieved < DDC_EDID_BLOCK_SIZE; +- retrieved += DEFAULT_AUX_MAX_DATA_SIZE) { +- +- uint8_t offset = base_offset + retrieved; +- +- struct aux_payload payloads[3] = { +- { +- .i2c_over_aux = true, +- .write = true, +- .address = DDC_EDID_SEGMENT_ADDRESS, +- .length = 1, +- .data = &segment }, +- { +- .i2c_over_aux = true, +- .write = true, +- .address = address, +- .length = 1, +- .data = &offset }, +- { +- .i2c_over_aux = true, +- .write = false, +- .address = address, +- .length = DEFAULT_AUX_MAX_DATA_SIZE, +- .data = &buf[retrieved] } }; +- +- if (segment == 0) { +- cmd.payloads = &payloads[1]; +- cmd.number_of_payloads = 2; +- } else { +- cmd.payloads = payloads; +- cmd.number_of_payloads = 3; +- } +- +- if (!dal_i2caux_submit_aux_command( +- ddc->ctx->i2caux, +- ddc->ddc_pin, +- &cmd)) +- /* cannot read, break*/ +- break; +- } +- +- /* Reset segment to 0. Needed by some panels */ +- if (0 != segment) { +- struct aux_payload payloads[1] = { { +- .i2c_over_aux = true, +- .write = true, +- .address = DDC_EDID_SEGMENT_ADDRESS, +- .length = 1, +- .data = &segment } }; +- bool result = false; +- +- segment = 0; +- +- cmd.number_of_payloads = ARRAY_SIZE(payloads); +- cmd.payloads = payloads; +- +- result = dal_i2caux_submit_aux_command( +- ddc->ctx->i2caux, +- ddc->ddc_pin, +- &cmd); +- +- if (false == result) +- dm_logger_write( +- ddc->ctx->logger, LOG_ERROR, +- "%s: Writing of EDID Segment (0x30) failed!\n", +- __func__); +- } +- +- return retrieved; +-} +- +-static uint8_t i2c_read_edid_block( +- struct ddc_service *ddc, +- uint8_t address, +- uint8_t index, +- uint8_t *buf) +-{ +- bool ret = false; +- uint8_t offset = (index % DDC_EDID_BLOCKS_PER_SEGMENT) * +- DDC_EDID_BLOCK_SIZE; +- uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; +- +- struct i2c_command cmd = { +- .payloads = NULL, +- .number_of_payloads = 0, +- .engine = DDC_I2C_COMMAND_ENGINE, +- .speed = ddc->ctx->dc->caps.i2c_speed_in_khz }; +- +- struct i2c_payload payloads[3] = { +- { +- .write = true, +- .address = DDC_EDID_SEGMENT_ADDRESS, +- .length = 1, +- .data = &segment }, +- { +- .write = true, +- .address = address, +- .length = 1, +- .data = &offset }, +- { +- .write = false, +- .address = address, +- .length = DDC_EDID_BLOCK_SIZE, +- .data = buf } }; +-/* +- * Some I2C engines don't handle stop/start between write-offset and read-data +- * commands properly. For those displays, we have to force the newer E-DDC +- * behavior of repeated-start which can be enabled by runtime parameter. */ +-/* Originally implemented for OnLive using NXP receiver chip */ +- +- if (index == 0 && !ddc->flags.FORCE_READ_REPEATED_START) { +- /* base block, use use DDC2B, submit as 2 commands */ +- cmd.payloads = &payloads[1]; +- cmd.number_of_payloads = 1; +- +- if (dm_helpers_submit_i2c( +- ddc->ctx, +- &ddc->link->public, +- &cmd)) { +- +- cmd.payloads = &payloads[2]; +- cmd.number_of_payloads = 1; +- +- ret = dm_helpers_submit_i2c( +- ddc->ctx, +- &ddc->link->public, +- &cmd); +- } +- +- } else { +- /* +- * extension block use E-DDC, submit as 1 command +- * or if repeated-start is forced by runtime parameter +- */ +- if (segment != 0) { +- /* include segment offset in command*/ +- cmd.payloads = payloads; +- cmd.number_of_payloads = 3; +- } else { +- /* we are reading first segment, +- * segment offset is not required */ +- cmd.payloads = &payloads[1]; +- cmd.number_of_payloads = 2; +- } +- +- ret = dm_helpers_submit_i2c( +- ddc->ctx, +- &ddc->link->public, +- &cmd); +- } +- +- return ret ? DDC_EDID_BLOCK_SIZE : 0; +-} +- +-static uint32_t query_edid_block( +- struct ddc_service *ddc, +- uint8_t address, +- uint8_t index, +- uint8_t *buf, +- uint32_t size) +-{ +- uint32_t size_retrieved = 0; +- +- if (size < DDC_EDID_BLOCK_SIZE) +- return 0; +- +- if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { +- size_retrieved = +- aux_read_edid_block(ddc, address, index, buf); +- } else { +- size_retrieved = +- i2c_read_edid_block(ddc, address, index, buf); +- } +- +- return size_retrieved; +-} +- +-#define DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS 0x261 +-#define DDC_TEST_ACK_ADDRESS 0x260 +-#define DDC_DPCD_EDID_TEST_ACK 0x04 +-#define DDC_DPCD_EDID_TEST_MASK 0x04 +-#define DDC_DPCD_TEST_REQUEST_ADDRESS 0x218 +- +-/* AG TODO GO throug DM callback here like for DPCD */ +- +-static void write_dp_edid_checksum( +- struct ddc_service *ddc, +- uint8_t checksum) +-{ +- uint8_t dpcd_data; +- +- dal_ddc_service_read_dpcd_data( +- ddc, +- DDC_DPCD_TEST_REQUEST_ADDRESS, +- &dpcd_data, +- 1); +- +- if (dpcd_data & DDC_DPCD_EDID_TEST_MASK) { +- +- dal_ddc_service_write_dpcd_data( +- ddc, +- DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS, +- &checksum, +- 1); +- +- dpcd_data = DDC_DPCD_EDID_TEST_ACK; +- +- dal_ddc_service_write_dpcd_data( +- ddc, +- DDC_TEST_ACK_ADDRESS, +- &dpcd_data, +- 1); +- } +-} +- +-uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc) +-{ +- uint32_t bytes_read = 0; +- uint32_t ext_cnt = 0; +- +- uint8_t address; +- uint32_t i; +- +- for (address = DDC_EDID_ADDRESS_START; +- address <= DDC_EDID_ADDRESS_END; ++address) { +- +- bytes_read = query_edid_block( +- ddc, +- address, +- 0, +- ddc->edid_buf, +- sizeof(ddc->edid_buf) - bytes_read); +- +- if (bytes_read != DDC_EDID_BLOCK_SIZE) +- continue; +- +- /* get the number of ext blocks*/ +- ext_cnt = ddc->edid_buf[DDC_EDID_EXT_COUNT_OFFSET]; +- +- /* EDID 2.0, need to read 1 more block because EDID2.0 is +- * 256 byte in size*/ +- if (ddc->edid_buf[DDC_EDID_20_SIGNATURE_OFFSET] == +- DDC_EDID_20_SIGNATURE) +- ext_cnt = 1; +- +- for (i = 0; i < ext_cnt; i++) { +- /* read additional ext blocks accordingly */ +- bytes_read += query_edid_block( +- ddc, +- address, +- i+1, +- &ddc->edid_buf[bytes_read], +- sizeof(ddc->edid_buf) - bytes_read); +- } +- +- /*this is special code path for DP compliance*/ +- if (DDC_TRANSACTION_TYPE_I2C_OVER_AUX == ddc->transaction_type) +- write_dp_edid_checksum( +- ddc, +- ddc->edid_buf[(ext_cnt * DDC_EDID_BLOCK_SIZE) + +- DDC_EDID1X_CHECKSUM_OFFSET]); +- +- /*remembers the address where we fetch the EDID from +- * for later signature check use */ +- ddc->address = address; +- +- break;/* already read edid, done*/ +- } +- +- ddc->edid_buf_len = bytes_read; +- return bytes_read; +-} +- +-uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc) +-{ +- return ddc->edid_buf_len; +-} +- +-void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf) +-{ +- memmove(edid_buf, +- ddc->edid_buf, ddc->edid_buf_len); +-} +- + void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( + struct ddc_service *ddc, + struct display_sink_capability *sink_cap) +@@ -960,12 +635,14 @@ bool dal_ddc_service_query_ddc_data( + + enum ddc_result dal_ddc_service_read_dpcd_data( + struct ddc_service *ddc, ++ bool i2c, ++ enum i2c_mot_mode mot, + uint32_t address, + uint8_t *data, + uint32_t len) + { + struct aux_payload read_payload = { +- .i2c_over_aux = false, ++ .i2c_over_aux = i2c, + .write = false, + .address = address, + .length = len, +@@ -976,6 +653,7 @@ enum ddc_result dal_ddc_service_read_dpcd_data( + .number_of_payloads = 1, + .defer_delay = 0, + .max_defer_write_retry = 0, ++ .mot = mot + }; + + if (len > DEFAULT_AUX_MAX_DATA_SIZE) { +@@ -994,12 +672,14 @@ enum ddc_result dal_ddc_service_read_dpcd_data( + + enum ddc_result dal_ddc_service_write_dpcd_data( + struct ddc_service *ddc, ++ bool i2c, ++ enum i2c_mot_mode mot, + uint32_t address, + const uint8_t *data, + uint32_t len) + { + struct aux_payload write_payload = { +- .i2c_over_aux = false, ++ .i2c_over_aux = i2c, + .write = true, + .address = address, + .length = len, +@@ -1010,6 +690,7 @@ enum ddc_result dal_ddc_service_write_dpcd_data( + .number_of_payloads = 1, + .defer_delay = 0, + .max_defer_write_retry = 0, ++ .mot = mot + }; + + if (len > DEFAULT_AUX_MAX_DATA_SIZE) { +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +index 6cfd880..802d8cc 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +@@ -1481,22 +1481,25 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) + if (link->public.psr_caps.psr_version == 0) + return false; + +- dal_ddc_service_read_dpcd_data( +- link->ddc, +- 368 /*DpcdAddress_PSR_Enable_Cfg*/, +- &psr_configuration.raw, +- sizeof(psr_configuration.raw)); ++ dm_helpers_dp_read_dpcd( ++ link->ctx, ++ &link->public, ++ 368,/*DpcdAddress_PSR_Enable_Cfg*/ ++ &psr_configuration.raw, ++ sizeof(psr_configuration.raw)); ++ + + if (psr_configuration.bits.ENABLE) { + unsigned char dpcdbuf[3] = {0}; + union psr_error_status psr_error_status; + union psr_sink_psr_status psr_sink_psr_status; + +- dal_ddc_service_read_dpcd_data( +- link->ddc, +- 0x2006 /*DpcdAddress_PSR_Error_Status*/, +- (unsigned char *) dpcdbuf, +- sizeof(dpcdbuf)); ++ dm_helpers_dp_read_dpcd( ++ link->ctx, ++ &link->public, ++ 0x2006, /*DpcdAddress_PSR_Error_Status*/ ++ (unsigned char *) dpcdbuf, ++ sizeof(dpcdbuf)); + + /*DPCD 2006h ERROR STATUS*/ + psr_error_status.raw = dpcdbuf[0]; +@@ -1506,9 +1509,10 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) + if (psr_error_status.bits.LINK_CRC_ERROR || + psr_error_status.bits.RFB_STORAGE_ERROR) { + /* Acknowledge and clear error bits */ +- dal_ddc_service_write_dpcd_data( +- link->ddc, +- 8198 /*DpcdAddress_PSR_Error_Status*/, ++ dm_helpers_dp_write_dpcd( ++ link->ctx, ++ &link->public, ++ 8198,/*DpcdAddress_PSR_Error_Status*/ + &psr_error_status.raw, + sizeof(psr_error_status.raw)); + +diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h +index d296055..a27a6ab 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc.h ++++ b/drivers/gpu/drm/amd/display/dc/dc.h +@@ -594,6 +594,7 @@ struct dc_link { + union compliance_test_state compliance_test_state; + + void *priv; ++ bool aux_mode; + }; + + struct dpcd_caps { +@@ -788,20 +789,36 @@ const struct ddc_service *dc_get_ddc_at_index( + * DPCD access interfaces + */ + +-bool dc_read_dpcd( ++bool dc_read_aux_dpcd( + struct dc *dc, + uint32_t link_index, + uint32_t address, + uint8_t *data, + uint32_t size); + +-bool dc_write_dpcd( ++bool dc_write_aux_dpcd( + struct dc *dc, + uint32_t link_index, + uint32_t address, + const uint8_t *data, + uint32_t size); + ++bool dc_read_aux_i2c( ++ struct dc *dc, ++ uint32_t link_index, ++ enum i2c_mot_mode mot, ++ uint32_t address, ++ uint8_t *data, ++ uint32_t size); ++ ++bool dc_write_aux_i2c( ++ struct dc *dc, ++ uint32_t link_index, ++ enum i2c_mot_mode mot, ++ uint32_t address, ++ const uint8_t *data, ++ uint32_t size); ++ + bool dc_query_ddc_data( + struct dc *dc, + uint32_t link_index, +diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h +index 242dd7b..e0436e3 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_types.h +@@ -489,4 +489,10 @@ struct psr_caps { + unsigned int psr_sdp_transmit_line_num_deadline; + }; + ++enum i2c_mot_mode { ++ I2C_MOT_UNDEF, ++ I2C_MOT_TRUE, ++ I2C_MOT_FALSE ++}; ++ + #endif /* DC_TYPES_H_ */ +diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h +index d6c52d3..c15a25c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h ++++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h +@@ -98,4 +98,14 @@ bool dm_helpers_submit_i2c( + struct i2c_command *cmd); + + ++ ++ ++ ++ ++enum dc_edid_status dm_helpers_read_local_edid( ++ struct dc_context *ctx, ++ struct dc_link *link, ++ struct dc_sink *sink); ++ ++ + #endif /* __DM_HELPERS__ */ +diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +index bd84b93..0743265 100644 +--- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c ++++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +@@ -185,6 +185,7 @@ bool dal_i2caux_submit_aux_command( + struct aux_engine *engine; + uint8_t index_of_payload = 0; + bool result; ++ bool mot; + + if (!ddc) { + BREAK_TO_DEBUGGER(); +@@ -207,12 +208,14 @@ bool dal_i2caux_submit_aux_command( + result = true; + + while (index_of_payload < cmd->number_of_payloads) { +- bool mot = (index_of_payload != cmd->number_of_payloads - 1); +- + struct aux_payload *payload = cmd->payloads + index_of_payload; +- + struct i2caux_transaction_request request = { 0 }; + ++ if (cmd->mot == I2C_MOT_UNDEF) ++ mot = (index_of_payload != cmd->number_of_payloads - 1); ++ else ++ mot = (cmd->mot == I2C_MOT_TRUE); ++ + request.operation = payload->write ? + I2CAUX_TRANSACTION_WRITE : + I2CAUX_TRANSACTION_READ; +diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h +index 830fc3d..9c2f670 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h +@@ -31,6 +31,23 @@ + + #define EDID_SEGMENT_SIZE 256 + ++/* Address range from 0x00 to 0x1F.*/ ++#define DP_ADAPTOR_TYPE2_SIZE 0x20 ++#define DP_ADAPTOR_TYPE2_REG_ID 0x10 ++#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D ++/* Identifies adaptor as Dual-mode adaptor */ ++#define DP_ADAPTOR_TYPE2_ID 0xA0 ++/* MHz*/ ++#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600 ++/* MHz*/ ++#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25 ++/* kHZ*/ ++#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000 ++/* kHZ*/ ++#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000 ++ ++#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW ++ + struct ddc_service; + struct graphics_object_id; + enum ddc_result; +@@ -83,12 +100,6 @@ void dal_ddc_service_set_transaction_type( + + bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc); + +-uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc); +- +-uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc); +- +-void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf); +- + void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( + struct ddc_service *ddc, + struct display_sink_capability *sink_cap); +@@ -103,12 +114,16 @@ bool dal_ddc_service_query_ddc_data( + + enum ddc_result dal_ddc_service_read_dpcd_data( + struct ddc_service *ddc, ++ bool i2c, ++ enum i2c_mot_mode mot, + uint32_t address, + uint8_t *data, + uint32_t len); + + enum ddc_result dal_ddc_service_write_dpcd_data( + struct ddc_service *ddc, ++ bool i2c, ++ enum i2c_mot_mode mot, + uint32_t address, + const uint8_t *data, + uint32_t len); +@@ -130,16 +145,7 @@ void dal_ddc_service_set_ddc_pin( + + struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service); + +-enum ddc_result dal_ddc_service_read_dpcd_data( +- struct ddc_service *ddc, +- uint32_t address, +- uint8_t *data, +- uint32_t len); +-enum ddc_result dal_ddc_service_write_dpcd_data( +- struct ddc_service *ddc, +- uint32_t address, +- const uint8_t *data, +- uint32_t len); ++uint32_t get_defer_delay(struct ddc_service *ddc); + + #endif /* __DAL_DDC_SERVICE_H__ */ + +diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h +index effe03b..0ff2a89 100644 +--- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h ++++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h +@@ -115,34 +115,6 @@ struct av_sync_data { + uint8_t aud_del_ins3;/* DPCD 0002Dh */ + }; + +-/** EDID retrieval related constants, also used by MstMgr **/ +- +-#define DDC_EDID_SEGMENT_SIZE 256 +-#define DDC_EDID_BLOCK_SIZE 128 +-#define DDC_EDID_BLOCKS_PER_SEGMENT \ +- (DDC_EDID_SEGMENT_SIZE / DDC_EDID_BLOCK_SIZE) +- +-#define DDC_EDID_EXT_COUNT_OFFSET 0x7E +- +-#define DDC_EDID_ADDRESS_START 0x50 +-#define DDC_EDID_ADDRESS_END 0x52 +-#define DDC_EDID_SEGMENT_ADDRESS 0x30 +- +-/* signatures for Edid 1x */ +-#define DDC_EDID1X_VENDORID_SIGNATURE_OFFSET 8 +-#define DDC_EDID1X_VENDORID_SIGNATURE_LEN 4 +-#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_OFFSET 126 +-#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_LEN 2 +-#define DDC_EDID1X_CHECKSUM_OFFSET 127 +-/* signatures for Edid 20*/ +-#define DDC_EDID_20_SIGNATURE_OFFSET 0 +-#define DDC_EDID_20_SIGNATURE 0x20 +- +-#define DDC_EDID20_VENDORID_SIGNATURE_OFFSET 1 +-#define DDC_EDID20_VENDORID_SIGNATURE_LEN 4 +-#define DDC_EDID20_CHECKSUM_OFFSET 255 +-#define DDC_EDID20_CHECKSUM_LEN 1 +- + /*DP to VGA converter*/ + static const uint8_t DP_VGA_CONVERTER_ID_1[] = "mVGAa"; + /*DP to Dual link DVI converter*/ +diff --git a/drivers/gpu/drm/amd/display/include/i2caux_interface.h b/drivers/gpu/drm/amd/display/include/i2caux_interface.h +index d2ec04d..13a3c82 100644 +--- a/drivers/gpu/drm/amd/display/include/i2caux_interface.h ++++ b/drivers/gpu/drm/amd/display/include/i2caux_interface.h +@@ -26,6 +26,7 @@ + #ifndef __DAL_I2CAUX_INTERFACE_H__ + #define __DAL_I2CAUX_INTERFACE_H__ + ++#include "dc_types.h" + #include "gpio_service_interface.h" + + +@@ -54,6 +55,8 @@ struct aux_command { + + /* zero means "use default value" */ + uint32_t max_defer_write_retry; ++ ++ enum i2c_mot_mode mot; + }; + + union aux_config { +-- +2.7.4 + |