From patchwork Sun Jan 4 20:05:38 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 425191 X-Patchwork-Delegate: ijc@hellion.org.uk Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 4E2B6140082 for ; Mon, 5 Jan 2015 07:06:19 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 8CFFD4B77A; Sun, 4 Jan 2015 21:06:14 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Og7FXQqJ9LtY; Sun, 4 Jan 2015 21:06:14 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id F12694B755; Sun, 4 Jan 2015 21:06:09 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 1EC404B741 for ; Sun, 4 Jan 2015 21:06:02 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id N89KACGlNj9f for ; Sun, 4 Jan 2015 21:06:02 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by theia.denx.de (Postfix) with ESMTPS id 99F614B73C for ; Sun, 4 Jan 2015 21:05:57 +0100 (CET) Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t04K5i5T026407 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Sun, 4 Jan 2015 15:05:44 -0500 Received: from shalem.localdomain.com (vpn1-4-122.ams2.redhat.com [10.36.4.122]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t04K5f1g024722; Sun, 4 Jan 2015 15:05:42 -0500 From: Hans de Goede To: Ian Campbell Date: Sun, 4 Jan 2015 21:05:38 +0100 Message-Id: <1420401940-15136-1-git-send-email-hdegoede@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 Cc: u-boot@lists.denx.de Subject: [U-Boot] [PATCH 1/3] sunxi: video: Add lvds support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.13 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Add support for lvds lcd panels Signed-off-by: Hans de Goede --- arch/arm/include/asm/arch-sunxi/clock_sun4i.h | 2 ++ arch/arm/include/asm/arch-sunxi/display.h | 12 ++++++++++ arch/arm/include/asm/arch-sunxi/gpio.h | 1 + board/sunxi/Kconfig | 14 ++++++++++++ drivers/video/sunxi_display.c | 33 +++++++++++++++++++++++++-- 5 files changed, 60 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h index 64b5c38..70b789e 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h @@ -284,6 +284,8 @@ struct sunxi_ccm_reg { /* Enable / disable both ch1 sclk1 and sclk2 at the same time */ #define CCM_LCD_CH1_CTRL_GATE (0x1 << 31 | 0x1 << 15) +#define CCM_LVDS_CTRL_RST (1 << 0) + #define CCM_HDMI_CTRL_M(n) ((((n) - 1) & 0xf) << 0) #define CCM_HDMI_CTRL_PLL_MASK (3 << 24) #define CCM_HDMI_CTRL_PLL3 (0 << 24) diff --git a/arch/arm/include/asm/arch-sunxi/display.h b/arch/arm/include/asm/arch-sunxi/display.h index 44a274d..f1dfde1 100644 --- a/arch/arm/include/asm/arch-sunxi/display.h +++ b/arch/arm/include/asm/arch-sunxi/display.h @@ -88,6 +88,9 @@ struct sunxi_lcdc_reg { u8 res3[0x44]; /* 0xac */ u32 tcon1_io_polarity; /* 0xf0 */ u32 tcon1_io_tristate; /* 0xf4 */ + u8 res4[0x128]; /* 0xf8 */ + u32 lvds_ana0; /* 0x220 */ + u32 lvds_ana1; /* 0x224 */ }; struct sunxi_hdmi_reg { @@ -241,12 +244,21 @@ struct sunxi_tve_reg { #define SUNXI_LCDC_TCON0_TIMING_H_TOTAL(n) (((n) - 1) << 16) #define SUNXI_LCDC_TCON0_TIMING_V_BP(n) (((n) - 1) << 0) #define SUNXI_LCDC_TCON0_TIMING_V_TOTAL(n) (((n) * 2) << 16) +#define SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(n) ((n) << 26) +#define SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE (1 << 31) +#define SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE0 (0 << 28) +#define SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE60 (1 << 28) +#define SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE120 (2 << 28) #define SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(n) (((n) & 0x1f) << 4) #define SUNXI_LCDC_TCON1_CTRL_ENABLE (1 << 31) #define SUNXI_LCDC_TCON1_TIMING_H_BP(n) (((n) - 1) << 0) #define SUNXI_LCDC_TCON1_TIMING_H_TOTAL(n) (((n) - 1) << 16) #define SUNXI_LCDC_TCON1_TIMING_V_BP(n) (((n) - 1) << 0) #define SUNXI_LCDC_TCON1_TIMING_V_TOTAL(n) (((n) * 2) << 16) +#define SUNXI_LCDC_LVDS_ANA0 0x3f310000 +#define SUNXI_LCDC_LVDS_ANA0_UPDATE (1 << 22) +#define SUNXI_LCDC_LVDS_ANA1_INIT1 (0x1f << 26 | 0x1f << 10) +#define SUNXI_LCDC_LVDS_ANA1_INIT2 (0x1f << 16 | 0x1f << 00) /* * HDMI register constants. diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 9438f5a..71cc879 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -151,6 +151,7 @@ enum sunxi_gpio_number { #define SUNXI_GPC6_SDC2 3 #define SUNXI_GPD0_LCD0 2 +#define SUNXI_GPD0_LVDS0 3 #define SUNXI_GPF0_SDC0 2 diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index 8782394..fdb18a4 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -345,6 +345,20 @@ config VIDEO_LCD_BL_PWM Set the backlight pwm pin for the LCD panel. This takes a string in the format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H. +choice + prompt "LCD panel support" + depends on VIDEO + ---help--- + Select which type of LCD panel to support. + +config VIDEO_LCD_PANEL_PARALLEL + bool "Generic parallel interface LCD panel" + +config VIDEO_LCD_PANEL_LVDS + bool "Generic lvds interface LCD panel" + +endchoice + config USB_KEYBOARD boolean "Enable USB keyboard support" default y diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index 319e578..4b63b01 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -339,8 +339,12 @@ static void sunxi_lcdc_pll_set(int tcon, int dotclock, int best_double = 0; if (tcon == 0) { +#ifdef CONFIG_VIDEO_LCD_PANEL_LVDS + min_m = max_m = 7; +#else min_m = 6; max_m = 127; +#endif } else { min_m = 1; max_m = 15; @@ -420,6 +424,9 @@ static void sunxi_lcdc_init(void) /* Clock on */ setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0); +#ifdef CONFIG_VIDEO_LCD_PANEL_LVDS + setbits_le32(&ccm->lvds_clk_cfg, CCM_LVDS_CTRL_RST); +#endif /* Init lcdc */ writel(0, &lcdc->ctrl); /* Disable tcon */ @@ -439,6 +446,16 @@ static void sunxi_lcdc_enable(void) (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; setbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE); +#ifdef CONFIG_VIDEO_LCD_PANEL_LVDS + setbits_le32(&lcdc->tcon0_lvds_intf, SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE); + setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0); + setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE); + udelay(2); /* delay at least 1200 ns */ + setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT1); + udelay(1); /* delay at least 120 ns */ + setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT2); + setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE); +#endif } static void sunxi_lcdc_panel_enable(void) @@ -507,7 +524,11 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode) int bp, clk_delay, clk_div, clk_double, pin, total, val; for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++) +#ifdef CONFIG_VIDEO_LCD_PANEL_LVDS + sunxi_gpio_set_cfgpin(pin, SUNXI_GPD0_LVDS0); +#else sunxi_gpio_set_cfgpin(pin, SUNXI_GPD0_LCD0); +#endif sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double); @@ -535,12 +556,16 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode) writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) | SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v); +#ifdef CONFIG_VIDEO_LCD_PANEL_LVDS + val = (sunxi_display.depth == 18) ? 1 : 0; + writel(SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(val), &lcdc->tcon0_lvds_intf); +#else writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len), &lcdc->tcon0_timing_sync); - /* We only support hv-sync parallel lcd-s for now */ writel(0, &lcdc->tcon0_hv_intf); writel(0, &lcdc->tcon0_cpu_intf); +#endif if (sunxi_display.depth == 18 || sunxi_display.depth == 17) { writel(SUNXI_LCDC_FRAME_CTRL_DITHER0, &lcdc->frame_ctrl[1]); @@ -559,7 +584,11 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode) &lcdc->frame_ctrl[0]); } - val = 0; +#ifdef CONFIG_VIDEO_LCD_PANEL_LVDS + val = SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE60; +#else + val = SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE0; +#endif if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT)) val |= SUNXI_LCDC_TCON_HSYNC_MASK; if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))