From 94b23ff3904b82dbfb1653319e5f6b8123c03234 Mon Sep 17 00:00:00 2001 From: Robby Cai Date: Mon, 8 Mar 2010 20:50:58 +0800 Subject: [PATCH] ENGR00121272-2 [MX23] porting lcdif and framebuffer driver to new MSL porting LMS430 lcd panel driver, and adjust mxs lcdif and framebuffer for MX23 Signed-off-by: Robby Cai --- arch/arm/mach-mx23/include/mach/lcdif.h | 1 + drivers/video/backlight/Kconfig | 2 +- drivers/video/mxs/Kconfig | 11 +- drivers/video/mxs/Makefile | 1 + drivers/video/mxs/lcd_lms430.c | 241 +++++++++--------------- drivers/video/mxs/lcdif.c | 1 + drivers/video/mxs/mxsfb.c | 4 +- 7 files changed, 102 insertions(+), 159 deletions(-) diff --git a/arch/arm/mach-mx23/include/mach/lcdif.h b/arch/arm/mach-mx23/include/mach/lcdif.h index 33fe188291d..f0ee0d5e5c1 100644 --- a/arch/arm/mach-mx23/include/mach/lcdif.h +++ b/arch/arm/mach-mx23/include/mach/lcdif.h @@ -32,6 +32,7 @@ #include #include +#include #include "regs-lcdif.h" diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index c30926a7230..17432a6edfa 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -268,7 +268,7 @@ config BACKLIGHT_STMP37XX config BACKLIGHT_MXS tristate "Freescale MXS Backlight Driver" - depends on BACKLIGHT_CLASS_DEVICE && ARCH_MX28 + depends on BACKLIGHT_CLASS_DEVICE && ARCH_MXS default y help If you have a MXS, say y to enable the backlight driver. diff --git a/drivers/video/mxs/Kconfig b/drivers/video/mxs/Kconfig index fa0dd1e2718..aef4aa59dca 100644 --- a/drivers/video/mxs/Kconfig +++ b/drivers/video/mxs/Kconfig @@ -1,6 +1,6 @@ config FB_MXS tristate "MXS Framebuffer driver" - depends on FB && ARCH_MX28 + depends on FB && ARCH_MXS select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -12,4 +12,11 @@ config FB_MXS config FB_MXS_LCD_43WVF1G depends on FB_MXS tristate "SEIKO 4.3' LCD WVGA(800x480) PANEL" - default y + default y if ARCH_MX28 + +config FB_MXS_LCD_LMS430 + depends on FB_MXS + bool "LMS430" + default y if ARCH_MX23 + ---help--- + Use LMS430 dotclock LCD panel for MXS diff --git a/drivers/video/mxs/Makefile b/drivers/video/mxs/Makefile index 892b04f0d7c..a9580add375 100644 --- a/drivers/video/mxs/Makefile +++ b/drivers/video/mxs/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_ARCH_MXS) += lcdif.o obj-$(CONFIG_FB_MXS) += mxsfb.o obj-$(CONFIG_FB_MXS_LCD_43WVF1G) += lcd_43wvf1g.o +obj-$(CONFIG_FB_MXS_LCD_LMS430) += lcd_lms430.o diff --git a/drivers/video/mxs/lcd_lms430.c b/drivers/video/mxs/lcd_lms430.c index 4654cc3893c..00273b73158 100644 --- a/drivers/video/mxs/lcd_lms430.c +++ b/drivers/video/mxs/lcd_lms430.c @@ -1,38 +1,39 @@ /* - * Freescale STMP378X Samsung LMS430 LCD panel initialization + * Freescale MXS Samsung LMS430 LCD panel initialization * * Embedded Alley Solutions, Inc * * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. * Copyright 2009 Embedded Alley Solutions, Inc All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ #include #include #include #include #include +#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include -#include +#include +#include + +#define REGS_PWM_BASE IO_ADDRESS(PWM_PHYS_ADDR) #define DOTCLK_H_ACTIVE 480 #define DOTCLK_H_PULSE_WIDTH 1 @@ -41,85 +42,36 @@ #define DOTCLK_H_WAIT_CNT (DOTCLK_H_PULSE_WIDTH + (3 * DOTCLK_HB_PORCH)) #define DOTCLK_H_PERIOD (DOTCLK_H_WAIT_CNT + DOTCLK_HF_PORCH + DOTCLK_H_ACTIVE) -#define DOTCLK_V_PULSE_WIDTH 1 #define DOTCLK_V_ACTIVE 272 +#define DOTCLK_V_PULSE_WIDTH 1 #define DOTCLK_VF_PORCH 4 #define DOTCLK_VB_PORCH 12 #define DOTCLK_V_WAIT_CNT (DOTCLK_V_PULSE_WIDTH + DOTCLK_VB_PORCH) #define DOTCLK_V_PERIOD (DOTCLK_VF_PORCH + DOTCLK_V_ACTIVE + DOTCLK_V_WAIT_CNT) -static struct stmp3xxx_platform_bl_data bl_data; -extern struct pin_group lcd_pins; -extern unsigned lcd_spi_pins[]; - -static int init_pinmux(void) -{ - return stmp3xxx_request_pin_group(&lcd_pins, "lcd_lms430"); -} - -static int init_pinmux_spi(void) -{ - int ret = -EINVAL; - - ret = gpio_request(lcd_spi_pins[SPI_MOSI], "lcd_lms430"); - if (ret) - goto out_1; - - ret = gpio_request(lcd_spi_pins[SPI_SCLK], "lcd_lms430"); - if (ret) - goto out_2; - ret = gpio_request(lcd_spi_pins[SPI_CS], "lcd_lms430"); - if (ret) - goto out_3; - - /* Enable these pins as outputs */ - gpio_direction_output(lcd_spi_pins[SPI_MOSI], 1); - gpio_direction_output(lcd_spi_pins[SPI_SCLK], 1); - gpio_direction_output(lcd_spi_pins[SPI_CS], 1); - - return 0; -out_3: - gpio_free(lcd_spi_pins[SPI_SCLK]); -out_2: - gpio_free(lcd_spi_pins[SPI_MOSI]); -out_1: - return ret; -} - -static void uninit_pinmux(void) -{ - stmp3xxx_release_pin_group(&lcd_pins, "lcd_lms430"); -} - -static void uninit_pinmux_spi(void) -{ - gpio_free(lcd_spi_pins[SPI_MOSI]); - gpio_free(lcd_spi_pins[SPI_SCLK]); - gpio_free(lcd_spi_pins[SPI_CS]); -} - +static struct mxs_platform_bl_data bl_data; static struct clk *lcd_clk; static int init_panel(struct device *dev, dma_addr_t phys, int memsize, - struct stmp3xxx_platform_fb_entry *pentry) + struct mxs_platform_fb_entry *pentry) { int ret = 0; - - lcd_clk = clk_get(dev, "lcdif"); + lcd_clk = clk_get(NULL, "lcdif"); if (IS_ERR(lcd_clk)) { ret = PTR_ERR(lcd_clk); - goto out_1; + goto out; } ret = clk_enable(lcd_clk); if (ret) { clk_put(lcd_clk); - goto out_1; + goto out; } - ret = clk_set_rate(lcd_clk, 1000000 / pentry->cycle_time_ns); /* kHz */ + + ret = clk_set_rate(lcd_clk, 1000000000 / pentry->cycle_time_ns); /* Hz */ if (ret) { clk_disable(lcd_clk); clk_put(lcd_clk); - goto out_1; + goto out; } /* @@ -127,55 +79,43 @@ static int init_panel(struct device *dev, dma_addr_t phys, int memsize, * First make it low for 100 msec, hi for 10 msec, low for 10 msec, * then hi. */ - stmp3xxx_clearl(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1); /* low */ + __raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR); /* low */ mdelay(100); - stmp3xxx_setl(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1); /* high */ + __raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET); /* high */ mdelay(10); - stmp3xxx_clearl(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1); /* low */ + __raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR); /* low */ /* For the Samsung, Reset must be held low at least 30 uSec * Therefore, we'll hold it low for about 10 mSec just to be sure. * Then we'll wait 1 mSec afterwards. */ mdelay(10); - stmp3xxx_setl(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1); /* high */ + __raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET); /* high */ mdelay(1); - ret = init_pinmux(); - if (ret) - goto out_1; - ret = init_pinmux_spi(); - if (ret) - goto out_2; - setup_dotclk_panel(DOTCLK_V_PULSE_WIDTH, DOTCLK_V_PERIOD, DOTCLK_V_WAIT_CNT, DOTCLK_V_ACTIVE, DOTCLK_H_PULSE_WIDTH, DOTCLK_H_PERIOD, DOTCLK_H_WAIT_CNT, DOTCLK_H_ACTIVE, 0); - ret = stmp3xxx_lcdif_dma_init(dev, phys, memsize, 1); + ret = mxs_lcdif_dma_init(dev, phys, memsize); if (ret) - goto out_3; + goto out; - stmp3xxx_lcd_set_bl_pdata(pentry->bl_data); - stmp3xxx_lcdif_notify_clients(STMP3XXX_LCDIF_PANEL_INIT, pentry); + mxs_lcd_set_bl_pdata(pentry->bl_data); + mxs_lcdif_notify_clients(MXS_LCDIF_PANEL_INIT, pentry); return 0; -out_3: - uninit_pinmux_spi(); -out_2: - uninit_pinmux(); -out_1: + +out: return ret; } static void release_panel(struct device *dev, - struct stmp3xxx_platform_fb_entry *pentry) + struct mxs_platform_fb_entry *pentry) { - stmp3xxx_lcdif_notify_clients(STMP3XXX_LCDIF_PANEL_RELEASE, pentry); - uninit_pinmux_spi(); - uninit_pinmux(); + mxs_lcdif_notify_clients(MXS_LCDIF_PANEL_RELEASE, pentry); release_dotclk_panel(); - stmp3xxx_lcdif_dma_release(); + mxs_lcdif_dma_release(); clk_disable(lcd_clk); clk_put(lcd_clk); } @@ -189,8 +129,8 @@ static int blank_panel(int blank) case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_POWERDOWN: - stmp3xxx_clearl(BM_LCDIF_CTRL_BYPASS_COUNT, - REGS_LCDIF_BASE + HW_LCDIF_CTRL); + __raw_writel(BM_LCDIF_CTRL_BYPASS_COUNT, + REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR); for (count = 10000; count; count--) { if (__raw_readl(REGS_LCDIF_BASE + HW_LCDIF_STAT) & BM_LCDIF_STAT_TXFIFO_EMPTY) @@ -200,8 +140,8 @@ static int blank_panel(int blank) break; case FB_BLANK_UNBLANK: - stmp3xxx_setl(BM_LCDIF_CTRL_BYPASS_COUNT, - REGS_LCDIF_BASE + HW_LCDIF_CTRL); + __raw_writel(BM_LCDIF_CTRL_BYPASS_COUNT, + REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET); break; default: @@ -210,75 +150,61 @@ static int blank_panel(int blank) return ret; } -static struct stmp3xxx_platform_fb_entry fb_entry = { +static struct mxs_platform_fb_entry fb_entry = { .name = "lms430", .x_res = 272, .y_res = 480, .bpp = 32, .cycle_time_ns = 150, - .lcd_type = STMP3XXX_LCD_PANEL_DOTCLK, + .lcd_type = MXS_LCD_PANEL_DOTCLK, .init_panel = init_panel, .release_panel = release_panel, .blank_panel = blank_panel, - .run_panel = stmp3xxx_lcdif_run, - .stop_panel = stmp3xxx_lcdif_stop, - .pan_display = stmp3xxx_lcdif_pan_display, + .run_panel = mxs_lcdif_run, + .stop_panel = mxs_lcdif_stop, + .pan_display = mxs_lcdif_pan_display, .bl_data = &bl_data, }; static struct clk *pwm_clk; -static int init_bl(struct stmp3xxx_platform_bl_data *data) +static int init_bl(struct mxs_platform_bl_data *data) { int ret = 0; pwm_clk = clk_get(NULL, "pwm"); if (IS_ERR(pwm_clk)) { ret = PTR_ERR(pwm_clk); - goto out; + return ret; } clk_enable(pwm_clk); - stmp3xxx_reset_block(REGS_PWM_BASE, 1); + mxs_reset_block(REGS_PWM_BASE, 1); - ret = stmp3xxx_request_pin(PINID_PWM2, PIN_FUN1, "lcd_lms430"); - if (ret) - goto out_mux; - - stmp3xxx_pin_voltage(PINID_PWM2, PIN_8MA, "lcd_lms430"); - stmp3xxx_pin_strength(PINID_PWM2, PIN_3_3V, "lcd_lms430"); - - __raw_writel(BF(0, PWM_ACTIVEn_INACTIVE) | - BF(0, PWM_ACTIVEn_ACTIVE), REGS_PWM_BASE + HW_PWM_ACTIVEn(2)); - __raw_writel(BF(6, PWM_PERIODn_CDIV) | /* divide by 64 */ - BF(2, PWM_PERIODn_INACTIVE_STATE) | /* low */ - BF(3, PWM_PERIODn_ACTIVE_STATE) | /* high */ - BF(599, PWM_PERIODn_PERIOD), + __raw_writel(BF_PWM_ACTIVEn_INACTIVE(0) | + BF_PWM_ACTIVEn_ACTIVE(0), + REGS_PWM_BASE + HW_PWM_ACTIVEn(2)); + __raw_writel(BF_PWM_PERIODn_CDIV(6) | /* divide by 64 */ + BF_PWM_PERIODn_INACTIVE_STATE(2) | /* low */ + BF_PWM_PERIODn_ACTIVE_STATE(3) | /* high */ + BF_PWM_PERIODn_PERIOD(599), REGS_PWM_BASE + HW_PWM_PERIODn(2)); - stmp3xxx_setl(BM_PWM_CTRL_PWM2_ENABLE, REGS_PWM_BASE + HW_PWM_CTRL); + __raw_writel(BM_PWM_CTRL_PWM2_ENABLE, REGS_PWM_BASE + HW_PWM_CTRL_SET); return 0; - -out_mux: - clk_put(pwm_clk); -out: - return ret; } -static void free_bl(struct stmp3xxx_platform_bl_data *data) +static void free_bl(struct mxs_platform_bl_data *data) { - __raw_writel(BF(0, PWM_ACTIVEn_INACTIVE) | - BF(0, PWM_ACTIVEn_ACTIVE), + __raw_writel(BF_PWM_ACTIVEn_INACTIVE(0) | + BF_PWM_ACTIVEn_ACTIVE(0), REGS_PWM_BASE + HW_PWM_ACTIVEn(2)); - __raw_writel(BF(6, PWM_PERIODn_CDIV) | /* divide by 64 */ - BF(2, PWM_PERIODn_INACTIVE_STATE) | /* low */ - BF(3, PWM_PERIODn_ACTIVE_STATE) | /* high */ - BF(599, PWM_PERIODn_PERIOD), + __raw_writel(BF_PWM_PERIODn_CDIV(6) | /* divide by 64 */ + BF_PWM_PERIODn_INACTIVE_STATE(2) | /* low */ + BF_PWM_PERIODn_ACTIVE_STATE(3) | /* high */ + BF_PWM_PERIODn_PERIOD(599), REGS_PWM_BASE + HW_PWM_PERIODn(2)); - stmp3xxx_clearl(BM_PWM_CTRL_PWM2_ENABLE, REGS_PWM_BASE + HW_PWM_CTRL); - stmp3xxx_pin_voltage(PINID_PWM2, PIN_4MA, "lcd_lms430"); - stmp3xxx_pin_strength(PINID_PWM2, PIN_1_8V, "lcd_lms430"); + __raw_writel(BM_PWM_CTRL_PWM2_ENABLE, REGS_PWM_BASE + HW_PWM_CTRL_CLR); - stmp3xxx_release_pin(PINID_PWM2, "lcd_lms430"); clk_disable(pwm_clk); clk_put(pwm_clk); } @@ -306,7 +232,7 @@ static int bl_to_power(int br) return base + (rem * (power[br / 10 + 1]) - base) / 10; } -static int set_bl_intensity(struct stmp3xxx_platform_bl_data *data, +static int set_bl_intensity(struct mxs_platform_bl_data *data, struct backlight_device *bd, int suspended) { int intensity = bd->props.brightness; @@ -333,18 +259,18 @@ static int set_bl_intensity(struct stmp3xxx_platform_bl_data *data, scaled_int += rem * (values[intensity / 10 + 1] - values[intensity / 10]) / 10; } - __raw_writel(BF(scaled_int, PWM_ACTIVEn_INACTIVE) | - BF(0, PWM_ACTIVEn_ACTIVE), + __raw_writel(BF_PWM_ACTIVEn_INACTIVE(scaled_int) | + BF_PWM_ACTIVEn_ACTIVE(0), REGS_PWM_BASE + HW_PWM_ACTIVEn(2)); - __raw_writel(BF(6, PWM_PERIODn_CDIV) | /* divide by 64 */ - BF(2, PWM_PERIODn_INACTIVE_STATE) | /* low */ - BF(3, PWM_PERIODn_ACTIVE_STATE) | /* high */ - BF(399, PWM_PERIODn_PERIOD), + __raw_writel(BF_PWM_PERIODn_CDIV(6) | /* divide by 64 */ + BF_PWM_PERIODn_INACTIVE_STATE(2) | /* low */ + BF_PWM_PERIODn_ACTIVE_STATE(3) | /* high */ + BF_PWM_PERIODn_PERIOD(399), REGS_PWM_BASE + HW_PWM_PERIODn(2)); return 0; } -static struct stmp3xxx_platform_bl_data bl_data = { +static struct mxs_platform_bl_data bl_data = { .bl_max_intensity = 100, .bl_default_intensity = 50, .bl_cons_intensity = 50, @@ -355,8 +281,13 @@ static struct stmp3xxx_platform_bl_data bl_data = { static int __init register_devices(void) { - stmp3xxx_lcd_register_entry(&fb_entry, - stmp3xxx_framebuffer.dev.platform_data); + struct platform_device *pdev; + pdev = mxs_get_device("mxs-fb", 0); + if (pdev == NULL || IS_ERR(pdev)) + return -ENODEV; + + mxs_lcd_register_entry(&fb_entry, pdev->dev.platform_data); + return 0; } diff --git a/drivers/video/mxs/lcdif.c b/drivers/video/mxs/lcdif.c index fc95e3d616d..03d4abd8b85 100644 --- a/drivers/video/mxs/lcdif.c +++ b/drivers/video/mxs/lcdif.c @@ -27,6 +27,7 @@ #include #include #include +#include #define REGS_LCDIF_BASE IO_ADDRESS(LCDIF_PHYS_ADDR) diff --git a/drivers/video/mxs/mxsfb.c b/drivers/video/mxs/mxsfb.c index a7eca468ac3..ba7acbad339 100644 --- a/drivers/video/mxs/mxsfb.c +++ b/drivers/video/mxs/mxsfb.c @@ -844,7 +844,9 @@ static int __devinit mxsfb_probe(struct platform_device *pdev) goto out_irq; pentry->run_panel(); - dev_dbg(&pdev->dev, "LCD DMA channel has been started\n"); + /* REVISIT: temporary workaround for MX23EVK */ + mxsfb_disable_controller(data); + mxsfb_enable_controller(data); data->cur_phys = data->phys_start; dev_dbg(&pdev->dev, "LCD running now\n");