aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/meson
diff options
context:
space:
mode:
authorNeil Armstrong <narmstrong@baylibre.com>2018-03-13 06:07:50 -0400
committerNeil Armstrong <narmstrong@baylibre.com>2018-03-13 06:50:23 -0400
commit9c936b12f15019b38edb5f8bae77bb5b0046d1b7 (patch)
tree76043dd3a31ba9c152fbfa685ef5b1010239e3da /drivers/gpu/drm/meson
parent2c18107b9d58972588cd45d89b8f58d0f033c110 (diff)
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 <jbrunet@baylibre.com> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Link: https://patchwork.freedesktop.org/patch/msgid/1520935670-14187-1-git-send-email-narmstrong@baylibre.com
Diffstat (limited to 'drivers/gpu/drm/meson')
-rw-r--r--drivers/gpu/drm/meson/meson_dw_hdmi.c22
-rw-r--r--drivers/gpu/drm/meson/meson_vclk.c219
-rw-r--r--drivers/gpu/drm/meson/meson_venc.c347
-rw-r--r--drivers/gpu/drm/meson/meson_venc.h1
4 files changed, 570 insertions, 19 deletions
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
index d49af17310c9..a393095aac1a 100644
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
@@ -538,7 +538,6 @@ static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id)
538 return IRQ_HANDLED; 538 return IRQ_HANDLED;
539} 539}
540 540
541/* TOFIX Enable support for non-vic modes */
542static enum drm_mode_status 541static enum drm_mode_status
543dw_hdmi_mode_valid(struct drm_connector *connector, 542dw_hdmi_mode_valid(struct drm_connector *connector,
544 const struct drm_display_mode *mode) 543 const struct drm_display_mode *mode)
@@ -555,12 +554,12 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
555 mode->vdisplay, mode->vsync_start, 554 mode->vdisplay, mode->vsync_start,
556 mode->vsync_end, mode->vtotal, mode->type, mode->flags); 555 mode->vsync_end, mode->vtotal, mode->type, mode->flags);
557 556
558 /* For now, only accept VIC modes */ 557 /* Check against non-VIC supported modes */
559 if (!vic) 558 if (!vic) {
560 return MODE_BAD; 559 if (!meson_venc_hdmi_supported_mode(mode))
561 560 return MODE_BAD;
562 /* For now, filter by supported VIC modes */ 561 /* Check against supported VIC modes */
563 if (!meson_venc_hdmi_supported_vic(vic)) 562 } else if (!meson_venc_hdmi_supported_vic(vic))
564 return MODE_BAD; 563 return MODE_BAD;
565 564
566 vclk_freq = mode->clock; 565 vclk_freq = mode->clock;
@@ -586,9 +585,14 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
586 585
587 /* Finally filter by configurable vclk frequencies */ 586 /* Finally filter by configurable vclk frequencies */
588 switch (vclk_freq) { 587 switch (vclk_freq) {
588 case 25175:
589 case 40000:
589 case 54000: 590 case 54000:
591 case 65000:
590 case 74250: 592 case 74250:
593 case 108000:
591 case 148500: 594 case 148500:
595 case 162000:
592 case 297000: 596 case 297000:
593 case 594000: 597 case 594000:
594 return MODE_OK; 598 return MODE_OK;
@@ -653,10 +657,6 @@ static void meson_venc_hdmi_encoder_mode_set(struct drm_encoder *encoder,
653 DRM_DEBUG_DRIVER("%d:\"%s\" vic %d\n", 657 DRM_DEBUG_DRIVER("%d:\"%s\" vic %d\n",
654 mode->base.id, mode->name, vic); 658 mode->base.id, mode->name, vic);
655 659
656 /* Should have been filtered */
657 if (!vic)
658 return;
659
660 /* VENC + VENC-DVI Mode setup */ 660 /* VENC + VENC-DVI Mode setup */
661 meson_venc_hdmi_mode_set(priv, vic, mode); 661 meson_venc_hdmi_mode_set(priv, vic, mode);
662 662
diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
index 47677047e42d..f0511220317f 100644
--- a/drivers/gpu/drm/meson/meson_vclk.c
+++ b/drivers/gpu/drm/meson/meson_vclk.c
@@ -328,14 +328,24 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
328#define MESON_VCLK_HDMI_DDR_54000 2 328#define MESON_VCLK_HDMI_DDR_54000 2
329/* 2970 /4 /1 /1 /5 /1 => /1 /2 */ 329/* 2970 /4 /1 /1 /5 /1 => /1 /2 */
330#define MESON_VCLK_HDMI_DDR_148500 3 330#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
331/* 2970 /2 /2 /2 /5 /1 => /1 /1 */ 337/* 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
333/* 2970 /1 /2 /2 /5 /1 => /1 /1 */ 341/* 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
335/* 2970 /1 /1 /1 /5 /2 => /1 /1 */ 345/* 2970 /1 /1 /1 /5 /2 => /1 /1 */
336#define MESON_VCLK_HDMI_297000 6 346#define MESON_VCLK_HDMI_297000 11
337/* 5940 /1 /1 /2 /5 /1 => /1 /1 */ 347/* 5940 /1 /1 /2 /5 /1 => /1 /1 */
338#define MESON_VCLK_HDMI_594000 7 348#define MESON_VCLK_HDMI_594000 12
339 349
340struct meson_vclk_params { 350struct meson_vclk_params {
341 unsigned int pll_base_freq; 351 unsigned int pll_base_freq;
@@ -401,6 +411,46 @@ struct meson_vclk_params {
401 .vid_pll_div = VID_PLL_DIV_5, 411 .vid_pll_div = VID_PLL_DIV_5,
402 .vclk_div = 1, 412 .vclk_div = 1,
403 }, 413 },
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 },
404}; 454};
405 455
406static inline unsigned int pll_od_to_reg(unsigned int od) 456static inline unsigned int pll_od_to_reg(unsigned int od)
@@ -451,6 +501,90 @@ void meson_hdmi_pll_set(struct meson_drm *priv,
451 0xFFFF, 0x4e00); 501 0xFFFF, 0x4e00);
452 break; 502 break;
453 503
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
454 case 4320000: 588 case 4320000:
455 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800025a); 589 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800025a);
456 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000); 590 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
@@ -485,6 +619,23 @@ void meson_hdmi_pll_set(struct meson_drm *priv,
485 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, 619 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
486 val, (val & HDMI_PLL_LOCK), 10, 0); 620 val, (val & HDMI_PLL_LOCK), 10, 0);
487 break; 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
631 /* unreset */
632 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
633 BIT(28), 0);
634
635 /* Poll for lock bit */
636 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
637 val, (val & HDMI_PLL_LOCK), 10, 0);
638 break;
488 }; 639 };
489 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || 640 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
490 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) { 641 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
@@ -498,6 +649,42 @@ void meson_hdmi_pll_set(struct meson_drm *priv,
498 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500); 649 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
499 break; 650 break;
500 651
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
501 case 4320000: 688 case 4320000:
502 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002b4); 689 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002b4);
503 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000); 690 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000);
@@ -516,6 +703,15 @@ void meson_hdmi_pll_set(struct meson_drm *priv,
516 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500); 703 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
517 break; 704 break;
518 705
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
519 }; 715 };
520 716
521 /* Reset PLL */ 717 /* Reset PLL */
@@ -590,15 +786,30 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
590 else 786 else
591 freq = MESON_VCLK_HDMI_DDR_54000; 787 freq = MESON_VCLK_HDMI_DDR_54000;
592 break; 788 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;
593 case 74250: 798 case 74250:
594 freq = MESON_VCLK_HDMI_74250; 799 freq = MESON_VCLK_HDMI_74250;
595 break; 800 break;
801 case 108000:
802 freq = MESON_VCLK_HDMI_108000;
803 break;
596 case 148500: 804 case 148500:
597 if (dac_freq != 148500) 805 if (dac_freq != 148500)
598 freq = MESON_VCLK_HDMI_DDR_148500; 806 freq = MESON_VCLK_HDMI_DDR_148500;
599 else 807 else
600 freq = MESON_VCLK_HDMI_148500; 808 freq = MESON_VCLK_HDMI_148500;
601 break; 809 break;
810 case 162000:
811 freq = MESON_VCLK_HDMI_162000;
812 break;
602 case 297000: 813 case 297000:
603 freq = MESON_VCLK_HDMI_297000; 814 freq = MESON_VCLK_HDMI_297000;
604 break; 815 break;
diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
index 9509017dbded..6e2701389801 100644
--- a/drivers/gpu/drm/meson/meson_venc.c
+++ b/drivers/gpu/drm/meson/meson_venc.c
@@ -697,6 +697,314 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
697 }, 697 },
698}; 698};
699 699
700union meson_hdmi_venc_mode meson_hdmi_encp_mode_640x480_60 = {
701 .encp = {
702 .dvi_settings = 0x21,
703 .video_mode = 0x4040,
704 .video_mode_adv = 0x18,
705 /* video_prog_mode */
706 /* video_sync_mode */
707 /* video_yc_dly */
708 /* video_rgb_ctrl */
709 /* video_filt_ctrl */
710 /* video_ofld_voav_ofst */
711 /* yfp1_htime */
712 /* yfp2_htime */
713 .max_pxcnt = 0x31f,
714 /* hspuls_begin */
715 /* hspuls_end */
716 /* hspuls_switch */
717 /* vspuls_begin */
718 /* vspuls_end */
719 /* vspuls_bline */
720 /* vspuls_eline */
721 .havon_begin = 0x90,
722 .havon_end = 0x30f,
723 .vavon_bline = 0x23,
724 .vavon_eline = 0x202,
725 /* eqpuls_begin */
726 /* eqpuls_end */
727 /* eqpuls_bline */
728 /* eqpuls_eline */
729 .hso_begin = 0,
730 .hso_end = 0x60,
731 .vso_begin = 0x1e,
732 .vso_end = 0x32,
733 .vso_bline = 0,
734 .vso_eline = 2,
735 .vso_eline_present = true,
736 /* sy_val */
737 /* sy2_val */
738 .max_lncnt = 0x20c,
739 },
740};
741
742union meson_hdmi_venc_mode meson_hdmi_encp_mode_800x600_60 = {
743 .encp = {
744 .dvi_settings = 0x21,
745 .video_mode = 0x4040,
746 .video_mode_adv = 0x18,
747 /* video_prog_mode */
748 /* video_sync_mode */
749 /* video_yc_dly */
750 /* video_rgb_ctrl */
751 /* video_filt_ctrl */
752 /* video_ofld_voav_ofst */
753 /* yfp1_htime */
754 /* yfp2_htime */
755 .max_pxcnt = 0x41f,
756 /* hspuls_begin */
757 /* hspuls_end */
758 /* hspuls_switch */
759 /* vspuls_begin */
760 /* vspuls_end */
761 /* vspuls_bline */
762 /* vspuls_eline */
763 .havon_begin = 0xD8,
764 .havon_end = 0x3f7,
765 .vavon_bline = 0x1b,
766 .vavon_eline = 0x272,
767 /* eqpuls_begin */
768 /* eqpuls_end */
769 /* eqpuls_bline */
770 /* eqpuls_eline */
771 .hso_begin = 0,
772 .hso_end = 0x80,
773 .vso_begin = 0x1e,
774 .vso_end = 0x32,
775 .vso_bline = 0,
776 .vso_eline = 4,
777 .vso_eline_present = true,
778 /* sy_val */
779 /* sy2_val */
780 .max_lncnt = 0x273,
781 },
782};
783
784union meson_hdmi_venc_mode meson_hdmi_encp_mode_1024x768_60 = {
785 .encp = {
786 .dvi_settings = 0x21,
787 .video_mode = 0x4040,
788 .video_mode_adv = 0x18,
789 /* video_prog_mode */
790 /* video_sync_mode */
791 /* video_yc_dly */
792 /* video_rgb_ctrl */
793 /* video_filt_ctrl */
794 /* video_ofld_voav_ofst */
795 /* yfp1_htime */
796 /* yfp2_htime */
797 .max_pxcnt = 1343,
798 /* hspuls_begin */
799 /* hspuls_end */
800 /* hspuls_switch */
801 /* vspuls_begin */
802 /* vspuls_end */
803 /* vspuls_bline */
804 /* vspuls_eline */
805 .havon_begin = 296,
806 .havon_end = 1319,
807 .vavon_bline = 35,
808 .vavon_eline = 802,
809 /* eqpuls_begin */
810 /* eqpuls_end */
811 /* eqpuls_bline */
812 /* eqpuls_eline */
813 .hso_begin = 0,
814 .hso_end = 136,
815 .vso_begin = 30,
816 .vso_end = 50,
817 .vso_bline = 0,
818 .vso_eline = 6,
819 .vso_eline_present = true,
820 /* sy_val */
821 /* sy2_val */
822 .max_lncnt = 805,
823 },
824};
825
826union meson_hdmi_venc_mode meson_hdmi_encp_mode_1152x864_75 = {
827 .encp = {
828 .dvi_settings = 0x21,
829 .video_mode = 0x4040,
830 .video_mode_adv = 0x18,
831 /* video_prog_mode */
832 /* video_sync_mode */
833 /* video_yc_dly */
834 /* video_rgb_ctrl */
835 /* video_filt_ctrl */
836 /* video_ofld_voav_ofst */
837 /* yfp1_htime */
838 /* yfp2_htime */
839 .max_pxcnt = 0x63f,
840 /* hspuls_begin */
841 /* hspuls_end */
842 /* hspuls_switch */
843 /* vspuls_begin */
844 /* vspuls_end */
845 /* vspuls_bline */
846 /* vspuls_eline */
847 .havon_begin = 0x180,
848 .havon_end = 0x5ff,
849 .vavon_bline = 0x23,
850 .vavon_eline = 0x382,
851 /* eqpuls_begin */
852 /* eqpuls_end */
853 /* eqpuls_bline */
854 /* eqpuls_eline */
855 .hso_begin = 0,
856 .hso_end = 0x80,
857 .vso_begin = 0x1e,
858 .vso_end = 0x32,
859 .vso_bline = 0,
860 .vso_eline = 3,
861 .vso_eline_present = true,
862 /* sy_val */
863 /* sy2_val */
864 .max_lncnt = 0x383,
865 },
866};
867
868union meson_hdmi_venc_mode meson_hdmi_encp_mode_1280x1024_60 = {
869 .encp = {
870 .dvi_settings = 0x21,
871 .video_mode = 0x4040,
872 .video_mode_adv = 0x18,
873 /* video_prog_mode */
874 /* video_sync_mode */
875 /* video_yc_dly */
876 /* video_rgb_ctrl */
877 /* video_filt_ctrl */
878 /* video_ofld_voav_ofst */
879 /* yfp1_htime */
880 /* yfp2_htime */
881 .max_pxcnt = 0x697,
882 /* hspuls_begin */
883 /* hspuls_end */
884 /* hspuls_switch */
885 /* vspuls_begin */
886 /* vspuls_end */
887 /* vspuls_bline */
888 /* vspuls_eline */
889 .havon_begin = 0x168,
890 .havon_end = 0x667,
891 .vavon_bline = 0x29,
892 .vavon_eline = 0x428,
893 /* eqpuls_begin */
894 /* eqpuls_end */
895 /* eqpuls_bline */
896 /* eqpuls_eline */
897 .hso_begin = 0,
898 .hso_end = 0x70,
899 .vso_begin = 0x1e,
900 .vso_end = 0x32,
901 .vso_bline = 0,
902 .vso_eline = 3,
903 .vso_eline_present = true,
904 /* sy_val */
905 /* sy2_val */
906 .max_lncnt = 0x429,
907 },
908};
909
910union meson_hdmi_venc_mode meson_hdmi_encp_mode_1600x1200_60 = {
911 .encp = {
912 .dvi_settings = 0x21,
913 .video_mode = 0x4040,
914 .video_mode_adv = 0x18,
915 /* video_prog_mode */
916 /* video_sync_mode */
917 /* video_yc_dly */
918 /* video_rgb_ctrl */
919 /* video_filt_ctrl */
920 /* video_ofld_voav_ofst */
921 /* yfp1_htime */
922 /* yfp2_htime */
923 .max_pxcnt = 0x86f,
924 /* hspuls_begin */
925 /* hspuls_end */
926 /* hspuls_switch */
927 /* vspuls_begin */
928 /* vspuls_end */
929 /* vspuls_bline */
930 /* vspuls_eline */
931 .havon_begin = 0x1f0,
932 .havon_end = 0x82f,
933 .vavon_bline = 0x31,
934 .vavon_eline = 0x4e0,
935 /* eqpuls_begin */
936 /* eqpuls_end */
937 /* eqpuls_bline */
938 /* eqpuls_eline */
939 .hso_begin = 0,
940 .hso_end = 0xc0,
941 .vso_begin = 0x1e,
942 .vso_end = 0x32,
943 .vso_bline = 0,
944 .vso_eline = 3,
945 .vso_eline_present = true,
946 /* sy_val */
947 /* sy2_val */
948 .max_lncnt = 0x4e1,
949 },
950};
951
952struct meson_hdmi_venc_dmt_mode {
953 struct drm_display_mode drm_mode;
954 union meson_hdmi_venc_mode *mode;
955} meson_hdmi_venc_dmt_modes[] = {
956 /* 640x480@60Hz */
957 {
958 { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
959 752, 800, 0, 480, 490, 492, 525, 0,
960 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
961 &meson_hdmi_encp_mode_640x480_60,
962 },
963 /* 800x600@60Hz */
964 {
965 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
966 968, 1056, 0, 600, 601, 605, 628, 0,
967 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
968 &meson_hdmi_encp_mode_800x600_60,
969 },
970 /* 1024x768@60Hz */
971 {
972 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024,
973 1048, 1184, 1344, 0, 768, 771, 777, 806, 0,
974 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
975 &meson_hdmi_encp_mode_1024x768_60,
976 },
977 /* 1152x864@75Hz */
978 {
979 { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152,
980 1216, 1344, 1600, 0, 864, 865, 868, 900, 0,
981 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
982 &meson_hdmi_encp_mode_1152x864_75,
983 },
984 /* 1280x1024@60Hz */
985 {
986 { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280,
987 1328, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
988 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
989 &meson_hdmi_encp_mode_1280x1024_60,
990 },
991 /* 1600x1200@60Hz */
992 {
993 { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600,
994 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
995 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
996 &meson_hdmi_encp_mode_1600x1200_60,
997 },
998 /* 1920x1080@60Hz */
999 {
1000 { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920,
1001 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
1002 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
1003 &meson_hdmi_encp_mode_1080p60
1004 },
1005 { }, /* sentinel */
1006};
1007
700struct meson_hdmi_venc_vic_mode { 1008struct meson_hdmi_venc_vic_mode {
701 unsigned int vic; 1009 unsigned int vic;
702 union meson_hdmi_venc_mode *mode; 1010 union meson_hdmi_venc_mode *mode;
@@ -736,6 +1044,20 @@ static unsigned long modulo(unsigned long a, unsigned long b)
736 return a; 1044 return a;
737} 1045}
738 1046
1047bool meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode)
1048{
1049 struct meson_hdmi_venc_dmt_mode *vmode = meson_hdmi_venc_dmt_modes;
1050
1051 while (vmode->mode) {
1052 if (drm_mode_equal(&vmode->drm_mode, mode))
1053 return true;
1054 vmode++;
1055 }
1056
1057 return false;
1058}
1059EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_mode);
1060
739bool meson_venc_hdmi_supported_vic(int vic) 1061bool meson_venc_hdmi_supported_vic(int vic)
740{ 1062{
741 struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes; 1063 struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes;
@@ -750,6 +1072,20 @@ bool meson_venc_hdmi_supported_vic(int vic)
750} 1072}
751EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic); 1073EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic);
752 1074
1075static union meson_hdmi_venc_mode
1076*meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode)
1077{
1078 struct meson_hdmi_venc_dmt_mode *vmode = meson_hdmi_venc_dmt_modes;
1079
1080 while (vmode->mode) {
1081 if (drm_mode_equal(&vmode->drm_mode, mode))
1082 return vmode->mode;
1083 vmode++;
1084 }
1085
1086 return NULL;
1087}
1088
753static union meson_hdmi_venc_mode *meson_venc_hdmi_get_vic_vmode(int vic) 1089static union meson_hdmi_venc_mode *meson_venc_hdmi_get_vic_vmode(int vic)
754{ 1090{
755 struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes; 1091 struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes;
@@ -811,10 +1147,13 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
811 unsigned int sof_lines; 1147 unsigned int sof_lines;
812 unsigned int vsync_lines; 1148 unsigned int vsync_lines;
813 1149
814 vmode = meson_venc_hdmi_get_vic_vmode(vic); 1150 if (meson_venc_hdmi_supported_vic(vic))
1151 vmode = meson_venc_hdmi_get_vic_vmode(vic);
1152 else
1153 vmode = meson_venc_hdmi_get_dmt_vmode(mode);
815 if (!vmode) { 1154 if (!vmode) {
816 dev_err(priv->dev, "%s: Fatal Error, unsupported vic %d\n", 1155 dev_err(priv->dev, "%s: Fatal Error, unsupported mode "
817 __func__, vic); 1156 DRM_MODE_FMT "\n", __func__, DRM_MODE_ARG(mode));
818 return; 1157 return;
819 } 1158 }
820 1159
@@ -864,7 +1203,7 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
864 hsync_pixels_venc *= 2; 1203 hsync_pixels_venc *= 2;
865 1204
866 /* Disable VDACs */ 1205 /* Disable VDACs */
867 writel_bits_relaxed(0x1f, 0x1f, 1206 writel_bits_relaxed(0xff, 0xff,
868 priv->io_base + _REG(VENC_VDAC_SETTING)); 1207 priv->io_base + _REG(VENC_VDAC_SETTING));
869 1208
870 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN)); 1209 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
diff --git a/drivers/gpu/drm/meson/meson_venc.h b/drivers/gpu/drm/meson/meson_venc.h
index a1b96e898c14..7c18a36a0dd0 100644
--- a/drivers/gpu/drm/meson/meson_venc.h
+++ b/drivers/gpu/drm/meson/meson_venc.h
@@ -58,6 +58,7 @@ struct meson_cvbs_enci_mode {
58}; 58};
59 59
60/* HDMI Clock parameters */ 60/* HDMI Clock parameters */
61bool meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode);
61bool meson_venc_hdmi_supported_vic(int vic); 62bool meson_venc_hdmi_supported_vic(int vic);
62bool meson_venc_hdmi_venc_repeat(int vic); 63bool meson_venc_hdmi_venc_repeat(int vic);
63 64