23 #include <linux/kernel.h>
25 #include <linux/wait.h>
26 #include <linux/i2c.h>
27 #include <linux/module.h>
39 #include <drm/exynos_drm.h>
49 #define MAX_WIDTH 1920
50 #define MAX_HEIGHT 1080
51 #define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev))
95 static const u8 hdmiphy_v13_conf27[32] = {
96 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
97 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
98 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
99 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
102 static const u8 hdmiphy_v13_conf27_027[32] = {
103 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
104 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
105 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
106 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
109 static const u8 hdmiphy_v13_conf74_175[32] = {
110 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
111 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
112 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
113 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
116 static const u8 hdmiphy_v13_conf74_25[32] = {
117 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
118 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
119 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
120 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
123 static const u8 hdmiphy_v13_conf148_5[32] = {
124 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
125 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
126 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
127 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
191 .h_blank = {0x8a, 0x00},
192 .v_blank = {0x0d, 0x6a, 0x01},
193 .h_v_line = {0x0d, 0xa2, 0x35},
195 .int_pro_mode = {0x00},
196 .v_blank_f = {0x00, 0x00, 0x00},
197 .h_sync_gen = {0x0e, 0x30, 0x11},
198 .v_sync_gen1 = {0x0f, 0x90, 0x00},
204 0x8a, 0x00, 0xd0, 0x02,
206 0x01, 0x00, 0x33, 0x02,
207 0x2d, 0x00, 0xe0, 0x01,
210 0x01, 0x00, 0x33, 0x02,
211 0x01, 0x00, 0x33, 0x02,
217 .h_blank = {0x72, 0x01},
218 .v_blank = {0xee, 0xf2, 0x00},
219 .h_v_line = {0xee, 0x22, 0x67},
221 .int_pro_mode = {0x00},
222 .v_blank_f = {0x00, 0x00, 0x00},
223 .h_sync_gen = {0x6c, 0x50, 0x02},
224 .v_sync_gen1 = {0x0a, 0x50, 0x00},
225 .v_sync_gen2 = {0x01, 0x10, 0x00},
226 .v_sync_gen3 = {0x01, 0x10, 0x00},
232 0x71, 0x01, 0x01, 0x05,
234 0x01, 0x00, 0x33, 0x02,
235 0x1e, 0x00, 0xd0, 0x02,
238 0x01, 0x00, 0x01, 0x00,
239 0x01, 0x00, 0x33, 0x02,
245 .h_blank = {0xd0, 0x02},
246 .v_blank = {0x32, 0xB2, 0x00},
247 .h_v_line = {0x65, 0x04, 0xa5},
249 .int_pro_mode = {0x01},
250 .v_blank_f = {0x49, 0x2A, 0x23},
251 .h_sync_gen = {0x0E, 0xEA, 0x08},
252 .v_sync_gen1 = {0x07, 0x20, 0x00},
253 .v_sync_gen2 = {0x39, 0x42, 0x23},
254 .v_sync_gen3 = {0x38, 0x87, 0x73},
260 0xCF, 0x02, 0x81, 0x07,
262 0x01, 0x00, 0x33, 0x02,
263 0x16, 0x00, 0x1c, 0x02,
266 0x01, 0x00, 0x33, 0x02,
267 0x01, 0x00, 0x33, 0x02,
273 .h_blank = {0xd0, 0x02},
274 .v_blank = {0x65, 0x6c, 0x01},
275 .h_v_line = {0x65, 0x04, 0xa5},
277 .int_pro_mode = {0x00},
278 .v_blank_f = {0x00, 0x00, 0x00},
279 .h_sync_gen = {0x0e, 0xea, 0x08},
280 .v_sync_gen1 = {0x09, 0x40, 0x00},
281 .v_sync_gen2 = {0x01, 0x10, 0x00},
282 .v_sync_gen3 = {0x01, 0x10, 0x00},
288 0xCF, 0x02, 0x81, 0x07,
290 0x01, 0x00, 0x33, 0x02,
291 0x2d, 0x00, 0x38, 0x04,
294 0x01, 0x00, 0x01, 0x00,
295 0x01, 0x00, 0x33, 0x02,
301 .h_blank = {0x18, 0x01},
302 .v_blank = {0x32, 0xB2, 0x00},
303 .h_v_line = {0x65, 0x84, 0x89},
305 .int_pro_mode = {0x01},
306 .v_blank_f = {0x49, 0x2A, 0x23},
307 .h_sync_gen = {0x56, 0x08, 0x02},
308 .v_sync_gen1 = {0x07, 0x20, 0x00},
309 .v_sync_gen2 = {0x39, 0x42, 0x23},
310 .v_sync_gen3 = {0xa4, 0x44, 0x4a},
316 0x17, 0x01, 0x81, 0x07,
318 0x01, 0x00, 0x33, 0x02,
319 0x16, 0x00, 0x1c, 0x02,
322 0x01, 0x00, 0x33, 0x02,
323 0x01, 0x00, 0x33, 0x02,
329 .h_blank = {0x18, 0x01},
330 .v_blank = {0x65, 0x6c, 0x01},
331 .h_v_line = {0x65, 0x84, 0x89},
333 .int_pro_mode = {0x00},
334 .v_blank_f = {0x00, 0x00, 0x00},
335 .h_sync_gen = {0x56, 0x08, 0x02},
336 .v_sync_gen1 = {0x09, 0x40, 0x00},
337 .v_sync_gen2 = {0x01, 0x10, 0x00},
338 .v_sync_gen3 = {0x01, 0x10, 0x00},
344 0x17, 0x01, 0x81, 0x07,
346 0x01, 0x00, 0x33, 0x02,
347 0x2d, 0x00, 0x38, 0x04,
350 0x01, 0x00, 0x01, 0x00,
351 0x01, 0x00, 0x33, 0x02,
356 { 1280, 720, 60,
false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 },
357 { 1280, 720, 50,
false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 },
358 { 720, 480, 60,
false, hdmiphy_v13_conf27_027, &hdmi_v13_conf_480p },
359 { 1920, 1080, 50,
true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i50 },
360 { 1920, 1080, 50,
false, hdmiphy_v13_conf148_5,
361 &hdmi_v13_conf_1080p50 },
362 { 1920, 1080, 60,
true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i60 },
363 { 1920, 1080, 60,
false, hdmiphy_v13_conf148_5,
364 &hdmi_v13_conf_1080p60 },
368 static const u8 hdmiphy_conf27_027[32] = {
369 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
370 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
371 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
372 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
375 static const u8 hdmiphy_conf74_176[32] = {
376 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x5b, 0xef, 0x08,
377 0x81, 0xa0, 0xb9, 0xd8, 0x45, 0xa0, 0xac, 0x80,
378 0x5a, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
379 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
382 static const u8 hdmiphy_conf74_25[32] = {
383 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
384 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
385 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
386 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
389 static const u8 hdmiphy_conf148_5[32] = {
390 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
391 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
392 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
393 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
488 .h_blank = {0x8a, 0x00},
489 .v2_blank = {0x0d, 0x02},
490 .v1_blank = {0x2d, 0x00},
491 .v_line = {0x0d, 0x02},
492 .h_line = {0x5a, 0x03},
495 .int_pro_mode = {0x00},
496 .v_blank_f0 = {0xff, 0xff},
497 .v_blank_f1 = {0xff, 0xff},
498 .h_sync_start = {0x0e, 0x00},
499 .h_sync_end = {0x4c, 0x00},
500 .v_sync_line_bef_2 = {0x0f, 0x00},
501 .v_sync_line_bef_1 = {0x09, 0x00},
502 .v_sync_line_aft_2 = {0xff, 0xff},
503 .v_sync_line_aft_1 = {0xff, 0xff},
504 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
505 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
506 .v_blank_f2 = {0xff, 0xff},
507 .v_blank_f3 = {0xff, 0xff},
508 .v_blank_f4 = {0xff, 0xff},
509 .v_blank_f5 = {0xff, 0xff},
510 .v_sync_line_aft_3 = {0xff, 0xff},
511 .v_sync_line_aft_4 = {0xff, 0xff},
512 .v_sync_line_aft_5 = {0xff, 0xff},
513 .v_sync_line_aft_6 = {0xff, 0xff},
514 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
515 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
516 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
517 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
518 .vact_space_1 = {0xff, 0xff},
519 .vact_space_2 = {0xff, 0xff},
520 .vact_space_3 = {0xff, 0xff},
521 .vact_space_4 = {0xff, 0xff},
522 .vact_space_5 = {0xff, 0xff},
523 .vact_space_6 = {0xff, 0xff},
529 0x8a, 0x00, 0xd0, 0x02,
531 0x01, 0x00, 0x33, 0x02,
532 0x2d, 0x00, 0xe0, 0x01,
537 0x01, 0x00, 0x01, 0x00,
538 0x01, 0x00, 0x33, 0x02,
545 .h_blank = {0xbc, 0x02},
546 .v2_blank = {0xee, 0x02},
547 .v1_blank = {0x1e, 0x00},
548 .v_line = {0xee, 0x02},
549 .h_line = {0xbc, 0x07},
552 .int_pro_mode = {0x00},
553 .v_blank_f0 = {0xff, 0xff},
554 .v_blank_f1 = {0xff, 0xff},
555 .h_sync_start = {0xb6, 0x01},
556 .h_sync_end = {0xde, 0x01},
557 .v_sync_line_bef_2 = {0x0a, 0x00},
558 .v_sync_line_bef_1 = {0x05, 0x00},
559 .v_sync_line_aft_2 = {0xff, 0xff},
560 .v_sync_line_aft_1 = {0xff, 0xff},
561 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
562 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
563 .v_blank_f2 = {0xff, 0xff},
564 .v_blank_f3 = {0xff, 0xff},
565 .v_blank_f4 = {0xff, 0xff},
566 .v_blank_f5 = {0xff, 0xff},
567 .v_sync_line_aft_3 = {0xff, 0xff},
568 .v_sync_line_aft_4 = {0xff, 0xff},
569 .v_sync_line_aft_5 = {0xff, 0xff},
570 .v_sync_line_aft_6 = {0xff, 0xff},
571 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
572 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
573 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
574 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
575 .vact_space_1 = {0xff, 0xff},
576 .vact_space_2 = {0xff, 0xff},
577 .vact_space_3 = {0xff, 0xff},
578 .vact_space_4 = {0xff, 0xff},
579 .vact_space_5 = {0xff, 0xff},
580 .vact_space_6 = {0xff, 0xff},
586 0xbc, 0x02, 0x00, 0x05,
588 0x01, 0x00, 0x33, 0x02,
589 0x1e, 0x00, 0xd0, 0x02,
594 0x01, 0x00, 0x01, 0x00,
595 0x01, 0x00, 0x33, 0x02,
602 .h_blank = {0x72, 0x01},
603 .v2_blank = {0xee, 0x02},
604 .v1_blank = {0x1e, 0x00},
605 .v_line = {0xee, 0x02},
606 .h_line = {0x72, 0x06},
609 .int_pro_mode = {0x00},
610 .v_blank_f0 = {0xff, 0xff},
611 .v_blank_f1 = {0xff, 0xff},
612 .h_sync_start = {0x6c, 0x00},
613 .h_sync_end = {0x94, 0x00},
614 .v_sync_line_bef_2 = {0x0a, 0x00},
615 .v_sync_line_bef_1 = {0x05, 0x00},
616 .v_sync_line_aft_2 = {0xff, 0xff},
617 .v_sync_line_aft_1 = {0xff, 0xff},
618 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
619 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
620 .v_blank_f2 = {0xff, 0xff},
621 .v_blank_f3 = {0xff, 0xff},
622 .v_blank_f4 = {0xff, 0xff},
623 .v_blank_f5 = {0xff, 0xff},
624 .v_sync_line_aft_3 = {0xff, 0xff},
625 .v_sync_line_aft_4 = {0xff, 0xff},
626 .v_sync_line_aft_5 = {0xff, 0xff},
627 .v_sync_line_aft_6 = {0xff, 0xff},
628 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
629 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
630 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
631 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
632 .vact_space_1 = {0xff, 0xff},
633 .vact_space_2 = {0xff, 0xff},
634 .vact_space_3 = {0xff, 0xff},
635 .vact_space_4 = {0xff, 0xff},
636 .vact_space_5 = {0xff, 0xff},
637 .vact_space_6 = {0xff, 0xff},
643 0x72, 0x01, 0x00, 0x05,
645 0x01, 0x00, 0x33, 0x02,
646 0x1e, 0x00, 0xd0, 0x02,
651 0x01, 0x00, 0x01, 0x00,
652 0x01, 0x00, 0x33, 0x02,
659 .h_blank = {0xd0, 0x02},
660 .v2_blank = {0x32, 0x02},
661 .v1_blank = {0x16, 0x00},
662 .v_line = {0x65, 0x04},
663 .h_line = {0x50, 0x0a},
666 .int_pro_mode = {0x01},
667 .v_blank_f0 = {0x49, 0x02},
668 .v_blank_f1 = {0x65, 0x04},
669 .h_sync_start = {0x0e, 0x02},
670 .h_sync_end = {0x3a, 0x02},
671 .v_sync_line_bef_2 = {0x07, 0x00},
672 .v_sync_line_bef_1 = {0x02, 0x00},
673 .v_sync_line_aft_2 = {0x39, 0x02},
674 .v_sync_line_aft_1 = {0x34, 0x02},
675 .v_sync_line_aft_pxl_2 = {0x38, 0x07},
676 .v_sync_line_aft_pxl_1 = {0x38, 0x07},
677 .v_blank_f2 = {0xff, 0xff},
678 .v_blank_f3 = {0xff, 0xff},
679 .v_blank_f4 = {0xff, 0xff},
680 .v_blank_f5 = {0xff, 0xff},
681 .v_sync_line_aft_3 = {0xff, 0xff},
682 .v_sync_line_aft_4 = {0xff, 0xff},
683 .v_sync_line_aft_5 = {0xff, 0xff},
684 .v_sync_line_aft_6 = {0xff, 0xff},
685 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
686 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
687 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
688 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
689 .vact_space_1 = {0xff, 0xff},
690 .vact_space_2 = {0xff, 0xff},
691 .vact_space_3 = {0xff, 0xff},
692 .vact_space_4 = {0xff, 0xff},
693 .vact_space_5 = {0xff, 0xff},
694 .vact_space_6 = {0xff, 0xff},
700 0xd0, 0x02, 0x80, 0x07,
702 0x01, 0x00, 0x33, 0x02,
703 0x16, 0x00, 0x1c, 0x02,
708 0x01, 0x00, 0x33, 0x02,
709 0x01, 0x00, 0x33, 0x02,
716 .h_blank = {0x18, 0x01},
717 .v2_blank = {0x32, 0x02},
718 .v1_blank = {0x16, 0x00},
719 .v_line = {0x65, 0x04},
720 .h_line = {0x98, 0x08},
723 .int_pro_mode = {0x01},
724 .v_blank_f0 = {0x49, 0x02},
725 .v_blank_f1 = {0x65, 0x04},
726 .h_sync_start = {0x56, 0x00},
727 .h_sync_end = {0x82, 0x00},
728 .v_sync_line_bef_2 = {0x07, 0x00},
729 .v_sync_line_bef_1 = {0x02, 0x00},
730 .v_sync_line_aft_2 = {0x39, 0x02},
731 .v_sync_line_aft_1 = {0x34, 0x02},
732 .v_sync_line_aft_pxl_2 = {0xa4, 0x04},
733 .v_sync_line_aft_pxl_1 = {0xa4, 0x04},
734 .v_blank_f2 = {0xff, 0xff},
735 .v_blank_f3 = {0xff, 0xff},
736 .v_blank_f4 = {0xff, 0xff},
737 .v_blank_f5 = {0xff, 0xff},
738 .v_sync_line_aft_3 = {0xff, 0xff},
739 .v_sync_line_aft_4 = {0xff, 0xff},
740 .v_sync_line_aft_5 = {0xff, 0xff},
741 .v_sync_line_aft_6 = {0xff, 0xff},
742 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
743 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
744 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
745 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
746 .vact_space_1 = {0xff, 0xff},
747 .vact_space_2 = {0xff, 0xff},
748 .vact_space_3 = {0xff, 0xff},
749 .vact_space_4 = {0xff, 0xff},
750 .vact_space_5 = {0xff, 0xff},
751 .vact_space_6 = {0xff, 0xff},
757 0x18, 0x01, 0x80, 0x07,
759 0x01, 0x00, 0x33, 0x02,
760 0x16, 0x00, 0x1c, 0x02,
765 0x01, 0x00, 0x33, 0x02,
766 0x01, 0x00, 0x33, 0x02,
773 .h_blank = {0x18, 0x01},
774 .v2_blank = {0x65, 0x04},
775 .v1_blank = {0x2d, 0x00},
776 .v_line = {0x65, 0x04},
777 .h_line = {0x98, 0x08},
780 .int_pro_mode = {0x00},
781 .v_blank_f0 = {0xff, 0xff},
782 .v_blank_f1 = {0xff, 0xff},
783 .h_sync_start = {0x56, 0x00},
784 .h_sync_end = {0x82, 0x00},
785 .v_sync_line_bef_2 = {0x09, 0x00},
786 .v_sync_line_bef_1 = {0x04, 0x00},
787 .v_sync_line_aft_2 = {0xff, 0xff},
788 .v_sync_line_aft_1 = {0xff, 0xff},
789 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
790 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
791 .v_blank_f2 = {0xff, 0xff},
792 .v_blank_f3 = {0xff, 0xff},
793 .v_blank_f4 = {0xff, 0xff},
794 .v_blank_f5 = {0xff, 0xff},
795 .v_sync_line_aft_3 = {0xff, 0xff},
796 .v_sync_line_aft_4 = {0xff, 0xff},
797 .v_sync_line_aft_5 = {0xff, 0xff},
798 .v_sync_line_aft_6 = {0xff, 0xff},
799 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
800 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
801 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
802 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
803 .vact_space_1 = {0xff, 0xff},
804 .vact_space_2 = {0xff, 0xff},
805 .vact_space_3 = {0xff, 0xff},
806 .vact_space_4 = {0xff, 0xff},
807 .vact_space_5 = {0xff, 0xff},
808 .vact_space_6 = {0xff, 0xff},
814 0x18, 0x01, 0x80, 0x07,
816 0x01, 0x00, 0x33, 0x02,
817 0x2d, 0x00, 0x38, 0x04,
822 0x01, 0x00, 0x01, 0x00,
823 0x01, 0x00, 0x33, 0x02,
830 .h_blank = {0xd0, 0x02},
831 .v2_blank = {0x65, 0x04},
832 .v1_blank = {0x2d, 0x00},
833 .v_line = {0x65, 0x04},
834 .h_line = {0x50, 0x0a},
837 .int_pro_mode = {0x00},
838 .v_blank_f0 = {0xff, 0xff},
839 .v_blank_f1 = {0xff, 0xff},
840 .h_sync_start = {0x0e, 0x02},
841 .h_sync_end = {0x3a, 0x02},
842 .v_sync_line_bef_2 = {0x09, 0x00},
843 .v_sync_line_bef_1 = {0x04, 0x00},
844 .v_sync_line_aft_2 = {0xff, 0xff},
845 .v_sync_line_aft_1 = {0xff, 0xff},
846 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
847 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
848 .v_blank_f2 = {0xff, 0xff},
849 .v_blank_f3 = {0xff, 0xff},
850 .v_blank_f4 = {0xff, 0xff},
851 .v_blank_f5 = {0xff, 0xff},
852 .v_sync_line_aft_3 = {0xff, 0xff},
853 .v_sync_line_aft_4 = {0xff, 0xff},
854 .v_sync_line_aft_5 = {0xff, 0xff},
855 .v_sync_line_aft_6 = {0xff, 0xff},
856 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
857 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
858 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
859 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
860 .vact_space_1 = {0xff, 0xff},
861 .vact_space_2 = {0xff, 0xff},
862 .vact_space_3 = {0xff, 0xff},
863 .vact_space_4 = {0xff, 0xff},
864 .vact_space_5 = {0xff, 0xff},
865 .vact_space_6 = {0xff, 0xff},
871 0xd0, 0x02, 0x80, 0x07,
873 0x01, 0x00, 0x33, 0x02,
874 0x2d, 0x00, 0x38, 0x04,
879 0x01, 0x00, 0x01, 0x00,
880 0x01, 0x00, 0x33, 0x02,
887 .h_blank = {0x18, 0x01},
888 .v2_blank = {0x65, 0x04},
889 .v1_blank = {0x2d, 0x00},
890 .v_line = {0x65, 0x04},
891 .h_line = {0x98, 0x08},
894 .int_pro_mode = {0x00},
895 .v_blank_f0 = {0xff, 0xff},
896 .v_blank_f1 = {0xff, 0xff},
897 .h_sync_start = {0x56, 0x00},
898 .h_sync_end = {0x82, 0x00},
899 .v_sync_line_bef_2 = {0x09, 0x00},
900 .v_sync_line_bef_1 = {0x04, 0x00},
901 .v_sync_line_aft_2 = {0xff, 0xff},
902 .v_sync_line_aft_1 = {0xff, 0xff},
903 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
904 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
905 .v_blank_f2 = {0xff, 0xff},
906 .v_blank_f3 = {0xff, 0xff},
907 .v_blank_f4 = {0xff, 0xff},
908 .v_blank_f5 = {0xff, 0xff},
909 .v_sync_line_aft_3 = {0xff, 0xff},
910 .v_sync_line_aft_4 = {0xff, 0xff},
911 .v_sync_line_aft_5 = {0xff, 0xff},
912 .v_sync_line_aft_6 = {0xff, 0xff},
913 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
914 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
915 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
916 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
922 0x18, 0x01, 0x80, 0x07,
924 0x01, 0x00, 0x33, 0x02,
925 0x2d, 0x00, 0x38, 0x04,
930 0x01, 0x00, 0x01, 0x00,
931 0x01, 0x00, 0x33, 0x02,
936 static const struct hdmi_conf hdmi_confs[] = {
937 { 720, 480, 60,
false, hdmiphy_conf27_027, &hdmi_conf_480p60 },
938 { 1280, 720, 50,
false, hdmiphy_conf74_25, &hdmi_conf_720p50 },
939 { 1280, 720, 60,
false, hdmiphy_conf74_25, &hdmi_conf_720p60 },
940 { 1920, 1080, 50,
true, hdmiphy_conf74_25, &hdmi_conf_1080i50 },
941 { 1920, 1080, 60,
true, hdmiphy_conf74_25, &hdmi_conf_1080i60 },
942 { 1920, 1080, 30,
false, hdmiphy_conf74_176, &hdmi_conf_1080p30 },
943 { 1920, 1080, 50,
false, hdmiphy_conf148_5, &hdmi_conf_1080p50 },
944 { 1920, 1080, 60,
false, hdmiphy_conf148_5, &hdmi_conf_1080p60 },
953 static inline void hdmi_reg_writeb(
struct hdmi_context *hdata,
959 static inline void hdmi_reg_writemask(
struct hdmi_context *hdata,
963 value = (value &
mask) | (old & ~mask);
969 #define DUMPREG(reg_id) \
970 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
971 readl(hdata->regs + reg_id))
972 DRM_DEBUG_KMS(
"%s: ---- CONTROL REGISTERS ----\n", prefix);
981 DRM_DEBUG_KMS(
"%s: ---- CORE REGISTERS ----\n", prefix);
994 DRM_DEBUG_KMS(
"%s: ---- CORE SYNC REGISTERS ----\n", prefix);
1021 DRM_DEBUG_KMS(
"%s: ---- TG REGISTERS ----\n", prefix);
1058 #define DUMPREG(reg_id) \
1059 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
1060 readl(hdata->regs + reg_id))
1062 DRM_DEBUG_KMS(
"%s: ---- CONTROL REGISTERS ----\n", prefix);
1076 DRM_DEBUG_KMS(
"%s: ---- CORE REGISTERS ----\n", prefix);
1089 DRM_DEBUG_KMS(
"%s: ---- CORE SYNC REGISTERS ----\n", prefix);
1169 DRM_DEBUG_KMS(
"%s: ---- TG REGISTERS ----\n", prefix);
1205 DRM_DEBUG_KMS(
"%s: ---- PACKET REGISTERS ----\n", prefix);
1215 for (i = 0; i < 7; ++
i)
1221 static void hdmi_regs_dump(
struct hdmi_context *hdata,
char *prefix)
1224 hdmi_v13_regs_dump(hdata, prefix);
1226 hdmi_v14_regs_dump(hdata, prefix);
1265 return hdmi_v13_conf_index(mode);
1267 return hdmi_v14_conf_index(mode);
1270 static bool hdmi_is_connected(
void *
ctx)
1280 struct edid *raw_edid;
1283 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
1293 DRM_DEBUG_KMS(
"%s : width[%d] x height[%d]\n",
1294 (hdata->
dvi_mode ?
"dvi monitor" :
"hdmi monitor"),
1303 static int hdmi_v13_check_timing(
struct fb_videomode *check_timing)
1307 DRM_DEBUG_KMS(
"valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1308 check_timing->
xres, check_timing->
yres,
1313 if (hdmi_v13_confs[i].
width == check_timing->
xres &&
1314 hdmi_v13_confs[i].
height == check_timing->
yres &&
1326 static int hdmi_v14_check_timing(
struct fb_videomode *check_timing)
1330 DRM_DEBUG_KMS(
"valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1331 check_timing->
xres, check_timing->
yres,
1336 if (hdmi_confs[i].
width == check_timing->
xres &&
1337 hdmi_confs[i].
height == check_timing->
yres &&
1349 static int hdmi_check_timing(
void *ctx,
void *
timing)
1354 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
1356 DRM_DEBUG_KMS(
"[%d]x[%d] [%d]Hz [%x]\n", check_timing->
xres,
1358 check_timing->
vmode);
1361 return hdmi_v13_check_timing(check_timing);
1363 return hdmi_v14_check_timing(check_timing);
1366 static void hdmi_set_acr(
u32 freq,
u8 *acr)
1406 acr[2] = cts >> 8 & 0xff;
1407 acr[3] = cts & 0xff;
1410 acr[5] = n >> 8 & 0xff;
1432 static void hdmi_audio_init(
struct hdmi_context *hdata)
1435 u32 data_num, bit_ch, sample_frq;
1439 sample_rate = 44100;
1440 bits_per_sample = 16;
1441 frame_size_code = 0;
1443 switch (bits_per_sample) {
1458 hdmi_set_acr(sample_rate, acr);
1459 hdmi_reg_acr(hdata, acr);
1470 sample_frq = (sample_rate == 44100) ? 0 :
1471 (sample_rate == 48000) ? 2 :
1472 (sample_rate == 32000) ? 3 :
1473 (sample_rate == 96000) ? 0xa : 0x0;
1522 hdmi_reg_writemask(hdata,
HDMI_CON_0, onoff ?
1526 static void hdmi_conf_reset(
struct hdmi_context *hdata)
1572 hdmi_reg_writemask(hdata,
HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1581 hdmi_reg_writemask(hdata,
HDMI_CON_1, 2, 3 << 5);
1585 static void hdmi_v13_timing_apply(
struct hdmi_context *hdata)
1650 for (tries = 100; tries; --tries) {
1658 DRM_ERROR(
"hdmiphy's pll could not reach steady state.\n");
1659 hdmi_regs_dump(hdata,
"timing apply");
1675 static void hdmi_v14_timing_apply(
struct hdmi_context *hdata)
1817 for (tries = 100; tries; --tries) {
1825 DRM_ERROR(
"hdmiphy's pll could not reach steady state.\n");
1826 hdmi_regs_dump(hdata,
"timing apply");
1842 static void hdmi_timing_apply(
struct hdmi_context *hdata)
1845 hdmi_v13_timing_apply(hdata);
1847 hdmi_v14_timing_apply(hdata);
1850 static void hdmiphy_conf_reset(
struct hdmi_context *hdata)
1878 static void hdmiphy_conf_apply(
struct hdmi_context *hdata)
1880 const u8 *hdmiphy_data;
1888 DRM_ERROR(
"hdmiphy is not attached\n");
1898 memcpy(buffer, hdmiphy_data, 32);
1901 DRM_ERROR(
"failed to configure HDMIPHY via I2C\n");
1908 operation[0] = 0x1f;
1909 operation[1] = 0x80;
1913 DRM_ERROR(
"failed to enable hdmiphy\n");
1919 DRM_ERROR(
"failed to read hdmiphy config\n");
1923 for (i = 0; i <
ret; i++)
1924 DRM_DEBUG_KMS(
"hdmiphy[0x%02x] write[0x%02x] - "
1925 "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
1928 static void hdmi_conf_apply(
struct hdmi_context *hdata)
1930 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
1932 hdmiphy_conf_reset(hdata);
1933 hdmiphy_conf_apply(hdata);
1936 hdmi_conf_reset(hdata);
1937 hdmi_conf_init(hdata);
1940 hdmi_audio_init(hdata);
1943 hdmi_timing_apply(hdata);
1944 hdmi_audio_control(hdata,
true);
1946 hdmi_regs_dump(hdata,
"start");
1949 static void hdmi_mode_fixup(
void *ctx,
struct drm_connector *connector,
1957 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
1962 index = hdmi_v13_conf_index(adjusted_mode);
1964 index = hdmi_v14_conf_index(adjusted_mode);
1976 index = hdmi_v13_conf_index(m);
1978 index = hdmi_v14_conf_index(m);
1981 DRM_INFO(
"desired mode doesn't exist so\n");
1982 DRM_INFO(
"use the most suitable mode among modes.\n");
1983 memcpy(adjusted_mode, m,
sizeof(*m));
1989 static void hdmi_mode_set(
void *ctx,
void *mode)
1994 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
1996 conf_idx = hdmi_conf_index(hdata, mode);
2000 DRM_DEBUG_KMS(
"not supported mode\n");
2003 static void hdmi_get_max_resol(
void *ctx,
unsigned int *
width,
2006 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
2012 static void hdmi_commit(
void *ctx)
2016 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
2018 hdmi_conf_apply(hdata);
2025 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
2037 pm_runtime_get_sync(hdata->
dev);
2049 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
2060 hdmiphy_conf_reset(hdata);
2067 pm_runtime_put_sync(hdata->
dev);
2077 static void hdmi_dpms(
void *ctx,
int mode)
2081 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
2085 hdmi_poweron(hdata);
2090 hdmi_poweroff(hdata);
2093 DRM_DEBUG_KMS(
"unknown dpms mode: %d\n", mode);
2100 .is_connected = hdmi_is_connected,
2101 .get_edid = hdmi_get_edid,
2102 .check_timing = hdmi_check_timing,
2105 .mode_fixup = hdmi_mode_fixup,
2106 .mode_set = hdmi_mode_set,
2107 .get_max_resol = hdmi_get_max_resol,
2108 .commit = hdmi_commit,
2127 static irqreturn_t hdmi_internal_irq_thread(
int irq,
void *arg)
2136 DRM_DEBUG_KMS(
"unplugged\n");
2138 HDMI_INTC_FLAG_HPD_UNPLUG);
2141 DRM_DEBUG_KMS(
"plugged\n");
2143 HDMI_INTC_FLAG_HPD_PLUG);
2156 static char *supply[] = {
2164 DRM_DEBUG_KMS(
"HDMI resource init\n");
2166 memset(res, 0,
sizeof(*res));
2170 if (IS_ERR_OR_NULL(res->
hdmi)) {
2171 DRM_ERROR(
"failed to get clock 'hdmi'\n");
2176 DRM_ERROR(
"failed to get clock 'sclk_hdmi'\n");
2181 DRM_ERROR(
"failed to get clock 'sclk_pixel'\n");
2186 DRM_ERROR(
"failed to get clock 'sclk_hdmiphy'\n");
2190 if (IS_ERR_OR_NULL(res->
hdmiphy)) {
2191 DRM_ERROR(
"failed to get clock 'hdmiphy'\n");
2200 DRM_ERROR(
"failed to get memory for regulators\n");
2209 DRM_ERROR(
"failed to get regulators\n");
2216 DRM_ERROR(
"HDMI resource init - failed\n");
2220 static int hdmi_resources_cleanup(
struct hdmi_context *hdata)
2227 if (!IS_ERR_OR_NULL(res->
hdmiphy))
2235 if (!IS_ERR_OR_NULL(res->
hdmi))
2237 memset(res, 0,
sizeof(*res));
2242 static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
2253 hdmi_hdmiphy = hdmiphy;
2267 DRM_ERROR(
"memory allocation for pdata failed\n");
2272 DRM_ERROR(
"no hpd gpio property found\n");
2293 .name =
"s5pv210-hdmi",
2296 .name =
"exynos4-hdmi",
2299 .name =
"exynos4-hdmi14",
2302 .name =
"exynos5-hdmi",
2311 .compatible =
"samsung,exynos5-hdmi",
2327 DRM_DEBUG_KMS(
"[%d]\n", __LINE__);
2329 if (pdev->
dev.of_node) {
2330 pdata = drm_hdmi_dt_parse_pdata(dev);
2331 if (IS_ERR(pdata)) {
2332 DRM_ERROR(
"failed to parse dt\n");
2333 return PTR_ERR(pdata);
2336 pdata = pdev->
dev.platform_data;
2340 DRM_ERROR(
"no platform data specified\n");
2346 if (!drm_hdmi_ctx) {
2347 DRM_ERROR(
"failed to allocate common hdmi context.\n");
2354 DRM_ERROR(
"out of memory\n");
2360 drm_hdmi_ctx->
ctx = (
void *)hdata;
2363 platform_set_drvdata(pdev, drm_hdmi_ctx);
2372 (pdev)->driver_data;
2378 ret = hdmi_resources_init(hdata);
2382 DRM_ERROR(
"hdmi_resources_init failed\n");
2388 DRM_ERROR(
"failed to find registers\n");
2395 DRM_ERROR(
"failed to map registers\n");
2402 DRM_ERROR(
"failed to request HPD gpio\n");
2408 DRM_ERROR(
"failed to register ddc i2c driver\n");
2417 DRM_ERROR(
"failed to register hdmiphy i2c driver\n");
2426 DRM_ERROR(
"failed to get GPIO external irq\n");
2433 DRM_ERROR(
"failed to get platform internal irq\n");
2443 "hdmi_external", drm_hdmi_ctx);
2445 DRM_ERROR(
"failed to register hdmi external interrupt\n");
2451 "hdmi_internal", drm_hdmi_ctx);
2453 DRM_ERROR(
"failed to register hdmi internal interrupt\n");
2476 hdmi_resources_cleanup(hdata);
2487 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
2489 pm_runtime_disable(dev);
2496 hdmi_resources_cleanup(hdata);
2506 #ifdef CONFIG_PM_SLEEP
2507 static int hdmi_suspend(
struct device *dev)
2519 hdmi_poweroff(hdata);
2524 static int hdmi_resume(
struct device *dev)
2538 .probe = hdmi_probe,
2540 .id_table = hdmi_driver_types,
2542 .
name =
"exynos-hdmi",
2545 .of_match_table = hdmi_match_types,