.. | .. |
---|
8 | 8 | */ |
---|
9 | 9 | |
---|
10 | 10 | #include <linux/clk.h> |
---|
| 11 | +#include <linux/gpio/consumer.h> |
---|
11 | 12 | #include <linux/mfd/syscon.h> |
---|
12 | 13 | #include <linux/module.h> |
---|
| 14 | +#include <linux/of_gpio.h> |
---|
13 | 15 | #include <linux/platform_device.h> |
---|
14 | 16 | #include <linux/phy/phy.h> |
---|
15 | 17 | #include <linux/regmap.h> |
---|
.. | .. |
---|
57 | 59 | #define RK3399_GRF_SOC_CON20 0x6250 |
---|
58 | 60 | #define RK3399_HDMI_LCDC_SEL BIT(6) |
---|
59 | 61 | |
---|
| 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 | + |
---|
60 | 78 | #define RK3568_GRF_VO_CON1 0x0364 |
---|
61 | 79 | #define RK3568_HDMI_SDAIN_MSK BIT(15) |
---|
62 | 80 | #define RK3568_HDMI_SCLIN_MSK BIT(14) |
---|
.. | .. |
---|
103 | 121 | struct rockchip_hdmi { |
---|
104 | 122 | struct device *dev; |
---|
105 | 123 | struct regmap *regmap; |
---|
| 124 | + void __iomem *gpio_base; |
---|
106 | 125 | struct drm_encoder encoder; |
---|
107 | 126 | const struct rockchip_hdmi_chip_data *chip_data; |
---|
108 | 127 | struct clk *phyref_clk; |
---|
109 | 128 | struct clk *grf_clk; |
---|
110 | 129 | struct clk *hclk_vio; |
---|
111 | 130 | struct clk *hclk_vop; |
---|
| 131 | + struct clk *dclk_vop; |
---|
112 | 132 | struct dw_hdmi *hdmi; |
---|
113 | 133 | |
---|
114 | 134 | struct phy *phy; |
---|
.. | .. |
---|
117 | 137 | bool unsupported_deep_color; |
---|
118 | 138 | bool skip_check_420_mode; |
---|
119 | 139 | bool mode_changed; |
---|
| 140 | + bool hpd_wake_en; |
---|
120 | 141 | u8 force_output; |
---|
121 | 142 | u8 id; |
---|
122 | 143 | |
---|
123 | 144 | unsigned long bus_format; |
---|
124 | 145 | unsigned long output_bus_format; |
---|
125 | 146 | unsigned long enc_out_encoding; |
---|
| 147 | + unsigned long prev_bus_format; |
---|
126 | 148 | int color_changed; |
---|
127 | 149 | |
---|
128 | 150 | struct drm_property *color_depth_property; |
---|
.. | .. |
---|
143 | 165 | unsigned int phy_bus_width; |
---|
144 | 166 | enum drm_hdmi_output_type hdmi_output; |
---|
145 | 167 | 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; |
---|
146 | 174 | }; |
---|
147 | 175 | |
---|
148 | 176 | #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) |
---|
.. | .. |
---|
460 | 488 | { ~0UL, 0x0000, 0x0000, 0x0000}, |
---|
461 | 489 | }; |
---|
462 | 490 | |
---|
| 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 | + |
---|
463 | 522 | static int rockchip_hdmi_update_phy_table(struct rockchip_hdmi *hdmi, |
---|
464 | 523 | u32 *config, |
---|
465 | 524 | int phy_table_size) |
---|
.. | .. |
---|
482 | 541 | } |
---|
483 | 542 | |
---|
484 | 543 | 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); |
---|
485 | 593 | } |
---|
486 | 594 | |
---|
487 | 595 | static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) |
---|
.. | .. |
---|
539 | 647 | return PTR_ERR(hdmi->hclk_vop); |
---|
540 | 648 | } |
---|
541 | 649 | |
---|
| 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 | + |
---|
542 | 656 | ret = of_property_read_u32(np, "max-tmdsclk", |
---|
543 | 657 | &hdmi->max_tmdsclk); |
---|
544 | 658 | if (ret != -EINVAL && ret < 0) { |
---|
.. | .. |
---|
576 | 690 | kfree(phy_config); |
---|
577 | 691 | } else { |
---|
578 | 692 | 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); |
---|
579 | 757 | } |
---|
580 | 758 | |
---|
581 | 759 | return 0; |
---|
.. | .. |
---|
670 | 848 | struct drm_crtc *crtc = encoder->crtc; |
---|
671 | 849 | struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); |
---|
672 | 850 | |
---|
| 851 | + if (WARN_ON(!crtc || !crtc->state)) |
---|
| 852 | + return; |
---|
| 853 | + |
---|
673 | 854 | if (!hdmi->mode_changed) |
---|
674 | 855 | s->output_if &= ~VOP_OUTPUT_IF_HDMI0; |
---|
675 | 856 | /* |
---|
.. | .. |
---|
754 | 935 | unsigned int color_depth; |
---|
755 | 936 | bool support_dc = false; |
---|
756 | 937 | bool sink_is_hdmi = dw_hdmi_get_output_whether_hdmi(hdmi->hdmi); |
---|
| 938 | + bool yuv422_out = false; |
---|
757 | 939 | int max_tmds_clock = info->max_tmds_clock; |
---|
758 | 940 | int output_eotf; |
---|
759 | 941 | |
---|
.. | .. |
---|
829 | 1011 | *eotf = output_eotf; |
---|
830 | 1012 | } |
---|
831 | 1013 | |
---|
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))) { |
---|
837 | 1017 | *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)) { |
---|
842 | 1023 | *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 | + } |
---|
843 | 1031 | |
---|
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 */ |
---|
848 | 1035 | if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) |
---|
849 | 1036 | *color_format = DRM_HDMI_OUTPUT_YCBCR422; |
---|
850 | 1037 | } |
---|
.. | .. |
---|
1063 | 1250 | return hdmi->hdr_panel_blob_ptr; |
---|
1064 | 1251 | } |
---|
1065 | 1252 | |
---|
| 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 | + |
---|
1066 | 1261 | static bool |
---|
1067 | 1262 | dw_hdmi_rockchip_get_color_changed(void *data) |
---|
1068 | 1263 | { |
---|
.. | .. |
---|
1072 | 1267 | if (hdmi->color_changed) |
---|
1073 | 1268 | ret = true; |
---|
1074 | 1269 | 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 | + } |
---|
1075 | 1327 | |
---|
1076 | 1328 | return ret; |
---|
1077 | 1329 | } |
---|
.. | .. |
---|
1158 | 1410 | } |
---|
1159 | 1411 | |
---|
1160 | 1412 | hdmi->bus_format = color; |
---|
| 1413 | + hdmi->prev_bus_format = color; |
---|
1161 | 1414 | |
---|
1162 | 1415 | if (hdmi->hdmi_output == DRM_HDMI_OUTPUT_YCBCR422) { |
---|
1163 | 1416 | if (hdmi->colordepth == 12) |
---|
.. | .. |
---|
1581 | 1834 | .setup_hpd = dw_hdmi_rk3328_setup_hpd, |
---|
1582 | 1835 | }; |
---|
1583 | 1836 | |
---|
| 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 | + |
---|
1584 | 1851 | static struct rockchip_hdmi_chip_data rk3328_chip_data = { |
---|
1585 | 1852 | .lcdsel_grf_reg = -1, |
---|
1586 | 1853 | }; |
---|
.. | .. |
---|
1627 | 1894 | .ycbcr_420_allowed = true, |
---|
1628 | 1895 | }; |
---|
1629 | 1896 | |
---|
| 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 | + |
---|
1630 | 1913 | static struct rockchip_hdmi_chip_data rk3568_chip_data = { |
---|
1631 | 1914 | .lcdsel_grf_reg = -1, |
---|
1632 | 1915 | .ddc_en_reg = RK3568_GRF_VO_CON1, |
---|
.. | .. |
---|
1658 | 1941 | }, |
---|
1659 | 1942 | { .compatible = "rockchip,rk3399-dw-hdmi", |
---|
1660 | 1943 | .data = &rk3399_hdmi_drv_data |
---|
| 1944 | + }, |
---|
| 1945 | + { .compatible = "rockchip,rk3528-dw-hdmi", |
---|
| 1946 | + .data = &rk3528_hdmi_drv_data |
---|
1661 | 1947 | }, |
---|
1662 | 1948 | { .compatible = "rockchip,rk3568-dw-hdmi", |
---|
1663 | 1949 | .data = &rk3568_hdmi_drv_data |
---|
.. | .. |
---|
1713 | 1999 | dw_hdmi_rockchip_get_hdr_blob; |
---|
1714 | 2000 | plat_data->get_color_changed = |
---|
1715 | 2001 | 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; |
---|
1716 | 2012 | plat_data->property_ops = &dw_hdmi_rockchip_property_ops; |
---|
1717 | 2013 | |
---|
1718 | 2014 | encoder = &hdmi->encoder; |
---|
.. | .. |
---|
1780 | 2076 | platform_set_drvdata(pdev, hdmi); |
---|
1781 | 2077 | |
---|
1782 | 2078 | hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); |
---|
1783 | | - |
---|
1784 | 2079 | /* |
---|
1785 | 2080 | * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), |
---|
1786 | 2081 | * which would have called the encoder cleanup. Do it manually. |
---|
.. | .. |
---|
1833 | 2128 | if (!hdmi) |
---|
1834 | 2129 | return; |
---|
1835 | 2130 | |
---|
| 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 | + } |
---|
1836 | 2136 | dw_hdmi_suspend(&pdev->dev, hdmi->hdmi); |
---|
1837 | 2137 | pm_runtime_put_sync(&pdev->dev); |
---|
1838 | 2138 | } |
---|
.. | .. |
---|
1849 | 2149 | { |
---|
1850 | 2150 | struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); |
---|
1851 | 2151 | |
---|
| 2152 | + if (hdmi->hpd_gpiod) |
---|
| 2153 | + disable_irq(hdmi->hpd_irq); |
---|
1852 | 2154 | dw_hdmi_suspend(dev, hdmi->hdmi); |
---|
1853 | 2155 | pm_runtime_put_sync(dev); |
---|
1854 | 2156 | |
---|
.. | .. |
---|
1859 | 2161 | { |
---|
1860 | 2162 | struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); |
---|
1861 | 2163 | |
---|
| 2164 | + if (hdmi->hpd_gpiod) { |
---|
| 2165 | + dw_hdmi_rk3528_gpio_hpd_init(hdmi); |
---|
| 2166 | + enable_irq(hdmi->hpd_irq); |
---|
| 2167 | + } |
---|
1862 | 2168 | pm_runtime_get_sync(dev); |
---|
1863 | 2169 | dw_hdmi_resume(dev, hdmi->hdmi); |
---|
1864 | 2170 | |
---|