hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/drivers/gpu/drm/bridge/cdns-dsi.c
....@@ -7,12 +7,14 @@
77
88 #include <drm/drm_atomic_helper.h>
99 #include <drm/drm_bridge.h>
10
-#include <drm/drm_crtc_helper.h>
10
+#include <drm/drm_drv.h>
1111 #include <drm/drm_mipi_dsi.h>
1212 #include <drm/drm_panel.h>
13
+#include <drm/drm_probe_helper.h>
1314 #include <video/mipi_display.h>
1415
1516 #include <linux/clk.h>
17
+#include <linux/interrupt.h>
1618 #include <linux/iopoll.h>
1719 #include <linux/module.h>
1820 #include <linux/of_address.h>
....@@ -20,6 +22,9 @@
2022 #include <linux/platform_device.h>
2123 #include <linux/pm_runtime.h>
2224 #include <linux/reset.h>
25
+
26
+#include <linux/phy/phy.h>
27
+#include <linux/phy/phy-mipi-dphy.h>
2328
2429 #define IP_CONF 0x0
2530 #define SP_HS_FIFO_DEPTH(x) (((x) & GENMASK(30, 26)) >> 26)
....@@ -419,44 +424,11 @@
419424 #define DSI_NULL_FRAME_OVERHEAD 6
420425 #define DSI_EOT_PKT_SIZE 4
421426
422
-#define REG_WAKEUP_TIME_NS 800
423
-#define DPHY_PLL_RATE_HZ 108000000
424
-
425
-/* DPHY registers */
426
-#define DPHY_PMA_CMN(reg) (reg)
427
-#define DPHY_PMA_LCLK(reg) (0x100 + (reg))
428
-#define DPHY_PMA_LDATA(lane, reg) (0x200 + ((lane) * 0x100) + (reg))
429
-#define DPHY_PMA_RCLK(reg) (0x600 + (reg))
430
-#define DPHY_PMA_RDATA(lane, reg) (0x700 + ((lane) * 0x100) + (reg))
431
-#define DPHY_PCS(reg) (0xb00 + (reg))
432
-
433
-#define DPHY_CMN_SSM DPHY_PMA_CMN(0x20)
434
-#define DPHY_CMN_SSM_EN BIT(0)
435
-#define DPHY_CMN_TX_MODE_EN BIT(9)
436
-
437
-#define DPHY_CMN_PWM DPHY_PMA_CMN(0x40)
438
-#define DPHY_CMN_PWM_DIV(x) ((x) << 20)
439
-#define DPHY_CMN_PWM_LOW(x) ((x) << 10)
440
-#define DPHY_CMN_PWM_HIGH(x) (x)
441
-
442
-#define DPHY_CMN_FBDIV DPHY_PMA_CMN(0x4c)
443
-#define DPHY_CMN_FBDIV_VAL(low, high) (((high) << 11) | ((low) << 22))
444
-#define DPHY_CMN_FBDIV_FROM_REG (BIT(10) | BIT(21))
445
-
446
-#define DPHY_CMN_OPIPDIV DPHY_PMA_CMN(0x50)
447
-#define DPHY_CMN_IPDIV_FROM_REG BIT(0)
448
-#define DPHY_CMN_IPDIV(x) ((x) << 1)
449
-#define DPHY_CMN_OPDIV_FROM_REG BIT(6)
450
-#define DPHY_CMN_OPDIV(x) ((x) << 7)
451
-
452
-#define DPHY_PSM_CFG DPHY_PCS(0x4)
453
-#define DPHY_PSM_CFG_FROM_REG BIT(0)
454
-#define DPHY_PSM_CLK_DIV(x) ((x) << 1)
455
-
456427 struct cdns_dsi_output {
457428 struct mipi_dsi_device *dev;
458429 struct drm_panel *panel;
459430 struct drm_bridge *bridge;
431
+ union phy_configure_opts phy_opts;
460432 };
461433
462434 enum cdns_dsi_input_id {
....@@ -465,48 +437,12 @@
465437 CDNS_DSC_INPUT,
466438 };
467439
468
-struct cdns_dphy_cfg {
469
- u8 pll_ipdiv;
470
- u8 pll_opdiv;
471
- u16 pll_fbdiv;
472
- unsigned long lane_bps;
473
- unsigned int nlanes;
474
-};
475
-
476440 struct cdns_dsi_cfg {
477441 unsigned int hfp;
478442 unsigned int hsa;
479443 unsigned int hbp;
480444 unsigned int hact;
481445 unsigned int htotal;
482
-};
483
-
484
-struct cdns_dphy;
485
-
486
-enum cdns_dphy_clk_lane_cfg {
487
- DPHY_CLK_CFG_LEFT_DRIVES_ALL = 0,
488
- DPHY_CLK_CFG_LEFT_DRIVES_RIGHT = 1,
489
- DPHY_CLK_CFG_LEFT_DRIVES_LEFT = 2,
490
- DPHY_CLK_CFG_RIGHT_DRIVES_ALL = 3,
491
-};
492
-
493
-struct cdns_dphy_ops {
494
- int (*probe)(struct cdns_dphy *dphy);
495
- void (*remove)(struct cdns_dphy *dphy);
496
- void (*set_psm_div)(struct cdns_dphy *dphy, u8 div);
497
- void (*set_clk_lane_cfg)(struct cdns_dphy *dphy,
498
- enum cdns_dphy_clk_lane_cfg cfg);
499
- void (*set_pll_cfg)(struct cdns_dphy *dphy,
500
- const struct cdns_dphy_cfg *cfg);
501
- unsigned long (*get_wakeup_time_ns)(struct cdns_dphy *dphy);
502
-};
503
-
504
-struct cdns_dphy {
505
- struct cdns_dphy_cfg cfg;
506
- void __iomem *regs;
507
- struct clk *psm_clk;
508
- struct clk *pll_ref_clk;
509
- const struct cdns_dphy_ops *ops;
510446 };
511447
512448 struct cdns_dsi_input {
....@@ -526,7 +462,7 @@
526462 struct reset_control *dsi_p_rst;
527463 struct clk *dsi_sys_clk;
528464 bool link_initialized;
529
- struct cdns_dphy *dphy;
465
+ struct phy *dphy;
530466 };
531467
532468 static inline struct cdns_dsi *input_to_dsi(struct cdns_dsi_input *input)
....@@ -545,173 +481,13 @@
545481 return container_of(bridge, struct cdns_dsi_input, bridge);
546482 }
547483
548
-static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
549
- struct cdns_dphy_cfg *cfg,
550
- unsigned int dpi_htotal,
551
- unsigned int dpi_bpp,
552
- unsigned int dpi_hz,
553
- unsigned int dsi_htotal,
554
- unsigned int dsi_nlanes,
555
- unsigned int *dsi_hfp_ext)
484
+static unsigned int mode_to_dpi_hfp(const struct drm_display_mode *mode,
485
+ bool mode_valid_check)
556486 {
557
- u64 dlane_bps, dlane_bps_max, fbdiv, fbdiv_max, adj_dsi_htotal;
558
- unsigned long pll_ref_hz = clk_get_rate(dphy->pll_ref_clk);
487
+ if (mode_valid_check)
488
+ return mode->hsync_start - mode->hdisplay;
559489
560
- memset(cfg, 0, sizeof(*cfg));
561
-
562
- cfg->nlanes = dsi_nlanes;
563
-
564
- if (pll_ref_hz < 9600000 || pll_ref_hz >= 150000000)
565
- return -EINVAL;
566
- else if (pll_ref_hz < 19200000)
567
- cfg->pll_ipdiv = 1;
568
- else if (pll_ref_hz < 38400000)
569
- cfg->pll_ipdiv = 2;
570
- else if (pll_ref_hz < 76800000)
571
- cfg->pll_ipdiv = 4;
572
- else
573
- cfg->pll_ipdiv = 8;
574
-
575
- /*
576
- * Make sure DSI htotal is aligned on a lane boundary when calculating
577
- * the expected data rate. This is done by extending HFP in case of
578
- * misalignment.
579
- */
580
- adj_dsi_htotal = dsi_htotal;
581
- if (dsi_htotal % dsi_nlanes)
582
- adj_dsi_htotal += dsi_nlanes - (dsi_htotal % dsi_nlanes);
583
-
584
- dlane_bps = (u64)dpi_hz * adj_dsi_htotal;
585
-
586
- /* data rate in bytes/sec is not an integer, refuse the mode. */
587
- if (do_div(dlane_bps, dsi_nlanes * dpi_htotal))
588
- return -EINVAL;
589
-
590
- /* data rate was in bytes/sec, convert to bits/sec. */
591
- dlane_bps *= 8;
592
-
593
- if (dlane_bps > 2500000000UL || dlane_bps < 160000000UL)
594
- return -EINVAL;
595
- else if (dlane_bps >= 1250000000)
596
- cfg->pll_opdiv = 1;
597
- else if (dlane_bps >= 630000000)
598
- cfg->pll_opdiv = 2;
599
- else if (dlane_bps >= 320000000)
600
- cfg->pll_opdiv = 4;
601
- else if (dlane_bps >= 160000000)
602
- cfg->pll_opdiv = 8;
603
-
604
- /*
605
- * Allow a deviation of 0.2% on the per-lane data rate to try to
606
- * recover a potential mismatch between DPI and PPI clks.
607
- */
608
- dlane_bps_max = dlane_bps + DIV_ROUND_DOWN_ULL(dlane_bps, 500);
609
- fbdiv_max = DIV_ROUND_DOWN_ULL(dlane_bps_max * 2 *
610
- cfg->pll_opdiv * cfg->pll_ipdiv,
611
- pll_ref_hz);
612
- fbdiv = DIV_ROUND_UP_ULL(dlane_bps * 2 * cfg->pll_opdiv *
613
- cfg->pll_ipdiv,
614
- pll_ref_hz);
615
-
616
- /*
617
- * Iterate over all acceptable fbdiv and try to find an adjusted DSI
618
- * htotal length providing an exact match.
619
- *
620
- * Note that we could do something even trickier by relying on the fact
621
- * that a new line is not necessarily aligned on a lane boundary, so,
622
- * by making adj_dsi_htotal non aligned on a dsi_lanes we can improve a
623
- * bit the precision. With this, the step would be
624
- *
625
- * pll_ref_hz / (2 * opdiv * ipdiv * nlanes)
626
- *
627
- * instead of
628
- *
629
- * pll_ref_hz / (2 * opdiv * ipdiv)
630
- *
631
- * The drawback of this approach is that we would need to make sure the
632
- * number or lines is a multiple of the realignment periodicity which is
633
- * a function of the number of lanes and the original misalignment. For
634
- * example, for NLANES = 4 and HTOTAL % NLANES = 3, it takes 4 lines
635
- * to realign on a lane:
636
- * LINE 0: expected number of bytes, starts emitting first byte of
637
- * LINE 1 on LANE 3
638
- * LINE 1: expected number of bytes, starts emitting first 2 bytes of
639
- * LINE 2 on LANES 2 and 3
640
- * LINE 2: expected number of bytes, starts emitting first 3 bytes of
641
- * of LINE 3 on LANES 1, 2 and 3
642
- * LINE 3: one byte less, now things are realigned on LANE 0 for LINE 4
643
- *
644
- * I figured this extra complexity was not worth the benefit, but if
645
- * someone really has unfixable mismatch, that would be something to
646
- * investigate.
647
- */
648
- for (; fbdiv <= fbdiv_max; fbdiv++) {
649
- u32 rem;
650
-
651
- adj_dsi_htotal = (u64)fbdiv * pll_ref_hz * dsi_nlanes *
652
- dpi_htotal;
653
-
654
- /*
655
- * Do the division in 2 steps to avoid an overflow on the
656
- * divider.
657
- */
658
- rem = do_div(adj_dsi_htotal, dpi_hz);
659
- if (rem)
660
- continue;
661
-
662
- rem = do_div(adj_dsi_htotal,
663
- cfg->pll_opdiv * cfg->pll_ipdiv * 2 * 8);
664
- if (rem)
665
- continue;
666
-
667
- cfg->pll_fbdiv = fbdiv;
668
- *dsi_hfp_ext = adj_dsi_htotal - dsi_htotal;
669
- break;
670
- }
671
-
672
- /* No match, let's just reject the display mode. */
673
- if (!cfg->pll_fbdiv)
674
- return -EINVAL;
675
-
676
- dlane_bps = DIV_ROUND_DOWN_ULL((u64)dpi_hz * adj_dsi_htotal * 8,
677
- dsi_nlanes * dpi_htotal);
678
- cfg->lane_bps = dlane_bps;
679
-
680
- return 0;
681
-}
682
-
683
-static int cdns_dphy_setup_psm(struct cdns_dphy *dphy)
684
-{
685
- unsigned long psm_clk_hz = clk_get_rate(dphy->psm_clk);
686
- unsigned long psm_div;
687
-
688
- if (!psm_clk_hz || psm_clk_hz > 100000000)
689
- return -EINVAL;
690
-
691
- psm_div = DIV_ROUND_CLOSEST(psm_clk_hz, 1000000);
692
- if (dphy->ops->set_psm_div)
693
- dphy->ops->set_psm_div(dphy, psm_div);
694
-
695
- return 0;
696
-}
697
-
698
-static void cdns_dphy_set_clk_lane_cfg(struct cdns_dphy *dphy,
699
- enum cdns_dphy_clk_lane_cfg cfg)
700
-{
701
- if (dphy->ops->set_clk_lane_cfg)
702
- dphy->ops->set_clk_lane_cfg(dphy, cfg);
703
-}
704
-
705
-static void cdns_dphy_set_pll_cfg(struct cdns_dphy *dphy,
706
- const struct cdns_dphy_cfg *cfg)
707
-{
708
- if (dphy->ops->set_pll_cfg)
709
- dphy->ops->set_pll_cfg(dphy, cfg);
710
-}
711
-
712
-static unsigned long cdns_dphy_get_wakeup_time_ns(struct cdns_dphy *dphy)
713
-{
714
- return dphy->ops->get_wakeup_time_ns(dphy);
490
+ return mode->crtc_hsync_start - mode->crtc_hdisplay;
715491 }
716492
717493 static unsigned int dpi_to_dsi_timing(unsigned int dpi_timing,
....@@ -731,14 +507,12 @@
731507 static int cdns_dsi_mode2cfg(struct cdns_dsi *dsi,
732508 const struct drm_display_mode *mode,
733509 struct cdns_dsi_cfg *dsi_cfg,
734
- struct cdns_dphy_cfg *dphy_cfg,
735510 bool mode_valid_check)
736511 {
737
- unsigned long dsi_htotal = 0, dsi_hss_hsa_hse_hbp = 0;
738512 struct cdns_dsi_output *output = &dsi->output;
739
- unsigned int dsi_hfp_ext = 0, dpi_hfp, tmp;
513
+ unsigned int tmp;
740514 bool sync_pulse = false;
741
- int bpp, nlanes, ret;
515
+ int bpp;
742516
743517 memset(dsi_cfg, 0, sizeof(*dsi_cfg));
744518
....@@ -746,7 +520,6 @@
746520 sync_pulse = true;
747521
748522 bpp = mipi_dsi_pixel_format_to_bpp(output->dev->format);
749
- nlanes = output->dev->lanes;
750523
751524 if (mode_valid_check)
752525 tmp = mode->htotal -
....@@ -757,8 +530,6 @@
757530 mode->crtc_hsync_end : mode->crtc_hsync_start);
758531
759532 dsi_cfg->hbp = dpi_to_dsi_timing(tmp, bpp, DSI_HBP_FRAME_OVERHEAD);
760
- dsi_htotal += dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
761
- dsi_hss_hsa_hse_hbp += dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
762533
763534 if (sync_pulse) {
764535 if (mode_valid_check)
....@@ -768,49 +539,104 @@
768539
769540 dsi_cfg->hsa = dpi_to_dsi_timing(tmp, bpp,
770541 DSI_HSA_FRAME_OVERHEAD);
771
- dsi_htotal += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD;
772
- dsi_hss_hsa_hse_hbp += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD;
773542 }
774543
775544 dsi_cfg->hact = dpi_to_dsi_timing(mode_valid_check ?
776545 mode->hdisplay : mode->crtc_hdisplay,
777546 bpp, 0);
547
+ dsi_cfg->hfp = dpi_to_dsi_timing(mode_to_dpi_hfp(mode, mode_valid_check),
548
+ bpp, DSI_HFP_FRAME_OVERHEAD);
549
+
550
+ return 0;
551
+}
552
+
553
+static int cdns_dsi_adjust_phy_config(struct cdns_dsi *dsi,
554
+ struct cdns_dsi_cfg *dsi_cfg,
555
+ struct phy_configure_opts_mipi_dphy *phy_cfg,
556
+ const struct drm_display_mode *mode,
557
+ bool mode_valid_check)
558
+{
559
+ struct cdns_dsi_output *output = &dsi->output;
560
+ unsigned long long dlane_bps;
561
+ unsigned long adj_dsi_htotal;
562
+ unsigned long dsi_htotal;
563
+ unsigned long dpi_htotal;
564
+ unsigned long dpi_hz;
565
+ unsigned int dsi_hfp_ext;
566
+ unsigned int lanes = output->dev->lanes;
567
+
568
+ dsi_htotal = dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
569
+ if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
570
+ dsi_htotal += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD;
571
+
778572 dsi_htotal += dsi_cfg->hact;
779
-
780
- if (mode_valid_check)
781
- dpi_hfp = mode->hsync_start - mode->hdisplay;
782
- else
783
- dpi_hfp = mode->crtc_hsync_start - mode->crtc_hdisplay;
784
-
785
- dsi_cfg->hfp = dpi_to_dsi_timing(dpi_hfp, bpp, DSI_HFP_FRAME_OVERHEAD);
786573 dsi_htotal += dsi_cfg->hfp + DSI_HFP_FRAME_OVERHEAD;
787574
788
- if (mode_valid_check)
789
- ret = cdns_dsi_get_dphy_pll_cfg(dsi->dphy, dphy_cfg,
790
- mode->htotal, bpp,
791
- mode->clock * 1000,
792
- dsi_htotal, nlanes,
793
- &dsi_hfp_ext);
794
- else
795
- ret = cdns_dsi_get_dphy_pll_cfg(dsi->dphy, dphy_cfg,
796
- mode->crtc_htotal, bpp,
797
- mode->crtc_clock * 1000,
798
- dsi_htotal, nlanes,
799
- &dsi_hfp_ext);
575
+ /*
576
+ * Make sure DSI htotal is aligned on a lane boundary when calculating
577
+ * the expected data rate. This is done by extending HFP in case of
578
+ * misalignment.
579
+ */
580
+ adj_dsi_htotal = dsi_htotal;
581
+ if (dsi_htotal % lanes)
582
+ adj_dsi_htotal += lanes - (dsi_htotal % lanes);
800583
584
+ dpi_hz = (mode_valid_check ? mode->clock : mode->crtc_clock) * 1000;
585
+ dlane_bps = (unsigned long long)dpi_hz * adj_dsi_htotal;
586
+
587
+ /* data rate in bytes/sec is not an integer, refuse the mode. */
588
+ dpi_htotal = mode_valid_check ? mode->htotal : mode->crtc_htotal;
589
+ if (do_div(dlane_bps, lanes * dpi_htotal))
590
+ return -EINVAL;
591
+
592
+ /* data rate was in bytes/sec, convert to bits/sec. */
593
+ phy_cfg->hs_clk_rate = dlane_bps * 8;
594
+
595
+ dsi_hfp_ext = adj_dsi_htotal - dsi_htotal;
596
+ dsi_cfg->hfp += dsi_hfp_ext;
597
+ dsi_cfg->htotal = dsi_htotal + dsi_hfp_ext;
598
+
599
+ return 0;
600
+}
601
+
602
+static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
603
+ const struct drm_display_mode *mode,
604
+ struct cdns_dsi_cfg *dsi_cfg,
605
+ bool mode_valid_check)
606
+{
607
+ struct cdns_dsi_output *output = &dsi->output;
608
+ struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
609
+ unsigned long dsi_hss_hsa_hse_hbp;
610
+ unsigned int nlanes = output->dev->lanes;
611
+ int ret;
612
+
613
+ ret = cdns_dsi_mode2cfg(dsi, mode, dsi_cfg, mode_valid_check);
801614 if (ret)
802615 return ret;
803616
804
- dsi_cfg->hfp += dsi_hfp_ext;
805
- dsi_htotal += dsi_hfp_ext;
806
- dsi_cfg->htotal = dsi_htotal;
617
+ phy_mipi_dphy_get_default_config(mode->crtc_clock * 1000,
618
+ mipi_dsi_pixel_format_to_bpp(output->dev->format),
619
+ nlanes, phy_cfg);
620
+
621
+ ret = cdns_dsi_adjust_phy_config(dsi, dsi_cfg, phy_cfg, mode, mode_valid_check);
622
+ if (ret)
623
+ return ret;
624
+
625
+ ret = phy_validate(dsi->dphy, PHY_MODE_MIPI_DPHY, 0, &output->phy_opts);
626
+ if (ret)
627
+ return ret;
628
+
629
+ dsi_hss_hsa_hse_hbp = dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
630
+ if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
631
+ dsi_hss_hsa_hse_hbp += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD;
807632
808633 /*
809634 * Make sure DPI(HFP) > DSI(HSS+HSA+HSE+HBP) to guarantee that the FIFO
810635 * is empty before we start a receiving a new line on the DPI
811636 * interface.
812637 */
813
- if ((u64)dphy_cfg->lane_bps * dpi_hfp * nlanes <
638
+ if ((u64)phy_cfg->hs_clk_rate *
639
+ mode_to_dpi_hfp(mode, mode_valid_check) * nlanes <
814640 (u64)dsi_hss_hsa_hse_hbp *
815641 (mode_valid_check ? mode->clock : mode->crtc_clock) * 1000)
816642 return -EINVAL;
....@@ -818,7 +644,8 @@
818644 return 0;
819645 }
820646
821
-static int cdns_dsi_bridge_attach(struct drm_bridge *bridge)
647
+static int cdns_dsi_bridge_attach(struct drm_bridge *bridge,
648
+ enum drm_bridge_attach_flags flags)
822649 {
823650 struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
824651 struct cdns_dsi *dsi = input_to_dsi(input);
....@@ -830,19 +657,20 @@
830657 return -ENOTSUPP;
831658 }
832659
833
- return drm_bridge_attach(bridge->encoder, output->bridge, bridge);
660
+ return drm_bridge_attach(bridge->encoder, output->bridge, bridge,
661
+ flags);
834662 }
835663
836664 static enum drm_mode_status
837665 cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
666
+ const struct drm_display_info *info,
838667 const struct drm_display_mode *mode)
839668 {
840669 struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
841670 struct cdns_dsi *dsi = input_to_dsi(input);
842671 struct cdns_dsi_output *output = &dsi->output;
843
- struct cdns_dphy_cfg dphy_cfg;
844672 struct cdns_dsi_cfg dsi_cfg;
845
- int bpp, nlanes, ret;
673
+ int bpp, ret;
846674
847675 /*
848676 * VFP_DSI should be less than VFP_DPI and VFP_DSI should be at
....@@ -860,11 +688,9 @@
860688 if ((mode->hdisplay * bpp) % 32)
861689 return MODE_H_ILLEGAL;
862690
863
- nlanes = output->dev->lanes;
864
-
865
- ret = cdns_dsi_mode2cfg(dsi, mode, &dsi_cfg, &dphy_cfg, true);
691
+ ret = cdns_dsi_check_conf(dsi, mode, &dsi_cfg, true);
866692 if (ret)
867
- return MODE_CLOCK_RANGE;
693
+ return MODE_BAD;
868694
869695 return MODE_OK;
870696 }
....@@ -885,9 +711,9 @@
885711 pm_runtime_put(dsi->base.dev);
886712 }
887713
888
-static void cdns_dsi_hs_init(struct cdns_dsi *dsi,
889
- const struct cdns_dphy_cfg *dphy_cfg)
714
+static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
890715 {
716
+ struct cdns_dsi_output *output = &dsi->output;
891717 u32 status;
892718
893719 /*
....@@ -898,30 +724,10 @@
898724 DPHY_CMN_PDN | DPHY_PLL_PDN,
899725 dsi->regs + MCTL_DPHY_CFG0);
900726
901
- /*
902
- * Configure the internal PSM clk divider so that the DPHY has a
903
- * 1MHz clk (or something close).
904
- */
905
- WARN_ON_ONCE(cdns_dphy_setup_psm(dsi->dphy));
906
-
907
- /*
908
- * Configure attach clk lanes to data lanes: the DPHY has 2 clk lanes
909
- * and 8 data lanes, each clk lane can be attache different set of
910
- * data lanes. The 2 groups are named 'left' and 'right', so here we
911
- * just say that we want the 'left' clk lane to drive the 'left' data
912
- * lanes.
913
- */
914
- cdns_dphy_set_clk_lane_cfg(dsi->dphy, DPHY_CLK_CFG_LEFT_DRIVES_LEFT);
915
-
916
- /*
917
- * Configure the DPHY PLL that will be used to generate the TX byte
918
- * clk.
919
- */
920
- cdns_dphy_set_pll_cfg(dsi->dphy, dphy_cfg);
921
-
922
- /* Start TX state machine. */
923
- writel(DPHY_CMN_SSM_EN | DPHY_CMN_TX_MODE_EN,
924
- dsi->dphy->regs + DPHY_CMN_SSM);
727
+ phy_init(dsi->dphy);
728
+ phy_set_mode(dsi->dphy, PHY_MODE_MIPI_DPHY);
729
+ phy_configure(dsi->dphy, &output->phy_opts);
730
+ phy_power_on(dsi->dphy);
925731
926732 /* Activate the PLL and wait until it's locked. */
927733 writel(PLL_LOCKED, dsi->regs + MCTL_MAIN_STS_CLR);
....@@ -931,7 +737,7 @@
931737 status & PLL_LOCKED, 100, 100));
932738 /* De-assert data and clock reset lines. */
933739 writel(DPHY_CMN_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN | DPHY_CMN_PDN |
934
- DPHY_D_RSTB(dphy_cfg->nlanes) | DPHY_C_RSTB,
740
+ DPHY_D_RSTB(output->dev->lanes) | DPHY_C_RSTB,
935741 dsi->regs + MCTL_DPHY_CFG0);
936742 }
937743
....@@ -977,22 +783,21 @@
977783 struct cdns_dsi *dsi = input_to_dsi(input);
978784 struct cdns_dsi_output *output = &dsi->output;
979785 struct drm_display_mode *mode;
980
- struct cdns_dphy_cfg dphy_cfg;
786
+ struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
981787 unsigned long tx_byte_period;
982788 struct cdns_dsi_cfg dsi_cfg;
983789 u32 tmp, reg_wakeup, div;
984
- int bpp, nlanes;
790
+ int nlanes;
985791
986792 if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
987793 return;
988794
989795 mode = &bridge->encoder->crtc->state->adjusted_mode;
990
- bpp = mipi_dsi_pixel_format_to_bpp(output->dev->format);
991796 nlanes = output->dev->lanes;
992797
993
- WARN_ON_ONCE(cdns_dsi_mode2cfg(dsi, mode, &dsi_cfg, &dphy_cfg, false));
798
+ WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, false));
994799
995
- cdns_dsi_hs_init(dsi, &dphy_cfg);
800
+ cdns_dsi_hs_init(dsi);
996801 cdns_dsi_init_link(dsi);
997802
998803 writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
....@@ -1028,9 +833,8 @@
1028833 tmp -= DIV_ROUND_UP(DSI_EOT_PKT_SIZE, nlanes);
1029834
1030835 tx_byte_period = DIV_ROUND_DOWN_ULL((u64)NSEC_PER_SEC * 8,
1031
- dphy_cfg.lane_bps);
1032
- reg_wakeup = cdns_dphy_get_wakeup_time_ns(dsi->dphy) /
1033
- tx_byte_period;
836
+ phy_cfg->hs_clk_rate);
837
+ reg_wakeup = (phy_cfg->hs_prepare + phy_cfg->hs_zero) / tx_byte_period;
1034838 writel(REG_WAKEUP_TIME(reg_wakeup) | REG_LINE_DURATION(tmp),
1035839 dsi->regs + VID_DPHY_TIME);
1036840
....@@ -1153,7 +957,8 @@
1153957
1154958 panel = of_drm_find_panel(np);
1155959 if (!IS_ERR(panel)) {
1156
- bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DSI);
960
+ bridge = drm_panel_bridge_add_typed(panel,
961
+ DRM_MODE_CONNECTOR_DSI);
1157962 } else {
1158963 bridge = of_drm_find_bridge(dev->dev.of_node);
1159964 if (!bridge)
....@@ -1223,7 +1028,7 @@
12231028 struct mipi_dsi_packet packet;
12241029 int ret, i, tx_len, rx_len;
12251030
1226
- ret = pm_runtime_get_sync(host->dev);
1031
+ ret = pm_runtime_resume_and_get(host->dev);
12271032 if (ret < 0)
12281033 return ret;
12291034
....@@ -1344,8 +1149,6 @@
13441149 reset_control_deassert(dsi->dsi_p_rst);
13451150 clk_prepare_enable(dsi->dsi_p_clk);
13461151 clk_prepare_enable(dsi->dsi_sys_clk);
1347
- clk_prepare_enable(dsi->dphy->psm_clk);
1348
- clk_prepare_enable(dsi->dphy->pll_ref_clk);
13491152
13501153 return 0;
13511154 }
....@@ -1354,8 +1157,6 @@
13541157 {
13551158 struct cdns_dsi *dsi = dev_get_drvdata(dev);
13561159
1357
- clk_disable_unprepare(dsi->dphy->pll_ref_clk);
1358
- clk_disable_unprepare(dsi->dphy->psm_clk);
13591160 clk_disable_unprepare(dsi->dsi_sys_clk);
13601161 clk_disable_unprepare(dsi->dsi_p_clk);
13611162 reset_control_assert(dsi->dsi_p_rst);
....@@ -1365,121 +1166,6 @@
13651166
13661167 static UNIVERSAL_DEV_PM_OPS(cdns_dsi_pm_ops, cdns_dsi_suspend, cdns_dsi_resume,
13671168 NULL);
1368
-
1369
-static unsigned long cdns_dphy_ref_get_wakeup_time_ns(struct cdns_dphy *dphy)
1370
-{
1371
- /* Default wakeup time is 800 ns (in a simulated environment). */
1372
- return 800;
1373
-}
1374
-
1375
-static void cdns_dphy_ref_set_pll_cfg(struct cdns_dphy *dphy,
1376
- const struct cdns_dphy_cfg *cfg)
1377
-{
1378
- u32 fbdiv_low, fbdiv_high;
1379
-
1380
- fbdiv_low = (cfg->pll_fbdiv / 4) - 2;
1381
- fbdiv_high = cfg->pll_fbdiv - fbdiv_low - 2;
1382
-
1383
- writel(DPHY_CMN_IPDIV_FROM_REG | DPHY_CMN_OPDIV_FROM_REG |
1384
- DPHY_CMN_IPDIV(cfg->pll_ipdiv) |
1385
- DPHY_CMN_OPDIV(cfg->pll_opdiv),
1386
- dphy->regs + DPHY_CMN_OPIPDIV);
1387
- writel(DPHY_CMN_FBDIV_FROM_REG |
1388
- DPHY_CMN_FBDIV_VAL(fbdiv_low, fbdiv_high),
1389
- dphy->regs + DPHY_CMN_FBDIV);
1390
- writel(DPHY_CMN_PWM_HIGH(6) | DPHY_CMN_PWM_LOW(0x101) |
1391
- DPHY_CMN_PWM_DIV(0x8),
1392
- dphy->regs + DPHY_CMN_PWM);
1393
-}
1394
-
1395
-static void cdns_dphy_ref_set_psm_div(struct cdns_dphy *dphy, u8 div)
1396
-{
1397
- writel(DPHY_PSM_CFG_FROM_REG | DPHY_PSM_CLK_DIV(div),
1398
- dphy->regs + DPHY_PSM_CFG);
1399
-}
1400
-
1401
-/*
1402
- * This is the reference implementation of DPHY hooks. Specific integration of
1403
- * this IP may have to re-implement some of them depending on how they decided
1404
- * to wire things in the SoC.
1405
- */
1406
-static const struct cdns_dphy_ops ref_dphy_ops = {
1407
- .get_wakeup_time_ns = cdns_dphy_ref_get_wakeup_time_ns,
1408
- .set_pll_cfg = cdns_dphy_ref_set_pll_cfg,
1409
- .set_psm_div = cdns_dphy_ref_set_psm_div,
1410
-};
1411
-
1412
-static const struct of_device_id cdns_dphy_of_match[] = {
1413
- { .compatible = "cdns,dphy", .data = &ref_dphy_ops },
1414
- { /* sentinel */ },
1415
-};
1416
-
1417
-static struct cdns_dphy *cdns_dphy_probe(struct platform_device *pdev)
1418
-{
1419
- const struct of_device_id *match;
1420
- struct cdns_dphy *dphy;
1421
- struct of_phandle_args args;
1422
- struct resource res;
1423
- int ret;
1424
-
1425
- ret = of_parse_phandle_with_args(pdev->dev.of_node, "phys",
1426
- "#phy-cells", 0, &args);
1427
- if (ret)
1428
- return ERR_PTR(-ENOENT);
1429
-
1430
- match = of_match_node(cdns_dphy_of_match, args.np);
1431
- if (!match || !match->data)
1432
- return ERR_PTR(-EINVAL);
1433
-
1434
- dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
1435
- if (!dphy)
1436
- return ERR_PTR(-ENOMEM);
1437
-
1438
- dphy->ops = match->data;
1439
-
1440
- ret = of_address_to_resource(args.np, 0, &res);
1441
- if (ret)
1442
- return ERR_PTR(ret);
1443
-
1444
- dphy->regs = devm_ioremap_resource(&pdev->dev, &res);
1445
- if (IS_ERR(dphy->regs))
1446
- return ERR_CAST(dphy->regs);
1447
-
1448
- dphy->psm_clk = of_clk_get_by_name(args.np, "psm");
1449
- if (IS_ERR(dphy->psm_clk))
1450
- return ERR_CAST(dphy->psm_clk);
1451
-
1452
- dphy->pll_ref_clk = of_clk_get_by_name(args.np, "pll_ref");
1453
- if (IS_ERR(dphy->pll_ref_clk)) {
1454
- ret = PTR_ERR(dphy->pll_ref_clk);
1455
- goto err_put_psm_clk;
1456
- }
1457
-
1458
- if (dphy->ops->probe) {
1459
- ret = dphy->ops->probe(dphy);
1460
- if (ret)
1461
- goto err_put_pll_ref_clk;
1462
- }
1463
-
1464
- return dphy;
1465
-
1466
-err_put_pll_ref_clk:
1467
- clk_put(dphy->pll_ref_clk);
1468
-
1469
-err_put_psm_clk:
1470
- clk_put(dphy->psm_clk);
1471
-
1472
- return ERR_PTR(ret);
1473
-}
1474
-
1475
-static void cdns_dphy_remove(struct cdns_dphy *dphy)
1476
-{
1477
- if (dphy->ops->remove)
1478
- dphy->ops->remove(dphy);
1479
-
1480
- clk_put(dphy->pll_ref_clk);
1481
- clk_put(dphy->psm_clk);
1482
-}
14831169
14841170 static int cdns_dsi_drm_probe(struct platform_device *pdev)
14851171 {
....@@ -1519,13 +1205,13 @@
15191205 if (irq < 0)
15201206 return irq;
15211207
1522
- dsi->dphy = cdns_dphy_probe(pdev);
1208
+ dsi->dphy = devm_phy_get(&pdev->dev, "dphy");
15231209 if (IS_ERR(dsi->dphy))
15241210 return PTR_ERR(dsi->dphy);
15251211
15261212 ret = clk_prepare_enable(dsi->dsi_p_clk);
15271213 if (ret)
1528
- goto err_remove_dphy;
1214
+ return ret;
15291215
15301216 val = readl(dsi->regs + ID_REG);
15311217 if (REV_VENDOR_ID(val) != 0xcad) {
....@@ -1583,9 +1269,6 @@
15831269 err_disable_pclk:
15841270 clk_disable_unprepare(dsi->dsi_p_clk);
15851271
1586
-err_remove_dphy:
1587
- cdns_dphy_remove(dsi->dphy);
1588
-
15891272 return ret;
15901273 }
15911274
....@@ -1595,7 +1278,6 @@
15951278
15961279 mipi_dsi_host_unregister(&dsi->base);
15971280 pm_runtime_disable(&pdev->dev);
1598
- cdns_dphy_remove(dsi->dphy);
15991281
16001282 return 0;
16011283 }
....@@ -1604,6 +1286,7 @@
16041286 { .compatible = "cdns,dsi" },
16051287 { },
16061288 };
1289
+MODULE_DEVICE_TABLE(of, cdns_dsi_of_match);
16071290
16081291 static struct platform_driver cdns_dsi_platform_driver = {
16091292 .probe = cdns_dsi_drm_probe,