hc
2023-11-06 e3e12f52b214121840b44c91de5b3e5af5d3eb84
kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
....@@ -8,8 +8,10 @@
88 */
99
1010 #include <linux/clk.h>
11
+#include <linux/gpio/consumer.h>
1112 #include <linux/mfd/syscon.h>
1213 #include <linux/module.h>
14
+#include <linux/of_gpio.h>
1315 #include <linux/platform_device.h>
1416 #include <linux/phy/phy.h>
1517 #include <linux/regmap.h>
....@@ -57,6 +59,22 @@
5759 #define RK3399_GRF_SOC_CON20 0x6250
5860 #define RK3399_HDMI_LCDC_SEL BIT(6)
5961
62
+#define RK3528_VO_GRF_HDMI_MASK 0x60014
63
+#define RK3528_HDMI_SNKDET_SEL BIT(6)
64
+#define RK3528_HDMI_SNKDET BIT(5)
65
+#define RK3528_HDMI_CECIN_MSK BIT(2)
66
+#define RK3528_HDMI_SDAIN_MSK BIT(1)
67
+#define RK3528_HDMI_SCLIN_MSK BIT(0)
68
+
69
+#define RK3528PMU_GRF_SOC_CON6 0x70018
70
+#define RK3528_HDMI_SDA5V_GRF BIT(6)
71
+#define RK3528_HDMI_SCL5V_GRF BIT(5)
72
+#define RK3528_HDMI_CEC5V_GRF BIT(4)
73
+#define RK3528_HDMI_HPD5V_GRF BIT(3)
74
+
75
+#define RK3528_GPIO_SWPORT_DR_L 0x0000
76
+#define RK3528_GPIO0_A2_DR BIT(2)
77
+
6078 #define RK3568_GRF_VO_CON1 0x0364
6179 #define RK3568_HDMI_SDAIN_MSK BIT(15)
6280 #define RK3568_HDMI_SCLIN_MSK BIT(14)
....@@ -103,12 +121,14 @@
103121 struct rockchip_hdmi {
104122 struct device *dev;
105123 struct regmap *regmap;
124
+ void __iomem *gpio_base;
106125 struct drm_encoder encoder;
107126 const struct rockchip_hdmi_chip_data *chip_data;
108127 struct clk *phyref_clk;
109128 struct clk *grf_clk;
110129 struct clk *hclk_vio;
111130 struct clk *hclk_vop;
131
+ struct clk *dclk_vop;
112132 struct dw_hdmi *hdmi;
113133
114134 struct phy *phy;
....@@ -117,12 +137,14 @@
117137 bool unsupported_deep_color;
118138 bool skip_check_420_mode;
119139 bool mode_changed;
140
+ bool hpd_wake_en;
120141 u8 force_output;
121142 u8 id;
122143
123144 unsigned long bus_format;
124145 unsigned long output_bus_format;
125146 unsigned long enc_out_encoding;
147
+ unsigned long prev_bus_format;
126148 int color_changed;
127149
128150 struct drm_property *color_depth_property;
....@@ -143,6 +165,12 @@
143165 unsigned int phy_bus_width;
144166 enum drm_hdmi_output_type hdmi_output;
145167 struct rockchip_drm_sub_dev sub_dev;
168
+
169
+ struct gpio_desc *hpd_gpiod;
170
+ struct pinctrl *p;
171
+ struct pinctrl_state *idle_state;
172
+ struct pinctrl_state *default_state;
173
+ int hpd_irq;
146174 };
147175
148176 #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x)
....@@ -460,6 +488,37 @@
460488 { ~0UL, 0x0000, 0x0000, 0x0000},
461489 };
462490
491
+static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
492
+{
493
+ switch (bus_format) {
494
+ case MEDIA_BUS_FMT_RGB888_1X24:
495
+ case MEDIA_BUS_FMT_YUV8_1X24:
496
+ case MEDIA_BUS_FMT_UYVY8_1X16:
497
+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
498
+ return 8;
499
+
500
+ case MEDIA_BUS_FMT_RGB101010_1X30:
501
+ case MEDIA_BUS_FMT_YUV10_1X30:
502
+ case MEDIA_BUS_FMT_UYVY10_1X20:
503
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
504
+ return 10;
505
+
506
+ case MEDIA_BUS_FMT_RGB121212_1X36:
507
+ case MEDIA_BUS_FMT_YUV12_1X36:
508
+ case MEDIA_BUS_FMT_UYVY12_1X24:
509
+ case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
510
+ return 12;
511
+
512
+ case MEDIA_BUS_FMT_RGB161616_1X48:
513
+ case MEDIA_BUS_FMT_YUV16_1X48:
514
+ case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
515
+ return 16;
516
+
517
+ default:
518
+ return 0;
519
+ }
520
+}
521
+
463522 static int rockchip_hdmi_update_phy_table(struct rockchip_hdmi *hdmi,
464523 u32 *config,
465524 int phy_table_size)
....@@ -482,6 +541,55 @@
482541 }
483542
484543 return 0;
544
+}
545
+
546
+static irqreturn_t rockchip_hdmi_hpd_irq_handler(int irq, void *arg)
547
+{
548
+ u32 val;
549
+ struct rockchip_hdmi *hdmi = arg;
550
+
551
+ val = gpiod_get_value(hdmi->hpd_gpiod);
552
+ if (val) {
553
+ val = HIWORD_UPDATE(RK3528_HDMI_SNKDET, RK3528_HDMI_SNKDET);
554
+ if (hdmi->hdmi && hdmi->hpd_wake_en && hdmi->hpd_gpiod)
555
+ dw_hdmi_set_hpd_wake(hdmi->hdmi);
556
+ } else {
557
+ val = HIWORD_UPDATE(0, RK3528_HDMI_SNKDET);
558
+ }
559
+ regmap_write(hdmi->regmap, RK3528_VO_GRF_HDMI_MASK, val);
560
+
561
+ return IRQ_HANDLED;
562
+}
563
+
564
+static void dw_hdmi_rk3528_gpio_hpd_init(struct rockchip_hdmi *hdmi)
565
+{
566
+ u32 val;
567
+
568
+ if (hdmi->hpd_gpiod) {
569
+ /* gpio0_a2's input enable is controlled by gpio output data bit */
570
+ val = HIWORD_UPDATE(RK3528_GPIO0_A2_DR, RK3528_GPIO0_A2_DR);
571
+ writel(val, hdmi->gpio_base + RK3528_GPIO_SWPORT_DR_L);
572
+
573
+ val = HIWORD_UPDATE(RK3528_HDMI_SNKDET_SEL | RK3528_HDMI_SDAIN_MSK |
574
+ RK3528_HDMI_SCLIN_MSK,
575
+ RK3528_HDMI_SNKDET_SEL | RK3528_HDMI_SDAIN_MSK |
576
+ RK3528_HDMI_SCLIN_MSK);
577
+ } else {
578
+ val = HIWORD_UPDATE(RK3528_HDMI_SDAIN_MSK | RK3528_HDMI_SCLIN_MSK,
579
+ RK3528_HDMI_SDAIN_MSK | RK3528_HDMI_SCLIN_MSK);
580
+ }
581
+
582
+ regmap_write(hdmi->regmap, RK3528_VO_GRF_HDMI_MASK, val);
583
+
584
+ val = gpiod_get_value(hdmi->hpd_gpiod);
585
+ if (val) {
586
+ val = HIWORD_UPDATE(RK3528_HDMI_SNKDET, RK3528_HDMI_SNKDET);
587
+ if (hdmi->hdmi && hdmi->hpd_wake_en && hdmi->hpd_gpiod)
588
+ dw_hdmi_set_hpd_wake(hdmi->hdmi);
589
+ } else {
590
+ val = HIWORD_UPDATE(0, RK3528_HDMI_SNKDET);
591
+ }
592
+ regmap_write(hdmi->regmap, RK3528_VO_GRF_HDMI_MASK, val);
485593 }
486594
487595 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
....@@ -539,6 +647,12 @@
539647 return PTR_ERR(hdmi->hclk_vop);
540648 }
541649
650
+ hdmi->dclk_vop = devm_clk_get_optional(hdmi->dev, "dclk_vop");
651
+ if (IS_ERR(hdmi->dclk_vop)) {
652
+ dev_err(hdmi->dev, "failed to get dclk_vop\n");
653
+ return PTR_ERR(hdmi->dclk_vop);
654
+ }
655
+
542656 ret = of_property_read_u32(np, "max-tmdsclk",
543657 &hdmi->max_tmdsclk);
544658 if (ret != -EINVAL && ret < 0) {
....@@ -576,6 +690,70 @@
576690 kfree(phy_config);
577691 } else {
578692 dev_dbg(hdmi->dev, "use default hdmi phy table\n");
693
+ }
694
+
695
+ hdmi->hpd_gpiod = devm_gpiod_get_optional(hdmi->dev, "hpd", GPIOD_IN);
696
+
697
+ if (IS_ERR(hdmi->hpd_gpiod)) {
698
+ dev_err(hdmi->dev, "error getting HDP GPIO: %ld\n",
699
+ PTR_ERR(hdmi->hpd_gpiod));
700
+ return PTR_ERR(hdmi->hpd_gpiod);
701
+ }
702
+
703
+ if (hdmi->hpd_gpiod) {
704
+ struct resource *res;
705
+ struct platform_device *pdev = to_platform_device(hdmi->dev);
706
+
707
+ /* gpio interrupt reflects hpd status */
708
+ hdmi->hpd_irq = gpiod_to_irq(hdmi->hpd_gpiod);
709
+ if (hdmi->hpd_irq < 0)
710
+ return -EINVAL;
711
+
712
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
713
+ if (!res) {
714
+ DRM_DEV_ERROR(hdmi->dev, "failed to get gpio regs\n");
715
+ return -EINVAL;
716
+ }
717
+
718
+ hdmi->gpio_base = devm_ioremap(hdmi->dev, res->start, resource_size(res));
719
+ if (IS_ERR(hdmi->gpio_base)) {
720
+ DRM_DEV_ERROR(hdmi->dev, "Unable to get gpio ioregmap\n");
721
+ return PTR_ERR(hdmi->gpio_base);
722
+ }
723
+
724
+ dw_hdmi_rk3528_gpio_hpd_init(hdmi);
725
+ ret = devm_request_threaded_irq(hdmi->dev, hdmi->hpd_irq, NULL,
726
+ rockchip_hdmi_hpd_irq_handler,
727
+ IRQF_TRIGGER_RISING |
728
+ IRQF_TRIGGER_FALLING |
729
+ IRQF_ONESHOT,
730
+ "hdmi-hpd", hdmi);
731
+ if (ret) {
732
+ dev_err(hdmi->dev, "failed to request hpd IRQ: %d\n", ret);
733
+ return ret;
734
+ }
735
+
736
+ hdmi->hpd_wake_en = device_property_read_bool(hdmi->dev, "hpd-wake-up");
737
+ if (hdmi->hpd_wake_en)
738
+ enable_irq_wake(hdmi->hpd_irq);
739
+ }
740
+
741
+ hdmi->p = devm_pinctrl_get(hdmi->dev);
742
+ if (IS_ERR(hdmi->p)) {
743
+ dev_err(hdmi->dev, "could not get pinctrl\n");
744
+ return PTR_ERR(hdmi->p);
745
+ }
746
+
747
+ hdmi->idle_state = pinctrl_lookup_state(hdmi->p, "idle");
748
+ if (IS_ERR(hdmi->idle_state)) {
749
+ dev_dbg(hdmi->dev, "idle state is not defined\n");
750
+ return 0;
751
+ }
752
+
753
+ hdmi->default_state = pinctrl_lookup_state(hdmi->p, "default");
754
+ if (IS_ERR(hdmi->default_state)) {
755
+ dev_err(hdmi->dev, "could not find default state\n");
756
+ return PTR_ERR(hdmi->default_state);
579757 }
580758
581759 return 0;
....@@ -670,6 +848,9 @@
670848 struct drm_crtc *crtc = encoder->crtc;
671849 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
672850
851
+ if (WARN_ON(!crtc || !crtc->state))
852
+ return;
853
+
673854 if (!hdmi->mode_changed)
674855 s->output_if &= ~VOP_OUTPUT_IF_HDMI0;
675856 /*
....@@ -754,6 +935,7 @@
754935 unsigned int color_depth;
755936 bool support_dc = false;
756937 bool sink_is_hdmi = dw_hdmi_get_output_whether_hdmi(hdmi->hdmi);
938
+ bool yuv422_out = false;
757939 int max_tmds_clock = info->max_tmds_clock;
758940 int output_eotf;
759941
....@@ -829,22 +1011,27 @@
8291011 *eotf = output_eotf;
8301012 }
8311013
832
- if ((*eotf > TRADITIONAL_GAMMA_HDR &&
833
- conn_state->connector->hdr_sink_metadata.hdmi_type1.eotf &
834
- BIT(*eotf)) || (hdmi->colorimetry ==
835
- RK_HDMI_COLORIMETRY_BT2020 && info->hdmi.colorimetry &
836
- (BIT(6) | BIT(7))))
1014
+ /* bt2020 sdr/hdr output */
1015
+ if (hdmi->colorimetry == RK_HDMI_COLORIMETRY_BT2020 &&
1016
+ info->hdmi.colorimetry & (BIT(6) | BIT(7))) {
8371017 *enc_out_encoding = V4L2_YCBCR_ENC_BT2020;
838
- else if ((vic == 6) || (vic == 7) || (vic == 21) || (vic == 22) ||
839
- (vic == 2) || (vic == 3) || (vic == 17) || (vic == 18))
840
- *enc_out_encoding = V4L2_YCBCR_ENC_601;
841
- else
1018
+ yuv422_out = true;
1019
+ /* bt709 hdr output */
1020
+ } else if (hdmi->colorimetry != RK_HDMI_COLORIMETRY_BT2020 &&
1021
+ (conn_state->connector->hdr_sink_metadata.hdmi_type1.eotf & BIT(*eotf) &&
1022
+ *eotf > TRADITIONAL_GAMMA_HDR)) {
8421023 *enc_out_encoding = V4L2_YCBCR_ENC_709;
1024
+ yuv422_out = true;
1025
+ } else if ((vic == 6) || (vic == 7) || (vic == 21) || (vic == 22) ||
1026
+ (vic == 2) || (vic == 3) || (vic == 17) || (vic == 18)) {
1027
+ *enc_out_encoding = V4L2_YCBCR_ENC_601;
1028
+ } else {
1029
+ *enc_out_encoding = V4L2_YCBCR_ENC_709;
1030
+ }
8431031
844
- if (*enc_out_encoding == V4L2_YCBCR_ENC_BT2020) {
845
- /* BT2020 require color depth at lest 10bit */
846
- color_depth = 10;
847
- /* We prefer use YCbCr422 to send 10bit */
1032
+ if ((yuv422_out || hdmi->hdmi_output == DRM_HDMI_OUTPUT_YCBCR_HQ) &&
1033
+ color_depth == 10 && hdmi_bus_fmt_color_depth(hdmi->prev_bus_format) == 8) {
1034
+ /* We prefer use YCbCr422 to send hdr 10bit */
8481035 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
8491036 *color_format = DRM_HDMI_OUTPUT_YCBCR422;
8501037 }
....@@ -1063,6 +1250,14 @@
10631250 return hdmi->hdr_panel_blob_ptr;
10641251 }
10651252
1253
+static void dw_hdmi_rockchip_update_color_format(struct drm_connector_state *conn_state,
1254
+ void *data)
1255
+{
1256
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1257
+
1258
+ dw_hdmi_rockchip_check_color(conn_state, hdmi);
1259
+}
1260
+
10661261 static bool
10671262 dw_hdmi_rockchip_get_color_changed(void *data)
10681263 {
....@@ -1072,6 +1267,63 @@
10721267 if (hdmi->color_changed)
10731268 ret = true;
10741269 hdmi->color_changed = 0;
1270
+
1271
+ return ret;
1272
+}
1273
+
1274
+static bool
1275
+dw_hdmi_rockchip_check_hdr_color_change(struct drm_connector_state *conn_state,
1276
+ void *data)
1277
+{
1278
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1279
+
1280
+ if (!conn_state || !data)
1281
+ return false;
1282
+
1283
+ if (dw_hdmi_rockchip_check_color(conn_state, hdmi))
1284
+ return true;
1285
+
1286
+ return false;
1287
+}
1288
+
1289
+static void dw_hdmi_rockchip_set_prev_bus_format(void *data, unsigned long bus_format)
1290
+{
1291
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1292
+
1293
+ hdmi->prev_bus_format = bus_format;
1294
+}
1295
+
1296
+static void dw_hdmi_rockchip_set_ddc_io(void *data, bool enable)
1297
+{
1298
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1299
+
1300
+ if (!hdmi->p || !hdmi->idle_state || !hdmi->default_state)
1301
+ return;
1302
+
1303
+ if (!enable) {
1304
+ if (pinctrl_select_state(hdmi->p, hdmi->idle_state))
1305
+ dev_err(hdmi->dev, "could not select idle state\n");
1306
+ } else {
1307
+ if (pinctrl_select_state(hdmi->p, hdmi->default_state))
1308
+ dev_err(hdmi->dev, "could not select default state\n");
1309
+ }
1310
+}
1311
+
1312
+static int dw_hdmi_rockchip_dclk_set(void *data, bool enable, int vp_id)
1313
+{
1314
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1315
+ int ret = 0;
1316
+
1317
+ if (!hdmi->dclk_vop)
1318
+ return 0;
1319
+
1320
+ if (enable) {
1321
+ ret = clk_prepare_enable(hdmi->dclk_vop);
1322
+ if (ret < 0)
1323
+ dev_err(hdmi->dev, "failed to enable dclk_vop\n");
1324
+ } else {
1325
+ clk_disable_unprepare(hdmi->dclk_vop);
1326
+ }
10751327
10761328 return ret;
10771329 }
....@@ -1158,6 +1410,7 @@
11581410 }
11591411
11601412 hdmi->bus_format = color;
1413
+ hdmi->prev_bus_format = color;
11611414
11621415 if (hdmi->hdmi_output == DRM_HDMI_OUTPUT_YCBCR422) {
11631416 if (hdmi->colordepth == 12)
....@@ -1581,6 +1834,20 @@
15811834 .setup_hpd = dw_hdmi_rk3328_setup_hpd,
15821835 };
15831836
1837
+static enum drm_connector_status
1838
+dw_hdmi_rk3528_read_hpd(struct dw_hdmi *dw_hdmi, void *data)
1839
+{
1840
+ return dw_hdmi_phy_read_hpd(dw_hdmi, data);
1841
+}
1842
+
1843
+static const struct dw_hdmi_phy_ops rk3528_hdmi_phy_ops = {
1844
+ .init = dw_hdmi_rockchip_genphy_init,
1845
+ .disable = dw_hdmi_rockchip_genphy_disable,
1846
+ .read_hpd = dw_hdmi_rk3528_read_hpd,
1847
+ .update_hpd = dw_hdmi_phy_update_hpd,
1848
+ .setup_hpd = dw_hdmi_phy_setup_hpd,
1849
+};
1850
+
15841851 static struct rockchip_hdmi_chip_data rk3328_chip_data = {
15851852 .lcdsel_grf_reg = -1,
15861853 };
....@@ -1627,6 +1894,22 @@
16271894 .ycbcr_420_allowed = true,
16281895 };
16291896
1897
+static struct rockchip_hdmi_chip_data rk3528_chip_data = {
1898
+ .lcdsel_grf_reg = -1,
1899
+};
1900
+
1901
+static const struct dw_hdmi_plat_data rk3528_hdmi_drv_data = {
1902
+ .mode_valid = dw_hdmi_rockchip_mode_valid,
1903
+ .mpll_cfg = rockchip_mpll_cfg,
1904
+ .cur_ctr = rockchip_cur_ctr,
1905
+ .phy_config = rockchip_phy_config,
1906
+ .phy_data = &rk3528_chip_data,
1907
+ .phy_ops = &rk3528_hdmi_phy_ops,
1908
+ .phy_name = "inno_dw_hdmi_phy2",
1909
+ .phy_force_vendor = true,
1910
+ .ycbcr_420_allowed = true,
1911
+};
1912
+
16301913 static struct rockchip_hdmi_chip_data rk3568_chip_data = {
16311914 .lcdsel_grf_reg = -1,
16321915 .ddc_en_reg = RK3568_GRF_VO_CON1,
....@@ -1658,6 +1941,9 @@
16581941 },
16591942 { .compatible = "rockchip,rk3399-dw-hdmi",
16601943 .data = &rk3399_hdmi_drv_data
1944
+ },
1945
+ { .compatible = "rockchip,rk3528-dw-hdmi",
1946
+ .data = &rk3528_hdmi_drv_data
16611947 },
16621948 { .compatible = "rockchip,rk3568-dw-hdmi",
16631949 .data = &rk3568_hdmi_drv_data
....@@ -1713,6 +1999,16 @@
17131999 dw_hdmi_rockchip_get_hdr_blob;
17142000 plat_data->get_color_changed =
17152001 dw_hdmi_rockchip_get_color_changed;
2002
+ plat_data->update_color_format =
2003
+ dw_hdmi_rockchip_update_color_format;
2004
+ plat_data->check_hdr_color_change =
2005
+ dw_hdmi_rockchip_check_hdr_color_change;
2006
+ plat_data->set_prev_bus_format =
2007
+ dw_hdmi_rockchip_set_prev_bus_format;
2008
+ plat_data->set_ddc_io =
2009
+ dw_hdmi_rockchip_set_ddc_io;
2010
+ plat_data->dclk_set =
2011
+ dw_hdmi_rockchip_dclk_set;
17162012 plat_data->property_ops = &dw_hdmi_rockchip_property_ops;
17172013
17182014 encoder = &hdmi->encoder;
....@@ -1780,7 +2076,6 @@
17802076 platform_set_drvdata(pdev, hdmi);
17812077
17822078 hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
1783
-
17842079 /*
17852080 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
17862081 * which would have called the encoder cleanup. Do it manually.
....@@ -1833,6 +2128,11 @@
18332128 if (!hdmi)
18342129 return;
18352130
2131
+ if (hdmi->hpd_gpiod) {
2132
+ disable_irq(hdmi->hpd_irq);
2133
+ if (hdmi->hpd_wake_en)
2134
+ disable_irq_wake(hdmi->hpd_irq);
2135
+ }
18362136 dw_hdmi_suspend(&pdev->dev, hdmi->hdmi);
18372137 pm_runtime_put_sync(&pdev->dev);
18382138 }
....@@ -1849,6 +2149,8 @@
18492149 {
18502150 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
18512151
2152
+ if (hdmi->hpd_gpiod)
2153
+ disable_irq(hdmi->hpd_irq);
18522154 dw_hdmi_suspend(dev, hdmi->hdmi);
18532155 pm_runtime_put_sync(dev);
18542156
....@@ -1859,6 +2161,10 @@
18592161 {
18602162 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
18612163
2164
+ if (hdmi->hpd_gpiod) {
2165
+ dw_hdmi_rk3528_gpio_hpd_init(hdmi);
2166
+ enable_irq(hdmi->hpd_irq);
2167
+ }
18622168 pm_runtime_get_sync(dev);
18632169 dw_hdmi_resume(dev, hdmi->hdmi);
18642170