From patchwork Tue Jan 17 12:31:32 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 9520663 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 7A18D60244 for ; Tue, 17 Jan 2017 12:31:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5427B28500 for ; Tue, 17 Jan 2017 12:31:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 490D828522; Tue, 17 Jan 2017 12:31:52 +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 CBD8E28500 for ; Tue, 17 Jan 2017 12:31:51 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C2F9B6E66A; Tue, 17 Jan 2017 12:31:50 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-wm0-x22f.google.com (mail-wm0-x22f.google.com [IPv6:2a00:1450:400c:c09::22f]) by gabe.freedesktop.org (Postfix) with ESMTPS id CBDE56E66A for ; Tue, 17 Jan 2017 12:31:49 +0000 (UTC) Received: by mail-wm0-x22f.google.com with SMTP id c85so197938652wmi.1 for ; Tue, 17 Jan 2017 04:31:49 -0800 (PST) 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=bayIDHKmt9FnWz3B0omosDJUDwoDdKpU86Quc484XEM=; b=dKOP4mtjIXy5CZlHALe9/yqx2wnON/Q2ArfIO4NkSB0NiNAg0TObXcXslT8P9xViNG uL7GQv+s9DjBgwfAELDdkILtJCwVF37uAASyBlPC+bE3Rd85nZSsvar7Er5EgMYpT3Gm LfFx9q1MwUw4jBo8ty0NgwBsG03f9nwanLMv6ib+gCxpEi8dPIHh8aaSwScwNG8tRJgu bW+OF3f96o7EWnGKBuHEZNYZ9EpOcUaAiuRMhhEBuGh9RAO/07ebW4cWHEYDWL/jkS8H DtaEBDZHNjFKHonn/gpRG1gnKcQaAfUsl6foPqojESP9Jh9iWMuT96sl42HayDYD4UV7 LNng== 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=bayIDHKmt9FnWz3B0omosDJUDwoDdKpU86Quc484XEM=; b=K/sLO0uA2ppvIP5RrvBWr0n0IdfreOnuKi+g5CHcnufQXEhWSMcb5dz6tdKTOAcK1N hLyJU1G9bWg7+O752DUqejFQq2BzIND90Nl9WRKZqIxh06jUJ/ACfc0qNm1FGi/WZc64 Abgkm0vLtiM14T8qDKfIBShtRWc++jDwOfzpnj2yc3vybjcCkLsLq5MjBpy++nOLeDC1 kCn20pzIqHWs0Wg+IZiwaleVZiKL2CWHWfslB1ABPQ+6OlUrnRIlCqeTNaWL72xi6XpQ 8pg8+6zOd+1jtP/5Xo2u2sgQ8MiQ1e1ha0XKcJ8HftqANLHO4w55pYYXycPtNGrPGTZI oF/g== X-Gm-Message-State: AIkVDXJQvooJvqyMQHyGC2Il7zg59aJa1LZMweozdyDx2oRiim2HAhSVu7QLq7+KD/bMNrBy X-Received: by 10.223.148.2 with SMTP id 2mr11666936wrq.75.1484656308403; Tue, 17 Jan 2017 04:31:48 -0800 (PST) Received: from localhost.localdomain (home.amouriers.starnux.net. [82.228.250.61]) by smtp.gmail.com with ESMTPSA id l74sm36678858wmg.2.2017.01.17.04.31.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 17 Jan 2017 04:31:47 -0800 (PST) From: Neil Armstrong To: dri-devel@lists.freedesktop.org, laurent.pinchart+renesas@ideasonboard.com Subject: [RFC/RFT PATCH 2/4] drm/bridge: dw-hdmi: Add support for custom PHY handling Date: Tue, 17 Jan 2017 13:31:32 +0100 Message-Id: <1484656294-6140-3-git-send-email-narmstrong@baylibre.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1484656294-6140-1-git-send-email-narmstrong@baylibre.com> References: <1484656294-6140-1-git-send-email-narmstrong@baylibre.com> Cc: Jose.Abreu@synopsys.com, linux-amlogic@lists.infradead.org, kieran.bingham@ideasonboard.com, linux-kernel@vger.kernel.org, Neil Armstrong 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 Synopsys DesignWare HDMI TX Controller support various Transceivers (PHY) attached to the controller, but also allows fully custom PHYs to be connected. Add PHY init, disable functions in plat_data to handle fully custom PHY init. Some custom PHYs also handles the HPD and RxSense separately and do not use the internal signals exported in the Controller's IRQ stat, so a read_hpd is provided to switch to HPD status polling. To complete the implementation, add a function to mimic the Controllers interrupt HPD and RxSense handling from the vendor PHY wrapper code. Signed-off-by: Neil Armstrong --- drivers/gpu/drm/bridge/dw-hdmi.c | 78 +++++++++++++++++++++++++++++++--------- include/drm/bridge/dw_hdmi.h | 8 +++++ 2 files changed, 70 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index 13747fe..923e250 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c @@ -1434,9 +1434,18 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) hdmi_av_composer(hdmi, mode); /* HDMI Initializateion Step B.2 */ - ret = dw_hdmi_phy_init(hdmi); - if (ret) - return ret; + if (hdmi->plat_data->hdmi_phy_init) { + ret = hdmi->plat_data->hdmi_phy_init(hdmi, hdmi->plat_data, + &hdmi->previous_mode); + if (ret) + return ret; + + hdmi->phy_enabled = true; + } else { + ret = dw_hdmi_phy_init(hdmi); + if (ret) + return ret; + } /* HDMI Initialization Step B.3 */ dw_hdmi_enable_video_path(hdmi); @@ -1551,7 +1560,11 @@ static void dw_hdmi_poweron(struct dw_hdmi *hdmi) static void dw_hdmi_poweroff(struct dw_hdmi *hdmi) { - dw_hdmi_phy_disable(hdmi); + if (hdmi->phy_enabled && hdmi->plat_data->hdmi_phy_disable) { + hdmi->plat_data->hdmi_phy_disable(hdmi, hdmi->plat_data); + hdmi->phy_enabled = false; + } else + dw_hdmi_phy_disable(hdmi); hdmi->bridge_is_on = false; } @@ -1593,6 +1606,9 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi) { u8 old_mask = hdmi->phy_mask; + if (hdmi->plat_data && hdmi->plat_data->hdmi_read_hpd) + return; + if (hdmi->force || hdmi->disabled || !hdmi->rxsense) hdmi->phy_mask |= HDMI_PHY_RX_SENSE; else @@ -1614,6 +1630,11 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi) dw_hdmi_update_phy_mask(hdmi); mutex_unlock(&hdmi->mutex); + if (hdmi->plat_data && hdmi->plat_data->hdmi_read_hpd) + return hdmi->plat_data->hdmi_read_hpd(hdmi, hdmi->plat_data) ? + connector_status_connected : + connector_status_disconnected; + return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ? connector_status_connected : connector_status_disconnected; } @@ -1901,6 +1922,26 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) } }; +void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense) +{ + struct dw_hdmi *hdmi = dev_get_drvdata(dev); + + mutex_lock(&hdmi->mutex); + + if (!hdmi->disabled && !hdmi->force) { + if (!rx_sense) + hdmi->rxsense = false; + + if (hpd) + hdmi->rxsense = true; + + dw_hdmi_update_power(hdmi); + dw_hdmi_update_phy_mask(hdmi); + } + mutex_unlock(&hdmi->mutex); +} +EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense); + static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi) { unsigned int i; @@ -1921,7 +1962,9 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi) return -ENODEV; } - if (!hdmi->phy->configure && !hdmi->plat_data->configure_phy) { + if (!hdmi->phy->configure && + !hdmi->plat_data->configure_phy && + !hdmi->plat_data->hdmi_phy_init) { dev_err(hdmi->dev, "%s requires platform support\n", hdmi->phy->name); return -ENODEV; @@ -2101,15 +2144,17 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi) hdmi->ddc = NULL; } - /* - * Configure registers related to HDMI interrupt - * generation before registering IRQ. - */ - hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0); + if (!hdmi->plat_data || !hdmi->plat_data->hdmi_read_hpd) { + /* + * Configure registers related to HDMI interrupt + * generation before registering IRQ. + */ + hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0); - /* Clear Hotplug interrupts */ - hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, - HDMI_IH_PHY_STAT0); + /* Clear Hotplug interrupts */ + hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, + HDMI_IH_PHY_STAT0); + } hdmi->bridge.driver_private = hdmi; hdmi->bridge.funcs = &dw_hdmi_bridge_funcs; @@ -2119,9 +2164,10 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi) if (ret) goto err_iahb; - /* Unmute interrupts */ - hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), - HDMI_IH_MUTE_PHY_STAT0); + if (!hdmi->plat_data || !hdmi->plat_data->hdmi_read_hpd) + /* Unmute interrupts */ + hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), + HDMI_IH_MUTE_PHY_STAT0); 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 163842d..d6a0ab3 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -61,6 +61,13 @@ struct dw_hdmi_plat_data { enum drm_mode_status (*mode_valid)(struct drm_connector *connector, struct drm_display_mode *mode); struct regmap *regm; + int (*hdmi_phy_init)(struct dw_hdmi *hdmi, + const struct dw_hdmi_plat_data *data, + struct drm_display_mode *mode); + void (*hdmi_phy_disable)(struct dw_hdmi *hdmi, + const struct dw_hdmi_plat_data *data); + bool (*hdmi_read_hpd)(struct dw_hdmi *hdmi, + const struct dw_hdmi_plat_data *data); }; int dw_hdmi_probe(struct platform_device *pdev, @@ -70,6 +77,7 @@ 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);