[PATCH AUTOSEL 5.8 38/64] drm/amd/display: allow query ddc data over aux to be read only operation

From: Sasha Levin
Date: Mon Aug 10 2020 - 15:31:53 EST


From: Wenjing Liu <wenjing.liu@xxxxxxx>

[ Upstream commit 26b4750d6cf84cb2b3f0a84c9b345e7b71886410 ]

[why]
Two issues:
1. Add read only operation support for query ddc data over aux.
2. Fix a bug where if read size is multiple of 16,
mot of the last read transaction will not be set to 0.

Signed-off-by: Wenjing Liu <wenjing.liu@xxxxxxx>
Reviewed-by: Jun Lei <Jun.Lei@xxxxxxx>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@xxxxxxx>
Signed-off-by: Alex Deucher <alexander.deucher@xxxxxxx>
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---
.../gpu/drm/amd/display/dc/core/dc_link_ddc.c | 29 ++++++++++++-------
1 file changed, 18 insertions(+), 11 deletions(-)

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 aefd29a440b52..be8f265976b09 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
@@ -503,7 +503,7 @@ bool dal_ddc_service_query_ddc_data(
uint8_t *read_buf,
uint32_t read_size)
{
- bool ret = false;
+ bool success = true;
uint32_t payload_size =
dal_ddc_service_is_in_aux_transaction_mode(ddc) ?
DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE;
@@ -527,7 +527,6 @@ bool dal_ddc_service_query_ddc_data(
* but we want to read 256 over i2c!!!!*/
if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
struct aux_payload payload;
- bool read_available = true;

payload.i2c_over_aux = true;
payload.address = address;
@@ -536,21 +535,26 @@ bool dal_ddc_service_query_ddc_data(

if (write_size != 0) {
payload.write = true;
- payload.mot = false;
+ /* should not set mot (middle of transaction) to 0
+ * if there are pending read payloads
+ */
+ payload.mot = read_size == 0 ? false : true;
payload.length = write_size;
payload.data = write_buf;

- ret = dal_ddc_submit_aux_command(ddc, &payload);
- read_available = ret;
+ success = dal_ddc_submit_aux_command(ddc, &payload);
}

- if (read_size != 0 && read_available) {
+ if (read_size != 0 && success) {
payload.write = false;
+ /* should set mot (middle of transaction) to 0
+ * since it is the last payload to send
+ */
payload.mot = false;
payload.length = read_size;
payload.data = read_buf;

- ret = dal_ddc_submit_aux_command(ddc, &payload);
+ success = dal_ddc_submit_aux_command(ddc, &payload);
}
} else {
struct i2c_command command = {0};
@@ -573,7 +577,7 @@ bool dal_ddc_service_query_ddc_data(
command.number_of_payloads =
dal_ddc_i2c_payloads_get_count(&payloads);

- ret = dm_helpers_submit_i2c(
+ success = dm_helpers_submit_i2c(
ddc->ctx,
ddc->link,
&command);
@@ -581,7 +585,7 @@ bool dal_ddc_service_query_ddc_data(
dal_ddc_i2c_payloads_destroy(&payloads);
}

- return ret;
+ return success;
}

bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
@@ -598,7 +602,7 @@ bool dal_ddc_submit_aux_command(struct ddc_service *ddc,

do {
struct aux_payload current_payload;
- bool is_end_of_payload = (retrieved + DEFAULT_AUX_MAX_DATA_SIZE) >
+ bool is_end_of_payload = (retrieved + DEFAULT_AUX_MAX_DATA_SIZE) >=
payload->length;

current_payload.address = payload->address;
@@ -607,7 +611,10 @@ bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
current_payload.i2c_over_aux = payload->i2c_over_aux;
current_payload.length = is_end_of_payload ?
payload->length - retrieved : DEFAULT_AUX_MAX_DATA_SIZE;
- current_payload.mot = !is_end_of_payload;
+ /* set mot (middle of transaction) to false
+ * if it is the last payload
+ */
+ current_payload.mot = is_end_of_payload ? payload->mot:true;
current_payload.reply = payload->reply;
current_payload.write = payload->write;

--
2.25.1