forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
....@@ -5,6 +5,7 @@
55
66 #include <linux/delay.h>
77 #include <linux/of_address.h>
8
+#include <linux/of_platform.h>
89
910 #include "sun8i_dw_hdmi.h"
1011
....@@ -13,6 +14,114 @@
1314 * it is set in BSP driver.
1415 */
1516 #define I2C_ADDR 0x69
17
+
18
+static const struct dw_hdmi_mpll_config sun50i_h6_mpll_cfg[] = {
19
+ {
20
+ 30666000, {
21
+ { 0x00b3, 0x0000 },
22
+ { 0x2153, 0x0000 },
23
+ { 0x40f3, 0x0000 },
24
+ },
25
+ }, {
26
+ 36800000, {
27
+ { 0x00b3, 0x0000 },
28
+ { 0x2153, 0x0000 },
29
+ { 0x40a2, 0x0001 },
30
+ },
31
+ }, {
32
+ 46000000, {
33
+ { 0x00b3, 0x0000 },
34
+ { 0x2142, 0x0001 },
35
+ { 0x40a2, 0x0001 },
36
+ },
37
+ }, {
38
+ 61333000, {
39
+ { 0x0072, 0x0001 },
40
+ { 0x2142, 0x0001 },
41
+ { 0x40a2, 0x0001 },
42
+ },
43
+ }, {
44
+ 73600000, {
45
+ { 0x0072, 0x0001 },
46
+ { 0x2142, 0x0001 },
47
+ { 0x4061, 0x0002 },
48
+ },
49
+ }, {
50
+ 92000000, {
51
+ { 0x0072, 0x0001 },
52
+ { 0x2145, 0x0002 },
53
+ { 0x4061, 0x0002 },
54
+ },
55
+ }, {
56
+ 122666000, {
57
+ { 0x0051, 0x0002 },
58
+ { 0x2145, 0x0002 },
59
+ { 0x4061, 0x0002 },
60
+ },
61
+ }, {
62
+ 147200000, {
63
+ { 0x0051, 0x0002 },
64
+ { 0x2145, 0x0002 },
65
+ { 0x4064, 0x0003 },
66
+ },
67
+ }, {
68
+ 184000000, {
69
+ { 0x0051, 0x0002 },
70
+ { 0x214c, 0x0003 },
71
+ { 0x4064, 0x0003 },
72
+ },
73
+ }, {
74
+ 226666000, {
75
+ { 0x0040, 0x0003 },
76
+ { 0x214c, 0x0003 },
77
+ { 0x4064, 0x0003 },
78
+ },
79
+ }, {
80
+ 272000000, {
81
+ { 0x0040, 0x0003 },
82
+ { 0x214c, 0x0003 },
83
+ { 0x5a64, 0x0003 },
84
+ },
85
+ }, {
86
+ 340000000, {
87
+ { 0x0040, 0x0003 },
88
+ { 0x3b4c, 0x0003 },
89
+ { 0x5a64, 0x0003 },
90
+ },
91
+ }, {
92
+ 594000000, {
93
+ { 0x1a40, 0x0003 },
94
+ { 0x3b4c, 0x0003 },
95
+ { 0x5a64, 0x0003 },
96
+ },
97
+ }, {
98
+ ~0UL, {
99
+ { 0x0000, 0x0000 },
100
+ { 0x0000, 0x0000 },
101
+ { 0x0000, 0x0000 },
102
+ },
103
+ }
104
+};
105
+
106
+static const struct dw_hdmi_curr_ctrl sun50i_h6_cur_ctr[] = {
107
+ /* pixelclk bpp8 bpp10 bpp12 */
108
+ { 27000000, { 0x0012, 0x0000, 0x0000 }, },
109
+ { 74250000, { 0x0013, 0x001a, 0x001b }, },
110
+ { 148500000, { 0x0019, 0x0033, 0x0034 }, },
111
+ { 297000000, { 0x0019, 0x001b, 0x001b }, },
112
+ { 594000000, { 0x0010, 0x001b, 0x001b }, },
113
+ { ~0UL, { 0x0000, 0x0000, 0x0000 }, }
114
+};
115
+
116
+static const struct dw_hdmi_phy_config sun50i_h6_phy_config[] = {
117
+ /*pixelclk symbol term vlev*/
118
+ { 27000000, 0x8009, 0x0007, 0x02b0 },
119
+ { 74250000, 0x8009, 0x0006, 0x022d },
120
+ { 148500000, 0x8029, 0x0006, 0x0270 },
121
+ { 297000000, 0x8039, 0x0005, 0x01ab },
122
+ { 594000000, 0x8029, 0x0000, 0x008a },
123
+ { ~0UL, 0x0000, 0x0000, 0x0000}
124
+};
16125
17126 static int sun8i_hdmi_phy_config_a83t(struct dw_hdmi *hdmi,
18127 struct sun8i_hdmi_phy *phy,
....@@ -225,7 +334,8 @@
225334 }
226335
227336 static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
228
- struct drm_display_mode *mode)
337
+ const struct drm_display_info *display,
338
+ const struct drm_display_mode *mode)
229339 {
230340 struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data;
231341 u32 val = 0;
....@@ -280,8 +390,31 @@
280390 .setup_hpd = &dw_hdmi_phy_setup_hpd,
281391 };
282392
393
+static void sun8i_hdmi_phy_unlock(struct sun8i_hdmi_phy *phy)
394
+{
395
+ /* enable read access to HDMI controller */
396
+ regmap_write(phy->regs, SUN8I_HDMI_PHY_READ_EN_REG,
397
+ SUN8I_HDMI_PHY_READ_EN_MAGIC);
398
+
399
+ /* unscramble register offsets */
400
+ regmap_write(phy->regs, SUN8I_HDMI_PHY_UNSCRAMBLE_REG,
401
+ SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC);
402
+}
403
+
404
+static void sun50i_hdmi_phy_init_h6(struct sun8i_hdmi_phy *phy)
405
+{
406
+ regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG,
407
+ SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN,
408
+ SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN);
409
+
410
+ regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG,
411
+ 0xffff0000, 0x80c00000);
412
+}
413
+
283414 static void sun8i_hdmi_phy_init_a83t(struct sun8i_hdmi_phy *phy)
284415 {
416
+ sun8i_hdmi_phy_unlock(phy);
417
+
285418 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
286419 SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK,
287420 SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK);
....@@ -298,6 +431,8 @@
298431 static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy *phy)
299432 {
300433 unsigned int val;
434
+
435
+ sun8i_hdmi_phy_unlock(phy);
301436
302437 regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 0);
303438 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
....@@ -371,25 +506,79 @@
371506 phy->rcal = (val & SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK) >> 2;
372507 }
373508
374
-void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy)
509
+int sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy)
375510 {
376
- /* enable read access to HDMI controller */
377
- regmap_write(phy->regs, SUN8I_HDMI_PHY_READ_EN_REG,
378
- SUN8I_HDMI_PHY_READ_EN_MAGIC);
511
+ int ret;
379512
380
- /* unscramble register offsets */
381
- regmap_write(phy->regs, SUN8I_HDMI_PHY_UNSCRAMBLE_REG,
382
- SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC);
513
+ ret = reset_control_deassert(phy->rst_phy);
514
+ if (ret) {
515
+ dev_err(phy->dev, "Cannot deassert phy reset control: %d\n", ret);
516
+ return ret;
517
+ }
518
+
519
+ ret = clk_prepare_enable(phy->clk_bus);
520
+ if (ret) {
521
+ dev_err(phy->dev, "Cannot enable bus clock: %d\n", ret);
522
+ goto err_assert_rst_phy;
523
+ }
524
+
525
+ ret = clk_prepare_enable(phy->clk_mod);
526
+ if (ret) {
527
+ dev_err(phy->dev, "Cannot enable mod clock: %d\n", ret);
528
+ goto err_disable_clk_bus;
529
+ }
530
+
531
+ if (phy->variant->has_phy_clk) {
532
+ ret = sun8i_phy_clk_create(phy, phy->dev,
533
+ phy->variant->has_second_pll);
534
+ if (ret) {
535
+ dev_err(phy->dev, "Couldn't create the PHY clock\n");
536
+ goto err_disable_clk_mod;
537
+ }
538
+
539
+ clk_prepare_enable(phy->clk_phy);
540
+ }
383541
384542 phy->variant->phy_init(phy);
543
+
544
+ return 0;
545
+
546
+err_disable_clk_mod:
547
+ clk_disable_unprepare(phy->clk_mod);
548
+err_disable_clk_bus:
549
+ clk_disable_unprepare(phy->clk_bus);
550
+err_assert_rst_phy:
551
+ reset_control_assert(phy->rst_phy);
552
+
553
+ return ret;
385554 }
386555
387
-const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void)
556
+void sun8i_hdmi_phy_deinit(struct sun8i_hdmi_phy *phy)
388557 {
389
- return &sun8i_hdmi_phy_ops;
558
+ clk_disable_unprepare(phy->clk_mod);
559
+ clk_disable_unprepare(phy->clk_bus);
560
+ clk_disable_unprepare(phy->clk_phy);
561
+
562
+ reset_control_assert(phy->rst_phy);
390563 }
391564
392
-static struct regmap_config sun8i_hdmi_phy_regmap_config = {
565
+void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy,
566
+ struct dw_hdmi_plat_data *plat_data)
567
+{
568
+ struct sun8i_hdmi_phy_variant *variant = phy->variant;
569
+
570
+ if (variant->is_custom_phy) {
571
+ plat_data->phy_ops = &sun8i_hdmi_phy_ops;
572
+ plat_data->phy_name = "sun8i_dw_hdmi_phy";
573
+ plat_data->phy_data = phy;
574
+ } else {
575
+ plat_data->mpll_cfg = variant->mpll_cfg;
576
+ plat_data->cur_ctr = variant->cur_ctr;
577
+ plat_data->phy_config = variant->phy_cfg;
578
+ }
579
+}
580
+
581
+static const struct regmap_config sun8i_hdmi_phy_regmap_config = {
393582 .reg_bits = 32,
394583 .val_bits = 32,
395584 .reg_stride = 4,
....@@ -397,14 +586,8 @@
397586 .name = "phy"
398587 };
399588
400
-static const struct sun8i_hdmi_phy_variant sun50i_a64_hdmi_phy = {
401
- .has_phy_clk = true,
402
- .phy_init = &sun8i_hdmi_phy_init_h3,
403
- .phy_disable = &sun8i_hdmi_phy_disable_h3,
404
- .phy_config = &sun8i_hdmi_phy_config_h3,
405
-};
406
-
407589 static const struct sun8i_hdmi_phy_variant sun8i_a83t_hdmi_phy = {
590
+ .is_custom_phy = true,
408591 .phy_init = &sun8i_hdmi_phy_init_a83t,
409592 .phy_disable = &sun8i_hdmi_phy_disable_a83t,
410593 .phy_config = &sun8i_hdmi_phy_config_a83t,
....@@ -412,16 +595,37 @@
412595
413596 static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
414597 .has_phy_clk = true,
598
+ .is_custom_phy = true,
415599 .phy_init = &sun8i_hdmi_phy_init_h3,
416600 .phy_disable = &sun8i_hdmi_phy_disable_h3,
417601 .phy_config = &sun8i_hdmi_phy_config_h3,
418602 };
419603
604
+static const struct sun8i_hdmi_phy_variant sun8i_r40_hdmi_phy = {
605
+ .has_phy_clk = true,
606
+ .has_second_pll = true,
607
+ .is_custom_phy = true,
608
+ .phy_init = &sun8i_hdmi_phy_init_h3,
609
+ .phy_disable = &sun8i_hdmi_phy_disable_h3,
610
+ .phy_config = &sun8i_hdmi_phy_config_h3,
611
+};
612
+
613
+static const struct sun8i_hdmi_phy_variant sun50i_a64_hdmi_phy = {
614
+ .has_phy_clk = true,
615
+ .is_custom_phy = true,
616
+ .phy_init = &sun8i_hdmi_phy_init_h3,
617
+ .phy_disable = &sun8i_hdmi_phy_disable_h3,
618
+ .phy_config = &sun8i_hdmi_phy_config_h3,
619
+};
620
+
621
+static const struct sun8i_hdmi_phy_variant sun50i_h6_hdmi_phy = {
622
+ .cur_ctr = sun50i_h6_cur_ctr,
623
+ .mpll_cfg = sun50i_h6_mpll_cfg,
624
+ .phy_cfg = sun50i_h6_phy_config,
625
+ .phy_init = &sun50i_hdmi_phy_init_h6,
626
+};
627
+
420628 static const struct of_device_id sun8i_hdmi_phy_of_table[] = {
421
- {
422
- .compatible = "allwinner,sun50i-a64-hdmi-phy",
423
- .data = &sun50i_a64_hdmi_phy,
424
- },
425629 {
426630 .compatible = "allwinner,sun8i-a83t-hdmi-phy",
427631 .data = &sun8i_a83t_hdmi_phy,
....@@ -430,13 +634,45 @@
430634 .compatible = "allwinner,sun8i-h3-hdmi-phy",
431635 .data = &sun8i_h3_hdmi_phy,
432636 },
637
+ {
638
+ .compatible = "allwinner,sun8i-r40-hdmi-phy",
639
+ .data = &sun8i_r40_hdmi_phy,
640
+ },
641
+ {
642
+ .compatible = "allwinner,sun50i-a64-hdmi-phy",
643
+ .data = &sun50i_a64_hdmi_phy,
644
+ },
645
+ {
646
+ .compatible = "allwinner,sun50i-h6-hdmi-phy",
647
+ .data = &sun50i_h6_hdmi_phy,
648
+ },
433649 { /* sentinel */ }
434650 };
435651
436
-int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
652
+int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
653
+{
654
+ struct platform_device *pdev = of_find_device_by_node(node);
655
+ struct sun8i_hdmi_phy *phy;
656
+
657
+ if (!pdev)
658
+ return -EPROBE_DEFER;
659
+
660
+ phy = platform_get_drvdata(pdev);
661
+ if (!phy)
662
+ return -EPROBE_DEFER;
663
+
664
+ hdmi->phy = phy;
665
+
666
+ put_device(&pdev->dev);
667
+
668
+ return 0;
669
+}
670
+
671
+static int sun8i_hdmi_phy_probe(struct platform_device *pdev)
437672 {
438673 const struct of_device_id *match;
439
- struct device *dev = hdmi->dev;
674
+ struct device *dev = &pdev->dev;
675
+ struct device_node *node = dev->of_node;
440676 struct sun8i_hdmi_phy *phy;
441677 struct resource res;
442678 void __iomem *regs;
....@@ -453,6 +689,7 @@
453689 return -ENOMEM;
454690
455691 phy->variant = (struct sun8i_hdmi_phy_variant *)match->data;
692
+ phy->dev = dev;
456693
457694 ret = of_address_to_resource(node, 0, &res);
458695 if (ret) {
....@@ -511,47 +748,10 @@
511748 goto err_put_clk_pll1;
512749 }
513750
514
- ret = reset_control_deassert(phy->rst_phy);
515
- if (ret) {
516
- dev_err(dev, "Cannot deassert phy reset control: %d\n", ret);
517
- goto err_put_rst_phy;
518
- }
519
-
520
- ret = clk_prepare_enable(phy->clk_bus);
521
- if (ret) {
522
- dev_err(dev, "Cannot enable bus clock: %d\n", ret);
523
- goto err_deassert_rst_phy;
524
- }
525
-
526
- ret = clk_prepare_enable(phy->clk_mod);
527
- if (ret) {
528
- dev_err(dev, "Cannot enable mod clock: %d\n", ret);
529
- goto err_disable_clk_bus;
530
- }
531
-
532
- if (phy->variant->has_phy_clk) {
533
- ret = sun8i_phy_clk_create(phy, dev,
534
- phy->variant->has_second_pll);
535
- if (ret) {
536
- dev_err(dev, "Couldn't create the PHY clock\n");
537
- goto err_disable_clk_mod;
538
- }
539
-
540
- clk_prepare_enable(phy->clk_phy);
541
- }
542
-
543
- hdmi->phy = phy;
751
+ platform_set_drvdata(pdev, phy);
544752
545753 return 0;
546754
547
-err_disable_clk_mod:
548
- clk_disable_unprepare(phy->clk_mod);
549
-err_disable_clk_bus:
550
- clk_disable_unprepare(phy->clk_bus);
551
-err_deassert_rst_phy:
552
- reset_control_assert(phy->rst_phy);
553
-err_put_rst_phy:
554
- reset_control_put(phy->rst_phy);
555755 err_put_clk_pll1:
556756 clk_put(phy->clk_pll1);
557757 err_put_clk_pll0:
....@@ -564,15 +764,9 @@
564764 return ret;
565765 }
566766
567
-void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi)
767
+static int sun8i_hdmi_phy_remove(struct platform_device *pdev)
568768 {
569
- struct sun8i_hdmi_phy *phy = hdmi->phy;
570
-
571
- clk_disable_unprepare(phy->clk_mod);
572
- clk_disable_unprepare(phy->clk_bus);
573
- clk_disable_unprepare(phy->clk_phy);
574
-
575
- reset_control_assert(phy->rst_phy);
769
+ struct sun8i_hdmi_phy *phy = platform_get_drvdata(pdev);
576770
577771 reset_control_put(phy->rst_phy);
578772
....@@ -580,4 +774,14 @@
580774 clk_put(phy->clk_pll1);
581775 clk_put(phy->clk_mod);
582776 clk_put(phy->clk_bus);
777
+ return 0;
583778 }
779
+
780
+struct platform_driver sun8i_hdmi_phy_driver = {
781
+ .probe = sun8i_hdmi_phy_probe,
782
+ .remove = sun8i_hdmi_phy_remove,
783
+ .driver = {
784
+ .name = "sun8i-hdmi-phy",
785
+ .of_match_table = sun8i_hdmi_phy_of_table,
786
+ },
787
+};