summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorRobby Cai <R63905@freescale.com>2010-01-27 21:57:21 +0800
committerAlejandro Gonzalez <alex.gonzalez@digi.com>2010-05-25 11:13:35 +0200
commit93d8cc863026587589dd6bc97f5b49340a048d3f (patch)
treeb32f4935e5df93e9179cdb88441df02e9e633fa1 /drivers/video
parentc24986360fa6ca2e5ce49b78191e14549b29d4af (diff)
ENGR00117728-2 MX28 Add lcdif and framebuffer driver support
add lcdif, fb, lcd controller(43wvf1g) driver Signed-off-by: Robby Cai <R63905@freescale.com> Signed-off-by: Alejandro Gonzalez <alex.gonzalez@digi.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig4
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/mxs/Kconfig15
-rw-r--r--drivers/video/mxs/Makefile3
-rw-r--r--drivers/video/mxs/lcd_43wvf1g.c289
-rw-r--r--drivers/video/mxs/lcdif.c224
-rw-r--r--drivers/video/mxs/mxsfb.c485
7 files changed, 622 insertions, 399 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 53de81d71ed2..1b3bd4429adc 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -385,6 +385,10 @@ if ARCH_MXC
source "drivers/video/mxc/Kconfig"
endif
+if ARCH_MXS
+source "drivers/video/mxs/Kconfig"
+endif
+
config FB_SA1100
bool "SA-1100 LCD support"
depends on (FB = y) && ARM && ARCH_SA1100
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index e56f7b139957..d3d951e0c4eb 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -118,6 +118,7 @@ obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/
obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/
obj-$(CONFIG_FB_MXC) += mxc/
+obj-$(CONFIG_FB_MXS) += mxs/
obj-$(CONFIG_FB_STMP37XX) += stmp37xxfb.o
obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
obj-$(CONFIG_FB_PS3) += ps3fb.o
diff --git a/drivers/video/mxs/Kconfig b/drivers/video/mxs/Kconfig
new file mode 100644
index 000000000000..fa0dd1e2718e
--- /dev/null
+++ b/drivers/video/mxs/Kconfig
@@ -0,0 +1,15 @@
+config FB_MXS
+ tristate "MXS Framebuffer driver"
+ depends on FB && ARCH_MX28
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ default y
+ ---help---
+ Say Y here to enable support for the framebuffer driver for the
+ Freescale MXS Board.
+
+config FB_MXS_LCD_43WVF1G
+ depends on FB_MXS
+ tristate "SEIKO 4.3' LCD WVGA(800x480) PANEL"
+ default y
diff --git a/drivers/video/mxs/Makefile b/drivers/video/mxs/Makefile
new file mode 100644
index 000000000000..892b04f0d7cc
--- /dev/null
+++ b/drivers/video/mxs/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_ARCH_MXS) += lcdif.o
+obj-$(CONFIG_FB_MXS) += mxsfb.o
+obj-$(CONFIG_FB_MXS_LCD_43WVF1G) += lcd_43wvf1g.o
diff --git a/drivers/video/mxs/lcd_43wvf1g.c b/drivers/video/mxs/lcd_43wvf1g.c
new file mode 100644
index 000000000000..1a8157f277a0
--- /dev/null
+++ b/drivers/video/mxs/lcd_43wvf1g.c
@@ -0,0 +1,289 @@
+/*
+ * Freescale MX28 Seiko 43WVF1G LCD panel driver
+ *
+ * Copyright (C) 2009-2010 Freescale Semiconductor, 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.
+ */
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/notifier.h>
+#include <linux/regulator/consumer.h>
+#include <linux/platform_device.h>
+
+#include <mach/device.h>
+#include <mach/lcdif.h>
+#include <mach/regs-pwm.h>
+#include <mach/system.h>
+
+#define DOTCLK_H_ACTIVE 800
+#define DOTCLK_H_PULSE_WIDTH 10
+#define DOTCLK_HF_PORCH 164
+#define DOTCLK_HB_PORCH 89
+#define DOTCLK_H_WAIT_CNT (DOTCLK_H_PULSE_WIDTH + DOTCLK_HB_PORCH)
+#define DOTCLK_H_PERIOD (DOTCLK_H_WAIT_CNT + DOTCLK_HF_PORCH + DOTCLK_H_ACTIVE)
+
+#define DOTCLK_V_ACTIVE 480
+#define DOTCLK_V_PULSE_WIDTH 10
+#define DOTCLK_VF_PORCH 10
+#define DOTCLK_VB_PORCH 23
+#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 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 mxs_platform_fb_entry *pentry)
+{
+ int ret = 0;
+ lcd_clk = clk_get(dev, "dis_lcdif");
+ if (IS_ERR(lcd_clk)) {
+ ret = PTR_ERR(lcd_clk);
+ goto out;
+ }
+ ret = clk_enable(lcd_clk);
+ if (ret) {
+ clk_put(lcd_clk);
+ goto out;
+ }
+
+ ret = clk_set_rate(lcd_clk, 1000000 / pentry->cycle_time_ns); /* kHz */
+ if (ret) {
+ clk_disable(lcd_clk);
+ clk_put(lcd_clk);
+ goto out;
+ }
+
+ /*
+ * Make sure we do a high-to-low transition to reset the panel.
+ * First make it low for 100 msec, hi for 10 msec, low for 10 msec,
+ * then hi.
+ */
+ __raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR); /* low */
+ mdelay(100);
+ __raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET); /* high */
+ mdelay(10);
+ __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);
+ __raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET); /* high */
+ mdelay(1);
+
+ 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 = mxs_lcdif_dma_init(dev, phys, memsize);
+ if (ret)
+ goto out;
+
+ mxs_lcd_set_bl_pdata(pentry->bl_data);
+ mxs_lcdif_notify_clients(MXS_LCDIF_PANEL_INIT, pentry);
+ return 0;
+
+out:
+ return ret;
+}
+
+static void release_panel(struct device *dev,
+ struct mxs_platform_fb_entry *pentry)
+{
+ mxs_lcdif_notify_clients(MXS_LCDIF_PANEL_RELEASE, pentry);
+ release_dotclk_panel();
+ mxs_lcdif_dma_release();
+ clk_disable(lcd_clk);
+ clk_put(lcd_clk);
+}
+
+static int blank_panel(int blank)
+{
+ int ret = 0, count;
+
+ switch (blank) {
+ case FB_BLANK_NORMAL:
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_POWERDOWN:
+ __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)
+ break;
+ udelay(1);
+ }
+ break;
+
+ case FB_BLANK_UNBLANK:
+ __raw_writel(BM_LCDIF_CTRL_BYPASS_COUNT,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static struct mxs_platform_fb_entry fb_entry = {
+ .name = "43wvf1g",
+ .x_res = 480,
+ .y_res = 800,
+ .bpp = 32,
+ .cycle_time_ns = 30,
+ .lcd_type = MXS_LCD_PANEL_DOTCLK,
+ .init_panel = init_panel,
+ .release_panel = release_panel,
+ .blank_panel = blank_panel,
+ .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 mxs_platform_bl_data *data)
+{
+ int ret = 0;
+
+ pwm_clk = clk_get(NULL, "pwm");
+ if (IS_ERR(pwm_clk)) {
+ ret = PTR_ERR(pwm_clk);
+ return ret;
+ }
+ clk_enable(pwm_clk);
+ mxs_reset_block(REGS_PWM_BASE, 1);
+
+ __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));
+ __raw_writel(BM_PWM_CTRL_PWM2_ENABLE, REGS_PWM_BASE + HW_PWM_CTRL_SET);
+
+ return 0;
+}
+
+static void free_bl(struct mxs_platform_bl_data *data)
+{
+ __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));
+ __raw_writel(BM_PWM_CTRL_PWM2_ENABLE, REGS_PWM_BASE + HW_PWM_CTRL_CLR);
+
+ clk_disable(pwm_clk);
+ clk_put(pwm_clk);
+}
+
+static int values[] = { 0, 4, 9, 14, 20, 27, 35, 45, 57, 75, 100 };
+
+static int power[] = {
+ 0, 1500, 3600, 6100, 10300,
+ 15500, 74200, 114200, 155200,
+ 190100, 191000
+};
+
+static int bl_to_power(int br)
+{
+ int base;
+ int rem;
+
+ if (br > 100)
+ br = 100;
+ base = power[br / 10];
+ rem = br % 10;
+ if (!rem)
+ return base;
+ else
+ return base + (rem * (power[br / 10 + 1]) - base) / 10;
+}
+
+static int set_bl_intensity(struct mxs_platform_bl_data *data,
+ struct backlight_device *bd, int suspended)
+{
+ int intensity = bd->props.brightness;
+ int scaled_int;
+
+ if (bd->props.power != FB_BLANK_UNBLANK)
+ intensity = 0;
+ if (bd->props.fb_blank != FB_BLANK_UNBLANK)
+ intensity = 0;
+ if (suspended)
+ intensity = 0;
+
+ /*
+ * This is not too cool but what can we do?
+ * Luminance changes non-linearly...
+ */
+ if (regulator_set_current_limit
+ (data->regulator, bl_to_power(intensity), bl_to_power(intensity)))
+ return -EBUSY;
+
+ scaled_int = values[intensity / 10];
+ if (scaled_int < 100) {
+ int rem = intensity - 10 * (intensity / 10); /* r = i % 10; */
+ scaled_int += rem * (values[intensity / 10 + 1] -
+ values[intensity / 10]) / 10;
+ }
+ __raw_writel(BF_PWM_ACTIVEn_INACTIVE(scaled_int) |
+ 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(399),
+ REGS_PWM_BASE + HW_PWM_PERIODn(2));
+ return 0;
+}
+
+static struct mxs_platform_bl_data bl_data = {
+ .bl_max_intensity = 100,
+ .bl_default_intensity = 50,
+ .bl_cons_intensity = 50,
+ .init_bl = init_bl,
+ .free_bl = free_bl,
+ .set_bl_intensity = set_bl_intensity,
+};
+
+static int __init register_devices(void)
+{
+ 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;
+}
+
+subsys_initcall(register_devices);
diff --git a/drivers/video/mxs/lcdif.c b/drivers/video/mxs/lcdif.c
index 5cdd52a0f10b..fc95e3d616d7 100644
--- a/drivers/video/mxs/lcdif.c
+++ b/drivers/video/mxs/lcdif.c
@@ -1,210 +1,138 @@
/*
- * Freescale STMP378X LCDIF low-level routines
+ * Freescale MXS LCDIF low-level routines
*
* Author: Vitaly Wool <vital@embeddedalley.com>
*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
- */
-
-/*
- * 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:
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
*
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ * 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.
*/
-/* #define DEBUG */
-#include <linux/dma-mapping.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <mach/hardware.h>
-#include <mach/dma.h>
-#include <mach/dma.h>
-#include <mach/regs-lcdif.h>
-#include <mach/regs-pinctrl.h>
#include <mach/lcdif.h>
+#include <mach/regs-lcdif.h>
-#define MAX_CHAIN_LEN 10
-
-static struct stmp3xxx_dma_descriptor video_dma_descriptor[MAX_CHAIN_LEN];
-static struct stmp3xxx_lcd_dma_chain_info dma_chain_info[MAX_CHAIN_LEN];
-static unsigned dma_chain_info_pos;
+#define REGS_LCDIF_BASE IO_ADDRESS(LCDIF_PHYS_ADDR)
-void stmp3xxx_init_lcdif(void)
+void mxs_init_lcdif(void)
{
- stmp3xxx_clearl(BM_LCDIF_CTRL_CLKGATE, REGS_LCDIF_BASE + HW_LCDIF_CTRL);
+ __raw_writel(BM_LCDIF_CTRL_CLKGATE,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);
/* Reset controller */
- stmp3xxx_setl(BM_LCDIF_CTRL_SFTRST, REGS_LCDIF_BASE + HW_LCDIF_CTRL);
+ __raw_writel(BM_LCDIF_CTRL_SFTRST, REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);
udelay(10);
/* Take controller out of reset */
- stmp3xxx_clearl(BM_LCDIF_CTRL_SFTRST | BM_LCDIF_CTRL_CLKGATE,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL);
+ __raw_writel(BM_LCDIF_CTRL_SFTRST | BM_LCDIF_CTRL_CLKGATE,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);
/* Setup the bus protocol */
- stmp3xxx_clearl(BM_LCDIF_CTRL1_MODE86,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL1);
- stmp3xxx_clearl(BM_LCDIF_CTRL1_BUSY_ENABLE,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL1);
+ __raw_writel(BM_LCDIF_CTRL1_MODE86,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR);
+ __raw_writel(BM_LCDIF_CTRL1_BUSY_ENABLE,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR);
/* Take display out of reset */
- stmp3xxx_setl(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1);
+ __raw_writel(BM_LCDIF_CTRL1_RESET,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET);
/* VSYNC is an input by default */
- stmp3xxx_setl(BM_LCDIF_VDCTRL0_VSYNC_OEB,
- REGS_LCDIF_BASE + HW_LCDIF_VDCTRL0);
+ __raw_writel(BM_LCDIF_VDCTRL0_VSYNC_OEB,
+ REGS_LCDIF_BASE + HW_LCDIF_VDCTRL0_SET);
/* Reset display */
- stmp3xxx_clearl(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1);
+ __raw_writel(BM_LCDIF_CTRL1_RESET,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR);
udelay(10);
- stmp3xxx_setl(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1);
+ __raw_writel(BM_LCDIF_CTRL1_RESET,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET);
udelay(10);
}
+EXPORT_SYMBOL(mxs_init_lcdif);
-EXPORT_SYMBOL(stmp3xxx_init_lcdif);
-
-static int stmp378x_lcd_master = 1;
-int stmp3xxx_lcdif_dma_init(struct device *dev, dma_addr_t phys, int memsize,
- int lcd_master)
+int mxs_lcdif_dma_init(struct device *dev, dma_addr_t phys, int memsize)
{
- int ret = 0;
-
- stmp378x_lcd_master = lcd_master;
- if (lcd_master) {
- stmp3xxx_setl(BM_LCDIF_CTRL_LCDIF_MASTER,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL);
-
- __raw_writel(phys, REGS_LCDIF_BASE + HW_LCDIF_CUR_BUF);
- __raw_writel(phys, REGS_LCDIF_BASE + HW_LCDIF_NEXT_BUF);
- } else {
- ret =
- stmp3xxx_dma_request(STMP3XXX_DMA
- (LCD_DMA_CHANNEL, STMP3XXX_BUS_APBH),
- dev, "lcdif");
- if (ret) {
- dev_err(dev,
- "stmp3xxx_dma_request failed: error %d\n", ret);
- goto out;
- }
-
- stmp3xxx_dma_reset_channel(STMP3XXX_DMA
- (LCD_DMA_CHANNEL,
- STMP3XXX_BUS_APBH));
-
- stmp3xxx_dma_clear_interrupt(STMP3XXX_DMA
- (LCD_DMA_CHANNEL,
- STMP3XXX_BUS_APBH));
- stmp3xxx_dma_enable_interrupt(STMP3XXX_DMA
- (LCD_DMA_CHANNEL,
- STMP3XXX_BUS_APBH));
-
- dotclk_dma_chain_init(memsize, phys, video_dma_descriptor,
- dma_chain_info, &dma_chain_info_pos);
- }
-out:
- return ret;
-}
+ __raw_writel(BM_LCDIF_CTRL_LCDIF_MASTER,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);
-EXPORT_SYMBOL(stmp3xxx_lcdif_dma_init);
+ __raw_writel(phys, REGS_LCDIF_BASE + HW_LCDIF_CUR_BUF);
+ __raw_writel(phys, REGS_LCDIF_BASE + HW_LCDIF_NEXT_BUF);
-void stmp3xxx_lcdif_dma_release(void)
-{
- int i;
-
- if (stmp378x_lcd_master) {
- stmp3xxx_clearl(BM_LCDIF_CTRL_LCDIF_MASTER,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL);
- return;
- }
-
- for (i = 0; i < dma_chain_info_pos; i++)
- stmp3xxx_dma_free_command(STMP3XXX_DMA
- (LCD_DMA_CHANNEL, STMP3XXX_BUS_APBH),
- &video_dma_descriptor[i]);
- stmp3xxx_dma_release(STMP3XXX_DMA(LCD_DMA_CHANNEL, STMP3XXX_BUS_APBH));
-
- dma_chain_info_pos = 0;
+ return 0;
}
+EXPORT_SYMBOL(mxs_lcdif_dma_init);
-EXPORT_SYMBOL(stmp3xxx_lcdif_dma_release);
-
-void stmp3xxx_lcdif_run(void)
+void mxs_lcdif_dma_release(void)
{
- if (stmp378x_lcd_master) {
- stmp3xxx_setl(BM_LCDIF_CTRL_LCDIF_MASTER,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL);
- stmp3xxx_setl(BM_LCDIF_CTRL_RUN,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL);
- } else {
- video_dma_descriptor[dma_chain_info_pos - 1].command->cmd &=
- ~BM_APBH_CHn_CMD_SEMAPHORE;
- stmp3xxx_dma_go(STMP3XXX_DMA
- (LCD_DMA_CHANNEL, STMP3XXX_BUS_APBH),
- video_dma_descriptor, 1);
- }
+ __raw_writel(BM_LCDIF_CTRL_LCDIF_MASTER,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);
+ return;
}
+EXPORT_SYMBOL(mxs_lcdif_dma_release);
-EXPORT_SYMBOL(stmp3xxx_lcdif_run);
-
-void stmp3xxx_lcdif_stop(void)
+void mxs_lcdif_run(void)
{
- if (stmp378x_lcd_master) {
- stmp3xxx_clearl(BM_LCDIF_CTRL_RUN,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL);
- stmp3xxx_clearl(BM_LCDIF_CTRL_LCDIF_MASTER,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL);
- udelay(100);
- } else {
- video_dma_descriptor[dma_chain_info_pos - 1].command->cmd |=
- BM_APBH_CHn_CMD_SEMAPHORE;
- udelay(100);
- }
- stmp3xxx_setl(BM_LCDIF_CTRL_CLKGATE, REGS_LCDIF_BASE + HW_LCDIF_CTRL);
+ __raw_writel(BM_LCDIF_CTRL_LCDIF_MASTER,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);
+ __raw_writel(BM_LCDIF_CTRL_RUN, REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);
}
+EXPORT_SYMBOL(mxs_lcdif_run);
-EXPORT_SYMBOL(stmp3xxx_lcdif_stop);
+void mxs_lcdif_stop(void)
+{
+ __raw_writel(BM_LCDIF_CTRL_RUN, REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);
+ __raw_writel(BM_LCDIF_CTRL_LCDIF_MASTER,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);
+ udelay(100);
+
+ __raw_writel(BM_LCDIF_CTRL_CLKGATE,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);
+}
+EXPORT_SYMBOL(mxs_lcdif_stop);
-int stmp3xxx_lcdif_pan_display(dma_addr_t addr)
+int mxs_lcdif_pan_display(dma_addr_t addr)
{
- if (stmp378x_lcd_master)
- __raw_writel(addr, REGS_LCDIF_BASE + HW_LCDIF_NEXT_BUF);
- else {
- int i;
- /* Modify the chain addresses */
- for (i = 0; i < dma_chain_info_pos; ++i) {
- *dma_chain_info[i].dma_addr_p = addr +
- dma_chain_info[i].offset;
- barrier();
- }
- }
+ __raw_writel(addr, REGS_LCDIF_BASE + HW_LCDIF_NEXT_BUF);
+
return 0;
}
-EXPORT_SYMBOL(stmp3xxx_lcdif_pan_display);
+EXPORT_SYMBOL(mxs_lcdif_pan_display);
static BLOCKING_NOTIFIER_HEAD(lcdif_client_list);
-int stmp3xxx_lcdif_register_client(struct notifier_block *nb)
+int mxs_lcdif_register_client(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&lcdif_client_list, nb);
}
-EXPORT_SYMBOL(stmp3xxx_lcdif_register_client);
+EXPORT_SYMBOL(mxs_lcdif_register_client);
-void stmp3xxx_lcdif_unregister_client(struct notifier_block *nb)
+void mxs_lcdif_unregister_client(struct notifier_block *nb)
{
blocking_notifier_chain_unregister(&lcdif_client_list, nb);
}
+EXPORT_SYMBOL(mxs_lcdif_unregister_client);
-EXPORT_SYMBOL(stmp3xxx_lcdif_unregister_client);
-
-void stmp3xxx_lcdif_notify_clients(unsigned long event,
- struct stmp3xxx_platform_fb_entry *pentry)
+void mxs_lcdif_notify_clients(unsigned long event,
+ struct mxs_platform_fb_entry *pentry)
{
blocking_notifier_call_chain(&lcdif_client_list, event, pentry);
}
-
-EXPORT_SYMBOL(stmp3xxx_lcdif_notify_clients);
+EXPORT_SYMBOL(mxs_lcdif_notify_clients);
diff --git a/drivers/video/mxs/mxsfb.c b/drivers/video/mxs/mxsfb.c
index 9ecbde89b735..a7eca468ac3e 100644
--- a/drivers/video/mxs/mxsfb.c
+++ b/drivers/video/mxs/mxsfb.c
@@ -1,20 +1,26 @@
/*
- * Freescale STMP37XX/STMP378X framebuffer driver
+ * Freescale MXS framebuffer driver
*
* Author: Vitaly Wool <vital@embeddedalley.com>
*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
- */
-
-/*
- * 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:
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
*
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ * 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.
*/
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
@@ -31,14 +37,10 @@
#include <linux/cpufreq.h>
#include <mach/hardware.h>
-#include <mach/regs-pinctrl.h>
#include <mach/regs-lcdif.h>
-#include <mach/regs-clkctrl.h>
-#include <mach/regs-apbh.h>
+#include <mach/clock.h>
#include <mach/lcdif.h>
-#include <mach/stmp3xxx.h>
-
#define NUM_SCREENS 1
enum {
@@ -47,9 +49,9 @@ enum {
F_REENABLE,
};
-struct stmp3xxx_fb_data {
+struct mxs_fb_data {
struct fb_info info;
- struct stmp3xxx_platform_fb_data *pdata;
+ struct mxs_platform_fb_data *pdata;
struct work_struct work;
struct mutex blank_mutex;
u32 state;
@@ -58,8 +60,8 @@ struct stmp3xxx_fb_data {
ssize_t map_size;
dma_addr_t phys_start;
dma_addr_t cur_phys;
- int dma_irq;
- int err_irq;
+ int irq;
+ unsigned long regbase;
void *virt_start;
struct device *dev;
wait_queue_head_t vsync_wait_q;
@@ -68,31 +70,31 @@ struct stmp3xxx_fb_data {
};
/* forward declaration */
-static int stmp3xxxfb_blank(int blank, struct fb_info *info);
+static int mxsfb_blank(int blank, struct fb_info *info);
static unsigned char *default_panel_name;
-static struct stmp3xxx_fb_data *cdata;
-static void init_timings(struct stmp3xxx_fb_data *data);
+static struct mxs_fb_data *cdata;
+static void init_timings(struct mxs_fb_data *data);
-static void stmp3xxxfb_enable_controller(struct stmp3xxx_fb_data *data)
+static void mxsfb_enable_controller(struct mxs_fb_data *data)
{
- struct stmp3xxx_platform_fb_entry *pentry = data->pdata->cur;
+ struct mxs_platform_fb_entry *pentry = data->pdata->cur;
if (!data || !data->pdata || !data->pdata->cur)
return;
- stmp3xxx_init_lcdif();
+ mxs_init_lcdif();
init_timings(data);
pentry->init_panel(data->dev, data->phys_start,
- data->info.fix.smem_len, data->pdata->cur);
+ data->info.fix.smem_len, data->pdata->cur);
pentry->run_panel();
if (pentry->blank_panel)
pentry->blank_panel(FB_BLANK_UNBLANK);
}
-static void stmp3xxxfb_disable_controller(struct stmp3xxx_fb_data *data)
+static void mxsfb_disable_controller(struct mxs_fb_data *data)
{
- struct stmp3xxx_platform_fb_entry *pentry = data->pdata->cur;
+ struct mxs_platform_fb_entry *pentry = data->pdata->cur;
if (!data || !data->pdata || !data->pdata->cur)
return;
@@ -105,9 +107,9 @@ static void stmp3xxxfb_disable_controller(struct stmp3xxx_fb_data *data)
pentry->release_panel(data->dev, pentry);
}
-static void set_controller_state(struct stmp3xxx_fb_data *data, u32 state)
+static void set_controller_state(struct mxs_fb_data *data, u32 state)
{
- struct stmp3xxx_platform_fb_entry *pentry = data->pdata->cur;
+ struct mxs_platform_fb_entry *pentry = data->pdata->cur;
struct fb_info *info = &data->info;
u32 old_state;
@@ -122,7 +124,7 @@ static void set_controller_state(struct stmp3xxx_fb_data *data, u32 state)
*/
if (old_state != F_DISABLE) {
data->state = F_DISABLE;
- stmp3xxxfb_disable_controller(data);
+ mxsfb_disable_controller(data);
}
break;
@@ -131,21 +133,21 @@ static void set_controller_state(struct stmp3xxx_fb_data *data, u32 state)
* Re-enable the controller when panel changed.
*/
if (old_state == F_ENABLE) {
- stmp3xxxfb_disable_controller(data);
+ mxsfb_disable_controller(data);
pentry = data->pdata->cur = data->pdata->next;
info->fix.smem_len = pentry->y_res * pentry->x_res *
- pentry->bpp / 8;
+ pentry->bpp / 8;
info->screen_size = info->fix.smem_len;
memset((void *)info->screen_base, 0, info->screen_size);
- stmp3xxxfb_enable_controller(data);
+ mxsfb_enable_controller(data);
data->state = F_ENABLE;
} else if (old_state == F_DISABLE) {
pentry = data->pdata->cur = data->pdata->next;
info->fix.smem_len = pentry->y_res * pentry->x_res *
- pentry->bpp / 8;
+ pentry->bpp / 8;
info->screen_size = info->fix.smem_len;
memset((void *)info->screen_base, 0, info->screen_size);
@@ -156,7 +158,7 @@ static void set_controller_state(struct stmp3xxx_fb_data *data, u32 state)
case F_ENABLE:
if (old_state != F_ENABLE) {
data->state = F_ENABLE;
- stmp3xxxfb_enable_controller(data);
+ mxsfb_enable_controller(data);
}
break;
}
@@ -164,19 +166,18 @@ static void set_controller_state(struct stmp3xxx_fb_data *data, u32 state)
}
-static void stmp3xxxfb_task(struct work_struct *work)
+static void mxsfb_task(struct work_struct *work)
{
- struct stmp3xxx_fb_data *data =
- container_of(work, struct stmp3xxx_fb_data, work);
+ struct mxs_fb_data *data = container_of(work, struct mxs_fb_data, work);
u32 state = xchg(&data->task_state, -1);
pr_debug("%s: state = %d, data->task_state = %d\n",
- __func__, state, data->task_state);
+ __func__, state, data->task_state);
set_controller_state(data, state);
}
-static void stmp3xxx_schedule_work(struct stmp3xxx_fb_data *data, u32 state)
+static void mxs_schedule_work(struct mxs_fb_data *data, u32 state)
{
unsigned long flags;
@@ -190,67 +191,61 @@ static void stmp3xxx_schedule_work(struct stmp3xxx_fb_data *data, u32 state)
static irqreturn_t lcd_irq_handler(int irq, void *dev_id)
{
- struct stmp3xxx_fb_data *data = dev_id;
- u32 status_lcd = __raw_readl(REGS_LCDIF_BASE + HW_LCDIF_CTRL1);
- u32 status_apbh = __raw_readl(REGS_APBH_BASE + HW_APBH_CTRL1);
+ struct mxs_fb_data *data = dev_id;
+ u32 status_lcd = __raw_readl(data->regbase + HW_LCDIF_CTRL1);
pr_debug("%s: irq %d\n", __func__, irq);
- if (status_apbh & BM_APBH_CTRL1_CH0_CMDCMPLT_IRQ)
- __raw_writel(BM_APBH_CTRL1_CH0_CMDCMPLT_IRQ,
- REGS_APBH_BASE + HW_APBH_CTRL1_CLR);
-
if (status_lcd & BM_LCDIF_CTRL1_VSYNC_EDGE_IRQ) {
pr_debug("%s: VSYNC irq\n", __func__);
data->vsync_count++;
__raw_writel(BM_LCDIF_CTRL1_VSYNC_EDGE_IRQ,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR);
+ data->regbase + HW_LCDIF_CTRL1_CLR);
wake_up_interruptible(&data->vsync_wait_q);
}
if (status_lcd & BM_LCDIF_CTRL1_CUR_FRAME_DONE_IRQ) {
pr_debug("%s: frame done irq\n", __func__);
__raw_writel(BM_LCDIF_CTRL1_CUR_FRAME_DONE_IRQ,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR);
+ data->regbase + HW_LCDIF_CTRL1_CLR);
data->vsync_count++;
}
if (status_lcd & BM_LCDIF_CTRL1_UNDERFLOW_IRQ) {
pr_debug("%s: underflow irq\n", __func__);
__raw_writel(BM_LCDIF_CTRL1_UNDERFLOW_IRQ,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR);
+ data->regbase + HW_LCDIF_CTRL1_CLR);
}
if (status_lcd & BM_LCDIF_CTRL1_OVERFLOW_IRQ) {
pr_debug("%s: overflow irq\n", __func__);
__raw_writel(BM_LCDIF_CTRL1_OVERFLOW_IRQ,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR);
+ data->regbase + HW_LCDIF_CTRL1_CLR);
}
return IRQ_HANDLED;
}
-static struct fb_var_screeninfo stmp3xxxfb_default __devinitdata = {
- .activate = FB_ACTIVATE_TEST,
- .height = -1,
- .width = -1,
- .pixclock = 20000,
- .left_margin = 64,
- .right_margin = 64,
- .upper_margin = 32,
- .lower_margin = 32,
- .hsync_len = 64,
- .vsync_len = 2,
- .vmode = FB_VMODE_NONINTERLACED,
+static struct fb_var_screeninfo mxsfb_default __devinitdata = {
+ .activate = FB_ACTIVATE_TEST,
+ .height = -1,
+ .width = -1,
+ .pixclock = 20000,
+ .left_margin = 64,
+ .right_margin = 64,
+ .upper_margin = 32,
+ .lower_margin = 32,
+ .hsync_len = 64,
+ .vsync_len = 2,
+ .vmode = FB_VMODE_NONINTERLACED,
};
-static struct fb_fix_screeninfo stmp3xxxfb_fix __devinitdata = {
- .id = "stmp3xxxfb",
- .type = FB_TYPE_PACKED_PIXELS,
- .visual = FB_VISUAL_TRUECOLOR,
- .xpanstep = 0,
- .ypanstep = 0,
- .ywrapstep = 0,
- .accel = FB_ACCEL_NONE,
+static struct fb_fix_screeninfo mxsfb_fix __devinitdata = {
+ .id = "mxsfb",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .xpanstep = 0,
+ .ypanstep = 0,
+ .ywrapstep = 0,
+ .accel = FB_ACCEL_NONE,
};
-int stmp3xxxfb_get_info(struct fb_var_screeninfo *var,
- struct fb_fix_screeninfo *fix)
+int mxsfb_get_info(struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix)
{
if (!cdata)
return -ENODEV;
@@ -260,7 +255,7 @@ int stmp3xxxfb_get_info(struct fb_var_screeninfo *var,
return 0;
}
-void stmp3xxxfb_cfg_pxp(int enable, dma_addr_t pxp_phys)
+void mxsfb_cfg_pxp(int enable, dma_addr_t pxp_phys)
{
if (enable)
cdata->pdata->cur->pan_display(pxp_phys);
@@ -268,35 +263,34 @@ void stmp3xxxfb_cfg_pxp(int enable, dma_addr_t pxp_phys)
cdata->pdata->cur->pan_display(cdata->cur_phys);
}
-static int stmp3xxxfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+static int mxsfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
- struct stmp3xxx_fb_data *data = (struct stmp3xxx_fb_data *)info;
+ struct mxs_fb_data *data = (struct mxs_fb_data *)info;
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
if (off < info->fix.smem_len)
return dma_mmap_writecombine(data->dev, vma,
- data->virt_start,
- data->phys_start,
- info->fix.smem_len);
+ data->virt_start,
+ data->phys_start,
+ info->fix.smem_len);
else
return -EINVAL;
}
-static int stmp3xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info)
+static int mxsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
{
if (regno >= 256) /* no. of hw registers */
return 1;
/*
- * Program hardware... do anything you want with transp
- */
+ * Program hardware... do anything you want with transp
+ */
/* grayscale works only partially under directcolor */
if (info->var.grayscale) {
/* grayscale = 0.30*R + 0.59*G + 0.11*B */
- red = green = blue =
- (red * 77 + green * 151 + blue * 28) >> 8;
+ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
}
/* Directcolor:
@@ -304,7 +298,7 @@ static int stmp3xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* var->{color}.length contains length of bitfield
* {hardwarespecific} contains width of RAMDAC
* cmap[X] is programmed to
- * (X << red.offset) | (X << green.offset) | (X << blue.offset)
+ * (X << red.offset) | (X << green.offset) | (X << blue.offset)
* RAMDAC[X] is programmed to (red, green, blue)
*
* Pseudocolor:
@@ -318,8 +312,8 @@ static int stmp3xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* var->{color}.offset contains start of bitfield
* var->{color}.length contains length of bitfield
* cmap is programmed to
- * (red << red.offset) | (green << green.offset) |
- * (blue << blue.offset) | (transp << transp.offset)
+ * (red << red.offset) | (green << green.offset) |
+ * (blue << blue.offset) | (transp << transp.offset)
* RAMDAC does not exist
*/
#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
@@ -347,10 +341,10 @@ static int stmp3xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
return 1;
((u32 *) (info->pseudo_palette))[regno] =
- (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset) |
- (transp << info->var.transp.offset);
+ (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset) |
+ (transp << info->var.transp.offset);
}
return 0;
}
@@ -365,23 +359,21 @@ static inline u_long get_line_length(int xres_virtual, int bpp)
return length;
}
-static int get_matching_pentry(struct stmp3xxx_platform_fb_entry *pentry,
+static int get_matching_pentry(struct mxs_platform_fb_entry *pentry,
void *data, int ret_prev)
{
struct fb_var_screeninfo *info = data;
pr_debug("%s: %d:%d:%d vs %d:%d:%d\n", __func__,
- pentry->x_res, pentry->y_res, pentry->bpp,
- info->yres, info->xres, info->bits_per_pixel);
+ pentry->x_res, pentry->y_res, pentry->bpp,
+ info->yres, info->xres, info->bits_per_pixel);
if (pentry->x_res == info->yres && pentry->y_res == info->xres &&
pentry->bpp == info->bits_per_pixel)
ret_prev = (int)pentry;
return ret_prev;
}
-static int get_matching_pentry_by_name(
- struct stmp3xxx_platform_fb_entry *pentry,
- void *data,
- int ret_prev)
+static int get_matching_pentry_by_name(struct mxs_platform_fb_entry *pentry,
+ void *data, int ret_prev)
{
unsigned char *name = data;
if (!strcmp(pentry->name, name))
@@ -396,20 +388,17 @@ static int get_matching_pentry_by_name(
*
* XXX: REVISIT
*/
-static int stmp3xxxfb_set_par(struct fb_info *info)
+static int mxsfb_set_par(struct fb_info *info)
{
- struct stmp3xxx_fb_data *data = (struct stmp3xxx_fb_data *)info;
- struct stmp3xxx_platform_fb_data *pdata = data->pdata;
- struct stmp3xxx_platform_fb_entry *pentry;
- pentry = (void *)stmp3xxx_lcd_iterate_pdata(pdata,
- get_matching_pentry,
- &info->var);
+ struct mxs_fb_data *data = (struct mxs_fb_data *)info;
+ struct mxs_platform_fb_data *pdata = data->pdata;
+ struct mxs_platform_fb_entry *pentry;
+ pentry = (void *)mxs_lcd_iterate_pdata(pdata,
+ get_matching_pentry, &info->var);
dev_dbg(data->dev, "%s: xres %d, yres %d, bpp %d\n",
__func__,
- info->var.xres,
- info->var.yres,
- info->var.bits_per_pixel);
+ info->var.xres, info->var.yres, info->var.bits_per_pixel);
if (!pentry)
return -EINVAL;
@@ -427,12 +416,11 @@ static int stmp3xxxfb_set_par(struct fb_info *info)
return 0;
}
-static int stmp3xxxfb_check_var(struct fb_var_screeninfo *var,
- struct fb_info *info)
+static int mxsfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
u32 line_length;
- struct stmp3xxx_fb_data *data = (struct stmp3xxx_fb_data *)info;
- struct stmp3xxx_platform_fb_data *pdata = data->pdata;
+ struct mxs_fb_data *data = (struct mxs_fb_data *)info;
+ struct mxs_platform_fb_data *pdata = data->pdata;
/*
* FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
@@ -446,7 +434,7 @@ static int stmp3xxxfb_check_var(struct fb_var_screeninfo *var,
}
pr_debug("%s: xres %d, yres %d, bpp %d\n", __func__,
- var->xres, var->yres, var->bits_per_pixel);
+ var->xres, var->yres, var->bits_per_pixel);
/*
* Some very basic checks
*/
@@ -471,7 +459,7 @@ static int stmp3xxxfb_check_var(struct fb_var_screeninfo *var,
if (line_length * var->yres_virtual > data->map_size)
return -ENOMEM;
- if (!stmp3xxx_lcd_iterate_pdata(pdata, get_matching_pentry, var))
+ if (!mxs_lcd_iterate_pdata(pdata, get_matching_pentry, var))
return -EINVAL;
if (var->bits_per_pixel == 16) {
@@ -512,19 +500,19 @@ static int stmp3xxxfb_check_var(struct fb_var_screeninfo *var,
return 0;
}
-
-static int stmp3xxxfb_wait_for_vsync(u32 channel, struct fb_info *info)
+static int mxsfb_wait_for_vsync(u32 channel, struct fb_info *info)
{
- struct stmp3xxx_fb_data *data = (struct stmp3xxx_fb_data *)info;
+ struct mxs_fb_data *data = (struct mxs_fb_data *)info;
u32 count = data->vsync_count;
int ret = 0;
__raw_writel(BM_LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET);
+ data->regbase + HW_LCDIF_CTRL1_SET);
ret = wait_event_interruptible_timeout(data->vsync_wait_q,
- count != data->vsync_count, HZ / 10);
+ count != data->vsync_count,
+ HZ / 10);
__raw_writel(BM_LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN,
- REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR);
+ data->regbase + HW_LCDIF_CTRL1_CLR);
if (!ret) {
dev_err(data->dev, "wait for vsync timed out\n");
ret = -ETIMEDOUT;
@@ -532,8 +520,8 @@ static int stmp3xxxfb_wait_for_vsync(u32 channel, struct fb_info *info)
return ret;
}
-static int stmp3xxxfb_ioctl(struct fb_info *info, unsigned int cmd,
- unsigned long arg)
+static int mxsfb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
{
u32 channel = 0;
int ret = -EINVAL;
@@ -541,7 +529,7 @@ static int stmp3xxxfb_ioctl(struct fb_info *info, unsigned int cmd,
switch (cmd) {
case FBIO_WAITFORVSYNC:
if (!get_user(channel, (__u32 __user *) arg))
- ret = stmp3xxxfb_wait_for_vsync(channel, info);
+ ret = mxsfb_wait_for_vsync(channel, info);
break;
default:
break;
@@ -549,9 +537,9 @@ static int stmp3xxxfb_ioctl(struct fb_info *info, unsigned int cmd,
return ret;
}
-static int stmp3xxxfb_blank(int blank, struct fb_info *info)
+static int mxsfb_blank(int blank, struct fb_info *info)
{
- struct stmp3xxx_fb_data *data = (struct stmp3xxx_fb_data *)info;
+ struct mxs_fb_data *data = (struct mxs_fb_data *)info;
int ret = 0;
switch (blank) {
@@ -560,12 +548,12 @@ static int stmp3xxxfb_blank(int blank, struct fb_info *info)
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_POWERDOWN:
pr_debug("%s: FB_BLANK_POWERDOWN\n", __func__);
- stmp3xxx_schedule_work(data, F_DISABLE);
+ mxs_schedule_work(data, F_DISABLE);
break;
case FB_BLANK_UNBLANK:
pr_debug("%s: FB_BLANK_UNBLANK\n", __func__);
- stmp3xxx_schedule_work(data, F_ENABLE);
+ mxs_schedule_work(data, F_ENABLE);
break;
default:
@@ -574,14 +562,14 @@ static int stmp3xxxfb_blank(int blank, struct fb_info *info)
return ret;
}
-static int stmp3xxxfb_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *info)
+static int mxsfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
- struct stmp3xxx_fb_data *data = (struct stmp3xxx_fb_data *)info;
+ struct mxs_fb_data *data = (struct mxs_fb_data *)info;
int ret = 0;
pr_debug("%s: var->xoffset %d, info->var.xoffset %d\n",
- __func__, var->xoffset, info->var.xoffset);
+ __func__, var->xoffset, info->var.xoffset);
/* check if var is valid; also, xpan is not supported */
if (!var || (var->xoffset != info->var.xoffset) ||
(var->yoffset + var->yres > var->yres_virtual)) {
@@ -596,27 +584,27 @@ static int stmp3xxxfb_pan_display(struct fb_var_screeninfo *var,
/* update framebuffer visual */
data->cur_phys = data->phys_start +
- info->fix.line_length * var->yoffset;
+ info->fix.line_length * var->yoffset;
data->pdata->cur->pan_display(data->cur_phys);
out:
return ret;
}
-static struct fb_ops stmp3xxxfb_ops = {
+static struct fb_ops mxsfb_ops = {
.owner = THIS_MODULE,
- .fb_check_var = stmp3xxxfb_check_var,
- .fb_set_par = stmp3xxxfb_set_par,
- .fb_mmap = stmp3xxxfb_mmap,
- .fb_setcolreg = stmp3xxxfb_setcolreg,
- .fb_ioctl = stmp3xxxfb_ioctl,
- .fb_blank = stmp3xxxfb_blank,
- .fb_pan_display = stmp3xxxfb_pan_display,
+ .fb_check_var = mxsfb_check_var,
+ .fb_set_par = mxsfb_set_par,
+ .fb_mmap = mxsfb_mmap,
+ .fb_setcolreg = mxsfb_setcolreg,
+ .fb_ioctl = mxsfb_ioctl,
+ .fb_blank = mxsfb_blank,
+ .fb_pan_display = mxsfb_pan_display,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
-static void init_timings(struct stmp3xxx_fb_data *data)
+static void init_timings(struct mxs_fb_data *data)
{
unsigned phase_time;
unsigned timings;
@@ -628,23 +616,23 @@ static void init_timings(struct stmp3xxx_fb_data *data)
timings = phase_time;
timings |= timings << 8;
timings |= timings << 16;
- __raw_writel(timings, REGS_LCDIF_BASE + HW_LCDIF_TIMING);
+ __raw_writel(timings, data->regbase + HW_LCDIF_TIMING);
}
#ifdef CONFIG_CPU_FREQ
-struct stmp3xxxfb_notifier_block {
- struct stmp3xxx_fb_data *fb_data;
+struct mxsfb_notifier_block {
+ struct mxs_fb_data *fb_data;
struct notifier_block nb;
};
-static int stmp3xxxfb_notifier(struct notifier_block *self,
- unsigned long phase, void *p)
+static int mxsfb_notifier(struct notifier_block *self,
+ unsigned long phase, void *p)
{
- struct stmp3xxxfb_notifier_block *block =
- container_of(self, struct stmp3xxxfb_notifier_block, nb);
- struct stmp3xxx_fb_data *data = block->fb_data;
- struct stmp3xxx_platform_fb_entry *pentry = data->pdata->cur;
+ struct mxsfb_notifier_block *block =
+ container_of(self, struct mxsfb_notifier_block, nb);
+ struct mxs_fb_data *data = block->fb_data;
+ struct mxs_platform_fb_entry *pentry = data->pdata->cur;
u32 old_state = data->state;
if (!data || !data->pdata || !data->pdata->cur)
@@ -671,31 +659,31 @@ static int stmp3xxxfb_notifier(struct notifier_block *self,
return NOTIFY_DONE;
}
-static struct stmp3xxxfb_notifier_block stmp3xxxfb_nb = {
+static struct mxsfb_notifier_block mxsfb_nb = {
.nb = {
- .notifier_call = stmp3xxxfb_notifier,
- },
+ .notifier_call = mxsfb_notifier,
+ },
};
#endif /* CONFIG_CPU_FREQ */
-static int get_max_memsize(struct stmp3xxx_platform_fb_entry *pentry,
+static int get_max_memsize(struct mxs_platform_fb_entry *pentry,
void *data, int ret_prev)
{
- struct stmp3xxx_fb_data *fbdata = data;
+ struct mxs_fb_data *fbdata = data;
int sz = pentry->x_res * pentry->y_res * pentry->bpp / 8;
fbdata->mem_size = sz < ret_prev ? ret_prev : sz;
pr_debug("%s: mem_size now %d\n", __func__, fbdata->mem_size);
return fbdata->mem_size;
}
-static int __devinit stmp3xxxfb_probe(struct platform_device *pdev)
+static int __devinit mxsfb_probe(struct platform_device *pdev)
{
int ret = 0;
- struct stmp3xxx_fb_data *data;
+ struct mxs_fb_data *data;
struct resource *res;
struct fb_info *info;
- struct stmp3xxx_platform_fb_data *pdata = pdev->dev.platform_data;
- struct stmp3xxx_platform_fb_entry *pentry;
+ struct mxs_platform_fb_data *pdata = pdev->dev.platform_data;
+ struct mxs_platform_fb_entry *pentry = NULL;
if (pdata == NULL) {
ret = -ENODEV;
@@ -703,11 +691,11 @@ static int __devinit stmp3xxxfb_probe(struct platform_device *pdev)
}
if (default_panel_name) {
- pentry = (void *)stmp3xxx_lcd_iterate_pdata(pdata,
- get_matching_pentry_by_name,
- default_panel_name);
+ pentry = (void *)mxs_lcd_iterate_pdata(pdata,
+ get_matching_pentry_by_name,
+ default_panel_name);
if (pentry) {
- stmp3xxx_lcd_move_pentry_up(pentry, pdata);
+ mxs_lcd_move_pentry_up(pentry, pdata);
pdata->cur = pentry;
}
}
@@ -719,10 +707,11 @@ static int __devinit stmp3xxxfb_probe(struct platform_device *pdev)
goto out;
}
- data = (struct stmp3xxx_fb_data *)framebuffer_alloc(
- sizeof(struct stmp3xxx_fb_data) +
- sizeof(u32) * 256 -
- sizeof(struct fb_info), &pdev->dev);
+ data =
+ (struct mxs_fb_data *)framebuffer_alloc(sizeof(struct mxs_fb_data) +
+ sizeof(u32) * 256 -
+ sizeof(struct fb_info),
+ &pdev->dev);
if (data == NULL) {
ret = -ENOMEM;
goto out;
@@ -737,15 +726,15 @@ static int __devinit stmp3xxxfb_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "resolution %dx%d, bpp %d\n", pentry->x_res,
pentry->y_res, pentry->bpp);
- stmp3xxx_lcd_iterate_pdata(pdata, get_max_memsize, data);
+ mxs_lcd_iterate_pdata(pdata, get_max_memsize, data);
data->map_size = PAGE_ALIGN(data->mem_size) * NUM_SCREENS;
dev_dbg(&pdev->dev, "memory to allocate: %d\n", data->map_size);
data->virt_start = dma_alloc_writecombine(&pdev->dev,
- data->map_size,
- &data->phys_start,
- GFP_KERNEL);
+ data->map_size,
+ &data->phys_start,
+ GFP_KERNEL);
if (data->virt_start == NULL) {
ret = -ENOMEM;
@@ -754,44 +743,43 @@ static int __devinit stmp3xxxfb_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "allocated at %p:0x%x\n", data->virt_start,
data->phys_start);
mutex_init(&data->blank_mutex);
- INIT_WORK(&data->work, stmp3xxxfb_task);
+ INIT_WORK(&data->work, mxsfb_task);
data->state = F_ENABLE;
- stmp3xxxfb_default.bits_per_pixel = pentry->bpp;
+ mxsfb_default.bits_per_pixel = pentry->bpp;
/* NB: rotated */
- stmp3xxxfb_default.xres = pentry->y_res;
- stmp3xxxfb_default.yres = pentry->x_res;
- stmp3xxxfb_default.xres_virtual = pentry->y_res;
- stmp3xxxfb_default.yres_virtual = data->map_size /
- (pentry->y_res * pentry->bpp / 8);
- if (stmp3xxxfb_default.yres_virtual >= stmp3xxxfb_default.yres * 2)
- stmp3xxxfb_default.yres_virtual = stmp3xxxfb_default.yres * 2;
+ mxsfb_default.xres = pentry->y_res;
+ mxsfb_default.yres = pentry->x_res;
+ mxsfb_default.xres_virtual = pentry->y_res;
+ mxsfb_default.yres_virtual = data->map_size /
+ (pentry->y_res * pentry->bpp / 8);
+ if (mxsfb_default.yres_virtual >= mxsfb_default.yres * 2)
+ mxsfb_default.yres_virtual = mxsfb_default.yres * 2;
else
- stmp3xxxfb_default.yres_virtual = stmp3xxxfb_default.yres;
+ mxsfb_default.yres_virtual = mxsfb_default.yres;
- stmp3xxxfb_fix.smem_start = data->phys_start;
- stmp3xxxfb_fix.smem_len = pentry->y_res * pentry->x_res * pentry->bpp /
- 8;
- stmp3xxxfb_fix.ypanstep = 1;
+ mxsfb_fix.smem_start = data->phys_start;
+ mxsfb_fix.smem_len = pentry->y_res * pentry->x_res * pentry->bpp / 8;
+ mxsfb_fix.ypanstep = 1;
switch (pentry->bpp) {
case 32:
case 24:
- stmp3xxxfb_default.red.offset = 16;
- stmp3xxxfb_default.red.length = 8;
- stmp3xxxfb_default.green.offset = 8;
- stmp3xxxfb_default.green.length = 8;
- stmp3xxxfb_default.blue.offset = 0;
- stmp3xxxfb_default.blue.length = 8;
+ mxsfb_default.red.offset = 16;
+ mxsfb_default.red.length = 8;
+ mxsfb_default.green.offset = 8;
+ mxsfb_default.green.length = 8;
+ mxsfb_default.blue.offset = 0;
+ mxsfb_default.blue.length = 8;
break;
case 16:
- stmp3xxxfb_default.red.offset = 11;
- stmp3xxxfb_default.red.length = 5;
- stmp3xxxfb_default.green.offset = 5;
- stmp3xxxfb_default.green.length = 6;
- stmp3xxxfb_default.blue.offset = 0;
- stmp3xxxfb_default.blue.length = 5;
+ mxsfb_default.red.offset = 11;
+ mxsfb_default.red.length = 5;
+ mxsfb_default.green.offset = 5;
+ mxsfb_default.green.length = 6;
+ mxsfb_default.blue.offset = 0;
+ mxsfb_default.blue.length = 5;
break;
default:
@@ -801,9 +789,9 @@ static int __devinit stmp3xxxfb_probe(struct platform_device *pdev)
}
info->screen_base = data->virt_start;
- info->fbops = &stmp3xxxfb_ops;
- info->var = stmp3xxxfb_default;
- info->fix = stmp3xxxfb_fix;
+ info->fbops = &mxsfb_ops;
+ info->var = mxsfb_default;
+ info->fix = mxsfb_fix;
info->pseudo_palette = &data->par;
data->par = NULL;
info->flags = FBINFO_FLAG_DEFAULT;
@@ -811,29 +799,33 @@ static int __devinit stmp3xxxfb_probe(struct platform_device *pdev)
init_waitqueue_head(&data->vsync_wait_q);
data->vsync_count = 0;
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&pdev->dev, "cannot get IRQ resource\n");
ret = -ENODEV;
goto out_dma;
}
- data->dma_irq = res->start;
+ data->regbase = (unsigned long)IO_ADDRESS(res->start);
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res == NULL) {
dev_err(&pdev->dev, "cannot get IRQ resource\n");
ret = -ENODEV;
goto out_dma;
}
- data->err_irq = res->start;
+ data->irq = res->start;
+
+ mxsfb_check_var(&info->var, info);
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret)
goto out_cmap;
- stmp3xxx_init_lcdif();
+ mxsfb_set_par(info);
+
+ mxs_init_lcdif();
ret = pentry->init_panel(data->dev, data->phys_start,
- stmp3xxxfb_fix.smem_len, pentry);
+ mxsfb_fix.smem_len, pentry);
if (ret) {
dev_err(&pdev->dev, "cannot initialize LCD panel\n");
goto out_panel;
@@ -841,21 +833,15 @@ static int __devinit stmp3xxxfb_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "LCD panel initialized\n");
init_timings(data);
- ret = request_irq(data->dma_irq, lcd_irq_handler, 0, "fb_dma", data);
+ ret = request_irq(data->irq, lcd_irq_handler, 0, "fb_irq", data);
if (ret) {
dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n",
- data->dma_irq, ret);
+ data->irq, ret);
goto out_panel;
}
- ret = request_irq(data->err_irq, lcd_irq_handler, 0, "fb_error", data);
- if (ret) {
- dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n",
- data->err_irq, ret);
- goto out_irq;
- }
ret = register_framebuffer(info);
if (ret)
- goto out_register;
+ goto out_irq;
pentry->run_panel();
dev_dbg(&pdev->dev, "LCD DMA channel has been started\n");
@@ -863,91 +849,87 @@ static int __devinit stmp3xxxfb_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "LCD running now\n");
#ifdef CONFIG_CPU_FREQ
- stmp3xxxfb_nb.fb_data = data;
- cpufreq_register_notifier(&stmp3xxxfb_nb.nb,
- CPUFREQ_TRANSITION_NOTIFIER);
+ mxsfb_nb.fb_data = data;
+ cpufreq_register_notifier(&mxsfb_nb.nb, CPUFREQ_TRANSITION_NOTIFIER);
#endif /* CONFIG_CPU_FREQ */
goto out;
-out_register:
- free_irq(data->err_irq, data);
out_irq:
- free_irq(data->dma_irq, data);
+ free_irq(data->irq, data);
out_panel:
fb_dealloc_cmap(&info->cmap);
out_cmap:
dma_free_writecombine(&pdev->dev, data->map_size, data->virt_start,
- data->phys_start);
+ data->phys_start);
out_dma:
kfree(data);
out:
return ret;
}
-static int stmp3xxxfb_remove(struct platform_device *pdev)
+static int mxsfb_remove(struct platform_device *pdev)
{
- struct stmp3xxx_fb_data *data = platform_get_drvdata(pdev);
+ struct mxs_fb_data *data = platform_get_drvdata(pdev);
set_controller_state(data, F_DISABLE);
unregister_framebuffer(&data->info);
framebuffer_release(&data->info);
fb_dealloc_cmap(&data->info.cmap);
- free_irq(data->dma_irq, data);
- free_irq(data->err_irq, data);
+ free_irq(data->irq, data);
dma_free_writecombine(&pdev->dev, data->map_size, data->virt_start,
- data->phys_start);
+ data->phys_start);
kfree(data);
platform_set_drvdata(pdev, NULL);
return 0;
}
#ifdef CONFIG_PM
-static int stmp3xxxfb_suspend(struct platform_device *pdev, pm_message_t state)
+static int mxsfb_suspend(struct platform_device *pdev, pm_message_t state)
{
- struct stmp3xxx_fb_data *data = platform_get_drvdata(pdev);
+ struct mxs_fb_data *data = platform_get_drvdata(pdev);
set_controller_state(data, F_DISABLE);
return 0;
}
-static int stmp3xxxfb_resume(struct platform_device *pdev)
+static int mxsfb_resume(struct platform_device *pdev)
{
- struct stmp3xxx_fb_data *data = platform_get_drvdata(pdev);
+ struct mxs_fb_data *data = platform_get_drvdata(pdev);
set_controller_state(data, F_ENABLE);
return 0;
}
#else
-#define stmp3xxxfb_suspend NULL
-#define stmp3xxxfb_resume NULL
+#define mxsfb_suspend NULL
+#define mxsfb_resume NULL
#endif
-static struct platform_driver stmp3xxxfb_driver = {
- .probe = stmp3xxxfb_probe,
- .remove = stmp3xxxfb_remove,
- .suspend = stmp3xxxfb_suspend,
- .resume = stmp3xxxfb_resume,
- .driver = {
- .name = "stmp3xxx-fb",
- .owner = THIS_MODULE,
- },
+static struct platform_driver mxsfb_driver = {
+ .probe = mxsfb_probe,
+ .remove = mxsfb_remove,
+ .suspend = mxsfb_suspend,
+ .resume = mxsfb_resume,
+ .driver = {
+ .name = "mxs-fb",
+ .owner = THIS_MODULE,
+ },
};
-static int __init stmp3xxxfb_init(void)
+static int __init mxsfb_init(void)
{
- return platform_driver_register(&stmp3xxxfb_driver);
+ return platform_driver_register(&mxsfb_driver);
}
-static void __exit stmp3xxxfb_exit(void)
+static void __exit mxsfb_exit(void)
{
- platform_driver_unregister(&stmp3xxxfb_driver);
+ platform_driver_unregister(&mxsfb_driver);
}
-module_init(stmp3xxxfb_init);
-module_exit(stmp3xxxfb_exit);
+module_init(mxsfb_init);
+module_exit(mxsfb_exit);
/*
* LCD panel select
@@ -957,8 +939,9 @@ static int __init default_panel_select(char *str)
default_panel_name = str;
return 0;
}
+
__setup("lcd_panel=", default_panel_select);
MODULE_AUTHOR("Vitaly Wool <vital@embeddedalley.com>");
-MODULE_DESCRIPTION("STMP3xxx Framebuffer Driver");
+MODULE_DESCRIPTION("MXS Framebuffer Driver");
MODULE_LICENSE("GPL");