This source file includes following definitions.
- dal_ddc_i2c_payloads_create
- dal_ddc_i2c_payloads_get
- dal_ddc_i2c_payloads_get_count
- dal_ddc_i2c_payloads_destroy
- dal_ddc_i2c_payloads_add
- construct
- dal_ddc_service_create
- destruct
- dal_ddc_service_destroy
- dal_ddc_service_get_type
- dal_ddc_service_set_transaction_type
- dal_ddc_service_is_in_aux_transaction_mode
- ddc_service_set_dongle_type
- defer_delay_converter_wa
- get_defer_delay
- i2c_read
- dal_ddc_service_i2c_query_dp_dual_mode_adaptor
- dal_ddc_service_query_ddc_data
- dc_link_aux_transfer_raw
- dc_link_aux_transfer_with_retries
- dal_ddc_service_set_ddc_pin
- dal_ddc_service_get_ddc_pin
- dal_ddc_service_write_scdc_data
- dal_ddc_service_read_scdc_data
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
40 #define AUX_POWER_UP_WA_DELAY 500
41 #define I2C_OVER_AUX_DEFER_WA_DELAY 70
42
43
44 #define CV_SMART_DONGLE_ADDRESS 0x20
45
46 #define DVI_HDMI_DONGLE_ADDRESS 0x68
47 struct dvi_hdmi_dongle_signature_data {
48 int8_t vendor[3];
49 uint8_t version[2];
50 uint8_t size;
51 int8_t id[11];
52 };
53
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];
60 uint8_t eot;
61 };
62
63
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
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
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
152 static uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p)
153 {
154 return p->payloads.count;
155 }
156
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
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
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
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
243 static void destruct(struct ddc_service *ddc)
244 {
245 if (ddc->ddc_pin)
246 dal_gpio_destroy_ddc(&ddc->ddc_pin);
247 }
248
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
260 enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc)
261 {
262 return DDC_SERVICE_TYPE_CONNECTOR;
263 }
264
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
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
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
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
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
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
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
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
381 *dongle = DISPLAY_DONGLE_NONE;
382 sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK;
383
384
385 if (!i2c_read(
386 ddc,
387 DP_HDMI_DONGLE_ADDRESS,
388 type2_dongle_buf,
389 sizeof(type2_dongle_buf))) {
390
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
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
420 if (dongle_signature->eot != DP_HDMI_DONGLE_SIGNATURE_EOT) {
421 is_valid_hdmi_signature = false;
422 }
423
424
425 for (i = 0; i < sizeof(dongle_signature->id); ++i) {
426
427
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
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
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
528
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
589
590
591
592
593
594
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
603
604
605
606
607
608
609
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
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
624 struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service)
625 {
626 return ddc_service->ddc_pin;
627 }
628
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
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
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
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
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