From patchwork Thu May 2 22:53:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 10927725 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3FA191398 for ; Thu, 2 May 2019 22:54:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 267D92434C for ; Thu, 2 May 2019 22:54:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 19BD826E47; Thu, 2 May 2019 22:54:28 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 B43192434C for ; Thu, 2 May 2019 22:54:27 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 10FDC8925D; Thu, 2 May 2019 22:54:25 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-pg1-x544.google.com (mail-pg1-x544.google.com [IPv6:2607:f8b0:4864:20::544]) by gabe.freedesktop.org (Postfix) with ESMTPS id 88C038925D for ; Thu, 2 May 2019 22:54:24 +0000 (UTC) Received: by mail-pg1-x544.google.com with SMTP id n2so1710673pgg.13 for ; Thu, 02 May 2019 15:54:24 -0700 (PDT) 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:mime-version :content-transfer-encoding; bh=U2bbAFLYHg7BbnCqa8Z/3P6ZnGKzIwrgxFqmU0u6MtQ=; b=D1NX5TmPXtb7qxK3+1Ztynw4+2uJvsuUHMmPNW5HLtbWNpfxZfwh+KWKqechMTAdJh preLJ5WLmboeoExgyIszAA8E7PgV75jaJPsi5tXWONJJLVl9VH5nxti0tUPIXwzDqpD8 cwreSf4ZSn3rtEVABFKBqk8V+iINCBGPFGH4jYdEaK48HhzBqcxtn7vpLmHk22KsAgU3 M4IYY3S+lRwIf8/w62Jsq2TSHK+qmPSlNuwEGzde8kEVeWS40We82h0oskJNbPMCY+uQ VJyKnjHx0de2S6jNGH3WLm61xRV1Es1NLRX2YwpEpUHy8T1v1Q9wf331w6dTxYFg1CJL oo3g== X-Gm-Message-State: APjAAAVyrWd64C0FO5VC2/mGXOV62nwKw/hVqQJn2p+6vtq2r9fRfGoF cRylTs90Sh3hD0tnrFEll1CwkA== X-Google-Smtp-Source: APXvYqwTNwDX8rXg0Agwu8rSnUQ7+u0qFbATbHXFLNSH3EgUqxCM+Vs9APjZJjt0fwjZRPzV6nerSA== X-Received: by 2002:a65:6688:: with SMTP id b8mr6519822pgw.81.1556837664123; Thu, 02 May 2019 15:54:24 -0700 (PDT) Received: from tictac2.mtv.corp.google.com ([2620:15c:202:1:24fa:e766:52c9:e3b2]) by smtp.gmail.com with ESMTPSA id v15sm264736pff.105.2019.05.02.15.54.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 May 2019 15:54:23 -0700 (PDT) From: Douglas Anderson To: Heiko Stuebner , Sandy Huang , Andrzej Hajda , Laurent Pinchart , Rob Herring Subject: [PATCH 1/5] dt-bindings: drm/bridge/synopsys: dw-hdmi: Add "unwedge" for ddc bus Date: Thu, 2 May 2019 15:53:32 -0700 Message-Id: <20190502225336.206885-1-dianders@chromium.org> X-Mailer: git-send-email 2.21.0.1020.gf2820cf01a-goog MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=U2bbAFLYHg7BbnCqa8Z/3P6ZnGKzIwrgxFqmU0u6MtQ=; b=nvDXTTBkx6gM2GY6hocJXtXsnawL+o/xemGlJje4+eusDN2A0o97J9U5hlrR6RCeYY IaJiOv66CzjRFRG/86f/hhXlcSZ+ENN1Ls1spzYSyWL9Pe4VRgvlST5J0rYjN+wmNlBC i7F+im4W83ea6FPef3xVPExFEFv7Pdt/bcRcQ= X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , devicetree@vger.kernel.org, Neil Armstrong , David Airlie , Douglas Anderson , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, mka@chromium.org, Sean Paul , linux-arm-kernel@lists.infradead.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP In certain situations it was seen that we could wedge up the DDC bus on the HDMI adapter on rk3288. The only way to unwedge was to mux one of the pins over to GPIO output-driven-low temporarily and then quickly mux back. Full details can be found in the patch ("drm/bridge/synopsys: dw-hdmi: Add "unwedge" for ddc bus"). Since unwedge requires remuxing the pins, we first need to add to the bindings so that we can specify what state the pins should be in for unwedging. Signed-off-by: Douglas Anderson Reviewed-by: Rob Herring --- .../bindings/display/rockchip/dw_hdmi-rockchip.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt index 39143424a474..8346bac81f1c 100644 --- a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt +++ b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt @@ -38,6 +38,13 @@ Optional properties - phys: from general PHY binding: the phandle for the PHY device. - phy-names: Should be "hdmi" if phys references an external phy. +Optional pinctrl entry: +- If you have both a "unwedge" and "default" pinctrl entry, dw_hdmi + will switch to the unwedge pinctrl state for 10ms if it ever gets an + i2c timeout. It's intended that this unwedge pinctrl entry will + cause the SDA line to be driven low to work around a hardware + errata. + Example: hdmi: hdmi@ff980000 { From patchwork Thu May 2 22:53:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 10927727 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5BE82912 for ; Thu, 2 May 2019 22:54:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4B3F122F3E for ; Thu, 2 May 2019 22:54:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3F46A26E3D; Thu, 2 May 2019 22:54:30 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 B13352434C for ; Thu, 2 May 2019 22:54:29 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id AD2C689453; Thu, 2 May 2019 22:54:27 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-pf1-x441.google.com (mail-pf1-x441.google.com [IPv6:2607:f8b0:4864:20::441]) by gabe.freedesktop.org (Postfix) with ESMTPS id D085189453 for ; Thu, 2 May 2019 22:54:25 +0000 (UTC) Received: by mail-pf1-x441.google.com with SMTP id e67so1845771pfe.10 for ; Thu, 02 May 2019 15:54:25 -0700 (PDT) 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:mime-version:content-transfer-encoding; bh=l64/bY1LxWfLDdKRyx3HvfnrnrE3pPmc5ecC8BHS8F8=; b=VsLuGo0wUu2F5qQ7YAIO+uh7Cq+yRmRNGeRFHKR2nmv2V1CPYPGpD6KoRHlxOT5u4P Zg6emLE/xDIQgZXskALnXCN69KR4hrpcdIpH5Pc9KsKx4Zh0Nu8ZrNePL//zxnBtA1ng ry3R/mm7WI3L5BD91XE5P9NMiqlvhOXjxh03PXw9rh7vyJn5UyEW4ZRJWZe1JnCwNN3Y Qi/cmb+OVYNriNfRmM1ilF6RPZsdKUb9PWMbcBVdpNFi/F6ABwcGYye4k4fE29bSnzfy 4Qi1JwYdrq7t8ELYyjGKVtV1bZT402p+8yh/BKDOol9Hi6xw0y3NNFuBimvFwWOQDMi3 wUeQ== X-Gm-Message-State: APjAAAWLBxIji+5d3zLfkNtxbsOVL+erv3BOL7wG3DOtbe47PIvQ841X vaJ5RTwZtbKI+4BFRv73INZs5g== X-Google-Smtp-Source: APXvYqw76PWYSXX61eOhftbcTudFyvpDPm4S/i4gNcHsWTvjZHUKRbeYb0d9ibyOWF51AFQB+grXKg== X-Received: by 2002:a63:f707:: with SMTP id x7mr6521431pgh.343.1556837665388; Thu, 02 May 2019 15:54:25 -0700 (PDT) Received: from tictac2.mtv.corp.google.com ([2620:15c:202:1:24fa:e766:52c9:e3b2]) by smtp.gmail.com with ESMTPSA id v15sm264736pff.105.2019.05.02.15.54.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 May 2019 15:54:24 -0700 (PDT) From: Douglas Anderson To: Heiko Stuebner , Sandy Huang , Andrzej Hajda , Laurent Pinchart , Rob Herring Subject: [PATCH 2/5] drm/bridge/synopsys: dw-hdmi: Add "unwedge" for ddc bus Date: Thu, 2 May 2019 15:53:33 -0700 Message-Id: <20190502225336.206885-2-dianders@chromium.org> X-Mailer: git-send-email 2.21.0.1020.gf2820cf01a-goog In-Reply-To: <20190502225336.206885-1-dianders@chromium.org> References: <20190502225336.206885-1-dianders@chromium.org> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=l64/bY1LxWfLDdKRyx3HvfnrnrE3pPmc5ecC8BHS8F8=; b=RwI3FCTdhPlmT+vMtbOwvhHezJhcz6S3wikgsAnwkzLmQ+9lRGGWZfnNLQ7JOD3f3V O618Ee2olbH1vL5uLwrwyxrNnp/TRnW88UEo6BeI7bB6wvtvXpGkZYd/9QPsiyrQWmTc S0/rHacmhEwblVNjhViOt5F8O/gOx/K3I45VM= X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Jernej Skrabec , Neil Armstrong , David Airlie , Douglas Anderson , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, mka@chromium.org, Sean Paul Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP See the PhD thesis in the comments in this patch for details, but to summarize this adds a hacky "unwedge" feature to the dw_hdmi i2c bus to workaround what appears to be a hardware errata. This relies on a pinctrl entry to help change around muxing to perform the unwedge. NOTE that the specific TV this was tested on was the "Samsung UN40HU6950FXZA" and the specific port was the "STB" port. Signed-off-by: Douglas Anderson Reviewed-by: Sean Paul --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 116 +++++++++++++++++++--- 1 file changed, 100 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index db761329a1e3..c66587e33813 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -169,6 +170,10 @@ struct dw_hdmi { bool sink_is_hdmi; bool sink_has_audio; + struct pinctrl *pinctrl; + struct pinctrl_state *default_state; + struct pinctrl_state *unwedge_state; + struct mutex mutex; /* for state below and previous_mode */ enum drm_connector_force force; /* mutex-protected force state */ bool disabled; /* DRM has disabled our bridge */ @@ -247,11 +252,82 @@ static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi) HDMI_IH_MUTE_I2CM_STAT0); } +static bool dw_hdmi_i2c_unwedge(struct dw_hdmi *hdmi) +{ + /* If no unwedge state then give up */ + if (IS_ERR(hdmi->unwedge_state)) + return false; + + dev_info(hdmi->dev, "Attempting to unwedge stuck i2c bus\n"); + + /* + * This is a huge hack to workaround a problem where the dw_hdmi i2c + * bus could sometimes get wedged. Once wedged there doesn't appear + * to be any way to unwedge it (including the HDMI_I2CM_SOFTRSTZ) + * other than pulsing the SDA line. + * + * We appear to be able to pulse the SDA line (in the eyes of dw_hdmi) + * by: + * 1. Remux the pin as a GPIO output, driven low. + * 2. Wait a little while. 1 ms seems to work, but we'll do 10. + * 3. Immediately jump to remux the pin as dw_hdmi i2c again. + * + * At the moment of remuxing, the line will still be low due to its + * recent stint as an output, but then it will be pulled high by the + * (presumed) external pullup. dw_hdmi seems to see this as a rising + * edge and that seems to get it out of its jam. + * + * This wedging was only ever seen on one TV, and only on one of + * its HDMI ports. It happened when the TV was powered on while the + * device was plugged in. A scope trace shows the TV bringing both SDA + * and SCL low, then bringing them both back up at roughly the same + * time. Presumably this confuses dw_hdmi because it saw activity but + * no real STOP (maybe it thinks there's another master on the bus?). + * Giving it a clean rising edge of SDA while SCL is already high + * presumably makes dw_hdmi see a STOP which seems to bring dw_hdmi out + * of its stupor. + * + * Note that after coming back alive, transfers seem to immediately + * resume, so if we unwedge due to a timeout we should wait a little + * longer for our transfer to finish, since it might have just started + * now. + */ + pinctrl_select_state(hdmi->pinctrl, hdmi->unwedge_state); + msleep(10); + pinctrl_select_state(hdmi->pinctrl, hdmi->default_state); + + return true; +} + +static int dw_hdmi_i2c_wait(struct dw_hdmi *hdmi) +{ + struct dw_hdmi_i2c *i2c = hdmi->i2c; + int stat; + + stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); + if (!stat) { + /* If we can't unwedge, return timeout */ + if (!dw_hdmi_i2c_unwedge(hdmi)) + return -EAGAIN; + + /* We tried to unwedge; give it another chance */ + stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); + if (!stat) + return -EAGAIN; + } + + /* Check for error condition on the bus */ + if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR) + return -EIO; + + return 0; +} + static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi, unsigned char *buf, unsigned int length) { struct dw_hdmi_i2c *i2c = hdmi->i2c; - int stat; + int ret; if (!i2c->is_regaddr) { dev_dbg(hdmi->dev, "set read register address to 0\n"); @@ -270,13 +346,9 @@ static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi, hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ, HDMI_I2CM_OPERATION); - stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); - if (!stat) - return -EAGAIN; - - /* Check for error condition on the bus */ - if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR) - return -EIO; + ret = dw_hdmi_i2c_wait(hdmi); + if (ret) + return ret; *buf++ = hdmi_readb(hdmi, HDMI_I2CM_DATAI); } @@ -289,7 +361,7 @@ static int dw_hdmi_i2c_write(struct dw_hdmi *hdmi, unsigned char *buf, unsigned int length) { struct dw_hdmi_i2c *i2c = hdmi->i2c; - int stat; + int ret; if (!i2c->is_regaddr) { /* Use the first write byte as register address */ @@ -307,13 +379,9 @@ static int dw_hdmi_i2c_write(struct dw_hdmi *hdmi, hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_WRITE, HDMI_I2CM_OPERATION); - stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); - if (!stat) - return -EAGAIN; - - /* Check for error condition on the bus */ - if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR) - return -EIO; + ret = dw_hdmi_i2c_wait(hdmi); + if (ret) + return ret; } return 0; @@ -2606,6 +2674,22 @@ __dw_hdmi_probe(struct platform_device *pdev, /* If DDC bus is not specified, try to register HDMI I2C bus */ if (!hdmi->ddc) { + /* Look for (optional) stuff related to unwedging */ + hdmi->pinctrl = devm_pinctrl_get(dev); + if (!IS_ERR(hdmi->pinctrl)) { + hdmi->unwedge_state = + pinctrl_lookup_state(hdmi->pinctrl, "unwedge"); + hdmi->default_state = + pinctrl_lookup_state(hdmi->pinctrl, "default"); + + if (IS_ERR(hdmi->default_state) && + !IS_ERR(hdmi->unwedge_state)) { + dev_warn(dev, + "Unwedge requires default pinctrl\n"); + hdmi->unwedge_state = ERR_PTR(-ENODEV); + } + } + hdmi->ddc = dw_hdmi_i2c_adapter(hdmi); if (IS_ERR(hdmi->ddc)) hdmi->ddc = NULL;