From patchwork Sat Feb 11 17:44:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Priit Laes X-Patchwork-Id: 9568051 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 483B360231 for ; Sat, 11 Feb 2017 17:46:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 372B428494 for ; Sat, 11 Feb 2017 17:46:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2A549284E9; Sat, 11 Feb 2017 17:46:04 +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=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 93D6428494 for ; Sat, 11 Feb 2017 17:46:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=v+UweuwFmQSheqdXERTp9Z7PZWWn4jHmOojTbqnPZgQ=; b=Lu1tAftP1HiFnQcRx8eWGlMvga fcXeltTvcG3P66PPnbbznTYaci+Kw/Py2hi+KuUaBs2vWpLtQ8CrP+RR7P3LEnjuCZNvnBi85Sa7u hZ1POYstVWWnDS/s9FXhgSIAAGH3tw80hAJrBCayffXxBTiFH0jUFNmCZZRALDHxAvFP/NA9LG9TQ CCHXA+DVuc9qVldMA56Nan6McNaP91XoNkZkt+HQXBEcNXI1jcRcAhRGUWzaz5WsmGNQqx3tfhueP 75222Z5TPTde0EVxK9//GsB7WNftQhXAaY2rTcQktfave7JdqVEFcqAdlRpkp5q/KTxNbI4t4AHGn KjfoP5Hg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1ccbkI-0001Ly-Lf; Sat, 11 Feb 2017 17:46:02 +0000 Received: from plaes.org ([188.166.43.21]) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1ccbjT-0007aK-Pz for linux-arm-kernel@lists.infradead.org; Sat, 11 Feb 2017 17:45:20 +0000 Received: from localhost (71-43-196-88.dyn.estpak.ee [88.196.43.71]) by plaes.org (Postfix) with ESMTPSA id 3D5B940A7A; Sat, 11 Feb 2017 17:44:24 +0000 (UTC) From: Priit Laes To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, Jonathan Liu , Thierry Reding , Russell King , Chen-Yu Tsai , Mark Rutland , Rob Herring , David Airlie , Maxime Ripard Subject: [PATCH 7/8] drm/sun4i: Add various bits and pieces to enable LVDS support on sun4i Date: Sat, 11 Feb 2017 19:44:04 +0200 Message-Id: <20170211174405.28395-8-plaes@plaes.org> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170211174405.28395-1-plaes@plaes.org> References: <20170211174405.28395-1-plaes@plaes.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170211_094513_209343_30044028 X-CRM114-Status: GOOD ( 16.57 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Quentin Schulz , linux-sunxi@googlegroups.com, Priit Laes MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP TODO: We still rely on u-boot for lvds reset bit setup :( Signed-off-by: Priit Laes --- drivers/gpu/drm/sun4i/sun4i_lvds.c | 29 ++++++++++++++++++++ drivers/gpu/drm/sun4i/sun4i_tcon.c | 54 ++++++++++++++++++++++++++++++++------ drivers/gpu/drm/sun4i/sun4i_tcon.h | 15 +++++++++++ 3 files changed, 90 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c index 2ba4705..de738e5 100644 --- a/drivers/gpu/drm/sun4i/sun4i_lvds.c +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c @@ -114,6 +114,35 @@ static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder) /* encoder->bridge can be NULL; drm_bridge_enable checks for it */ drm_bridge_enable(encoder->bridge); + /* Enable the LVDS */ + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, + SUN4I_TCON0_LVDS_IF_ENABLE, + SUN4I_TCON0_LVDS_IF_ENABLE); + + /* + * TODO: SUN4I_TCON0_LVDS_ANA0_REG_C and SUN4I_TCON0_LVDS_ANA0_PD + * registers span 3 bits, but we only set upper 2 for both + * of them based on values taken from Allwinner driver. + */ + regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, + SUN4I_TCON0_LVDS_ANA0_CK_EN | + SUN4I_TCON0_LVDS_ANA0_REG_V | + SUN4I_TCON0_LVDS_ANA0_REG_C | + SUN4I_TCON0_LVDS_ANA0_EN_MB | + SUN4I_TCON0_LVDS_ANA0_PD | + SUN4I_TCON0_LVDS_ANA0_DCHS); + + udelay(2000); + + regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA1_REG, + SUN4I_TCON0_LVDS_ANA1_INIT); + + udelay(1000); + + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA1_REG, + SUN4I_TCON0_LVDS_ANA1_UPDATE, + SUN4I_TCON0_LVDS_ANA1_UPDATE); + sun4i_tcon_channel_enable(tcon, 0); } diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 71d0087..468a3ce 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -29,6 +30,7 @@ #include "sun4i_crtc.h" #include "sun4i_dotclock.h" #include "sun4i_drv.h" +#include "sun4i_lvds.h" #include "sun4i_rgb.h" #include "sun4i_tcon.h" @@ -169,12 +171,29 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon, SUN4I_TCON0_BASIC2_V_BACKPORCH(bp)); /* Set Hsync and Vsync length */ - hsync = mode->crtc_hsync_end - mode->crtc_hsync_start; - vsync = mode->crtc_vsync_end - mode->crtc_vsync_start; - DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync); - regmap_write(tcon->regs, SUN4I_TCON0_BASIC3_REG, - SUN4I_TCON0_BASIC3_V_SYNC(vsync) | - SUN4I_TCON0_BASIC3_H_SYNC(hsync)); + if (type != DRM_MODE_ENCODER_LVDS) { + // Not needed for LVDS? + hsync = mode->crtc_hsync_end - mode->crtc_hsync_start; + vsync = mode->crtc_vsync_end - mode->crtc_vsync_start; + DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync); + regmap_write(tcon->regs, SUN4I_TCON0_BASIC3_REG, + SUN4I_TCON0_BASIC3_V_SYNC(vsync) | + SUN4I_TCON0_BASIC3_H_SYNC(hsync)); + } + + if (type == DRM_MODE_ENCODER_LVDS) { + /* Setup bit depth */ + /* TODO: Figure out where to get display bit depth + * val = (1: 18-bit, 0: 24-bit) + * TODO: Should we set more registers: + * BIT(28) - LVDS_DIRECTION + * BIT(27) - LVDS_MODE + * BIT(23) - LVDS_CORRECT_MODE + */ + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, + SUN4I_TCON0_LVDS_IF_BITWIDTH, + SUN4I_TCON0_LVDS_IF_BITWIDTH); + } /* Setup the polarity of the various signals */ if (!(mode->flags & DRM_MODE_FLAG_PHSYNC)) @@ -183,8 +202,15 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon, if (!(mode->flags & DRM_MODE_FLAG_PVSYNC)) val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE; + + /* Set proper DCLK phase value */ + if (type == DRM_MODE_ENCODER_LVDS) + val |= SUN4I_TCON0_IO_POL_DCLK_PHASE(1); + regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG, - SUN4I_TCON0_IO_POL_HSYNC_POSITIVE | SUN4I_TCON0_IO_POL_VSYNC_POSITIVE, + SUN4I_TCON0_IO_POL_HSYNC_POSITIVE | + SUN4I_TCON0_IO_POL_VSYNC_POSITIVE | + SUN4I_TCON0_IO_POL_DCLK_PHASE_MASK, val); /* Map output pins to channel 0 */ @@ -480,6 +506,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, struct drm_device *drm = data; struct sun4i_drv *drv = drm->dev_private; struct sun4i_tcon *tcon; + const char *mode; int ret; tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL); @@ -525,7 +552,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, goto err_free_clocks; } - ret = sun4i_rgb_init(drm); + /* Check which output mode is set, defaulting to RGB */ + ret = of_property_read_string(dev->of_node, "mode", &mode); + + if (ret || !strcmp(mode, "rgb")) + ret = sun4i_rgb_init(drm); + else if (!strcmp(mode, "lvds")) + ret = sun4i_lvds_init(drm); + else { + dev_err(dev, "Unknown TCON mode: %s\n", mode); + ret = -1; + } + if (ret < 0) goto err_free_clocks; diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index b040e10..dc4e350 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h @@ -69,8 +69,11 @@ #define SUN4I_TCON0_TTL3_REG 0x7c #define SUN4I_TCON0_TTL4_REG 0x80 #define SUN4I_TCON0_LVDS_IF_REG 0x84 +#define SUN4I_TCON0_LVDS_IF_ENABLE BIT(31) +#define SUN4I_TCON0_LVDS_IF_BITWIDTH BIT(26) #define SUN4I_TCON0_IO_POL_REG 0x88 #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase) ((phase & 3) << 28) +#define SUN4I_TCON0_IO_POL_DCLK_PHASE_MASK (3 << 28) #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE BIT(25) #define SUN4I_TCON0_IO_POL_VSYNC_POSITIVE BIT(24) @@ -128,6 +131,18 @@ #define SUN4I_TCON_CEU_RANGE_G_REG 0x144 #define SUN4I_TCON_CEU_RANGE_B_REG 0x148 #define SUN4I_TCON_MUX_CTRL_REG 0x200 +#define SUN4I_TCON0_LVDS_ANA0_REG 0x220 +#define SUN4I_TCON0_LVDS_ANA0_CK_EN BIT(29) | BIT(28) +#define SUN4I_TCON0_LVDS_ANA0_REG_V BIT(27) | BIT(26) +/* TODO: BIT(23) also belongs to ANA0_REG_C register set */ +#define SUN4I_TCON0_LVDS_ANA0_REG_C BIT(25) | BIT(24) +#define SUN4I_TCON0_LVDS_ANA0_EN_MB BIT(22) +/* TODO: BIT(19) also belongs to ANA0_PD register set */ +#define SUN4I_TCON0_LVDS_ANA0_PD BIT(21) | BIT(20) +#define SUN4I_TCON0_LVDS_ANA0_DCHS BIT(16) +#define SUN4I_TCON0_LVDS_ANA1_REG 0x224 +#define SUN4I_TCON0_LVDS_ANA1_INIT (0x1f << 26 | 0x1f << 10) +#define SUN4I_TCON0_LVDS_ANA1_UPDATE (0x1f << 16 | 0x1f << 00) #define SUN4I_TCON1_FILL_CTL_REG 0x300 #define SUN4I_TCON1_FILL_BEG0_REG 0x304 #define SUN4I_TCON1_FILL_END0_REG 0x308