From: Laurent Pinchart Date: Tue, 17 Jan 2017 08:29:03 +0000 (+0200) Subject: UPSTREAM: drm: bridge: dw-hdmi: Reject invalid product IDs X-Git-Tag: release-20171130_firefly~4^2~717 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=98ef5b0ab2afd36ce2cad906e5df97bc4b0aca34;p=firefly-linux-kernel-4.4.55.git UPSTREAM: drm: bridge: dw-hdmi: Reject invalid product IDs The DWC HDMI TX can be recognized by the two product identification registers. If the registers don't read as expect the IP will be very different than what the driver has been designed for, or will be misconfigured in a way that makes it non-operational (invalid memory address, incorrect clocks, ...). We should reject this situation with an error. While this isn't critical for proper operation with supported IPs at the moment, the driver will soon gain automatic device-specific handling based on runtime device identification. This change makes it easier to implement that without having to default to a random guess in case the device can't be identified. While at it print a readable version number in the device identification message instead of raw register values. Signed-off-by: Laurent Pinchart Reviewed-by: Jose Abreu Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-14-laurent.pinchart+renesas@ideasonboard.com Change-Id: Iaa8e17429e9b4033f97b2bf49504e6f390ce7c44 Signed-off-by: Zheng Yang (cherry pick from 0527e12e8264ae96b1fcc550b4a9e5940f4ffc30) --- diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index 901477a79c8b..706dc344cc1c 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c @@ -2402,6 +2402,9 @@ int dw_hdmi_bind(struct device *dev, struct device *master, struct dw_hdmi *hdmi; int ret; u32 val = 1; + u16 version; + u8 prod_id0; + u8 prod_id1; u8 config0; u8 config1; @@ -2503,12 +2506,22 @@ int dw_hdmi_bind(struct device *dev, struct device *master, } /* Product and revision IDs */ - dev_info(dev, - "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n", - hdmi_readb(hdmi, HDMI_DESIGN_ID), - hdmi_readb(hdmi, HDMI_REVISION_ID), - hdmi_readb(hdmi, HDMI_PRODUCT_ID0), - hdmi_readb(hdmi, HDMI_PRODUCT_ID1)); + version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8) + | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0); + prod_id0 = hdmi_readb(hdmi, HDMI_PRODUCT_ID0); + prod_id1 = hdmi_readb(hdmi, HDMI_PRODUCT_ID1); + + if (prod_id0 != HDMI_PRODUCT_ID0_HDMI_TX || + (prod_id1 & ~HDMI_PRODUCT_ID1_HDCP) != HDMI_PRODUCT_ID1_HDMI_TX) { + dev_err(dev, "Unsupported HDMI controller (%04x:%02x:%02x)\n", + version, prod_id0, prod_id1); + ret = -ENODEV; + goto err_iahb; + } + + dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP\n", + version >> 12, version & 0xfff, + prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without"); init_hpd_work(hdmi); initialize_hdmi_ih_mutes(hdmi); diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h index f8e25c926e62..29218a56ba77 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.h +++ b/drivers/gpu/drm/bridge/dw-hdmi.h @@ -556,6 +556,13 @@ #define HDMI_I2CM_SDA_HOLD 0x7E13 enum { +/* PRODUCT_ID0 field values */ + HDMI_PRODUCT_ID0_HDMI_TX = 0xa0, + +/* PRODUCT_ID1 field values */ + HDMI_PRODUCT_ID1_HDCP = 0xc0, + HDMI_PRODUCT_ID1_HDMI_RX = 0x02, + HDMI_PRODUCT_ID1_HDMI_TX = 0x01, /* CONFIG0_ID field values */ HDMI_CONFIG0_I2S = 0x10,