From: Laurent Pinchart Date: Tue, 17 Jan 2017 08:29:06 +0000 (+0200) Subject: UPSTREAM: drm: bridge: dw-hdmi: Detect PHY type at runtime X-Git-Tag: release-20171130_firefly~4^2~714 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=71fa607baab5a2d45d69059a862a13442d94104e;p=firefly-linux-kernel-4.4.55.git UPSTREAM: drm: bridge: dw-hdmi: Detect PHY type at runtime Detect the PHY type and use it to handle the PHY type-specific SVSRET signal. Signed-off-by: Laurent Pinchart Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-17-laurent.pinchart+renesas@ideasonboard.com Change-Id: I6f128e5e513e68a4e42a6161d7cd55721a748dc8 Signed-off-by: Zheng Yang (cherry pick from faba6c3cff177689aec132291b1cf537831d9a2e) --- diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index 293b38ee4f32..d5e6b10fa40c 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c @@ -180,6 +180,12 @@ struct dw_hdmi_i2c { unsigned int scl_low_ns; }; +struct dw_hdmi_phy_data { + enum dw_hdmi_phy_type type; + const char *name; + bool has_svsret; +}; + struct dw_hdmi { struct drm_connector connector; struct drm_encoder *encoder; @@ -202,7 +208,9 @@ struct dw_hdmi { u8 edid[HDMI_EDID_LEN]; bool cable_plugin; + const struct dw_hdmi_phy_data *phy; bool phy_enabled; + struct drm_display_mode previous_mode; struct i2c_adapter *ddc; @@ -1293,7 +1301,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon) dw_hdmi_phy_gen2_txpwron(hdmi, 1); dw_hdmi_phy_gen2_pddq(hdmi, 0); - if (is_rockchip(hdmi->dev_type)) + /* The DWC MHL and HDMI 2.0 PHYs need the SVSRET signal to be set. */ + if (hdmi->phy->has_svsret) dw_hdmi_phy_enable_svsret(hdmi, 1); /* Wait for PHY PLL lock */ @@ -2224,6 +2233,54 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static const struct dw_hdmi_phy_data dw_hdmi_phys[] = { + { + .type = DW_HDMI_PHY_DWC_HDMI_TX_PHY, + .name = "DWC HDMI TX PHY", + }, { + .type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC, + .name = "DWC MHL PHY + HEAC PHY", + .has_svsret = true, + }, { + .type = DW_HDMI_PHY_DWC_MHL_PHY, + .name = "DWC MHL PHY", + .has_svsret = true, + }, { + .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC, + .name = "DWC HDMI 3D TX PHY + HEAC PHY", + }, { + .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY, + .name = "DWC HDMI 3D TX PHY", + }, { + .type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY, + .name = "DWC HDMI 2.0 TX PHY", + .has_svsret = true, + } +}; + +static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi) +{ + unsigned int i; + u8 phy_type; + + phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID); + + for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) { + if (dw_hdmi_phys[i].type == phy_type) { + hdmi->phy = &dw_hdmi_phys[i]; + return 0; + } + } + + if (phy_type == DW_HDMI_PHY_VENDOR_PHY) + dev_err(hdmi->dev, "Unsupported vendor HDMI PHY\n"); + else + dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n", + phy_type); + + return -ENODEV; +} + static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi) { struct drm_encoder *encoder = hdmi->encoder; @@ -2539,9 +2596,14 @@ int dw_hdmi_bind(struct device *dev, struct device *master, goto err_iahb; } - dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP\n", + ret = dw_hdmi_detect_phy(hdmi); + if (ret < 0) + goto err_iahb; + + dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n", hdmi->version >> 12, hdmi->version & 0xfff, - prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without"); + prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without", + hdmi->phy->name); init_hpd_work(hdmi); initialize_hdmi_ih_mutes(hdmi); diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 696b84994ae5..b72782289e7c 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -36,6 +36,16 @@ struct dw_hdmi_audio_tmds_n { unsigned int n_48k; }; +enum dw_hdmi_phy_type { + DW_HDMI_PHY_DWC_HDMI_TX_PHY = 0x00, + DW_HDMI_PHY_DWC_MHL_PHY_HEAC = 0xb2, + DW_HDMI_PHY_DWC_MHL_PHY = 0xc2, + DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC = 0xe2, + DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY = 0xf2, + DW_HDMI_PHY_DWC_HDMI20_TX_PHY = 0xf3, + DW_HDMI_PHY_VENDOR_PHY = 0xfe, +}; + struct dw_hdmi_mpll_config { unsigned long mpixelclock; struct {