From patchwork Fri Mar 3 17:20:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 9603311 X-Patchwork-Delegate: geert@linux-m68k.org 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 DB572600CB for ; Fri, 3 Mar 2017 17:23:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C89DC285D0 for ; Fri, 3 Mar 2017 17:23:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BB9DA285C0; Fri, 3 Mar 2017 17:23:37 +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=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 26966285C0 for ; Fri, 3 Mar 2017 17:23:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752089AbdCCRXc (ORCPT ); Fri, 3 Mar 2017 12:23:32 -0500 Received: from galahad.ideasonboard.com ([185.26.127.97]:40901 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751734AbdCCRXE (ORCPT ); Fri, 3 Mar 2017 12:23:04 -0500 Received: from avalon.bb.dnainternet.fi (dfj612ybrt5fhg77mgycy-3.rev.dnainternet.fi [IPv6:2001:14ba:21f5:5b00:2e86:4862:ef6a:2804]) by galahad.ideasonboard.com (Postfix) with ESMTPSA id 6B635204E0; Fri, 3 Mar 2017 18:18:41 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1488561522; bh=0GJEcDJVY/9Q1GlEQyvGjO+4tbT0TJ9YsTml8Cp5+/Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ll+0NjDoGO3Kz8HxxdgUXXS8POwZPhw6nYtb9ZiErj6o/RO1ZJqWr5GKavzGGj5s6 VG7+A7DfNab/xgZVY8RuvBdcKLbymzQzcUm/OOMtX8q+3Z40UTuVWS58vJhJkb5F2x RgFdMN1+uveHnwDVfTQG8SagW95u3sNcHR7JytAM= From: Laurent Pinchart To: dri-devel@lists.freedesktop.org Cc: Andy Yan , Archit Taneja , Fabio Estevam , Jose Abreu , Kieran Bingham , Neil Armstrong , Nickey Yang , Russell King , Vladimir Zapolskiy , linux-renesas-soc@vger.kernel.org Subject: [PATCH v5 05/10] drm: bridge: dw-hdmi: Fix the PHY power up sequence Date: Fri, 3 Mar 2017 19:20:02 +0200 Message-Id: <20170303172007.26541-6-laurent.pinchart+renesas@ideasonboard.com> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20170303172007.26541-1-laurent.pinchart+renesas@ideasonboard.com> References: <20170303172007.26541-1-laurent.pinchart+renesas@ideasonboard.com> Sender: linux-renesas-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When powering the PHY up we need to wait for the PLL to lock. This is done by polling the TX_PHY_LOCK bit in the HDMI_PHY_STAT0 register (interrupt-based wait could be implemented as well but is likely overkill). The bit is asserted when the PLL locks, but the current code incorrectly waits for the bit to be deasserted. Fix it, and while at it, replace the udelay() with a sleep as the code never runs in non-sleepable context. To be consistent with the power down implementation move the poll loop to the power off function. Signed-off-by: Laurent Pinchart Tested-by: Neil Armstrong Reviewed-by: Jose Abreu --- drivers/gpu/drm/bridge/dw-hdmi.c | 65 +++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index 85348ba6bb1c..0aa3ad404f77 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c @@ -949,9 +949,44 @@ static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi) dw_hdmi_phy_gen2_pddq(hdmi, 1); } +static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi) +{ + const struct dw_hdmi_phy_data *phy = hdmi->phy.data; + unsigned int i; + u8 val; + + if (phy->gen == 1) { + dw_hdmi_phy_enable_powerdown(hdmi, false); + + /* Toggle TMDS enable. */ + dw_hdmi_phy_enable_tmds(hdmi, 0); + dw_hdmi_phy_enable_tmds(hdmi, 1); + return 0; + } + + dw_hdmi_phy_gen2_txpwron(hdmi, 1); + dw_hdmi_phy_gen2_pddq(hdmi, 0); + + /* Wait for PHY PLL lock */ + for (i = 0; i < 5; ++i) { + val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK; + if (val) + break; + + usleep_range(1000, 2000); + } + + if (!val) { + dev_err(hdmi->dev, "PHY PLL failed to lock\n"); + return -ETIMEDOUT; + } + + dev_dbg(hdmi->dev, "PHY PLL locked %u iterations\n", i); + return 0; +} + static int hdmi_phy_configure(struct dw_hdmi *hdmi) { - u8 val, msec; const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; @@ -1019,33 +1054,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE, HDMI_3D_TX_PHY_CKCALCTRL); - dw_hdmi_phy_enable_powerdown(hdmi, false); - - /* toggle TMDS enable */ - dw_hdmi_phy_enable_tmds(hdmi, 0); - dw_hdmi_phy_enable_tmds(hdmi, 1); - - /* gen2 tx power on */ - dw_hdmi_phy_gen2_txpwron(hdmi, 1); - dw_hdmi_phy_gen2_pddq(hdmi, 0); - - /* Wait for PHY PLL lock */ - msec = 5; - do { - val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK; - if (!val) - break; - - if (msec == 0) { - dev_err(hdmi->dev, "PHY PLL not locked\n"); - return -ETIMEDOUT; - } - - udelay(1000); - msec--; - } while (1); - - return 0; + return dw_hdmi_phy_power_on(hdmi); } static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)