1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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#include "dmub/inc/dmub_cmd.h"
40
41#define DC_LOGGER_INIT(logger)
42
43static const uint8_t DP_VGA_DONGLE_BRANCH_DEV_NAME[] = "DpVga";
44
45static const uint8_t DP_DVI_CONVERTER_ID_4[] = "m2DVIa";
46static const uint8_t DP_DVI_CONVERTER_ID_5[] = "3393N2";
47
48#define AUX_POWER_UP_WA_DELAY 500
49#define I2C_OVER_AUX_DEFER_WA_DELAY 70
50#define DPVGA_DONGLE_AUX_DEFER_WA_DELAY 40
51#define I2C_OVER_AUX_DEFER_WA_DELAY_1MS 1
52
53
54#define CV_SMART_DONGLE_ADDRESS 0x20
55
56#define DVI_HDMI_DONGLE_ADDRESS 0x68
57struct dvi_hdmi_dongle_signature_data {
58 int8_t vendor[3];
59 uint8_t version[2];
60 uint8_t size;
61 int8_t id[11];
62};
63
64#define DP_HDMI_DONGLE_ADDRESS 0x40
65static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR";
66#define DP_HDMI_DONGLE_SIGNATURE_EOT 0x04
67
68struct dp_hdmi_dongle_signature_data {
69 int8_t id[15];
70 uint8_t eot;
71};
72
73
74#define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3
75#define HDMI_SCDC_ADDRESS 0x54
76#define HDMI_SCDC_SINK_VERSION 0x01
77#define HDMI_SCDC_SOURCE_VERSION 0x02
78#define HDMI_SCDC_UPDATE_0 0x10
79#define HDMI_SCDC_TMDS_CONFIG 0x20
80#define HDMI_SCDC_SCRAMBLER_STATUS 0x21
81#define HDMI_SCDC_CONFIG_0 0x30
82#define HDMI_SCDC_STATUS_FLAGS 0x40
83#define HDMI_SCDC_ERR_DETECT 0x50
84#define HDMI_SCDC_TEST_CONFIG 0xC0
85
86union hdmi_scdc_update_read_data {
87 uint8_t byte[2];
88 struct {
89 uint8_t STATUS_UPDATE:1;
90 uint8_t CED_UPDATE:1;
91 uint8_t RR_TEST:1;
92 uint8_t RESERVED:5;
93 uint8_t RESERVED2:8;
94 } fields;
95};
96
97union hdmi_scdc_status_flags_data {
98 uint8_t byte[2];
99 struct {
100 uint8_t CLOCK_DETECTED:1;
101 uint8_t CH0_LOCKED:1;
102 uint8_t CH1_LOCKED:1;
103 uint8_t CH2_LOCKED:1;
104 uint8_t RESERVED:4;
105 uint8_t RESERVED2:8;
106 uint8_t RESERVED3:8;
107
108 } fields;
109};
110
111union hdmi_scdc_ced_data {
112 uint8_t byte[7];
113 struct {
114 uint8_t CH0_8LOW:8;
115 uint8_t CH0_7HIGH:7;
116 uint8_t CH0_VALID:1;
117 uint8_t CH1_8LOW:8;
118 uint8_t CH1_7HIGH:7;
119 uint8_t CH1_VALID:1;
120 uint8_t CH2_8LOW:8;
121 uint8_t CH2_7HIGH:7;
122 uint8_t CH2_VALID:1;
123 uint8_t CHECKSUM:8;
124 uint8_t RESERVED:8;
125 uint8_t RESERVED2:8;
126 uint8_t RESERVED3:8;
127 uint8_t RESERVED4:4;
128 } fields;
129};
130
131struct i2c_payloads {
132 struct vector payloads;
133};
134
135struct aux_payloads {
136 struct vector payloads;
137};
138
139static bool dal_ddc_i2c_payloads_create(
140 struct dc_context *ctx,
141 struct i2c_payloads *payloads,
142 uint32_t count)
143{
144 if (dal_vector_construct(
145 &payloads->payloads, ctx, count, sizeof(struct i2c_payload)))
146 return true;
147
148 return false;
149}
150
151static struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p)
152{
153 return (struct i2c_payload *)p->payloads.container;
154}
155
156static uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p)
157{
158 return p->payloads.count;
159}
160
161#define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b))
162
163void dal_ddc_i2c_payloads_add(
164 struct i2c_payloads *payloads,
165 uint32_t address,
166 uint32_t len,
167 uint8_t *data,
168 bool write)
169{
170 uint32_t payload_size = EDID_SEGMENT_SIZE;
171 uint32_t pos;
172
173 for (pos = 0; pos < len; pos += payload_size) {
174 struct i2c_payload payload = {
175 .write = write,
176 .address = address,
177 .length = DDC_MIN(payload_size, len - pos),
178 .data = data + pos };
179 dal_vector_append(&payloads->payloads, &payload);
180 }
181
182}
183
184static void ddc_service_construct(
185 struct ddc_service *ddc_service,
186 struct ddc_service_init_data *init_data)
187{
188 enum connector_id connector_id =
189 dal_graphics_object_id_get_connector_id(init_data->id);
190
191 struct gpio_service *gpio_service = init_data->ctx->gpio_service;
192 struct graphics_object_i2c_info i2c_info;
193 struct gpio_ddc_hw_info hw_info;
194 struct dc_bios *dcb = init_data->ctx->dc_bios;
195
196 ddc_service->link = init_data->link;
197 ddc_service->ctx = init_data->ctx;
198
199 if (init_data->is_dpia_link ||
200 dcb->funcs->get_i2c_info(dcb, init_data->id, &i2c_info) != BP_RESULT_OK) {
201 ddc_service->ddc_pin = NULL;
202 } else {
203 DC_LOGGER_INIT(ddc_service->ctx->logger);
204 DC_LOG_DC("BIOS object table - i2c_line: %d", i2c_info.i2c_line);
205 DC_LOG_DC("BIOS object table - i2c_engine_id: %d", i2c_info.i2c_engine_id);
206
207 hw_info.ddc_channel = i2c_info.i2c_line;
208 if (ddc_service->link != NULL)
209 hw_info.hw_supported = i2c_info.i2c_hw_assist;
210 else
211 hw_info.hw_supported = false;
212
213 ddc_service->ddc_pin = dal_gpio_create_ddc(
214 gpio_service,
215 i2c_info.gpio_info.clk_a_register_index,
216 1 << i2c_info.gpio_info.clk_a_shift,
217 &hw_info);
218 }
219
220 ddc_service->flags.EDID_QUERY_DONE_ONCE = false;
221 ddc_service->flags.FORCE_READ_REPEATED_START = false;
222 ddc_service->flags.EDID_STRESS_READ = false;
223
224 ddc_service->flags.IS_INTERNAL_DISPLAY =
225 connector_id == CONNECTOR_ID_EDP ||
226 connector_id == CONNECTOR_ID_LVDS;
227
228 ddc_service->wa.raw = 0;
229}
230
231struct ddc_service *dal_ddc_service_create(
232 struct ddc_service_init_data *init_data)
233{
234 struct ddc_service *ddc_service;
235
236 ddc_service = kzalloc(sizeof(struct ddc_service), GFP_KERNEL);
237
238 if (!ddc_service)
239 return NULL;
240
241 ddc_service_construct(ddc_service, init_data);
242 return ddc_service;
243}
244
245static void ddc_service_destruct(struct ddc_service *ddc)
246{
247 if (ddc->ddc_pin)
248 dal_gpio_destroy_ddc(&ddc->ddc_pin);
249}
250
251void dal_ddc_service_destroy(struct ddc_service **ddc)
252{
253 if (!ddc || !*ddc) {
254 BREAK_TO_DEBUGGER();
255 return;
256 }
257 ddc_service_destruct(*ddc);
258 kfree(*ddc);
259 *ddc = NULL;
260}
261
262enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc)
263{
264 return DDC_SERVICE_TYPE_CONNECTOR;
265}
266
267void dal_ddc_service_set_transaction_type(
268 struct ddc_service *ddc,
269 enum ddc_transaction_type type)
270{
271 ddc->transaction_type = type;
272}
273
274bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc)
275{
276 switch (ddc->transaction_type) {
277 case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
278 case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
279 case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER:
280 return true;
281 default:
282 break;
283 }
284 return false;
285}
286
287void ddc_service_set_dongle_type(struct ddc_service *ddc,
288 enum display_dongle_type dongle_type)
289{
290 ddc->dongle_type = dongle_type;
291}
292
293static uint32_t defer_delay_converter_wa(
294 struct ddc_service *ddc,
295 uint32_t defer_delay)
296{
297 struct dc_link *link = ddc->link;
298
299 if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER &&
300 link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_0080E1 &&
301 (link->dpcd_caps.branch_fw_revision[0] < 0x01 ||
302 (link->dpcd_caps.branch_fw_revision[0] == 0x01 &&
303 link->dpcd_caps.branch_fw_revision[1] < 0x40)) &&
304 !memcmp(link->dpcd_caps.branch_dev_name,
305 DP_VGA_DONGLE_BRANCH_DEV_NAME,
306 sizeof(link->dpcd_caps.branch_dev_name)))
307
308 return defer_delay > DPVGA_DONGLE_AUX_DEFER_WA_DELAY ?
309 defer_delay : DPVGA_DONGLE_AUX_DEFER_WA_DELAY;
310
311 if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_0080E1 &&
312 !memcmp(link->dpcd_caps.branch_dev_name,
313 DP_DVI_CONVERTER_ID_4,
314 sizeof(link->dpcd_caps.branch_dev_name)))
315 return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY ?
316 defer_delay : I2C_OVER_AUX_DEFER_WA_DELAY;
317 if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_006037 &&
318 !memcmp(link->dpcd_caps.branch_dev_name,
319 DP_DVI_CONVERTER_ID_5,
320 sizeof(link->dpcd_caps.branch_dev_name)))
321 return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY_1MS ?
322 I2C_OVER_AUX_DEFER_WA_DELAY_1MS : defer_delay;
323
324 return defer_delay;
325}
326
327#define DP_TRANSLATOR_DELAY 5
328
329uint32_t get_defer_delay(struct ddc_service *ddc)
330{
331 uint32_t defer_delay = 0;
332
333 switch (ddc->transaction_type) {
334 case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
335 if ((DISPLAY_DONGLE_DP_VGA_CONVERTER == ddc->dongle_type) ||
336 (DISPLAY_DONGLE_DP_DVI_CONVERTER == ddc->dongle_type) ||
337 (DISPLAY_DONGLE_DP_HDMI_CONVERTER ==
338 ddc->dongle_type)) {
339
340 defer_delay = DP_TRANSLATOR_DELAY;
341
342 defer_delay =
343 defer_delay_converter_wa(ddc, defer_delay);
344
345 } else
346 defer_delay = 0;
347 break;
348 case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
349 defer_delay = DP_TRANSLATOR_DELAY;
350 break;
351 default:
352 break;
353 }
354 return defer_delay;
355}
356
357static bool i2c_read(
358 struct ddc_service *ddc,
359 uint32_t address,
360 uint8_t *buffer,
361 uint32_t len)
362{
363 uint8_t offs_data = 0;
364 struct i2c_payload payloads[2] = {
365 {
366 .write = true,
367 .address = address,
368 .length = 1,
369 .data = &offs_data },
370 {
371 .write = false,
372 .address = address,
373 .length = len,
374 .data = buffer } };
375
376 struct i2c_command command = {
377 .payloads = payloads,
378 .number_of_payloads = 2,
379 .engine = DDC_I2C_COMMAND_ENGINE,
380 .speed = ddc->ctx->dc->caps.i2c_speed_in_khz };
381
382 return dm_helpers_submit_i2c(
383 ddc->ctx,
384 ddc->link,
385 &command);
386}
387
388void dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
389 struct ddc_service *ddc,
390 struct display_sink_capability *sink_cap)
391{
392 uint8_t i;
393 bool is_valid_hdmi_signature;
394 enum display_dongle_type *dongle = &sink_cap->dongle_type;
395 uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE];
396 bool is_type2_dongle = false;
397 int retry_count = 2;
398 struct dp_hdmi_dongle_signature_data *dongle_signature;
399
400
401 *dongle = DISPLAY_DONGLE_NONE;
402 sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK;
403
404
405 if (!i2c_read(
406 ddc,
407 DP_HDMI_DONGLE_ADDRESS,
408 type2_dongle_buf,
409 sizeof(type2_dongle_buf))) {
410
411 while (retry_count > 0) {
412 if (i2c_read(ddc,
413 DP_HDMI_DONGLE_ADDRESS,
414 type2_dongle_buf,
415 sizeof(type2_dongle_buf)))
416 break;
417 retry_count--;
418 }
419 if (retry_count == 0) {
420 *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
421 sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK;
422
423 CONN_DATA_DETECT(ddc->link, type2_dongle_buf, sizeof(type2_dongle_buf),
424 "DP-DVI passive dongle %dMhz: ",
425 DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000);
426 return;
427 }
428 }
429
430
431 if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID)
432 is_type2_dongle = true;
433
434 dongle_signature =
435 (struct dp_hdmi_dongle_signature_data *)type2_dongle_buf;
436
437 is_valid_hdmi_signature = true;
438
439
440 if (dongle_signature->eot != DP_HDMI_DONGLE_SIGNATURE_EOT) {
441 is_valid_hdmi_signature = false;
442 }
443
444
445 for (i = 0; i < sizeof(dongle_signature->id); ++i) {
446
447
448 if (dongle_signature->id[i] !=
449 dp_hdmi_dongle_signature_str[i] && i != 3) {
450
451 if (is_type2_dongle) {
452 is_valid_hdmi_signature = false;
453 break;
454 }
455
456 }
457 }
458
459 if (is_type2_dongle) {
460 uint32_t max_tmds_clk =
461 type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK];
462
463 max_tmds_clk = max_tmds_clk * 2 + max_tmds_clk / 2;
464
465 if (0 == max_tmds_clk ||
466 max_tmds_clk < DP_ADAPTOR_TYPE2_MIN_TMDS_CLK ||
467 max_tmds_clk > DP_ADAPTOR_TYPE2_MAX_TMDS_CLK) {
468 *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
469
470 CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
471 sizeof(type2_dongle_buf),
472 "DP-DVI passive dongle %dMhz: ",
473 DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000);
474 } else {
475 if (is_valid_hdmi_signature == true) {
476 *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
477
478 CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
479 sizeof(type2_dongle_buf),
480 "Type 2 DP-HDMI passive dongle %dMhz: ",
481 max_tmds_clk);
482 } else {
483 *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
484
485 CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
486 sizeof(type2_dongle_buf),
487 "Type 2 DP-HDMI passive dongle (no signature) %dMhz: ",
488 max_tmds_clk);
489
490 }
491
492
493 sink_cap->max_hdmi_pixel_clock =
494 max_tmds_clk * 1000;
495 }
496 sink_cap->is_dongle_type_one = false;
497
498 } else {
499 if (is_valid_hdmi_signature == true) {
500 *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
501
502 CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
503 sizeof(type2_dongle_buf),
504 "Type 1 DP-HDMI passive dongle %dMhz: ",
505 sink_cap->max_hdmi_pixel_clock / 1000);
506 } else {
507 *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
508
509 CONN_DATA_DETECT(ddc->link, type2_dongle_buf,
510 sizeof(type2_dongle_buf),
511 "Type 1 DP-HDMI passive dongle (no signature) %dMhz: ",
512 sink_cap->max_hdmi_pixel_clock / 1000);
513 }
514 sink_cap->is_dongle_type_one = true;
515 }
516
517 return;
518}
519
520enum {
521 DP_SINK_CAP_SIZE =
522 DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV + 1
523};
524
525bool dal_ddc_service_query_ddc_data(
526 struct ddc_service *ddc,
527 uint32_t address,
528 uint8_t *write_buf,
529 uint32_t write_size,
530 uint8_t *read_buf,
531 uint32_t read_size)
532{
533 bool success = true;
534 uint32_t payload_size =
535 dal_ddc_service_is_in_aux_transaction_mode(ddc) ?
536 DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE;
537
538 uint32_t write_payloads =
539 (write_size + payload_size - 1) / payload_size;
540
541 uint32_t read_payloads =
542 (read_size + payload_size - 1) / payload_size;
543
544 uint32_t payloads_num = write_payloads + read_payloads;
545
546 if (!payloads_num)
547 return false;
548
549 if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
550 struct aux_payload payload;
551
552 payload.i2c_over_aux = true;
553 payload.address = address;
554 payload.reply = NULL;
555 payload.defer_delay = get_defer_delay(ddc);
556 payload.write_status_update = false;
557
558 if (write_size != 0) {
559 payload.write = true;
560
561
562
563 payload.mot = !(read_size == 0);
564 payload.length = write_size;
565 payload.data = write_buf;
566
567 success = dal_ddc_submit_aux_command(ddc, &payload);
568 }
569
570 if (read_size != 0 && success) {
571 payload.write = false;
572
573
574
575 payload.mot = false;
576 payload.length = read_size;
577 payload.data = read_buf;
578
579 success = dal_ddc_submit_aux_command(ddc, &payload);
580 }
581 } else {
582 struct i2c_command command = {0};
583 struct i2c_payloads payloads;
584
585 if (!dal_ddc_i2c_payloads_create(ddc->ctx, &payloads, payloads_num))
586 return false;
587
588 command.payloads = dal_ddc_i2c_payloads_get(&payloads);
589 command.number_of_payloads = 0;
590 command.engine = DDC_I2C_COMMAND_ENGINE;
591 command.speed = ddc->ctx->dc->caps.i2c_speed_in_khz;
592
593 dal_ddc_i2c_payloads_add(
594 &payloads, address, write_size, write_buf, true);
595
596 dal_ddc_i2c_payloads_add(
597 &payloads, address, read_size, read_buf, false);
598
599 command.number_of_payloads =
600 dal_ddc_i2c_payloads_get_count(&payloads);
601
602 success = dm_helpers_submit_i2c(
603 ddc->ctx,
604 ddc->link,
605 &command);
606
607 dal_vector_destruct(&payloads.payloads);
608 }
609
610 return success;
611}
612
613bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
614 struct aux_payload *payload)
615{
616 uint32_t retrieved = 0;
617 bool ret = false;
618
619 if (!ddc)
620 return false;
621
622 if (!payload)
623 return false;
624
625 do {
626 struct aux_payload current_payload;
627 bool is_end_of_payload = (retrieved + DEFAULT_AUX_MAX_DATA_SIZE) >=
628 payload->length;
629 uint32_t payload_length = is_end_of_payload ?
630 payload->length - retrieved : DEFAULT_AUX_MAX_DATA_SIZE;
631
632 current_payload.address = payload->address;
633 current_payload.data = &payload->data[retrieved];
634 current_payload.defer_delay = payload->defer_delay;
635 current_payload.i2c_over_aux = payload->i2c_over_aux;
636 current_payload.length = payload_length;
637
638 current_payload.mot = is_end_of_payload ? payload->mot:true;
639 current_payload.write_status_update = false;
640 current_payload.reply = payload->reply;
641 current_payload.write = payload->write;
642
643 ret = dc_link_aux_transfer_with_retries(ddc, ¤t_payload);
644
645 retrieved += payload_length;
646 } while (retrieved < payload->length && ret == true);
647
648 return ret;
649}
650
651
652
653
654
655
656
657
658int dc_link_aux_transfer_raw(struct ddc_service *ddc,
659 struct aux_payload *payload,
660 enum aux_return_code_type *operation_result)
661{
662 if (ddc->ctx->dc->debug.enable_dmub_aux_for_legacy_ddc ||
663 !ddc->ddc_pin) {
664 return dce_aux_transfer_dmub_raw(ddc, payload, operation_result);
665 } else {
666 return dce_aux_transfer_raw(ddc, payload, operation_result);
667 }
668}
669
670
671
672
673
674
675
676
677
678bool dc_link_aux_transfer_with_retries(struct ddc_service *ddc,
679 struct aux_payload *payload)
680{
681 return dce_aux_transfer_with_retries(ddc, payload);
682}
683
684
685bool dc_link_aux_try_to_configure_timeout(struct ddc_service *ddc,
686 uint32_t timeout)
687{
688 bool result = false;
689 struct ddc *ddc_pin = ddc->ddc_pin;
690
691
692 if (ddc->link->ep_type != DISPLAY_ENDPOINT_PHY)
693 return true;
694
695 if (ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout) {
696 ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout(ddc, timeout);
697 result = true;
698 }
699 return result;
700}
701
702
703void dal_ddc_service_set_ddc_pin(
704 struct ddc_service *ddc_service,
705 struct ddc *ddc)
706{
707 ddc_service->ddc_pin = ddc;
708}
709
710struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service)
711{
712 return ddc_service->ddc_pin;
713}
714
715void dal_ddc_service_write_scdc_data(struct ddc_service *ddc_service,
716 uint32_t pix_clk,
717 bool lte_340_scramble)
718{
719 bool over_340_mhz = pix_clk > 340000 ? 1 : 0;
720 uint8_t slave_address = HDMI_SCDC_ADDRESS;
721 uint8_t offset = HDMI_SCDC_SINK_VERSION;
722 uint8_t sink_version = 0;
723 uint8_t write_buffer[2] = {0};
724
725
726 if (ddc_service->link->local_sink &&
727 ddc_service->link->local_sink->edid_caps.panel_patch.skip_scdc_overwrite)
728 return;
729
730 dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
731 sizeof(offset), &sink_version, sizeof(sink_version));
732 if (sink_version == 1) {
733
734 write_buffer[0] = HDMI_SCDC_SOURCE_VERSION;
735 write_buffer[1] = 1;
736 dal_ddc_service_query_ddc_data(ddc_service, slave_address,
737 write_buffer, sizeof(write_buffer), NULL, 0);
738
739 }
740 write_buffer[0] = HDMI_SCDC_TMDS_CONFIG;
741
742 if (over_340_mhz) {
743 write_buffer[1] = 3;
744 } else if (lte_340_scramble) {
745 write_buffer[1] = 1;
746 } else {
747 write_buffer[1] = 0;
748 }
749 dal_ddc_service_query_ddc_data(ddc_service, slave_address, write_buffer,
750 sizeof(write_buffer), NULL, 0);
751}
752
753void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service)
754{
755 uint8_t slave_address = HDMI_SCDC_ADDRESS;
756 uint8_t offset = HDMI_SCDC_TMDS_CONFIG;
757 uint8_t tmds_config = 0;
758
759 if (ddc_service->link->local_sink &&
760 ddc_service->link->local_sink->edid_caps.panel_patch.skip_scdc_overwrite)
761 return;
762
763 dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
764 sizeof(offset), &tmds_config, sizeof(tmds_config));
765 if (tmds_config & 0x1) {
766 union hdmi_scdc_status_flags_data status_data = {0};
767 uint8_t scramble_status = 0;
768
769 offset = HDMI_SCDC_SCRAMBLER_STATUS;
770 dal_ddc_service_query_ddc_data(ddc_service, slave_address,
771 &offset, sizeof(offset), &scramble_status,
772 sizeof(scramble_status));
773 offset = HDMI_SCDC_STATUS_FLAGS;
774 dal_ddc_service_query_ddc_data(ddc_service, slave_address,
775 &offset, sizeof(offset), status_data.byte,
776 sizeof(status_data.byte));
777 }
778}
779
780