1 /* $NetBSD: amdgpu_dc_link_ddc.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $ */
2
3 /*
4 * Copyright 2012-15 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: AMD
25 *
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_dc_link_ddc.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $");
30
31 #include <linux/slab.h>
32
33 #include "dm_services.h"
34 #include "dm_helpers.h"
35 #include "gpio_service_interface.h"
36 #include "include/ddc_service_types.h"
37 #include "include/grph_object_id.h"
38 #include "include/dpcd_defs.h"
39 #include "include/logger_interface.h"
40 #include "include/vector.h"
41 #include "core_types.h"
42 #include "dc_link_ddc.h"
43 #include "dce/dce_aux.h"
44
45 #define AUX_POWER_UP_WA_DELAY 500
46 #define I2C_OVER_AUX_DEFER_WA_DELAY 70
47
48 /* CV smart dongle slave address for retrieving supported HDTV modes*/
49 #define CV_SMART_DONGLE_ADDRESS 0x20
50 /* DVI-HDMI dongle slave address for retrieving dongle signature*/
51 #define DVI_HDMI_DONGLE_ADDRESS 0x68
52 struct dvi_hdmi_dongle_signature_data {
53 int8_t vendor[3];/* "AMD" */
54 uint8_t version[2];
55 uint8_t size;
56 int8_t id[11];/* "6140063500G"*/
57 };
58 /* DP-HDMI dongle slave address for retrieving dongle signature*/
59 #define DP_HDMI_DONGLE_ADDRESS 0x40
60 static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR";
61 #define DP_HDMI_DONGLE_SIGNATURE_EOT 0x04
62
63 struct dp_hdmi_dongle_signature_data {
64 int8_t id[15];/* "DP-HDMI ADAPTOR"*/
65 uint8_t eot;/* end of transmition '\x4' */
66 };
67
68 /* SCDC Address defines (HDMI 2.0)*/
69 #define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3
70 #define HDMI_SCDC_ADDRESS 0x54
71 #define HDMI_SCDC_SINK_VERSION 0x01
72 #define HDMI_SCDC_SOURCE_VERSION 0x02
73 #define HDMI_SCDC_UPDATE_0 0x10
74 #define HDMI_SCDC_TMDS_CONFIG 0x20
75 #define HDMI_SCDC_SCRAMBLER_STATUS 0x21
76 #define HDMI_SCDC_CONFIG_0 0x30
77 #define HDMI_SCDC_STATUS_FLAGS 0x40
78 #define HDMI_SCDC_ERR_DETECT 0x50
79 #define HDMI_SCDC_TEST_CONFIG 0xC0
80
81 union hdmi_scdc_update_read_data {
82 uint8_t byte[2];
83 struct {
84 uint8_t STATUS_UPDATE:1;
85 uint8_t CED_UPDATE:1;
86 uint8_t RR_TEST:1;
87 uint8_t RESERVED:5;
88 uint8_t RESERVED2:8;
89 } fields;
90 };
91
92 union hdmi_scdc_status_flags_data {
93 uint8_t byte[2];
94 struct {
95 uint8_t CLOCK_DETECTED:1;
96 uint8_t CH0_LOCKED:1;
97 uint8_t CH1_LOCKED:1;
98 uint8_t CH2_LOCKED:1;
99 uint8_t RESERVED:4;
100 uint8_t RESERVED2:8;
101 uint8_t RESERVED3:8;
102
103 } fields;
104 };
105
106 union hdmi_scdc_ced_data {
107 uint8_t byte[7];
108 struct {
109 uint8_t CH0_8LOW:8;
110 uint8_t CH0_7HIGH:7;
111 uint8_t CH0_VALID:1;
112 uint8_t CH1_8LOW:8;
113 uint8_t CH1_7HIGH:7;
114 uint8_t CH1_VALID:1;
115 uint8_t CH2_8LOW:8;
116 uint8_t CH2_7HIGH:7;
117 uint8_t CH2_VALID:1;
118 uint8_t CHECKSUM:8;
119 uint8_t RESERVED:8;
120 uint8_t RESERVED2:8;
121 uint8_t RESERVED3:8;
122 uint8_t RESERVED4:4;
123 } fields;
124 };
125
126 struct i2c_payloads {
127 struct vector payloads;
128 };
129
130 struct aux_payloads {
131 struct vector payloads;
132 };
133
dal_ddc_i2c_payloads_create(struct dc_context * ctx,uint32_t count)134 static struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count)
135 {
136 struct i2c_payloads *payloads;
137
138 payloads = kzalloc(sizeof(struct i2c_payloads), GFP_KERNEL);
139
140 if (!payloads)
141 return NULL;
142
143 if (dal_vector_construct(
144 &payloads->payloads, ctx, count, sizeof(struct i2c_payload)))
145 return payloads;
146
147 kfree(payloads);
148 return NULL;
149
150 }
151
dal_ddc_i2c_payloads_get(struct i2c_payloads * p)152 static struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p)
153 {
154 return (struct i2c_payload *)p->payloads.container;
155 }
156
dal_ddc_i2c_payloads_get_count(struct i2c_payloads * p)157 static uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p)
158 {
159 return p->payloads.count;
160 }
161
dal_ddc_i2c_payloads_destroy(struct i2c_payloads ** p)162 static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p)
163 {
164 if (!p || !*p)
165 return;
166 dal_vector_destruct(&(*p)->payloads);
167 kfree(*p);
168 *p = NULL;
169
170 }
171
172 #define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b))
173
dal_ddc_i2c_payloads_add(struct i2c_payloads * payloads,uint32_t address,uint32_t len,uint8_t * data,bool write)174 void dal_ddc_i2c_payloads_add(
175 struct i2c_payloads *payloads,
176 uint32_t address,
177 uint32_t len,
178 uint8_t *data,
179 bool write)
180 {
181 uint32_t payload_size = EDID_SEGMENT_SIZE;
182 uint32_t pos;
183
184 for (pos = 0; pos < len; pos += payload_size) {
185 struct i2c_payload payload = {
186 .write = write,
187 .address = address,
188 .length = DDC_MIN(payload_size, len - pos),
189 .data = data + pos };
190 dal_vector_append(&payloads->payloads, &payload);
191 }
192
193 }
194
ddc_service_construct(struct ddc_service * ddc_service,struct ddc_service_init_data * init_data)195 static void ddc_service_construct(
196 struct ddc_service *ddc_service,
197 struct ddc_service_init_data *init_data)
198 {
199 enum connector_id connector_id =
200 dal_graphics_object_id_get_connector_id(init_data->id);
201
202 struct gpio_service *gpio_service = init_data->ctx->gpio_service;
203 struct graphics_object_i2c_info i2c_info;
204 struct gpio_ddc_hw_info hw_info;
205 struct dc_bios *dcb = init_data->ctx->dc_bios;
206
207 ddc_service->link = init_data->link;
208 ddc_service->ctx = init_data->ctx;
209
210 if (BP_RESULT_OK != dcb->funcs->get_i2c_info(dcb, init_data->id, &i2c_info)) {
211 ddc_service->ddc_pin = NULL;
212 } else {
213 hw_info.ddc_channel = i2c_info.i2c_line;
214 if (ddc_service->link != NULL)
215 hw_info.hw_supported = i2c_info.i2c_hw_assist;
216 else
217 hw_info.hw_supported = false;
218
219 ddc_service->ddc_pin = dal_gpio_create_ddc(
220 gpio_service,
221 i2c_info.gpio_info.clk_a_register_index,
222 1 << i2c_info.gpio_info.clk_a_shift,
223 &hw_info);
224 }
225
226 ddc_service->flags.EDID_QUERY_DONE_ONCE = false;
227 ddc_service->flags.FORCE_READ_REPEATED_START = false;
228 ddc_service->flags.EDID_STRESS_READ = false;
229
230 ddc_service->flags.IS_INTERNAL_DISPLAY =
231 connector_id == CONNECTOR_ID_EDP ||
232 connector_id == CONNECTOR_ID_LVDS;
233
234 ddc_service->wa.raw = 0;
235 }
236
dal_ddc_service_create(struct ddc_service_init_data * init_data)237 struct ddc_service *dal_ddc_service_create(
238 struct ddc_service_init_data *init_data)
239 {
240 struct ddc_service *ddc_service;
241
242 ddc_service = kzalloc(sizeof(struct ddc_service), GFP_KERNEL);
243
244 if (!ddc_service)
245 return NULL;
246
247 ddc_service_construct(ddc_service, init_data);
248 return ddc_service;
249 }
250
ddc_service_destruct(struct ddc_service * ddc)251 static void ddc_service_destruct(struct ddc_service *ddc)
252 {
253 if (ddc->ddc_pin)
254 dal_gpio_destroy_ddc(&ddc->ddc_pin);
255 }
256
dal_ddc_service_destroy(struct ddc_service ** ddc)257 void dal_ddc_service_destroy(struct ddc_service **ddc)
258 {
259 if (!ddc || !*ddc) {
260 BREAK_TO_DEBUGGER();
261 return;
262 }
263 ddc_service_destruct(*ddc);
264 kfree(*ddc);
265 *ddc = NULL;
266 }
267
dal_ddc_service_get_type(struct ddc_service * ddc)268 enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc)
269 {
270 return DDC_SERVICE_TYPE_CONNECTOR;
271 }
272
dal_ddc_service_set_transaction_type(struct ddc_service * ddc,enum ddc_transaction_type type)273 void dal_ddc_service_set_transaction_type(
274 struct ddc_service *ddc,
275 enum ddc_transaction_type type)
276 {
277 ddc->transaction_type = type;
278 }
279
dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service * ddc)280 bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc)
281 {
282 switch (ddc->transaction_type) {
283 case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
284 case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
285 case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER:
286 return true;
287 default:
288 break;
289 }
290 return false;
291 }
292
ddc_service_set_dongle_type(struct ddc_service * ddc,enum display_dongle_type dongle_type)293 void ddc_service_set_dongle_type(struct ddc_service *ddc,
294 enum display_dongle_type dongle_type)
295 {
296 ddc->dongle_type = dongle_type;
297 }
298
defer_delay_converter_wa(struct ddc_service * ddc,uint32_t defer_delay)299 static uint32_t defer_delay_converter_wa(
300 struct ddc_service *ddc,
301 uint32_t defer_delay)
302 {
303 struct dc_link *link = ddc->link;
304
305 if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_0080E1 &&
306 !memcmp(link->dpcd_caps.branch_dev_name,
307 DP_DVI_CONVERTER_ID_4,
308 sizeof(link->dpcd_caps.branch_dev_name)))
309 return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY ?
310 defer_delay : I2C_OVER_AUX_DEFER_WA_DELAY;
311
312 return defer_delay;
313 }
314
315 #define DP_TRANSLATOR_DELAY 5
316
get_defer_delay(struct ddc_service * ddc)317 uint32_t get_defer_delay(struct ddc_service *ddc)
318 {
319 uint32_t defer_delay = 0;
320
321 switch (ddc->transaction_type) {
322 case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
323 if ((DISPLAY_DONGLE_DP_VGA_CONVERTER == ddc->dongle_type) ||
324 (DISPLAY_DONGLE_DP_DVI_CONVERTER == ddc->dongle_type) ||
325 (DISPLAY_DONGLE_DP_HDMI_CONVERTER ==
326 ddc->dongle_type)) {
327
328 defer_delay = DP_TRANSLATOR_DELAY;
329
330 defer_delay =
331 defer_delay_converter_wa(ddc, defer_delay);
332
333 } else /*sink has a delay different from an Active Converter*/
334 defer_delay = 0;
335 break;
336 case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
337 defer_delay = DP_TRANSLATOR_DELAY;
338 break;
339 default:
340 break;
341 }
342 return defer_delay;
343 }
344
i2c_read(struct ddc_service * ddc,uint32_t address,uint8_t * buffer,uint32_t len)345 static bool i2c_read(
346 struct ddc_service *ddc,
347 uint32_t address,
348 uint8_t *buffer,
349 uint32_t len)
350 {
351 uint8_t offs_data = 0;
352 struct i2c_payload payloads[2] = {
353 {
354 .write = true,
355 .address = address,
356 .length = 1,
357 .data = &offs_data },
358 {
359 .write = false,
360 .address = address,
361 .length = len,
362 .data = buffer } };
363
364 struct i2c_command command = {
365 .payloads = payloads,
366 .number_of_payloads = 2,
367 .engine = DDC_I2C_COMMAND_ENGINE,
368 .speed = ddc->ctx->dc->caps.i2c_speed_in_khz };
369
370 return dm_helpers_submit_i2c(
371 ddc->ctx,
372 ddc->link,
373 &command);
374 }
375
dal_ddc_service_i2c_query_dp_dual_mode_adaptor(struct ddc_service * ddc,struct display_sink_capability * sink_cap)376 void dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
377 struct ddc_service *ddc,
378 struct display_sink_capability *sink_cap)
379 {
380 uint8_t i;
381 bool is_valid_hdmi_signature;
382 enum display_dongle_type *dongle = &sink_cap->dongle_type;
383 uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE];
384 bool is_type2_dongle = false;
385 int retry_count = 2;
386 struct dp_hdmi_dongle_signature_data *dongle_signature;
387
388 /* Assume we have no valid DP passive dongle connected */
389 *dongle = DISPLAY_DONGLE_NONE;
390 sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK;
391
392 /* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/
393 if (!i2c_read(
394 ddc,
395 DP_HDMI_DONGLE_ADDRESS,
396 type2_dongle_buf,
397 sizeof(type2_dongle_buf))) {
398 /* Passive HDMI dongles can sometimes fail here without retrying*/
399 while (retry_count > 0) {
400 if (i2c_read(ddc,
401 DP_HDMI_DONGLE_ADDRESS,
402 type2_dongle_buf,
403 sizeof(type2_dongle_buf)))
404 break;
405 retry_count--;
406 }
407 if (retry_count == 0) {
408 *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
409 sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK;
410
411 CONN_DATA_DETECT(ddc->link, type2_dongle_buf, sizeof(type2_dongle_buf),
412 "DP-DVI passive dongle %dMhz: ",
413 DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000);
414 return;
415 }
416 }
417
418 /* Check if Type 2 dongle.*/
419 if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID)
420 is_type2_dongle = true;
421
422 dongle_signature =
423 (struct dp_hdmi_dongle_signature_data *)type2_dongle_buf;
424
425 is_valid_hdmi_signature = true;
426
427 /* Check EOT */
428 if (dongle_signature->eot != DP_HDMI_DONGLE_SIGNATURE_EOT) {
429 is_valid_hdmi_signature = false;
430 }
431
432 /* Check signature */
433 for (i = 0; i < sizeof(dongle_signature->id); ++i) {
434 /* If its not the right signature,
435 * skip mismatch in subversion byte.*/
436 if (dongle_signature->id[i] !=
437 dp_hdmi_dongle_signature_str[i] && i != 3) {
438
439 if (is_type2_dongle) {
440 is_valid_hdmi_signature = false;
441 break;
442 }
443
444 }
445 }
446
447 if (is_type2_dongle) {
448 uint32_t max_tmds_clk =
449 type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK];
450
451 max_tmds_clk = max_tmds_clk * 2 + max_tmds_clk / 2;
452
453 if (0 == max_tmds_clk ||
454 max_tmds_clk < DP_ADAPTOR_TYPE2_MIN_TMDS_CLK ||
455 max_tmds_clk > DP_ADAPTOR_TYPE2_MAX_TMDS_CLK) {
456 *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
457
458 CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
459 sizeof(type2_dongle_buf),
460 "DP-DVI passive dongle %dMhz: ",
461 DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000);
462 } else {
463 if (is_valid_hdmi_signature == true) {
464 *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
465
466 CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
467 sizeof(type2_dongle_buf),
468 "Type 2 DP-HDMI passive dongle %dMhz: ",
469 max_tmds_clk);
470 } else {
471 *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
472
473 CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
474 sizeof(type2_dongle_buf),
475 "Type 2 DP-HDMI passive dongle (no signature) %dMhz: ",
476 max_tmds_clk);
477
478 }
479
480 /* Multiply by 1000 to convert to kHz. */
481 sink_cap->max_hdmi_pixel_clock =
482 max_tmds_clk * 1000;
483 }
484
485 } else {
486 if (is_valid_hdmi_signature == true) {
487 *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
488
489 CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
490 sizeof(type2_dongle_buf),
491 "Type 1 DP-HDMI passive dongle %dMhz: ",
492 sink_cap->max_hdmi_pixel_clock / 1000);
493 } else {
494 *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
495
496 CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
497 sizeof(type2_dongle_buf),
498 "Type 1 DP-HDMI passive dongle (no signature) %dMhz: ",
499 sink_cap->max_hdmi_pixel_clock / 1000);
500 }
501 }
502
503 return;
504 }
505
506 enum {
507 DP_SINK_CAP_SIZE =
508 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV + 1
509 };
510
dal_ddc_service_query_ddc_data(struct ddc_service * ddc,uint32_t address,uint8_t * write_buf,uint32_t write_size,uint8_t * read_buf,uint32_t read_size)511 bool dal_ddc_service_query_ddc_data(
512 struct ddc_service *ddc,
513 uint32_t address,
514 uint8_t *write_buf,
515 uint32_t write_size,
516 uint8_t *read_buf,
517 uint32_t read_size)
518 {
519 bool ret = false;
520 uint32_t payload_size =
521 dal_ddc_service_is_in_aux_transaction_mode(ddc) ?
522 DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE;
523
524 uint32_t write_payloads =
525 (write_size + payload_size - 1) / payload_size;
526
527 uint32_t read_payloads =
528 (read_size + payload_size - 1) / payload_size;
529
530 uint32_t payloads_num = write_payloads + read_payloads;
531
532 if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE)
533 return false;
534
535 /*TODO: len of payload data for i2c and aux is uint8!!!!,
536 * but we want to read 256 over i2c!!!!*/
537 if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
538 struct aux_payload payload;
539 bool read_available = true;
540
541 payload.i2c_over_aux = true;
542 payload.address = address;
543 payload.reply = NULL;
544 payload.defer_delay = get_defer_delay(ddc);
545
546 if (write_size != 0) {
547 payload.write = true;
548 payload.mot = false;
549 payload.length = write_size;
550 payload.data = write_buf;
551
552 ret = dal_ddc_submit_aux_command(ddc, &payload);
553 read_available = ret;
554 }
555
556 if (read_size != 0 && read_available) {
557 payload.write = false;
558 payload.mot = false;
559 payload.length = read_size;
560 payload.data = read_buf;
561
562 ret = dal_ddc_submit_aux_command(ddc, &payload);
563 }
564 } else {
565 struct i2c_payloads *payloads =
566 dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num);
567
568 struct i2c_command command = {
569 .payloads = dal_ddc_i2c_payloads_get(payloads),
570 .number_of_payloads = 0,
571 .engine = DDC_I2C_COMMAND_ENGINE,
572 .speed = ddc->ctx->dc->caps.i2c_speed_in_khz };
573
574 dal_ddc_i2c_payloads_add(
575 payloads, address, write_size, write_buf, true);
576
577 dal_ddc_i2c_payloads_add(
578 payloads, address, read_size, read_buf, false);
579
580 command.number_of_payloads =
581 dal_ddc_i2c_payloads_get_count(payloads);
582
583 ret = dm_helpers_submit_i2c(
584 ddc->ctx,
585 ddc->link,
586 &command);
587
588 dal_ddc_i2c_payloads_destroy(&payloads);
589 }
590
591 return ret;
592 }
593
dal_ddc_submit_aux_command(struct ddc_service * ddc,struct aux_payload * payload)594 bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
595 struct aux_payload *payload)
596 {
597 uint32_t retrieved = 0;
598 bool ret = false;
599
600 if (!ddc)
601 return false;
602
603 if (!payload)
604 return false;
605
606 do {
607 struct aux_payload current_payload;
608 bool is_end_of_payload = (retrieved + DEFAULT_AUX_MAX_DATA_SIZE) >
609 payload->length ? true : false;
610
611 current_payload.address = payload->address;
612 current_payload.data = &payload->data[retrieved];
613 current_payload.defer_delay = payload->defer_delay;
614 current_payload.i2c_over_aux = payload->i2c_over_aux;
615 current_payload.length = is_end_of_payload ?
616 payload->length - retrieved : DEFAULT_AUX_MAX_DATA_SIZE;
617 current_payload.mot = !is_end_of_payload;
618 current_payload.reply = payload->reply;
619 current_payload.write = payload->write;
620
621 ret = dc_link_aux_transfer_with_retries(ddc, ¤t_payload);
622
623 retrieved += current_payload.length;
624 } while (retrieved < payload->length && ret == true);
625
626 return ret;
627 }
628
629 /* dc_link_aux_transfer_raw() - Attempt to transfer
630 * the given aux payload. This function does not perform
631 * retries or handle error states. The reply is returned
632 * in the payload->reply and the result through
633 * *operation_result. Returns the number of bytes transferred,
634 * or -1 on a failure.
635 */
dc_link_aux_transfer_raw(struct ddc_service * ddc,struct aux_payload * payload,enum aux_channel_operation_result * operation_result)636 int dc_link_aux_transfer_raw(struct ddc_service *ddc,
637 struct aux_payload *payload,
638 enum aux_channel_operation_result *operation_result)
639 {
640 return dce_aux_transfer_raw(ddc, payload, operation_result);
641 }
642
643 /* dc_link_aux_transfer_with_retries() - Attempt to submit an
644 * aux payload, retrying on timeouts, defers, and busy states
645 * as outlined in the DP spec. Returns true if the request
646 * was successful.
647 *
648 * Unless you want to implement your own retry semantics, this
649 * is probably the one you want.
650 */
dc_link_aux_transfer_with_retries(struct ddc_service * ddc,struct aux_payload * payload)651 bool dc_link_aux_transfer_with_retries(struct ddc_service *ddc,
652 struct aux_payload *payload)
653 {
654 return dce_aux_transfer_with_retries(ddc, payload);
655 }
656
657
dc_link_aux_configure_timeout(struct ddc_service * ddc,uint32_t timeout)658 uint32_t dc_link_aux_configure_timeout(struct ddc_service *ddc,
659 uint32_t timeout)
660 {
661 uint32_t prev_timeout = 0;
662 struct ddc *ddc_pin = ddc->ddc_pin;
663
664 if (ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout)
665 prev_timeout =
666 ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout(ddc, timeout);
667 return prev_timeout;
668 }
669
670 /*test only function*/
dal_ddc_service_set_ddc_pin(struct ddc_service * ddc_service,struct ddc * ddc)671 void dal_ddc_service_set_ddc_pin(
672 struct ddc_service *ddc_service,
673 struct ddc *ddc)
674 {
675 ddc_service->ddc_pin = ddc;
676 }
677
dal_ddc_service_get_ddc_pin(struct ddc_service * ddc_service)678 struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service)
679 {
680 return ddc_service->ddc_pin;
681 }
682
dal_ddc_service_write_scdc_data(struct ddc_service * ddc_service,uint32_t pix_clk,bool lte_340_scramble)683 void dal_ddc_service_write_scdc_data(struct ddc_service *ddc_service,
684 uint32_t pix_clk,
685 bool lte_340_scramble)
686 {
687 bool over_340_mhz = pix_clk > 340000 ? 1 : 0;
688 uint8_t slave_address = HDMI_SCDC_ADDRESS;
689 uint8_t offset = HDMI_SCDC_SINK_VERSION;
690 uint8_t sink_version = 0;
691 uint8_t write_buffer[2] = {0};
692 /*Lower than 340 Scramble bit from SCDC caps*/
693
694 dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
695 sizeof(offset), &sink_version, sizeof(sink_version));
696 if (sink_version == 1) {
697 /*Source Version = 1*/
698 write_buffer[0] = HDMI_SCDC_SOURCE_VERSION;
699 write_buffer[1] = 1;
700 dal_ddc_service_query_ddc_data(ddc_service, slave_address,
701 write_buffer, sizeof(write_buffer), NULL, 0);
702 /*Read Request from SCDC caps*/
703 }
704 write_buffer[0] = HDMI_SCDC_TMDS_CONFIG;
705
706 if (over_340_mhz) {
707 write_buffer[1] = 3;
708 } else if (lte_340_scramble) {
709 write_buffer[1] = 1;
710 } else {
711 write_buffer[1] = 0;
712 }
713 dal_ddc_service_query_ddc_data(ddc_service, slave_address, write_buffer,
714 sizeof(write_buffer), NULL, 0);
715 }
716
dal_ddc_service_read_scdc_data(struct ddc_service * ddc_service)717 void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service)
718 {
719 uint8_t slave_address = HDMI_SCDC_ADDRESS;
720 uint8_t offset = HDMI_SCDC_TMDS_CONFIG;
721 uint8_t tmds_config = 0;
722
723 dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
724 sizeof(offset), &tmds_config, sizeof(tmds_config));
725 if (tmds_config & 0x1) {
726 union hdmi_scdc_status_flags_data status_data = { {0} };
727 uint8_t scramble_status = 0;
728
729 offset = HDMI_SCDC_SCRAMBLER_STATUS;
730 dal_ddc_service_query_ddc_data(ddc_service, slave_address,
731 &offset, sizeof(offset), &scramble_status,
732 sizeof(scramble_status));
733 offset = HDMI_SCDC_STATUS_FLAGS;
734 dal_ddc_service_query_ddc_data(ddc_service, slave_address,
735 &offset, sizeof(offset), status_data.byte,
736 sizeof(status_data.byte));
737 }
738 }
739
740