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