summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c47
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c47
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c78
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c53
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c337
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c30
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_types.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dm_helpers.h10
-rw-r--r--drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h38
-rw-r--r--drivers/gpu/drm/amd/display/include/ddc_service_types.h28
-rw-r--r--drivers/gpu/drm/amd/display/include/i2caux_interface.h3
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 5b096be44e59..01d04fa2419e 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
@@ -435,3 +435,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 069511bb6fab..187464ac27b3 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;
@@ -418,7 +437,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 6130d62ac65c..418061f3b46b 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 c09af2b3350c..345df1b6d82b 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
@@ -2047,7 +2047,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)
@@ -3038,9 +3038,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 b3891228b499..40a800155fe6 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 74dd272d7452..0f825f6326ab 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 4e9465b630d1..2f5a89c5b063 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 b8c40e8bee5a..9f12ba87827a 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 d2960552c78e..a27a6aba0df1 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 242dd7b3b6b1..e0436e317341 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 d6c52d31f0f0..c15a25ce8049 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 bd84b932aaae..0743265e933c 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 830fc3d039c9..9c2f670c3dc3 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 effe03b8f418..0ff2a899b8f7 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 d2ec04d1c592..13a3c82d118f 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 {