From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753735AbdDCOnI (ORCPT ); Mon, 3 Apr 2017 10:43:08 -0400 Received: from mail-wr0-f174.google.com ([209.85.128.174]:34853 "EHLO mail-wr0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753604AbdDCOmx (ORCPT ); Mon, 3 Apr 2017 10:42:53 -0400 From: Neil Armstrong To: dri-devel@lists.freedesktop.org, laurent.pinchart+renesas@ideasonboard.com, architt@codeaurora.org Cc: Neil Armstrong , Jose.Abreu@synopsys.com, kieran.bingham@ideasonboard.com, linux-amlogic@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-media@vger.kernel.org Subject: [PATCH v6 6/6] drm: bridge: dw-hdmi: Move HPD handling to PHY operations Date: Mon, 3 Apr 2017 16:42:38 +0200 Message-Id: <1491230558-10804-7-git-send-email-narmstrong@baylibre.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1491230558-10804-1-git-send-email-narmstrong@baylibre.com> References: <1491230558-10804-1-git-send-email-narmstrong@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The HDMI TX controller support HPD and RXSENSE signaling from the PHY via it's STAT0 PHY interface, but some vendor PHYs can manage these signals independently from the controller, thus these STAT0 handling should be moved to PHY specific operations and become optional. The existing STAT0 HPD and RXSENSE handling code is refactored into a supplementaty set of default PHY operations that are used automatically when the platform glue doesn't provide its own operations. Reviewed-by: Jose Abreu Reviewed-by: Archit Taneja Signed-off-by: Neil Armstrong --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 135 ++++++++++++++++++------------ include/drm/bridge/dw_hdmi.h | 5 ++ 2 files changed, 86 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 16d5fff3..84cc949 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1229,10 +1229,46 @@ static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi, connector_status_connected : connector_status_disconnected; } +static void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data, + bool force, bool disabled, bool rxsense) +{ + u8 old_mask = hdmi->phy_mask; + + if (force || disabled || !rxsense) + hdmi->phy_mask |= HDMI_PHY_RX_SENSE; + else + hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE; + + if (old_mask != hdmi->phy_mask) + hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); +} + +static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data) +{ + /* + * Configure the PHY RX SENSE and HPD interrupts polarities and clear + * any pending interrupt. + */ + hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0); + hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, + HDMI_IH_PHY_STAT0); + + /* Enable cable hot plug irq. */ + hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); + + /* Clear and unmute interrupts. */ + hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, + HDMI_IH_PHY_STAT0); + hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), + HDMI_IH_MUTE_PHY_STAT0); +} + static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = { .init = dw_hdmi_phy_init, .disable = dw_hdmi_phy_disable, .read_hpd = dw_hdmi_phy_read_hpd, + .update_hpd = dw_hdmi_phy_update_hpd, + .setup_hpd = dw_hdmi_phy_setup_hpd, }; /* ----------------------------------------------------------------------------- @@ -1808,35 +1844,10 @@ static void dw_hdmi_update_power(struct dw_hdmi *hdmi) */ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi) { - u8 old_mask = hdmi->phy_mask; - - if (hdmi->force || hdmi->disabled || !hdmi->rxsense) - hdmi->phy_mask |= HDMI_PHY_RX_SENSE; - else - hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE; - - if (old_mask != hdmi->phy_mask) - hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); -} - -static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi) -{ - /* - * Configure the PHY RX SENSE and HPD interrupts polarities and clear - * any pending interrupt. - */ - hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0); - hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, - HDMI_IH_PHY_STAT0); - - /* Enable cable hot plug irq. */ - hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); - - /* Clear and unmute interrupts. */ - hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, - HDMI_IH_PHY_STAT0); - hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), - HDMI_IH_MUTE_PHY_STAT0); + if (hdmi->phy.ops->update_hpd) + hdmi->phy.ops->update_hpd(hdmi, hdmi->phy.data, + hdmi->force, hdmi->disabled, + hdmi->rxsense); } static enum drm_connector_status @@ -2028,6 +2039,41 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) return ret; } +void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) +{ + mutex_lock(&hdmi->mutex); + + if (!hdmi->force) { + /* + * If the RX sense status indicates we're disconnected, + * clear the software rxsense status. + */ + if (!rx_sense) + hdmi->rxsense = false; + + /* + * Only set the software rxsense status when both + * rxsense and hpd indicates we're connected. + * This avoids what seems to be bad behaviour in + * at least iMX6S versions of the phy. + */ + if (hpd) + hdmi->rxsense = true; + + dw_hdmi_update_power(hdmi); + dw_hdmi_update_phy_mask(hdmi); + } + mutex_unlock(&hdmi->mutex); +} + +void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense) +{ + struct dw_hdmi *hdmi = dev_get_drvdata(dev); + + __dw_hdmi_setup_rx_sense(hdmi, hpd, rx_sense); +} +EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense); + static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) { struct dw_hdmi *hdmi = dev_id; @@ -2060,30 +2106,10 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) * ask the source to re-read the EDID. */ if (intr_stat & - (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) { - mutex_lock(&hdmi->mutex); - if (!hdmi->force) { - /* - * If the RX sense status indicates we're disconnected, - * clear the software rxsense status. - */ - if (!(phy_stat & HDMI_PHY_RX_SENSE)) - hdmi->rxsense = false; - - /* - * Only set the software rxsense status when both - * rxsense and hpd indicates we're connected. - * This avoids what seems to be bad behaviour in - * at least iMX6S versions of the phy. - */ - if (phy_stat & HDMI_PHY_HPD) - hdmi->rxsense = true; - - dw_hdmi_update_power(hdmi); - dw_hdmi_update_phy_mask(hdmi); - } - mutex_unlock(&hdmi->mutex); - } + (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) + __dw_hdmi_setup_rx_sense(hdmi, + phy_stat & HDMI_PHY_HPD, + phy_stat & HDMI_PHY_RX_SENSE); if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { dev_dbg(hdmi->dev, "EVENT=%s\n", @@ -2357,7 +2383,8 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi) #endif dw_hdmi_setup_i2c(hdmi); - dw_hdmi_phy_setup_hpd(hdmi); + if (hdmi->phy.ops->setup_hpd) + hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data); memset(&pdevinfo, 0, sizeof(pdevinfo)); pdevinfo.parent = dev; diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 45c2c15..e63d675 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -117,6 +117,9 @@ struct dw_hdmi_phy_ops { struct drm_display_mode *mode); void (*disable)(struct dw_hdmi *hdmi, void *data); enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data); + void (*update_hpd)(struct dw_hdmi *hdmi, void *data, + bool force, bool disabled, bool rxsense); + void (*setup_hpd)(struct dw_hdmi *hdmi, void *data); }; struct dw_hdmi_plat_data { @@ -147,6 +150,8 @@ int dw_hdmi_probe(struct platform_device *pdev, int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, const struct dw_hdmi_plat_data *plat_data); +void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense); + void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate); void dw_hdmi_audio_enable(struct dw_hdmi *hdmi); void dw_hdmi_audio_disable(struct dw_hdmi *hdmi); -- 1.9.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Neil Armstrong Subject: [PATCH v6 6/6] drm: bridge: dw-hdmi: Move HPD handling to PHY operations Date: Mon, 3 Apr 2017 16:42:38 +0200 Message-ID: <1491230558-10804-7-git-send-email-narmstrong@baylibre.com> References: <1491230558-10804-1-git-send-email-narmstrong@baylibre.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from mail-wr0-x22d.google.com (mail-wr0-x22d.google.com [IPv6:2a00:1450:400c:c0c::22d]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1C95A6E350 for ; Mon, 3 Apr 2017 14:42:53 +0000 (UTC) Received: by mail-wr0-x22d.google.com with SMTP id k6so167325038wre.2 for ; Mon, 03 Apr 2017 07:42:53 -0700 (PDT) In-Reply-To: <1491230558-10804-1-git-send-email-narmstrong@baylibre.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: dri-devel@lists.freedesktop.org, laurent.pinchart+renesas@ideasonboard.com, architt@codeaurora.org Cc: Jose.Abreu@synopsys.com, linux-doc@vger.kernel.org, Neil Armstrong , kieran.bingham@ideasonboard.com, linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org, linux-media@vger.kernel.org List-Id: dri-devel@lists.freedesktop.org VGhlIEhETUkgVFggY29udHJvbGxlciBzdXBwb3J0IEhQRCBhbmQgUlhTRU5TRSBzaWduYWxpbmcg ZnJvbSB0aGUgUEhZCnZpYSBpdCdzIFNUQVQwIFBIWSBpbnRlcmZhY2UsIGJ1dCBzb21lIHZlbmRv ciBQSFlzIGNhbiBtYW5hZ2UgdGhlc2UKc2lnbmFscyBpbmRlcGVuZGVudGx5IGZyb20gdGhlIGNv bnRyb2xsZXIsIHRodXMgdGhlc2UgU1RBVDAgaGFuZGxpbmcKc2hvdWxkIGJlIG1vdmVkIHRvIFBI WSBzcGVjaWZpYyBvcGVyYXRpb25zIGFuZCBiZWNvbWUgb3B0aW9uYWwuCgpUaGUgZXhpc3Rpbmcg U1RBVDAgSFBEIGFuZCBSWFNFTlNFIGhhbmRsaW5nIGNvZGUgaXMgcmVmYWN0b3JlZCBpbnRvCmEg c3VwcGxlbWVudGF0eSBzZXQgb2YgZGVmYXVsdCBQSFkgb3BlcmF0aW9ucyB0aGF0IGFyZSB1c2Vk IGF1dG9tYXRpY2FsbHkKd2hlbiB0aGUgcGxhdGZvcm0gZ2x1ZSBkb2Vzbid0IHByb3ZpZGUgaXRz IG93biBvcGVyYXRpb25zLgoKUmV2aWV3ZWQtYnk6IEpvc2UgQWJyZXUgPGpvYWJyZXVAc3lub3Bz eXMuY29tPgpSZXZpZXdlZC1ieTogQXJjaGl0IFRhbmVqYSA8YXJjaGl0dEBjb2RlYXVyb3JhLm9y Zz4KU2lnbmVkLW9mZi1ieTogTmVpbCBBcm1zdHJvbmcgPG5hcm1zdHJvbmdAYmF5bGlicmUuY29t PgotLS0KIGRyaXZlcnMvZ3B1L2RybS9icmlkZ2Uvc3lub3BzeXMvZHctaGRtaS5jIHwgMTM1ICsr KysrKysrKysrKysrKysrKy0tLS0tLS0tLS0tLQogaW5jbHVkZS9kcm0vYnJpZGdlL2R3X2hkbWku aCAgICAgICAgICAgICAgfCAgIDUgKysKIDIgZmlsZXMgY2hhbmdlZCwgODYgaW5zZXJ0aW9ucygr KSwgNTQgZGVsZXRpb25zKC0pCgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL2JyaWRnZS9z eW5vcHN5cy9kdy1oZG1pLmMgYi9kcml2ZXJzL2dwdS9kcm0vYnJpZGdlL3N5bm9wc3lzL2R3LWhk bWkuYwppbmRleCAxNmQ1ZmZmMy4uODRjYzk0OSAxMDA2NDQKLS0tIGEvZHJpdmVycy9ncHUvZHJt L2JyaWRnZS9zeW5vcHN5cy9kdy1oZG1pLmMKKysrIGIvZHJpdmVycy9ncHUvZHJtL2JyaWRnZS9z eW5vcHN5cy9kdy1oZG1pLmMKQEAgLTEyMjksMTAgKzEyMjksNDYgQEAgc3RhdGljIGVudW0gZHJt X2Nvbm5lY3Rvcl9zdGF0dXMgZHdfaGRtaV9waHlfcmVhZF9ocGQoc3RydWN0IGR3X2hkbWkgKmhk bWksCiAJCWNvbm5lY3Rvcl9zdGF0dXNfY29ubmVjdGVkIDogY29ubmVjdG9yX3N0YXR1c19kaXNj b25uZWN0ZWQ7CiB9CiAKK3N0YXRpYyB2b2lkIGR3X2hkbWlfcGh5X3VwZGF0ZV9ocGQoc3RydWN0 IGR3X2hkbWkgKmhkbWksIHZvaWQgKmRhdGEsCisJCQkJICAgYm9vbCBmb3JjZSwgYm9vbCBkaXNh YmxlZCwgYm9vbCByeHNlbnNlKQoreworCXU4IG9sZF9tYXNrID0gaGRtaS0+cGh5X21hc2s7CisK KwlpZiAoZm9yY2UgfHwgZGlzYWJsZWQgfHwgIXJ4c2Vuc2UpCisJCWhkbWktPnBoeV9tYXNrIHw9 IEhETUlfUEhZX1JYX1NFTlNFOworCWVsc2UKKwkJaGRtaS0+cGh5X21hc2sgJj0gfkhETUlfUEhZ X1JYX1NFTlNFOworCisJaWYgKG9sZF9tYXNrICE9IGhkbWktPnBoeV9tYXNrKQorCQloZG1pX3dy aXRlYihoZG1pLCBoZG1pLT5waHlfbWFzaywgSERNSV9QSFlfTUFTSzApOworfQorCitzdGF0aWMg dm9pZCBkd19oZG1pX3BoeV9zZXR1cF9ocGQoc3RydWN0IGR3X2hkbWkgKmhkbWksIHZvaWQgKmRh dGEpCit7CisJLyoKKwkgKiBDb25maWd1cmUgdGhlIFBIWSBSWCBTRU5TRSBhbmQgSFBEIGludGVy cnVwdHMgcG9sYXJpdGllcyBhbmQgY2xlYXIKKwkgKiBhbnkgcGVuZGluZyBpbnRlcnJ1cHQuCisJ ICovCisJaGRtaV93cml0ZWIoaGRtaSwgSERNSV9QSFlfSFBEIHwgSERNSV9QSFlfUlhfU0VOU0Us IEhETUlfUEhZX1BPTDApOworCWhkbWlfd3JpdGViKGhkbWksIEhETUlfSUhfUEhZX1NUQVQwX0hQ RCB8IEhETUlfSUhfUEhZX1NUQVQwX1JYX1NFTlNFLAorCQkgICAgSERNSV9JSF9QSFlfU1RBVDAp OworCisJLyogRW5hYmxlIGNhYmxlIGhvdCBwbHVnIGlycS4gKi8KKwloZG1pX3dyaXRlYihoZG1p LCBoZG1pLT5waHlfbWFzaywgSERNSV9QSFlfTUFTSzApOworCisJLyogQ2xlYXIgYW5kIHVubXV0 ZSBpbnRlcnJ1cHRzLiAqLworCWhkbWlfd3JpdGViKGhkbWksIEhETUlfSUhfUEhZX1NUQVQwX0hQ RCB8IEhETUlfSUhfUEhZX1NUQVQwX1JYX1NFTlNFLAorCQkgICAgSERNSV9JSF9QSFlfU1RBVDAp OworCWhkbWlfd3JpdGViKGhkbWksIH4oSERNSV9JSF9QSFlfU1RBVDBfSFBEIHwgSERNSV9JSF9Q SFlfU1RBVDBfUlhfU0VOU0UpLAorCQkgICAgSERNSV9JSF9NVVRFX1BIWV9TVEFUMCk7Cit9CisK IHN0YXRpYyBjb25zdCBzdHJ1Y3QgZHdfaGRtaV9waHlfb3BzIGR3X2hkbWlfc3lub3BzeXNfcGh5 X29wcyA9IHsKIAkuaW5pdCA9IGR3X2hkbWlfcGh5X2luaXQsCiAJLmRpc2FibGUgPSBkd19oZG1p X3BoeV9kaXNhYmxlLAogCS5yZWFkX2hwZCA9IGR3X2hkbWlfcGh5X3JlYWRfaHBkLAorCS51cGRh dGVfaHBkID0gZHdfaGRtaV9waHlfdXBkYXRlX2hwZCwKKwkuc2V0dXBfaHBkID0gZHdfaGRtaV9w aHlfc2V0dXBfaHBkLAogfTsKIAogLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KQEAgLTE4MDgsMzUg KzE4NDQsMTAgQEAgc3RhdGljIHZvaWQgZHdfaGRtaV91cGRhdGVfcG93ZXIoc3RydWN0IGR3X2hk bWkgKmhkbWkpCiAgKi8KIHN0YXRpYyB2b2lkIGR3X2hkbWlfdXBkYXRlX3BoeV9tYXNrKHN0cnVj dCBkd19oZG1pICpoZG1pKQogewotCXU4IG9sZF9tYXNrID0gaGRtaS0+cGh5X21hc2s7Ci0KLQlp ZiAoaGRtaS0+Zm9yY2UgfHwgaGRtaS0+ZGlzYWJsZWQgfHwgIWhkbWktPnJ4c2Vuc2UpCi0JCWhk bWktPnBoeV9tYXNrIHw9IEhETUlfUEhZX1JYX1NFTlNFOwotCWVsc2UKLQkJaGRtaS0+cGh5X21h c2sgJj0gfkhETUlfUEhZX1JYX1NFTlNFOwotCi0JaWYgKG9sZF9tYXNrICE9IGhkbWktPnBoeV9t YXNrKQotCQloZG1pX3dyaXRlYihoZG1pLCBoZG1pLT5waHlfbWFzaywgSERNSV9QSFlfTUFTSzAp OwotfQotCi1zdGF0aWMgdm9pZCBkd19oZG1pX3BoeV9zZXR1cF9ocGQoc3RydWN0IGR3X2hkbWkg KmhkbWkpCi17Ci0JLyoKLQkgKiBDb25maWd1cmUgdGhlIFBIWSBSWCBTRU5TRSBhbmQgSFBEIGlu dGVycnVwdHMgcG9sYXJpdGllcyBhbmQgY2xlYXIKLQkgKiBhbnkgcGVuZGluZyBpbnRlcnJ1cHQu Ci0JICovCi0JaGRtaV93cml0ZWIoaGRtaSwgSERNSV9QSFlfSFBEIHwgSERNSV9QSFlfUlhfU0VO U0UsIEhETUlfUEhZX1BPTDApOwotCWhkbWlfd3JpdGViKGhkbWksIEhETUlfSUhfUEhZX1NUQVQw X0hQRCB8IEhETUlfSUhfUEhZX1NUQVQwX1JYX1NFTlNFLAotCQkgICAgSERNSV9JSF9QSFlfU1RB VDApOwotCi0JLyogRW5hYmxlIGNhYmxlIGhvdCBwbHVnIGlycS4gKi8KLQloZG1pX3dyaXRlYiho ZG1pLCBoZG1pLT5waHlfbWFzaywgSERNSV9QSFlfTUFTSzApOwotCi0JLyogQ2xlYXIgYW5kIHVu bXV0ZSBpbnRlcnJ1cHRzLiAqLwotCWhkbWlfd3JpdGViKGhkbWksIEhETUlfSUhfUEhZX1NUQVQw X0hQRCB8IEhETUlfSUhfUEhZX1NUQVQwX1JYX1NFTlNFLAotCQkgICAgSERNSV9JSF9QSFlfU1RB VDApOwotCWhkbWlfd3JpdGViKGhkbWksIH4oSERNSV9JSF9QSFlfU1RBVDBfSFBEIHwgSERNSV9J SF9QSFlfU1RBVDBfUlhfU0VOU0UpLAotCQkgICAgSERNSV9JSF9NVVRFX1BIWV9TVEFUMCk7CisJ aWYgKGhkbWktPnBoeS5vcHMtPnVwZGF0ZV9ocGQpCisJCWhkbWktPnBoeS5vcHMtPnVwZGF0ZV9o cGQoaGRtaSwgaGRtaS0+cGh5LmRhdGEsCisJCQkJCSAgaGRtaS0+Zm9yY2UsIGhkbWktPmRpc2Fi bGVkLAorCQkJCQkgIGhkbWktPnJ4c2Vuc2UpOwogfQogCiBzdGF0aWMgZW51bSBkcm1fY29ubmVj dG9yX3N0YXR1cwpAQCAtMjAyOCw2ICsyMDM5LDQxIEBAIHN0YXRpYyBpcnFyZXR1cm5fdCBkd19o ZG1pX2hhcmRpcnEoaW50IGlycSwgdm9pZCAqZGV2X2lkKQogCXJldHVybiByZXQ7CiB9CiAKK3Zv aWQgX19kd19oZG1pX3NldHVwX3J4X3NlbnNlKHN0cnVjdCBkd19oZG1pICpoZG1pLCBib29sIGhw ZCwgYm9vbCByeF9zZW5zZSkKK3sKKwltdXRleF9sb2NrKCZoZG1pLT5tdXRleCk7CisKKwlpZiAo IWhkbWktPmZvcmNlKSB7CisJCS8qCisJCSAqIElmIHRoZSBSWCBzZW5zZSBzdGF0dXMgaW5kaWNh dGVzIHdlJ3JlIGRpc2Nvbm5lY3RlZCwKKwkJICogY2xlYXIgdGhlIHNvZnR3YXJlIHJ4c2Vuc2Ug c3RhdHVzLgorCQkgKi8KKwkJaWYgKCFyeF9zZW5zZSkKKwkJCWhkbWktPnJ4c2Vuc2UgPSBmYWxz ZTsKKworCQkvKgorCQkgKiBPbmx5IHNldCB0aGUgc29mdHdhcmUgcnhzZW5zZSBzdGF0dXMgd2hl biBib3RoCisJCSAqIHJ4c2Vuc2UgYW5kIGhwZCBpbmRpY2F0ZXMgd2UncmUgY29ubmVjdGVkLgor CQkgKiBUaGlzIGF2b2lkcyB3aGF0IHNlZW1zIHRvIGJlIGJhZCBiZWhhdmlvdXIgaW4KKwkJICog YXQgbGVhc3QgaU1YNlMgdmVyc2lvbnMgb2YgdGhlIHBoeS4KKwkJICovCisJCWlmIChocGQpCisJ CQloZG1pLT5yeHNlbnNlID0gdHJ1ZTsKKworCQlkd19oZG1pX3VwZGF0ZV9wb3dlcihoZG1pKTsK KwkJZHdfaGRtaV91cGRhdGVfcGh5X21hc2soaGRtaSk7CisJfQorCW11dGV4X3VubG9jaygmaGRt aS0+bXV0ZXgpOworfQorCit2b2lkIGR3X2hkbWlfc2V0dXBfcnhfc2Vuc2Uoc3RydWN0IGRldmlj ZSAqZGV2LCBib29sIGhwZCwgYm9vbCByeF9zZW5zZSkKK3sKKwlzdHJ1Y3QgZHdfaGRtaSAqaGRt aSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOworCisJX19kd19oZG1pX3NldHVwX3J4X3NlbnNlKGhk bWksIGhwZCwgcnhfc2Vuc2UpOworfQorRVhQT1JUX1NZTUJPTF9HUEwoZHdfaGRtaV9zZXR1cF9y eF9zZW5zZSk7CisKIHN0YXRpYyBpcnFyZXR1cm5fdCBkd19oZG1pX2lycShpbnQgaXJxLCB2b2lk ICpkZXZfaWQpCiB7CiAJc3RydWN0IGR3X2hkbWkgKmhkbWkgPSBkZXZfaWQ7CkBAIC0yMDYwLDMw ICsyMTA2LDEwIEBAIHN0YXRpYyBpcnFyZXR1cm5fdCBkd19oZG1pX2lycShpbnQgaXJxLCB2b2lk ICpkZXZfaWQpCiAJICogYXNrIHRoZSBzb3VyY2UgdG8gcmUtcmVhZCB0aGUgRURJRC4KIAkgKi8K IAlpZiAoaW50cl9zdGF0ICYKLQkgICAgKEhETUlfSUhfUEhZX1NUQVQwX1JYX1NFTlNFIHwgSERN SV9JSF9QSFlfU1RBVDBfSFBEKSkgewotCQltdXRleF9sb2NrKCZoZG1pLT5tdXRleCk7Ci0JCWlm ICghaGRtaS0+Zm9yY2UpIHsKLQkJCS8qCi0JCQkgKiBJZiB0aGUgUlggc2Vuc2Ugc3RhdHVzIGlu ZGljYXRlcyB3ZSdyZSBkaXNjb25uZWN0ZWQsCi0JCQkgKiBjbGVhciB0aGUgc29mdHdhcmUgcnhz ZW5zZSBzdGF0dXMuCi0JCQkgKi8KLQkJCWlmICghKHBoeV9zdGF0ICYgSERNSV9QSFlfUlhfU0VO U0UpKQotCQkJCWhkbWktPnJ4c2Vuc2UgPSBmYWxzZTsKLQotCQkJLyoKLQkJCSAqIE9ubHkgc2V0 IHRoZSBzb2Z0d2FyZSByeHNlbnNlIHN0YXR1cyB3aGVuIGJvdGgKLQkJCSAqIHJ4c2Vuc2UgYW5k IGhwZCBpbmRpY2F0ZXMgd2UncmUgY29ubmVjdGVkLgotCQkJICogVGhpcyBhdm9pZHMgd2hhdCBz ZWVtcyB0byBiZSBiYWQgYmVoYXZpb3VyIGluCi0JCQkgKiBhdCBsZWFzdCBpTVg2UyB2ZXJzaW9u cyBvZiB0aGUgcGh5LgotCQkJICovCi0JCQlpZiAocGh5X3N0YXQgJiBIRE1JX1BIWV9IUEQpCi0J CQkJaGRtaS0+cnhzZW5zZSA9IHRydWU7Ci0KLQkJCWR3X2hkbWlfdXBkYXRlX3Bvd2VyKGhkbWkp OwotCQkJZHdfaGRtaV91cGRhdGVfcGh5X21hc2soaGRtaSk7Ci0JCX0KLQkJbXV0ZXhfdW5sb2Nr KCZoZG1pLT5tdXRleCk7Ci0JfQorCSAgICAoSERNSV9JSF9QSFlfU1RBVDBfUlhfU0VOU0UgfCBI RE1JX0lIX1BIWV9TVEFUMF9IUEQpKQorCQlfX2R3X2hkbWlfc2V0dXBfcnhfc2Vuc2UoaGRtaSwK KwkJCQkJIHBoeV9zdGF0ICYgSERNSV9QSFlfSFBELAorCQkJCQkgcGh5X3N0YXQgJiBIRE1JX1BI WV9SWF9TRU5TRSk7CiAKIAlpZiAoaW50cl9zdGF0ICYgSERNSV9JSF9QSFlfU1RBVDBfSFBEKSB7 CiAJCWRldl9kYmcoaGRtaS0+ZGV2LCAiRVZFTlQ9JXNcbiIsCkBAIC0yMzU3LDcgKzIzODMsOCBA QCBzdGF0aWMgaW50IGR3X2hkbWlfZGV0ZWN0X3BoeShzdHJ1Y3QgZHdfaGRtaSAqaGRtaSkKICNl bmRpZgogCiAJZHdfaGRtaV9zZXR1cF9pMmMoaGRtaSk7Ci0JZHdfaGRtaV9waHlfc2V0dXBfaHBk KGhkbWkpOworCWlmIChoZG1pLT5waHkub3BzLT5zZXR1cF9ocGQpCisJCWhkbWktPnBoeS5vcHMt PnNldHVwX2hwZChoZG1pLCBoZG1pLT5waHkuZGF0YSk7CiAKIAltZW1zZXQoJnBkZXZpbmZvLCAw LCBzaXplb2YocGRldmluZm8pKTsKIAlwZGV2aW5mby5wYXJlbnQgPSBkZXY7CmRpZmYgLS1naXQg YS9pbmNsdWRlL2RybS9icmlkZ2UvZHdfaGRtaS5oIGIvaW5jbHVkZS9kcm0vYnJpZGdlL2R3X2hk bWkuaAppbmRleCA0NWMyYzE1Li5lNjNkNjc1IDEwMDY0NAotLS0gYS9pbmNsdWRlL2RybS9icmlk Z2UvZHdfaGRtaS5oCisrKyBiL2luY2x1ZGUvZHJtL2JyaWRnZS9kd19oZG1pLmgKQEAgLTExNyw2 ICsxMTcsOSBAQCBzdHJ1Y3QgZHdfaGRtaV9waHlfb3BzIHsKIAkJICAgIHN0cnVjdCBkcm1fZGlz cGxheV9tb2RlICptb2RlKTsKIAl2b2lkICgqZGlzYWJsZSkoc3RydWN0IGR3X2hkbWkgKmhkbWks IHZvaWQgKmRhdGEpOwogCWVudW0gZHJtX2Nvbm5lY3Rvcl9zdGF0dXMgKCpyZWFkX2hwZCkoc3Ry dWN0IGR3X2hkbWkgKmhkbWksIHZvaWQgKmRhdGEpOworCXZvaWQgKCp1cGRhdGVfaHBkKShzdHJ1 Y3QgZHdfaGRtaSAqaGRtaSwgdm9pZCAqZGF0YSwKKwkJCSAgIGJvb2wgZm9yY2UsIGJvb2wgZGlz YWJsZWQsIGJvb2wgcnhzZW5zZSk7CisJdm9pZCAoKnNldHVwX2hwZCkoc3RydWN0IGR3X2hkbWkg KmhkbWksIHZvaWQgKmRhdGEpOwogfTsKIAogc3RydWN0IGR3X2hkbWlfcGxhdF9kYXRhIHsKQEAg LTE0Nyw2ICsxNTAsOCBAQCBpbnQgZHdfaGRtaV9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNl ICpwZGV2LAogaW50IGR3X2hkbWlfYmluZChzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2LCBz dHJ1Y3QgZHJtX2VuY29kZXIgKmVuY29kZXIsCiAJCSBjb25zdCBzdHJ1Y3QgZHdfaGRtaV9wbGF0 X2RhdGEgKnBsYXRfZGF0YSk7CiAKK3ZvaWQgZHdfaGRtaV9zZXR1cF9yeF9zZW5zZShzdHJ1Y3Qg ZGV2aWNlICpkZXYsIGJvb2wgaHBkLCBib29sIHJ4X3NlbnNlKTsKKwogdm9pZCBkd19oZG1pX3Nl dF9zYW1wbGVfcmF0ZShzdHJ1Y3QgZHdfaGRtaSAqaGRtaSwgdW5zaWduZWQgaW50IHJhdGUpOwog dm9pZCBkd19oZG1pX2F1ZGlvX2VuYWJsZShzdHJ1Y3QgZHdfaGRtaSAqaGRtaSk7CiB2b2lkIGR3 X2hkbWlfYXVkaW9fZGlzYWJsZShzdHJ1Y3QgZHdfaGRtaSAqaGRtaSk7Ci0tIAoxLjkuMQoKX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KZHJpLWRldmVsIG1h aWxpbmcgbGlzdApkcmktZGV2ZWxAbGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlzdHMu ZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vZHJpLWRldmVsCg== From mboxrd@z Thu Jan 1 00:00:00 1970 From: narmstrong@baylibre.com (Neil Armstrong) Date: Mon, 3 Apr 2017 16:42:38 +0200 Subject: [PATCH v6 6/6] drm: bridge: dw-hdmi: Move HPD handling to PHY operations In-Reply-To: <1491230558-10804-1-git-send-email-narmstrong@baylibre.com> References: <1491230558-10804-1-git-send-email-narmstrong@baylibre.com> Message-ID: <1491230558-10804-7-git-send-email-narmstrong@baylibre.com> To: linus-amlogic@lists.infradead.org List-Id: linus-amlogic.lists.infradead.org The HDMI TX controller support HPD and RXSENSE signaling from the PHY via it's STAT0 PHY interface, but some vendor PHYs can manage these signals independently from the controller, thus these STAT0 handling should be moved to PHY specific operations and become optional. The existing STAT0 HPD and RXSENSE handling code is refactored into a supplementaty set of default PHY operations that are used automatically when the platform glue doesn't provide its own operations. Reviewed-by: Jose Abreu Reviewed-by: Archit Taneja Signed-off-by: Neil Armstrong --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 135 ++++++++++++++++++------------ include/drm/bridge/dw_hdmi.h | 5 ++ 2 files changed, 86 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 16d5fff3..84cc949 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1229,10 +1229,46 @@ static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi, connector_status_connected : connector_status_disconnected; } +static void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data, + bool force, bool disabled, bool rxsense) +{ + u8 old_mask = hdmi->phy_mask; + + if (force || disabled || !rxsense) + hdmi->phy_mask |= HDMI_PHY_RX_SENSE; + else + hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE; + + if (old_mask != hdmi->phy_mask) + hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); +} + +static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data) +{ + /* + * Configure the PHY RX SENSE and HPD interrupts polarities and clear + * any pending interrupt. + */ + hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0); + hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, + HDMI_IH_PHY_STAT0); + + /* Enable cable hot plug irq. */ + hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); + + /* Clear and unmute interrupts. */ + hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, + HDMI_IH_PHY_STAT0); + hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), + HDMI_IH_MUTE_PHY_STAT0); +} + static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = { .init = dw_hdmi_phy_init, .disable = dw_hdmi_phy_disable, .read_hpd = dw_hdmi_phy_read_hpd, + .update_hpd = dw_hdmi_phy_update_hpd, + .setup_hpd = dw_hdmi_phy_setup_hpd, }; /* ----------------------------------------------------------------------------- @@ -1808,35 +1844,10 @@ static void dw_hdmi_update_power(struct dw_hdmi *hdmi) */ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi) { - u8 old_mask = hdmi->phy_mask; - - if (hdmi->force || hdmi->disabled || !hdmi->rxsense) - hdmi->phy_mask |= HDMI_PHY_RX_SENSE; - else - hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE; - - if (old_mask != hdmi->phy_mask) - hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); -} - -static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi) -{ - /* - * Configure the PHY RX SENSE and HPD interrupts polarities and clear - * any pending interrupt. - */ - hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0); - hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, - HDMI_IH_PHY_STAT0); - - /* Enable cable hot plug irq. */ - hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); - - /* Clear and unmute interrupts. */ - hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, - HDMI_IH_PHY_STAT0); - hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), - HDMI_IH_MUTE_PHY_STAT0); + if (hdmi->phy.ops->update_hpd) + hdmi->phy.ops->update_hpd(hdmi, hdmi->phy.data, + hdmi->force, hdmi->disabled, + hdmi->rxsense); } static enum drm_connector_status @@ -2028,6 +2039,41 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) return ret; } +void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) +{ + mutex_lock(&hdmi->mutex); + + if (!hdmi->force) { + /* + * If the RX sense status indicates we're disconnected, + * clear the software rxsense status. + */ + if (!rx_sense) + hdmi->rxsense = false; + + /* + * Only set the software rxsense status when both + * rxsense and hpd indicates we're connected. + * This avoids what seems to be bad behaviour in + * at least iMX6S versions of the phy. + */ + if (hpd) + hdmi->rxsense = true; + + dw_hdmi_update_power(hdmi); + dw_hdmi_update_phy_mask(hdmi); + } + mutex_unlock(&hdmi->mutex); +} + +void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense) +{ + struct dw_hdmi *hdmi = dev_get_drvdata(dev); + + __dw_hdmi_setup_rx_sense(hdmi, hpd, rx_sense); +} +EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense); + static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) { struct dw_hdmi *hdmi = dev_id; @@ -2060,30 +2106,10 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) * ask the source to re-read the EDID. */ if (intr_stat & - (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) { - mutex_lock(&hdmi->mutex); - if (!hdmi->force) { - /* - * If the RX sense status indicates we're disconnected, - * clear the software rxsense status. - */ - if (!(phy_stat & HDMI_PHY_RX_SENSE)) - hdmi->rxsense = false; - - /* - * Only set the software rxsense status when both - * rxsense and hpd indicates we're connected. - * This avoids what seems to be bad behaviour in - * at least iMX6S versions of the phy. - */ - if (phy_stat & HDMI_PHY_HPD) - hdmi->rxsense = true; - - dw_hdmi_update_power(hdmi); - dw_hdmi_update_phy_mask(hdmi); - } - mutex_unlock(&hdmi->mutex); - } + (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) + __dw_hdmi_setup_rx_sense(hdmi, + phy_stat & HDMI_PHY_HPD, + phy_stat & HDMI_PHY_RX_SENSE); if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { dev_dbg(hdmi->dev, "EVENT=%s\n", @@ -2357,7 +2383,8 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi) #endif dw_hdmi_setup_i2c(hdmi); - dw_hdmi_phy_setup_hpd(hdmi); + if (hdmi->phy.ops->setup_hpd) + hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data); memset(&pdevinfo, 0, sizeof(pdevinfo)); pdevinfo.parent = dev; diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 45c2c15..e63d675 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -117,6 +117,9 @@ struct dw_hdmi_phy_ops { struct drm_display_mode *mode); void (*disable)(struct dw_hdmi *hdmi, void *data); enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data); + void (*update_hpd)(struct dw_hdmi *hdmi, void *data, + bool force, bool disabled, bool rxsense); + void (*setup_hpd)(struct dw_hdmi *hdmi, void *data); }; struct dw_hdmi_plat_data { @@ -147,6 +150,8 @@ int dw_hdmi_probe(struct platform_device *pdev, int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, const struct dw_hdmi_plat_data *plat_data); +void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense); + void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate); void dw_hdmi_audio_enable(struct dw_hdmi *hdmi); void dw_hdmi_audio_disable(struct dw_hdmi *hdmi); -- 1.9.1