Skip to content

Commit 9c936b1

Browse files
committed
drm/meson: Add support for DMT modes on HDMI
This patch adds support for DMT display modes over HDMI. The modes timings configurations are from the Amlogic Vendor linux tree and tested over multiples monitors. Previously only a selected number of CEA modes were supported. Only these following modes are supported with these changes: - 640x480@60Hz - 800x600@60Hz - 1024x768@60Hz - 1152x864@75Hz - 1280x1024@60Hz - 1600x1200@60Hz - 1920x1080@60Hz The associated code to handle the clock rates is also added. Acked-by: Jerome Brunet <[email protected]> Signed-off-by: Neil Armstrong <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 2c18107 commit 9c936b1

File tree

4 files changed

+570
-19
lines changed

4 files changed

+570
-19
lines changed

drivers/gpu/drm/meson/meson_dw_hdmi.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,6 @@ static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id)
538538
return IRQ_HANDLED;
539539
}
540540

541-
/* TOFIX Enable support for non-vic modes */
542541
static enum drm_mode_status
543542
dw_hdmi_mode_valid(struct drm_connector *connector,
544543
const struct drm_display_mode *mode)
@@ -555,12 +554,12 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
555554
mode->vdisplay, mode->vsync_start,
556555
mode->vsync_end, mode->vtotal, mode->type, mode->flags);
557556

558-
/* For now, only accept VIC modes */
559-
if (!vic)
560-
return MODE_BAD;
561-
562-
/* For now, filter by supported VIC modes */
563-
if (!meson_venc_hdmi_supported_vic(vic))
557+
/* Check against non-VIC supported modes */
558+
if (!vic) {
559+
if (!meson_venc_hdmi_supported_mode(mode))
560+
return MODE_BAD;
561+
/* Check against supported VIC modes */
562+
} else if (!meson_venc_hdmi_supported_vic(vic))
564563
return MODE_BAD;
565564

566565
vclk_freq = mode->clock;
@@ -586,9 +585,14 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
586585

587586
/* Finally filter by configurable vclk frequencies */
588587
switch (vclk_freq) {
588+
case 25175:
589+
case 40000:
589590
case 54000:
591+
case 65000:
590592
case 74250:
593+
case 108000:
591594
case 148500:
595+
case 162000:
592596
case 297000:
593597
case 594000:
594598
return MODE_OK;
@@ -653,10 +657,6 @@ static void meson_venc_hdmi_encoder_mode_set(struct drm_encoder *encoder,
653657
DRM_DEBUG_DRIVER("%d:\"%s\" vic %d\n",
654658
mode->base.id, mode->name, vic);
655659

656-
/* Should have been filtered */
657-
if (!vic)
658-
return;
659-
660660
/* VENC + VENC-DVI Mode setup */
661661
meson_venc_hdmi_mode_set(priv, vic, mode);
662662

drivers/gpu/drm/meson/meson_vclk.c

Lines changed: 215 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,14 +328,24 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
328328
#define MESON_VCLK_HDMI_DDR_54000 2
329329
/* 2970 /4 /1 /1 /5 /1 => /1 /2 */
330330
#define MESON_VCLK_HDMI_DDR_148500 3
331+
/* 4028 /4 /4 /1 /5 /2 => /1 /1 */
332+
#define MESON_VCLK_HDMI_25175 4
333+
/* 3200 /4 /2 /1 /5 /2 => /1 /1 */
334+
#define MESON_VCLK_HDMI_40000 5
335+
/* 5200 /4 /2 /1 /5 /2 => /1 /1 */
336+
#define MESON_VCLK_HDMI_65000 6
331337
/* 2970 /2 /2 /2 /5 /1 => /1 /1 */
332-
#define MESON_VCLK_HDMI_74250 4
338+
#define MESON_VCLK_HDMI_74250 7
339+
/* 4320 /4 /1 /1 /5 /2 => /1 /1 */
340+
#define MESON_VCLK_HDMI_108000 8
333341
/* 2970 /1 /2 /2 /5 /1 => /1 /1 */
334-
#define MESON_VCLK_HDMI_148500 5
342+
#define MESON_VCLK_HDMI_148500 9
343+
/* 3240 /2 /1 /1 /5 /2 => /1 /1 */
344+
#define MESON_VCLK_HDMI_162000 10
335345
/* 2970 /1 /1 /1 /5 /2 => /1 /1 */
336-
#define MESON_VCLK_HDMI_297000 6
346+
#define MESON_VCLK_HDMI_297000 11
337347
/* 5940 /1 /1 /2 /5 /1 => /1 /1 */
338-
#define MESON_VCLK_HDMI_594000 7
348+
#define MESON_VCLK_HDMI_594000 12
339349

340350
struct meson_vclk_params {
341351
unsigned int pll_base_freq;
@@ -401,6 +411,46 @@ struct meson_vclk_params {
401411
.vid_pll_div = VID_PLL_DIV_5,
402412
.vclk_div = 1,
403413
},
414+
[MESON_VCLK_HDMI_25175] = {
415+
.pll_base_freq = 4028000,
416+
.pll_od1 = 4,
417+
.pll_od2 = 4,
418+
.pll_od3 = 1,
419+
.vid_pll_div = VID_PLL_DIV_5,
420+
.vclk_div = 2,
421+
},
422+
[MESON_VCLK_HDMI_40000] = {
423+
.pll_base_freq = 3200000,
424+
.pll_od1 = 4,
425+
.pll_od2 = 2,
426+
.pll_od3 = 1,
427+
.vid_pll_div = VID_PLL_DIV_5,
428+
.vclk_div = 2,
429+
},
430+
[MESON_VCLK_HDMI_65000] = {
431+
.pll_base_freq = 5200000,
432+
.pll_od1 = 4,
433+
.pll_od2 = 2,
434+
.pll_od3 = 1,
435+
.vid_pll_div = VID_PLL_DIV_5,
436+
.vclk_div = 2,
437+
},
438+
[MESON_VCLK_HDMI_108000] = {
439+
.pll_base_freq = 4320000,
440+
.pll_od1 = 4,
441+
.pll_od2 = 1,
442+
.pll_od3 = 1,
443+
.vid_pll_div = VID_PLL_DIV_5,
444+
.vclk_div = 2,
445+
},
446+
[MESON_VCLK_HDMI_162000] = {
447+
.pll_base_freq = 3240000,
448+
.pll_od1 = 2,
449+
.pll_od2 = 1,
450+
.pll_od3 = 1,
451+
.vid_pll_div = VID_PLL_DIV_5,
452+
.vclk_div = 2,
453+
},
404454
};
405455

406456
static inline unsigned int pll_od_to_reg(unsigned int od)
@@ -451,6 +501,90 @@ void meson_hdmi_pll_set(struct meson_drm *priv,
451501
0xFFFF, 0x4e00);
452502
break;
453503

504+
case 3200000:
505+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000242);
506+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
507+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
508+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
509+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
510+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
511+
512+
/* unreset */
513+
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
514+
BIT(28), 0);
515+
516+
/* Poll for lock bit */
517+
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
518+
val, (val & HDMI_PLL_LOCK), 10, 0);
519+
520+
/* div_frac */
521+
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
522+
0xFFFF, 0x4aab);
523+
break;
524+
525+
case 3240000:
526+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000243);
527+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
528+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
529+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
530+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
531+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
532+
533+
/* unreset */
534+
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
535+
BIT(28), 0);
536+
537+
/* Poll for lock bit */
538+
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
539+
val, (val & HDMI_PLL_LOCK), 10, 0);
540+
541+
/* div_frac */
542+
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
543+
0xFFFF, 0x4800);
544+
break;
545+
546+
case 3865000:
547+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000250);
548+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
549+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
550+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
551+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
552+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
553+
554+
/* unreset */
555+
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
556+
BIT(28), 0);
557+
558+
/* Poll for lock bit */
559+
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
560+
val, (val & HDMI_PLL_LOCK), 10, 0);
561+
562+
/* div_frac */
563+
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
564+
0xFFFF, 0x4855);
565+
break;
566+
567+
case 4028000:
568+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000253);
569+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
570+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
571+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
572+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
573+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
574+
575+
/* unreset */
576+
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
577+
BIT(28), 0);
578+
579+
/* Poll for lock bit */
580+
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
581+
val, (val & HDMI_PLL_LOCK), 10, 0);
582+
583+
/* div_frac */
584+
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
585+
0xFFFF, 0x4eab);
586+
break;
587+
454588
case 4320000:
455589
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800025a);
456590
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
@@ -477,6 +611,23 @@ void meson_hdmi_pll_set(struct meson_drm *priv,
477611
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
478612
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
479613

614+
/* unreset */
615+
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
616+
BIT(28), 0);
617+
618+
/* Poll for lock bit */
619+
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
620+
val, (val & HDMI_PLL_LOCK), 10, 0);
621+
break;
622+
623+
case 5200000:
624+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800026c);
625+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
626+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x135c5091);
627+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
628+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
629+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
630+
480631
/* unreset */
481632
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
482633
BIT(28), 0);
@@ -498,6 +649,42 @@ void meson_hdmi_pll_set(struct meson_drm *priv,
498649
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
499650
break;
500651

652+
case 3200000:
653+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000285);
654+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb155);
655+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
656+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
657+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
658+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
659+
break;
660+
661+
case 3240000:
662+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000287);
663+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000);
664+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
665+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
666+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
667+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
668+
break;
669+
670+
case 3865000:
671+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002a1);
672+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb02b);
673+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
674+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
675+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
676+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
677+
break;
678+
679+
case 4028000:
680+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002a7);
681+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb355);
682+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
683+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
684+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
685+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
686+
break;
687+
501688
case 4320000:
502689
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002b4);
503690
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000);
@@ -516,6 +703,15 @@ void meson_hdmi_pll_set(struct meson_drm *priv,
516703
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
517704
break;
518705

706+
case 5200000:
707+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002d8);
708+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb2ab);
709+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
710+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
711+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
712+
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
713+
break;
714+
519715
};
520716

521717
/* Reset PLL */
@@ -590,15 +786,30 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
590786
else
591787
freq = MESON_VCLK_HDMI_DDR_54000;
592788
break;
789+
case 25175:
790+
freq = MESON_VCLK_HDMI_25175;
791+
break;
792+
case 40000:
793+
freq = MESON_VCLK_HDMI_40000;
794+
break;
795+
case 65000:
796+
freq = MESON_VCLK_HDMI_65000;
797+
break;
593798
case 74250:
594799
freq = MESON_VCLK_HDMI_74250;
595800
break;
801+
case 108000:
802+
freq = MESON_VCLK_HDMI_108000;
803+
break;
596804
case 148500:
597805
if (dac_freq != 148500)
598806
freq = MESON_VCLK_HDMI_DDR_148500;
599807
else
600808
freq = MESON_VCLK_HDMI_148500;
601809
break;
810+
case 162000:
811+
freq = MESON_VCLK_HDMI_162000;
812+
break;
602813
case 297000:
603814
freq = MESON_VCLK_HDMI_297000;
604815
break;

0 commit comments

Comments
 (0)