From patchwork Fri Mar 31 14:25:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 9656479 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 9E96360351 for ; Fri, 31 Mar 2017 14:25:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 912F6286A9 for ; Fri, 31 Mar 2017 14:25:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8616E286B4; Fri, 31 Mar 2017 14:25:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 04AF0286A9 for ; Fri, 31 Mar 2017 14:25:44 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DE05F6EAE7; Fri, 31 Mar 2017 14:25:40 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-wm0-x231.google.com (mail-wm0-x231.google.com [IPv6:2a00:1450:400c:c09::231]) by gabe.freedesktop.org (Postfix) with ESMTPS id 84AF96EAD8 for ; Fri, 31 Mar 2017 14:25:34 +0000 (UTC) Received: by mail-wm0-x231.google.com with SMTP id o81so89807wmb.1 for ; Fri, 31 Mar 2017 07:25:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6tzvsoCimQ3Br6YNO+1kQrVyj8n/Fe4wvJf3VoNh3Pc=; b=xyG1SFMkIEwJ3w/pqFtZpIvXfrB7mo9hThbvgO3oucuLlOVo5b/U+g4v35zNs1PBzR h+9Yfdo4+QVheJ8/wTmsyQ6lznn9huMt2xoK2JV3z76YkvhqH0TJbaqKpG8JbYAQR1wW YWqu+a9MaHzQF/m6aWW+3HN0R0xMWomEMR1/vyXqYVrrfiWW7OADrtQweIcnZkDBjiiv k1fCcKjclX/wyK0DZnAILAzBqBMp7NMjuN1D6WR59M2hP2dIL1siC8GwvooYhh1uVe/r QXROjaUq/53b0isj6khC0KHKGVAqqwcRDS7D+rwtNlKleMosCckJjD3GY3tLE58VavIS oF2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6tzvsoCimQ3Br6YNO+1kQrVyj8n/Fe4wvJf3VoNh3Pc=; b=V1CvlfWT4tRy91HlO/D4nqJnhYILTmTSRYjybWhMIsodBKSKgDJUbCOxDFF7VVljkK l2wHnjHxmt6Zi7gghaFQGoyDCvkO+fGJEGQyP1E/5ghnuZJaGC8oxJsV3TblLEtqiWZS q/5HmoIHjYRKmXcG2FOH4VEXXrzVJpDDyWh9WpusGVabMZprHq8VdQLm8igFhFX0zjK5 ENlSDTfPD0Lj7OqArI+6CvcNjBUh6e8wQ/1CmgOpVEwp8xox8Wc+pivH8mRwniqMOBez xQzFSHcduew/83owEIyfCPT+G7cZeYWNEp69bjh0eFEgT4xHfyn38jAG6l2jsqqPssYy NfUg== X-Gm-Message-State: AFeK/H0z5KgNjYRYo2UAQ9yxRD2IwFj2xoPOptJjadU7usS9hl1d39aTgSOABF8sS/wGFvAi X-Received: by 10.28.150.145 with SMTP id y139mr3594269wmd.109.1490970332969; Fri, 31 Mar 2017 07:25:32 -0700 (PDT) Received: from localhost.localdomain ([90.63.244.31]) by smtp.gmail.com with ESMTPSA id 92sm6963478wrh.8.2017.03.31.07.25.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 31 Mar 2017 07:25:32 -0700 (PDT) From: Neil Armstrong To: dri-devel@lists.freedesktop.org, laurent.pinchart+renesas@ideasonboard.com, architt@codeaurora.org Subject: [PATCH v5.1 6/6] drm: bridge: dw-hdmi: Move HPD handling to PHY operations Date: Fri, 31 Mar 2017 16:25:19 +0200 Message-Id: <1490970319-24981-7-git-send-email-narmstrong@baylibre.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1490970319-24981-1-git-send-email-narmstrong@baylibre.com> References: <1490970319-24981-1-git-send-email-narmstrong@baylibre.com> 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 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 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);