aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/bridge/dw-hdmi.c68
-rw-r--r--include/drm/bridge/dw_hdmi.h10
2 files changed, 75 insertions, 3 deletions
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index f4faa14213e5..ef4f2f96ed2c 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -113,6 +113,12 @@ struct dw_hdmi_i2c {
113 bool is_regaddr; 113 bool is_regaddr;
114}; 114};
115 115
116struct dw_hdmi_phy_data {
117 enum dw_hdmi_phy_type type;
118 const char *name;
119 bool has_svsret;
120};
121
116struct dw_hdmi { 122struct dw_hdmi {
117 struct drm_connector connector; 123 struct drm_connector connector;
118 struct drm_bridge bridge; 124 struct drm_bridge bridge;
@@ -134,7 +140,9 @@ struct dw_hdmi {
134 u8 edid[HDMI_EDID_LEN]; 140 u8 edid[HDMI_EDID_LEN];
135 bool cable_plugin; 141 bool cable_plugin;
136 142
143 const struct dw_hdmi_phy_data *phy;
137 bool phy_enabled; 144 bool phy_enabled;
145
138 struct drm_display_mode previous_mode; 146 struct drm_display_mode previous_mode;
139 147
140 struct i2c_adapter *ddc; 148 struct i2c_adapter *ddc;
@@ -1015,7 +1023,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
1015 dw_hdmi_phy_gen2_txpwron(hdmi, 1); 1023 dw_hdmi_phy_gen2_txpwron(hdmi, 1);
1016 dw_hdmi_phy_gen2_pddq(hdmi, 0); 1024 dw_hdmi_phy_gen2_pddq(hdmi, 0);
1017 1025
1018 if (hdmi->dev_type == RK3288_HDMI) 1026 /* The DWC MHL and HDMI 2.0 PHYs need the SVSRET signal to be set. */
1027 if (hdmi->phy->has_svsret)
1019 dw_hdmi_phy_enable_svsret(hdmi, 1); 1028 dw_hdmi_phy_enable_svsret(hdmi, 1);
1020 1029
1021 /*Wait for PHY PLL lock */ 1030 /*Wait for PHY PLL lock */
@@ -1840,6 +1849,54 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
1840 return IRQ_HANDLED; 1849 return IRQ_HANDLED;
1841} 1850}
1842 1851
1852static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
1853 {
1854 .type = DW_HDMI_PHY_DWC_HDMI_TX_PHY,
1855 .name = "DWC HDMI TX PHY",
1856 }, {
1857 .type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC,
1858 .name = "DWC MHL PHY + HEAC PHY",
1859 .has_svsret = true,
1860 }, {
1861 .type = DW_HDMI_PHY_DWC_MHL_PHY,
1862 .name = "DWC MHL PHY",
1863 .has_svsret = true,
1864 }, {
1865 .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
1866 .name = "DWC HDMI 3D TX PHY + HEAC PHY",
1867 }, {
1868 .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
1869 .name = "DWC HDMI 3D TX PHY",
1870 }, {
1871 .type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
1872 .name = "DWC HDMI 2.0 TX PHY",
1873 .has_svsret = true,
1874 }
1875};
1876
1877static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
1878{
1879 unsigned int i;
1880 u8 phy_type;
1881
1882 phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
1883
1884 for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) {
1885 if (dw_hdmi_phys[i].type == phy_type) {
1886 hdmi->phy = &dw_hdmi_phys[i];
1887 return 0;
1888 }
1889 }
1890
1891 if (phy_type == DW_HDMI_PHY_VENDOR_PHY)
1892 dev_err(hdmi->dev, "Unsupported vendor HDMI PHY\n");
1893 else
1894 dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n",
1895 phy_type);
1896
1897 return -ENODEV;
1898}
1899
1843static struct dw_hdmi * 1900static struct dw_hdmi *
1844__dw_hdmi_probe(struct platform_device *pdev, 1901__dw_hdmi_probe(struct platform_device *pdev,
1845 const struct dw_hdmi_plat_data *plat_data) 1902 const struct dw_hdmi_plat_data *plat_data)
@@ -1950,9 +2007,14 @@ __dw_hdmi_probe(struct platform_device *pdev,
1950 goto err_iahb; 2007 goto err_iahb;
1951 } 2008 }
1952 2009
1953 dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP\n", 2010 ret = dw_hdmi_detect_phy(hdmi);
2011 if (ret < 0)
2012 goto err_iahb;
2013
2014 dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n",
1954 hdmi->version >> 12, hdmi->version & 0xfff, 2015 hdmi->version >> 12, hdmi->version & 0xfff,
1955 prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without"); 2016 prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without",
2017 hdmi->phy->name);
1956 2018
1957 initialize_hdmi_ih_mutes(hdmi); 2019 initialize_hdmi_ih_mutes(hdmi);
1958 2020
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 3bb22a849830..b080a171a23f 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -27,6 +27,16 @@ enum dw_hdmi_devtype {
27 RK3288_HDMI, 27 RK3288_HDMI,
28}; 28};
29 29
30enum dw_hdmi_phy_type {
31 DW_HDMI_PHY_DWC_HDMI_TX_PHY = 0x00,
32 DW_HDMI_PHY_DWC_MHL_PHY_HEAC = 0xb2,
33 DW_HDMI_PHY_DWC_MHL_PHY = 0xc2,
34 DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC = 0xe2,
35 DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY = 0xf2,
36 DW_HDMI_PHY_DWC_HDMI20_TX_PHY = 0xf3,
37 DW_HDMI_PHY_VENDOR_PHY = 0xfe,
38};
39
30struct dw_hdmi_mpll_config { 40struct dw_hdmi_mpll_config {
31 unsigned long mpixelclock; 41 unsigned long mpixelclock;
32 struct { 42 struct {