summaryrefslogtreecommitdiff
path: root/drivers/video/mxs
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/mxs')
-rw-r--r--drivers/video/mxs/Kconfig28
-rw-r--r--drivers/video/mxs/Makefile6
-rw-r--r--drivers/video/mxs/lcd_43wvf1g.c289
-rw-r--r--drivers/video/mxs/lcd_lms430.c300
-rw-r--r--drivers/video/mxs/lcdif.c136
-rw-r--r--drivers/video/mxs/mxsfb.c950
-rw-r--r--drivers/video/mxs/regs-tvenc.h583
-rw-r--r--drivers/video/mxs/tvenc.c279
8 files changed, 2571 insertions, 0 deletions
diff --git a/drivers/video/mxs/Kconfig b/drivers/video/mxs/Kconfig
new file mode 100644
index 000000000000..35b896e95d4f
--- /dev/null
+++ b/drivers/video/mxs/Kconfig
@@ -0,0 +1,28 @@
+config FB_MXS
+ tristate "MXS Framebuffer driver"
+ depends on FB && ARCH_MXS
+ 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 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
+
+config FB_MXS_TVENC
+ depends on ARCH_MXS
+ bool "TVENC"
+ ---help---
+ Use TVOUT encoder for MXS
diff --git a/drivers/video/mxs/Makefile b/drivers/video/mxs/Makefile
new file mode 100644
index 000000000000..fbab953718c7
--- /dev/null
+++ b/drivers/video/mxs/Makefile
@@ -0,0 +1,6 @@
+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
+# TVOUT support
+obj-$(CONFIG_FB_MXS_TVENC) += tvenc.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/lcd_lms430.c b/drivers/video/mxs/lcd_lms430.c
new file mode 100644
index 000000000000..c167774d5785
--- /dev/null
+++ b/drivers/video/mxs/lcd_lms430.c
@@ -0,0 +1,300 @@
+/*
+ * Freescale MXS Samsung LMS430 LCD panel initialization
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * 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.
+ */
+
+#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 REGS_PWM_BASE IO_ADDRESS(PWM_PHYS_ADDR)
+
+#define DOTCLK_H_ACTIVE 480
+#define DOTCLK_H_PULSE_WIDTH 1
+#define DOTCLK_HF_PORCH 8
+#define DOTCLK_HB_PORCH 15
+#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_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 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(NULL, "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, 1000000000 / pentry->cycle_time_ns); /* Hz */
+ 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)
+{
+ /* Reset LCD panel signel. */
+ __raw_writel(BM_LCDIF_CTRL1_RESET,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR);
+ mdelay(100);
+ mxs_lcdif_notify_clients(MXS_LCDIF_PANEL_RELEASE, pentry);
+ release_dotclk_panel();
+ mxs_lcdif_dma_release();
+ clk_disable(lcd_clk);
+ clk_put(lcd_clk);
+ __raw_writel(BM_LCDIF_CTRL_CLKGATE,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);
+}
+
+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 = "lms430",
+ .x_res = 272,
+ .y_res = 480,
+ .bpp = 32,
+ .cycle_time_ns = 150,
+ .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
new file mode 100644
index 000000000000..f7d48a6fb3e9
--- /dev/null
+++ b/drivers/video/mxs/lcdif.c
@@ -0,0 +1,136 @@
+/*
+ * Freescale MXS LCDIF low-level routines
+ *
+ * Author: Vitaly Wool <vital@embeddedalley.com>
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ * 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.
+ *
+ * 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/delay.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/hardware.h>
+#include <mach/lcdif.h>
+#include <mach/regs-lcdif.h>
+#include <mach/system.h>
+
+#define REGS_LCDIF_BASE IO_ADDRESS(LCDIF_PHYS_ADDR)
+
+void mxs_init_lcdif(void)
+{
+ __raw_writel(BM_LCDIF_CTRL_CLKGATE,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);
+ /* Reset controller */
+ __raw_writel(BM_LCDIF_CTRL_SFTRST, REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);
+ udelay(10);
+
+ /* Take controller out of reset */
+ __raw_writel(BM_LCDIF_CTRL_SFTRST | BM_LCDIF_CTRL_CLKGATE,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);
+
+ /* Setup the bus protocol */
+ __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 */
+ __raw_writel(BM_LCDIF_CTRL1_RESET,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET);
+
+ /* VSYNC is an input by default */
+ __raw_writel(BM_LCDIF_VDCTRL0_VSYNC_OEB,
+ REGS_LCDIF_BASE + HW_LCDIF_VDCTRL0_SET);
+
+ /* Reset display */
+ __raw_writel(BM_LCDIF_CTRL1_RESET,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR);
+ udelay(10);
+ __raw_writel(BM_LCDIF_CTRL1_RESET,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET);
+ udelay(10);
+}
+EXPORT_SYMBOL(mxs_init_lcdif);
+
+int mxs_lcdif_dma_init(struct device *dev, dma_addr_t phys, int memsize)
+{
+ __raw_writel(BM_LCDIF_CTRL_LCDIF_MASTER,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);
+
+ __raw_writel(phys, REGS_LCDIF_BASE + HW_LCDIF_CUR_BUF);
+ __raw_writel(phys, REGS_LCDIF_BASE + HW_LCDIF_NEXT_BUF);
+
+ return 0;
+}
+EXPORT_SYMBOL(mxs_lcdif_dma_init);
+
+void mxs_lcdif_dma_release(void)
+{
+ __raw_writel(BM_LCDIF_CTRL_LCDIF_MASTER,
+ REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);
+ return;
+}
+EXPORT_SYMBOL(mxs_lcdif_dma_release);
+
+void mxs_lcdif_run(void)
+{
+ __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);
+
+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);
+}
+EXPORT_SYMBOL(mxs_lcdif_stop);
+
+int mxs_lcdif_pan_display(dma_addr_t addr)
+{
+ __raw_writel(addr, REGS_LCDIF_BASE + HW_LCDIF_NEXT_BUF);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(mxs_lcdif_pan_display);
+
+static BLOCKING_NOTIFIER_HEAD(lcdif_client_list);
+
+int mxs_lcdif_register_client(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&lcdif_client_list, nb);
+}
+
+EXPORT_SYMBOL(mxs_lcdif_register_client);
+
+void mxs_lcdif_unregister_client(struct notifier_block *nb)
+{
+ blocking_notifier_chain_unregister(&lcdif_client_list, nb);
+}
+EXPORT_SYMBOL(mxs_lcdif_unregister_client);
+
+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(mxs_lcdif_notify_clients);
diff --git a/drivers/video/mxs/mxsfb.c b/drivers/video/mxs/mxsfb.c
new file mode 100644
index 000000000000..0e58ced83066
--- /dev/null
+++ b/drivers/video/mxs/mxsfb.c
@@ -0,0 +1,950 @@
+/*
+ * Freescale MXS framebuffer driver
+ *
+ * Author: Vitaly Wool <vital@embeddedalley.com>
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ * 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.
+ *
+ * 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/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+#include <linux/cpufreq.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-lcdif.h>
+#include <mach/clock.h>
+#include <mach/lcdif.h>
+
+#define NUM_SCREENS 1
+
+enum {
+ F_DISABLE = 0,
+ F_ENABLE,
+ F_REENABLE,
+};
+
+struct mxs_fb_data {
+ struct fb_info info;
+ struct mxs_platform_fb_data *pdata;
+ struct work_struct work;
+ struct mutex blank_mutex;
+ u32 state;
+ u32 task_state;
+ ssize_t mem_size;
+ ssize_t map_size;
+ dma_addr_t phys_start;
+ dma_addr_t cur_phys;
+ int irq;
+ unsigned long regbase;
+ void *virt_start;
+ struct device *dev;
+ wait_queue_head_t vsync_wait_q;
+ u32 vsync_count;
+ void *par;
+};
+
+/* forward declaration */
+static int mxsfb_blank(int blank, struct fb_info *info);
+static unsigned char *default_panel_name;
+static struct mxs_fb_data *cdata;
+static void init_timings(struct mxs_fb_data *data);
+
+static void mxsfb_enable_controller(struct mxs_fb_data *data)
+{
+ struct mxs_platform_fb_entry *pentry = data->pdata->cur;
+
+ if (!data || !data->pdata || !data->pdata->cur)
+ return;
+
+ mxs_init_lcdif();
+ init_timings(data);
+ pentry->init_panel(data->dev, data->phys_start,
+ data->info.fix.smem_len, data->pdata->cur);
+ pentry->run_panel();
+
+ if (pentry->blank_panel)
+ pentry->blank_panel(FB_BLANK_UNBLANK);
+}
+
+static void mxsfb_disable_controller(struct mxs_fb_data *data)
+{
+ struct mxs_platform_fb_entry *pentry = data->pdata->cur;
+
+ if (!data || !data->pdata || !data->pdata->cur)
+ return;
+
+ if (pentry->blank_panel)
+ pentry->blank_panel(FB_BLANK_POWERDOWN);
+
+ if (pentry->stop_panel)
+ pentry->stop_panel();
+ pentry->release_panel(data->dev, pentry);
+}
+
+static void set_controller_state(struct mxs_fb_data *data, u32 state)
+{
+ struct mxs_platform_fb_entry *pentry = data->pdata->cur;
+ struct fb_info *info = &data->info;
+ u32 old_state;
+
+ mutex_lock(&data->blank_mutex);
+ old_state = data->state;
+ pr_debug("%s, old_state %d, state %d\n", __func__, old_state, state);
+
+ switch (state) {
+ case F_DISABLE:
+ /*
+ * Disable controller
+ */
+ if (old_state != F_DISABLE) {
+ data->state = F_DISABLE;
+ mxsfb_disable_controller(data);
+ }
+ break;
+
+ case F_REENABLE:
+ /*
+ * Re-enable the controller when panel changed.
+ */
+ if (old_state == F_ENABLE) {
+ mxsfb_disable_controller(data);
+
+ pentry = data->pdata->cur = data->pdata->next;
+ info->fix.smem_len = pentry->y_res * pentry->x_res *
+ pentry->bpp / 8;
+ info->screen_size = info->fix.smem_len;
+ memset((void *)info->screen_base, 0, info->screen_size);
+
+ 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;
+ info->screen_size = info->fix.smem_len;
+ memset((void *)info->screen_base, 0, info->screen_size);
+
+ data->state = F_DISABLE;
+ }
+ break;
+
+ case F_ENABLE:
+ if (old_state != F_ENABLE) {
+ data->state = F_ENABLE;
+ mxsfb_enable_controller(data);
+ }
+ break;
+ }
+ mutex_unlock(&data->blank_mutex);
+
+}
+
+static void mxsfb_task(struct work_struct *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);
+
+ set_controller_state(data, state);
+}
+
+static void mxs_schedule_work(struct mxs_fb_data *data, u32 state)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ data->task_state = state;
+ schedule_work(&data->work);
+
+ local_irq_restore(flags);
+}
+
+static irqreturn_t lcd_irq_handler(int irq, void *dev_id)
+{
+ 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_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,
+ 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,
+ 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,
+ 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,
+ data->regbase + HW_LCDIF_CTRL1_CLR);
+ }
+ return IRQ_HANDLED;
+}
+
+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 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 mxsfb_get_info(struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix)
+{
+ if (!cdata)
+ return -ENODEV;
+
+ *var = cdata->info.var;
+ *fix = cdata->info.fix;
+ return 0;
+}
+
+void mxsfb_cfg_pxp(int enable, dma_addr_t pxp_phys)
+{
+ if (enable)
+ cdata->pdata->cur->pan_display(pxp_phys);
+ else
+ cdata->pdata->cur->pan_display(cdata->cur_phys);
+}
+
+static int mxsfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ 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);
+ else
+ return -EINVAL;
+}
+
+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
+ */
+
+ /* 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;
+ }
+
+ /* Directcolor:
+ * var->{color}.offset contains start of bitfield
+ * 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)
+ * RAMDAC[X] is programmed to (red, green, blue)
+ *
+ * Pseudocolor:
+ * uses offset = 0 && length = RAMDAC register width.
+ * var->{color}.offset is 0
+ * var->{color}.length contains widht of DAC
+ * cmap is not used
+ * RAMDAC[X] is programmed to (red, green, blue)
+ * Truecolor:
+ * does not use DAC. Usually 3 are present.
+ * 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)
+ * RAMDAC does not exist
+ */
+#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ case FB_VISUAL_PSEUDOCOLOR:
+ red = CNVT_TOHW(red, info->var.red.length);
+ green = CNVT_TOHW(green, info->var.green.length);
+ blue = CNVT_TOHW(blue, info->var.blue.length);
+ transp = CNVT_TOHW(transp, info->var.transp.length);
+ break;
+ case FB_VISUAL_DIRECTCOLOR:
+ red = CNVT_TOHW(red, 8); /* expect 8 bit DAC */
+ green = CNVT_TOHW(green, 8);
+ blue = CNVT_TOHW(blue, 8);
+ /* hey, there is bug in transp handling... */
+ transp = CNVT_TOHW(transp, 8);
+ break;
+ }
+#undef CNVT_TOHW
+ /* Truecolor has hardware independent palette */
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+
+ if (regno >= 16)
+ 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);
+ }
+ return 0;
+}
+
+static inline u_long get_line_length(int xres_virtual, int bpp)
+{
+ u_long length;
+
+ length = xres_virtual * bpp;
+ length = (length + 31) & ~31;
+ length >>= 3;
+ return length;
+}
+
+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);
+ 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 mxs_platform_fb_entry *pentry,
+ void *data, int ret_prev)
+{
+ unsigned char *name = data;
+ if (!strcmp(pentry->name, name))
+ ret_prev = (int)pentry;
+ return ret_prev;
+}
+
+/*
+ * This routine actually sets the video mode. It's in here where we
+ * the hardware state info->par and fix which can be affected by the
+ * change in par. For this driver it doesn't do much.
+ *
+ * XXX: REVISIT
+ */
+static int mxsfb_set_par(struct fb_info *info)
+{
+ 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);
+ if (!pentry)
+ return -EINVAL;
+
+ info->fix.line_length = get_line_length(info->var.xres_virtual,
+ info->var.bits_per_pixel);
+
+ if (pentry == pdata->cur || !pdata->cur)
+ return 0;
+
+ /* init next panel */
+ pdata->next = pentry;
+
+ set_controller_state(data, F_REENABLE);
+
+ return 0;
+}
+
+static int mxsfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ u32 line_length;
+ 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!
+ * as FB_VMODE_SMOOTH_XPAN is only used internally
+ */
+
+ if (var->vmode & FB_VMODE_CONUPDATE) {
+ var->vmode |= FB_VMODE_YWRAP;
+ var->xoffset = info->var.xoffset;
+ var->yoffset = info->var.yoffset;
+ }
+
+ pr_debug("%s: xres %d, yres %d, bpp %d\n", __func__,
+ var->xres, var->yres, var->bits_per_pixel);
+ /*
+ * Some very basic checks
+ */
+ if (!var->xres)
+ var->xres = 1;
+ if (!var->yres)
+ var->yres = 1;
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+
+ if (var->xres_virtual < var->xoffset + var->xres)
+ var->xres_virtual = var->xoffset + var->xres;
+ if (var->yres_virtual < var->yoffset + var->yres)
+ var->yres_virtual = var->yoffset + var->yres;
+
+ line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
+ dev_dbg(data->dev,
+ "line_length %d, var->yres_virtual %d, data->mem_size %d\n",
+ line_length, var->yres_virtual, data->mem_size);
+ if (line_length * var->yres_virtual > data->map_size)
+ return -ENOMEM;
+
+ if (!mxs_lcd_iterate_pdata(pdata, get_matching_pentry, var))
+ return -EINVAL;
+
+ if (var->bits_per_pixel == 16) {
+ /* RGBA 5551 */
+ if (var->transp.length) {
+ var->red.offset = 0;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 5;
+ var->blue.offset = 10;
+ var->blue.length = 5;
+ var->transp.offset = 15;
+ var->transp.length = 1;
+ } else { /* RGB 565 */
+ var->red.offset = 0;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 11;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ }
+ } else {
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ }
+
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ var->transp.msb_right = 0;
+
+ return 0;
+}
+
+static int mxsfb_wait_for_vsync(u32 channel, struct fb_info *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,
+ data->regbase + HW_LCDIF_CTRL1_SET);
+ ret = wait_event_interruptible_timeout(data->vsync_wait_q,
+ count != data->vsync_count,
+ HZ / 10);
+ __raw_writel(BM_LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN,
+ data->regbase + HW_LCDIF_CTRL1_CLR);
+ if (!ret) {
+ dev_err(data->dev, "wait for vsync timed out\n");
+ ret = -ETIMEDOUT;
+ }
+ return ret;
+}
+
+static int mxsfb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+{
+ u32 channel = 0;
+ int ret = -EINVAL;
+
+ switch (cmd) {
+ case FBIO_WAITFORVSYNC:
+ if (!get_user(channel, (__u32 __user *) arg))
+ ret = mxsfb_wait_for_vsync(channel, info);
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static int mxsfb_blank(int blank, struct fb_info *info)
+{
+ struct mxs_fb_data *data = (struct mxs_fb_data *)info;
+ int ret = 0;
+
+ switch (blank) {
+ case FB_BLANK_NORMAL:
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_POWERDOWN:
+ pr_debug("%s: FB_BLANK_POWERDOWN\n", __func__);
+ mxs_schedule_work(data, F_DISABLE);
+ break;
+
+ case FB_BLANK_UNBLANK:
+ pr_debug("%s: FB_BLANK_UNBLANK\n", __func__);
+ mxs_schedule_work(data, F_ENABLE);
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static int mxsfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *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);
+ /* check if var is valid; also, xpan is not supported */
+ if (!var || (var->xoffset != info->var.xoffset) ||
+ (var->yoffset + var->yres > var->yres_virtual)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!data->pdata->cur->pan_display) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* update framebuffer visual */
+ data->cur_phys = data->phys_start +
+ info->fix.line_length * var->yoffset;
+ data->pdata->cur->pan_display(data->cur_phys);
+out:
+ return ret;
+}
+
+static struct fb_ops mxsfb_ops = {
+ .owner = THIS_MODULE,
+ .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 mxs_fb_data *data)
+{
+ unsigned phase_time;
+ unsigned timings;
+
+ /* Just use a phase_time of 1. As optimal as it gets, now. */
+ phase_time = 1;
+
+ /* Program all 4 timings the same */
+ timings = phase_time;
+ timings |= timings << 8;
+ timings |= timings << 16;
+ __raw_writel(timings, data->regbase + HW_LCDIF_TIMING);
+}
+
+#ifdef CONFIG_CPU_FREQ
+
+struct mxsfb_notifier_block {
+ struct mxs_fb_data *fb_data;
+ struct notifier_block nb;
+};
+
+static int mxsfb_notifier(struct notifier_block *self,
+ unsigned long phase, void *p)
+{
+ 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)
+ return NOTIFY_BAD;
+
+ /* REVISIT */
+ switch (phase) {
+ case CPUFREQ_PRECHANGE:
+ if (old_state == F_ENABLE)
+ if (pentry->blank_panel)
+ pentry->blank_panel(FB_BLANK_POWERDOWN);
+ break;
+
+ case CPUFREQ_POSTCHANGE:
+ if (old_state == F_ENABLE)
+ if (pentry->blank_panel)
+ pentry->blank_panel(FB_BLANK_UNBLANK);
+ break;
+
+ default:
+ dev_dbg(data->dev, "didn't handle notify %ld\n", phase);
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct mxsfb_notifier_block mxsfb_nb = {
+ .nb = {
+ .notifier_call = mxsfb_notifier,
+ },
+};
+#endif /* CONFIG_CPU_FREQ */
+
+static int get_max_memsize(struct mxs_platform_fb_entry *pentry,
+ void *data, int ret_prev)
+{
+ 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 mxsfb_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct mxs_fb_data *data;
+ struct resource *res;
+ struct fb_info *info;
+ struct mxs_platform_fb_data *pdata = pdev->dev.platform_data;
+ struct mxs_platform_fb_entry *pentry = NULL;
+
+ if (pdata == NULL) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (default_panel_name) {
+ pentry = (void *)mxs_lcd_iterate_pdata(pdata,
+ get_matching_pentry_by_name,
+ default_panel_name);
+ if (pentry) {
+ mxs_lcd_move_pentry_up(pentry, pdata);
+ pdata->cur = pentry;
+ }
+ }
+ if (!default_panel_name || !pentry)
+ pentry = pdata->cur;
+ if (!pentry || !pentry->init_panel || !pentry->run_panel ||
+ !pentry->release_panel) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ 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;
+ }
+
+ cdata = data;
+ data->dev = &pdev->dev;
+ data->pdata = pdata;
+ platform_set_drvdata(pdev, data);
+ info = &data->info;
+
+ dev_dbg(&pdev->dev, "resolution %dx%d, bpp %d\n", pentry->x_res,
+ pentry->y_res, pentry->bpp);
+
+ 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);
+
+ if (data->virt_start == NULL) {
+ ret = -ENOMEM;
+ goto out_dma;
+ }
+ 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, mxsfb_task);
+ data->state = F_ENABLE;
+
+ mxsfb_default.bits_per_pixel = pentry->bpp;
+ /* NB: rotated */
+ 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
+ mxsfb_default.yres_virtual = mxsfb_default.yres;
+
+ 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:
+ 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:
+ 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:
+ dev_err(&pdev->dev, "unsupported bitwidth %d\n", pentry->bpp);
+ ret = -EINVAL;
+ goto out_dma;
+ }
+
+ info->screen_base = data->virt_start;
+ 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;
+
+ init_waitqueue_head(&data->vsync_wait_q);
+ data->vsync_count = 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->regbase = (unsigned long)IO_ADDRESS(res->start);
+
+ 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->irq = res->start;
+
+ mxsfb_check_var(&info->var, info);
+
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret)
+ goto out_cmap;
+
+ mxsfb_set_par(info);
+
+ mxs_init_lcdif();
+ ret = pentry->init_panel(data->dev, data->phys_start,
+ mxsfb_fix.smem_len, pentry);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot initialize LCD panel\n");
+ goto out_panel;
+ }
+ dev_dbg(&pdev->dev, "LCD panel initialized\n");
+ init_timings(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->irq, ret);
+ goto out_panel;
+ }
+ ret = register_framebuffer(info);
+ if (ret)
+ goto out_irq;
+
+ pentry->run_panel();
+ /* 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");
+
+#ifdef CONFIG_CPU_FREQ
+ mxsfb_nb.fb_data = data;
+ cpufreq_register_notifier(&mxsfb_nb.nb, CPUFREQ_TRANSITION_NOTIFIER);
+#endif /* CONFIG_CPU_FREQ */
+
+ goto out;
+
+out_irq:
+ 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);
+out_dma:
+ kfree(data);
+out:
+ return ret;
+}
+
+static int mxsfb_remove(struct platform_device *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->irq, data);
+ dma_free_writecombine(&pdev->dev, data->map_size, data->virt_start,
+ data->phys_start);
+ kfree(data);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxsfb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct mxs_fb_data *data = platform_get_drvdata(pdev);
+
+ set_controller_state(data, F_DISABLE);
+
+ return 0;
+}
+
+static int mxsfb_resume(struct platform_device *pdev)
+{
+ struct mxs_fb_data *data = platform_get_drvdata(pdev);
+
+ set_controller_state(data, F_ENABLE);
+ return 0;
+}
+#else
+#define mxsfb_suspend NULL
+#define mxsfb_resume NULL
+#endif
+
+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 mxsfb_init(void)
+{
+ return platform_driver_register(&mxsfb_driver);
+}
+
+static void __exit mxsfb_exit(void)
+{
+ platform_driver_unregister(&mxsfb_driver);
+}
+
+module_init(mxsfb_init);
+module_exit(mxsfb_exit);
+
+/*
+ * LCD panel select
+ */
+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("MXS Framebuffer Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/mxs/regs-tvenc.h b/drivers/video/mxs/regs-tvenc.h
new file mode 100644
index 000000000000..bd2493e2dee5
--- /dev/null
+++ b/drivers/video/mxs/regs-tvenc.h
@@ -0,0 +1,583 @@
+/*
+ * Freescale TVENC Register Definitions
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This file is created by xml file. Don't Edit it.
+ *
+ * Xml Revision: 1.00
+ * Template revision: 26195
+ */
+
+#ifndef __ARCH_ARM___TVENC_H
+#define __ARCH_ARM___TVENC_H
+
+
+#define HW_TVENC_CTRL (0x00000000)
+#define HW_TVENC_CTRL_SET (0x00000004)
+#define HW_TVENC_CTRL_CLR (0x00000008)
+#define HW_TVENC_CTRL_TOG (0x0000000c)
+
+#define BM_TVENC_CTRL_SFTRST 0x80000000
+#define BM_TVENC_CTRL_CLKGATE 0x40000000
+#define BM_TVENC_CTRL_TVENC_MACROVISION_PRESENT 0x20000000
+#define BM_TVENC_CTRL_TVENC_COMPOSITE_PRESENT 0x10000000
+#define BM_TVENC_CTRL_TVENC_SVIDEO_PRESENT 0x08000000
+#define BM_TVENC_CTRL_TVENC_COMPONENT_PRESENT 0x04000000
+#define BP_TVENC_CTRL_RSRVD1 6
+#define BM_TVENC_CTRL_RSRVD1 0x03FFFFC0
+#define BF_TVENC_CTRL_RSRVD1(v) \
+ (((v) << 6) & BM_TVENC_CTRL_RSRVD1)
+#define BM_TVENC_CTRL_DAC_FIFO_NO_WRITE 0x00000020
+#define BM_TVENC_CTRL_DAC_FIFO_NO_READ 0x00000010
+#define BM_TVENC_CTRL_DAC_DATA_FIFO_RST 0x00000008
+#define BP_TVENC_CTRL_RSRVD2 1
+#define BM_TVENC_CTRL_RSRVD2 0x00000006
+#define BF_TVENC_CTRL_RSRVD2(v) \
+ (((v) << 1) & BM_TVENC_CTRL_RSRVD2)
+#define BM_TVENC_CTRL_DAC_MUX_MODE 0x00000001
+
+#define HW_TVENC_CONFIG (0x00000010)
+#define HW_TVENC_CONFIG_SET (0x00000014)
+#define HW_TVENC_CONFIG_CLR (0x00000018)
+#define HW_TVENC_CONFIG_TOG (0x0000001c)
+
+#define BP_TVENC_CONFIG_RSRVD5 28
+#define BM_TVENC_CONFIG_RSRVD5 0xF0000000
+#define BF_TVENC_CONFIG_RSRVD5(v) \
+ (((v) << 28) & BM_TVENC_CONFIG_RSRVD5)
+#define BM_TVENC_CONFIG_DEFAULT_PICFORM 0x08000000
+#define BP_TVENC_CONFIG_YDEL_ADJ 24
+#define BM_TVENC_CONFIG_YDEL_ADJ 0x07000000
+#define BF_TVENC_CONFIG_YDEL_ADJ(v) \
+ (((v) << 24) & BM_TVENC_CONFIG_YDEL_ADJ)
+#define BM_TVENC_CONFIG_RSRVD4 0x00800000
+#define BM_TVENC_CONFIG_RSRVD3 0x00400000
+#define BM_TVENC_CONFIG_ADD_YPBPR_PED 0x00200000
+#define BM_TVENC_CONFIG_PAL_SHAPE 0x00100000
+#define BM_TVENC_CONFIG_NO_PED 0x00080000
+#define BM_TVENC_CONFIG_COLOR_BAR_EN 0x00040000
+#define BP_TVENC_CONFIG_YGAIN_SEL 16
+#define BM_TVENC_CONFIG_YGAIN_SEL 0x00030000
+#define BF_TVENC_CONFIG_YGAIN_SEL(v) \
+ (((v) << 16) & BM_TVENC_CONFIG_YGAIN_SEL)
+#define BP_TVENC_CONFIG_CGAIN 14
+#define BM_TVENC_CONFIG_CGAIN 0x0000C000
+#define BF_TVENC_CONFIG_CGAIN(v) \
+ (((v) << 14) & BM_TVENC_CONFIG_CGAIN)
+#define BP_TVENC_CONFIG_CLK_PHS 12
+#define BM_TVENC_CONFIG_CLK_PHS 0x00003000
+#define BF_TVENC_CONFIG_CLK_PHS(v) \
+ (((v) << 12) & BM_TVENC_CONFIG_CLK_PHS)
+#define BM_TVENC_CONFIG_RSRVD2 0x00000800
+#define BM_TVENC_CONFIG_FSYNC_ENBL 0x00000400
+#define BM_TVENC_CONFIG_FSYNC_PHS 0x00000200
+#define BM_TVENC_CONFIG_HSYNC_PHS 0x00000100
+#define BM_TVENC_CONFIG_VSYNC_PHS 0x00000080
+#define BP_TVENC_CONFIG_SYNC_MODE 4
+#define BM_TVENC_CONFIG_SYNC_MODE 0x00000070
+#define BF_TVENC_CONFIG_SYNC_MODE(v) \
+ (((v) << 4) & BM_TVENC_CONFIG_SYNC_MODE)
+#define BM_TVENC_CONFIG_RSRVD1 0x00000008
+#define BP_TVENC_CONFIG_ENCD_MODE 0
+#define BM_TVENC_CONFIG_ENCD_MODE 0x00000007
+#define BF_TVENC_CONFIG_ENCD_MODE(v) \
+ (((v) << 0) & BM_TVENC_CONFIG_ENCD_MODE)
+
+#define HW_TVENC_FILTCTRL (0x00000020)
+#define HW_TVENC_FILTCTRL_SET (0x00000024)
+#define HW_TVENC_FILTCTRL_CLR (0x00000028)
+#define HW_TVENC_FILTCTRL_TOG (0x0000002c)
+
+#define BP_TVENC_FILTCTRL_RSRVD1 20
+#define BM_TVENC_FILTCTRL_RSRVD1 0xFFF00000
+#define BF_TVENC_FILTCTRL_RSRVD1(v) \
+ (((v) << 20) & BM_TVENC_FILTCTRL_RSRVD1)
+#define BM_TVENC_FILTCTRL_YSHARP_BW 0x00080000
+#define BM_TVENC_FILTCTRL_YD_OFFSETSEL 0x00040000
+#define BM_TVENC_FILTCTRL_SEL_YLPF 0x00020000
+#define BM_TVENC_FILTCTRL_SEL_CLPF 0x00010000
+#define BM_TVENC_FILTCTRL_SEL_YSHARP 0x00008000
+#define BM_TVENC_FILTCTRL_YLPF_COEFSEL 0x00004000
+#define BM_TVENC_FILTCTRL_COEFSEL_CLPF 0x00002000
+#define BM_TVENC_FILTCTRL_YS_GAINSGN 0x00001000
+#define BP_TVENC_FILTCTRL_YS_GAINSEL 10
+#define BM_TVENC_FILTCTRL_YS_GAINSEL 0x00000C00
+#define BF_TVENC_FILTCTRL_YS_GAINSEL(v) \
+ (((v) << 10) & BM_TVENC_FILTCTRL_YS_GAINSEL)
+#define BM_TVENC_FILTCTRL_RSRVD2 0x00000200
+#define BM_TVENC_FILTCTRL_RSRVD3 0x00000100
+#define BP_TVENC_FILTCTRL_RSRVD4 0
+#define BM_TVENC_FILTCTRL_RSRVD4 0x000000FF
+#define BF_TVENC_FILTCTRL_RSRVD4(v) \
+ (((v) << 0) & BM_TVENC_FILTCTRL_RSRVD4)
+
+#define HW_TVENC_SYNCOFFSET (0x00000030)
+#define HW_TVENC_SYNCOFFSET_SET (0x00000034)
+#define HW_TVENC_SYNCOFFSET_CLR (0x00000038)
+#define HW_TVENC_SYNCOFFSET_TOG (0x0000003c)
+
+#define BM_TVENC_SYNCOFFSET_RSRVD1 0x80000000
+#define BP_TVENC_SYNCOFFSET_HSO 20
+#define BM_TVENC_SYNCOFFSET_HSO 0x7FF00000
+#define BF_TVENC_SYNCOFFSET_HSO(v) \
+ (((v) << 20) & BM_TVENC_SYNCOFFSET_HSO)
+#define BP_TVENC_SYNCOFFSET_VSO 10
+#define BM_TVENC_SYNCOFFSET_VSO 0x000FFC00
+#define BF_TVENC_SYNCOFFSET_VSO(v) \
+ (((v) << 10) & BM_TVENC_SYNCOFFSET_VSO)
+#define BP_TVENC_SYNCOFFSET_HLC 0
+#define BM_TVENC_SYNCOFFSET_HLC 0x000003FF
+#define BF_TVENC_SYNCOFFSET_HLC(v) \
+ (((v) << 0) & BM_TVENC_SYNCOFFSET_HLC)
+
+#define HW_TVENC_HTIMINGSYNC0 (0x00000040)
+#define HW_TVENC_HTIMINGSYNC0_SET (0x00000044)
+#define HW_TVENC_HTIMINGSYNC0_CLR (0x00000048)
+#define HW_TVENC_HTIMINGSYNC0_TOG (0x0000004c)
+
+#define BP_TVENC_HTIMINGSYNC0_RSRVD2 26
+#define BM_TVENC_HTIMINGSYNC0_RSRVD2 0xFC000000
+#define BF_TVENC_HTIMINGSYNC0_RSRVD2(v) \
+ (((v) << 26) & BM_TVENC_HTIMINGSYNC0_RSRVD2)
+#define BP_TVENC_HTIMINGSYNC0_SYNC_END 16
+#define BM_TVENC_HTIMINGSYNC0_SYNC_END 0x03FF0000
+#define BF_TVENC_HTIMINGSYNC0_SYNC_END(v) \
+ (((v) << 16) & BM_TVENC_HTIMINGSYNC0_SYNC_END)
+#define BP_TVENC_HTIMINGSYNC0_RSRVD1 10
+#define BM_TVENC_HTIMINGSYNC0_RSRVD1 0x0000FC00
+#define BF_TVENC_HTIMINGSYNC0_RSRVD1(v) \
+ (((v) << 10) & BM_TVENC_HTIMINGSYNC0_RSRVD1)
+#define BP_TVENC_HTIMINGSYNC0_SYNC_STRT 0
+#define BM_TVENC_HTIMINGSYNC0_SYNC_STRT 0x000003FF
+#define BF_TVENC_HTIMINGSYNC0_SYNC_STRT(v) \
+ (((v) << 0) & BM_TVENC_HTIMINGSYNC0_SYNC_STRT)
+
+#define HW_TVENC_HTIMINGSYNC1 (0x00000050)
+#define HW_TVENC_HTIMINGSYNC1_SET (0x00000054)
+#define HW_TVENC_HTIMINGSYNC1_CLR (0x00000058)
+#define HW_TVENC_HTIMINGSYNC1_TOG (0x0000005c)
+
+#define BP_TVENC_HTIMINGSYNC1_RSRVD2 26
+#define BM_TVENC_HTIMINGSYNC1_RSRVD2 0xFC000000
+#define BF_TVENC_HTIMINGSYNC1_RSRVD2(v) \
+ (((v) << 26) & BM_TVENC_HTIMINGSYNC1_RSRVD2)
+#define BP_TVENC_HTIMINGSYNC1_SYNC_EQEND 16
+#define BM_TVENC_HTIMINGSYNC1_SYNC_EQEND 0x03FF0000
+#define BF_TVENC_HTIMINGSYNC1_SYNC_EQEND(v) \
+ (((v) << 16) & BM_TVENC_HTIMINGSYNC1_SYNC_EQEND)
+#define BP_TVENC_HTIMINGSYNC1_RSRVD1 10
+#define BM_TVENC_HTIMINGSYNC1_RSRVD1 0x0000FC00
+#define BF_TVENC_HTIMINGSYNC1_RSRVD1(v) \
+ (((v) << 10) & BM_TVENC_HTIMINGSYNC1_RSRVD1)
+#define BP_TVENC_HTIMINGSYNC1_SYNC_SREND 0
+#define BM_TVENC_HTIMINGSYNC1_SYNC_SREND 0x000003FF
+#define BF_TVENC_HTIMINGSYNC1_SYNC_SREND(v) \
+ (((v) << 0) & BM_TVENC_HTIMINGSYNC1_SYNC_SREND)
+
+#define HW_TVENC_HTIMINGACTIVE (0x00000060)
+#define HW_TVENC_HTIMINGACTIVE_SET (0x00000064)
+#define HW_TVENC_HTIMINGACTIVE_CLR (0x00000068)
+#define HW_TVENC_HTIMINGACTIVE_TOG (0x0000006c)
+
+#define BP_TVENC_HTIMINGACTIVE_RSRVD2 26
+#define BM_TVENC_HTIMINGACTIVE_RSRVD2 0xFC000000
+#define BF_TVENC_HTIMINGACTIVE_RSRVD2(v) \
+ (((v) << 26) & BM_TVENC_HTIMINGACTIVE_RSRVD2)
+#define BP_TVENC_HTIMINGACTIVE_ACTV_END 16
+#define BM_TVENC_HTIMINGACTIVE_ACTV_END 0x03FF0000
+#define BF_TVENC_HTIMINGACTIVE_ACTV_END(v) \
+ (((v) << 16) & BM_TVENC_HTIMINGACTIVE_ACTV_END)
+#define BP_TVENC_HTIMINGACTIVE_RSRVD1 10
+#define BM_TVENC_HTIMINGACTIVE_RSRVD1 0x0000FC00
+#define BF_TVENC_HTIMINGACTIVE_RSRVD1(v) \
+ (((v) << 10) & BM_TVENC_HTIMINGACTIVE_RSRVD1)
+#define BP_TVENC_HTIMINGACTIVE_ACTV_STRT 0
+#define BM_TVENC_HTIMINGACTIVE_ACTV_STRT 0x000003FF
+#define BF_TVENC_HTIMINGACTIVE_ACTV_STRT(v) \
+ (((v) << 0) & BM_TVENC_HTIMINGACTIVE_ACTV_STRT)
+
+#define HW_TVENC_HTIMINGBURST0 (0x00000070)
+#define HW_TVENC_HTIMINGBURST0_SET (0x00000074)
+#define HW_TVENC_HTIMINGBURST0_CLR (0x00000078)
+#define HW_TVENC_HTIMINGBURST0_TOG (0x0000007c)
+
+#define BP_TVENC_HTIMINGBURST0_RSRVD2 26
+#define BM_TVENC_HTIMINGBURST0_RSRVD2 0xFC000000
+#define BF_TVENC_HTIMINGBURST0_RSRVD2(v) \
+ (((v) << 26) & BM_TVENC_HTIMINGBURST0_RSRVD2)
+#define BP_TVENC_HTIMINGBURST0_WBRST_STRT 16
+#define BM_TVENC_HTIMINGBURST0_WBRST_STRT 0x03FF0000
+#define BF_TVENC_HTIMINGBURST0_WBRST_STRT(v) \
+ (((v) << 16) & BM_TVENC_HTIMINGBURST0_WBRST_STRT)
+#define BP_TVENC_HTIMINGBURST0_RSRVD1 10
+#define BM_TVENC_HTIMINGBURST0_RSRVD1 0x0000FC00
+#define BF_TVENC_HTIMINGBURST0_RSRVD1(v) \
+ (((v) << 10) & BM_TVENC_HTIMINGBURST0_RSRVD1)
+#define BP_TVENC_HTIMINGBURST0_NBRST_STRT 0
+#define BM_TVENC_HTIMINGBURST0_NBRST_STRT 0x000003FF
+#define BF_TVENC_HTIMINGBURST0_NBRST_STRT(v) \
+ (((v) << 0) & BM_TVENC_HTIMINGBURST0_NBRST_STRT)
+
+#define HW_TVENC_HTIMINGBURST1 (0x00000080)
+#define HW_TVENC_HTIMINGBURST1_SET (0x00000084)
+#define HW_TVENC_HTIMINGBURST1_CLR (0x00000088)
+#define HW_TVENC_HTIMINGBURST1_TOG (0x0000008c)
+
+#define BP_TVENC_HTIMINGBURST1_RSRVD1 10
+#define BM_TVENC_HTIMINGBURST1_RSRVD1 0xFFFFFC00
+#define BF_TVENC_HTIMINGBURST1_RSRVD1(v) \
+ (((v) << 10) & BM_TVENC_HTIMINGBURST1_RSRVD1)
+#define BP_TVENC_HTIMINGBURST1_BRST_END 0
+#define BM_TVENC_HTIMINGBURST1_BRST_END 0x000003FF
+#define BF_TVENC_HTIMINGBURST1_BRST_END(v) \
+ (((v) << 0) & BM_TVENC_HTIMINGBURST1_BRST_END)
+
+#define HW_TVENC_VTIMING0 (0x00000090)
+#define HW_TVENC_VTIMING0_SET (0x00000094)
+#define HW_TVENC_VTIMING0_CLR (0x00000098)
+#define HW_TVENC_VTIMING0_TOG (0x0000009c)
+
+#define BP_TVENC_VTIMING0_RSRVD3 26
+#define BM_TVENC_VTIMING0_RSRVD3 0xFC000000
+#define BF_TVENC_VTIMING0_RSRVD3(v) \
+ (((v) << 26) & BM_TVENC_VTIMING0_RSRVD3)
+#define BP_TVENC_VTIMING0_VSTRT_PREEQ 16
+#define BM_TVENC_VTIMING0_VSTRT_PREEQ 0x03FF0000
+#define BF_TVENC_VTIMING0_VSTRT_PREEQ(v) \
+ (((v) << 16) & BM_TVENC_VTIMING0_VSTRT_PREEQ)
+#define BP_TVENC_VTIMING0_RSRVD2 14
+#define BM_TVENC_VTIMING0_RSRVD2 0x0000C000
+#define BF_TVENC_VTIMING0_RSRVD2(v) \
+ (((v) << 14) & BM_TVENC_VTIMING0_RSRVD2)
+#define BP_TVENC_VTIMING0_VSTRT_ACTV 8
+#define BM_TVENC_VTIMING0_VSTRT_ACTV 0x00003F00
+#define BF_TVENC_VTIMING0_VSTRT_ACTV(v) \
+ (((v) << 8) & BM_TVENC_VTIMING0_VSTRT_ACTV)
+#define BP_TVENC_VTIMING0_RSRVD1 6
+#define BM_TVENC_VTIMING0_RSRVD1 0x000000C0
+#define BF_TVENC_VTIMING0_RSRVD1(v) \
+ (((v) << 6) & BM_TVENC_VTIMING0_RSRVD1)
+#define BP_TVENC_VTIMING0_VSTRT_SUBPH 0
+#define BM_TVENC_VTIMING0_VSTRT_SUBPH 0x0000003F
+#define BF_TVENC_VTIMING0_VSTRT_SUBPH(v) \
+ (((v) << 0) & BM_TVENC_VTIMING0_VSTRT_SUBPH)
+
+#define HW_TVENC_VTIMING1 (0x000000a0)
+#define HW_TVENC_VTIMING1_SET (0x000000a4)
+#define HW_TVENC_VTIMING1_CLR (0x000000a8)
+#define HW_TVENC_VTIMING1_TOG (0x000000ac)
+
+#define BP_TVENC_VTIMING1_RSRVD3 30
+#define BM_TVENC_VTIMING1_RSRVD3 0xC0000000
+#define BF_TVENC_VTIMING1_RSRVD3(v) \
+ (((v) << 30) & BM_TVENC_VTIMING1_RSRVD3)
+#define BP_TVENC_VTIMING1_VSTRT_POSTEQ 24
+#define BM_TVENC_VTIMING1_VSTRT_POSTEQ 0x3F000000
+#define BF_TVENC_VTIMING1_VSTRT_POSTEQ(v) \
+ (((v) << 24) & BM_TVENC_VTIMING1_VSTRT_POSTEQ)
+#define BP_TVENC_VTIMING1_RSRVD2 22
+#define BM_TVENC_VTIMING1_RSRVD2 0x00C00000
+#define BF_TVENC_VTIMING1_RSRVD2(v) \
+ (((v) << 22) & BM_TVENC_VTIMING1_RSRVD2)
+#define BP_TVENC_VTIMING1_VSTRT_SERRA 16
+#define BM_TVENC_VTIMING1_VSTRT_SERRA 0x003F0000
+#define BF_TVENC_VTIMING1_VSTRT_SERRA(v) \
+ (((v) << 16) & BM_TVENC_VTIMING1_VSTRT_SERRA)
+#define BP_TVENC_VTIMING1_RSRVD1 10
+#define BM_TVENC_VTIMING1_RSRVD1 0x0000FC00
+#define BF_TVENC_VTIMING1_RSRVD1(v) \
+ (((v) << 10) & BM_TVENC_VTIMING1_RSRVD1)
+#define BP_TVENC_VTIMING1_LAST_FLD_LN 0
+#define BM_TVENC_VTIMING1_LAST_FLD_LN 0x000003FF
+#define BF_TVENC_VTIMING1_LAST_FLD_LN(v) \
+ (((v) << 0) & BM_TVENC_VTIMING1_LAST_FLD_LN)
+
+#define HW_TVENC_MISC (0x000000b0)
+#define HW_TVENC_MISC_SET (0x000000b4)
+#define HW_TVENC_MISC_CLR (0x000000b8)
+#define HW_TVENC_MISC_TOG (0x000000bc)
+
+#define BP_TVENC_MISC_RSRVD3 25
+#define BM_TVENC_MISC_RSRVD3 0xFE000000
+#define BF_TVENC_MISC_RSRVD3(v) \
+ (((v) << 25) & BM_TVENC_MISC_RSRVD3)
+#define BP_TVENC_MISC_LPF_RST_OFF 16
+#define BM_TVENC_MISC_LPF_RST_OFF 0x01FF0000
+#define BF_TVENC_MISC_LPF_RST_OFF(v) \
+ (((v) << 16) & BM_TVENC_MISC_LPF_RST_OFF)
+#define BP_TVENC_MISC_RSRVD2 12
+#define BM_TVENC_MISC_RSRVD2 0x0000F000
+#define BF_TVENC_MISC_RSRVD2(v) \
+ (((v) << 12) & BM_TVENC_MISC_RSRVD2)
+#define BM_TVENC_MISC_NTSC_LN_CNT 0x00000800
+#define BM_TVENC_MISC_PAL_FSC_PHASE_ALT 0x00000400
+#define BP_TVENC_MISC_FSC_PHASE_RST 8
+#define BM_TVENC_MISC_FSC_PHASE_RST 0x00000300
+#define BF_TVENC_MISC_FSC_PHASE_RST(v) \
+ (((v) << 8) & BM_TVENC_MISC_FSC_PHASE_RST)
+#define BP_TVENC_MISC_BRUCHB 6
+#define BM_TVENC_MISC_BRUCHB 0x000000C0
+#define BF_TVENC_MISC_BRUCHB(v) \
+ (((v) << 6) & BM_TVENC_MISC_BRUCHB)
+#define BP_TVENC_MISC_AGC_LVL_CTRL 4
+#define BM_TVENC_MISC_AGC_LVL_CTRL 0x00000030
+#define BF_TVENC_MISC_AGC_LVL_CTRL(v) \
+ (((v) << 4) & BM_TVENC_MISC_AGC_LVL_CTRL)
+#define BM_TVENC_MISC_RSRVD1 0x00000008
+#define BM_TVENC_MISC_CS_INVERT_CTRL 0x00000004
+#define BP_TVENC_MISC_Y_BLANK_CTRL 0
+#define BM_TVENC_MISC_Y_BLANK_CTRL 0x00000003
+#define BF_TVENC_MISC_Y_BLANK_CTRL(v) \
+ (((v) << 0) & BM_TVENC_MISC_Y_BLANK_CTRL)
+
+#define HW_TVENC_COLORSUB0 (0x000000c0)
+#define HW_TVENC_COLORSUB0_SET (0x000000c4)
+#define HW_TVENC_COLORSUB0_CLR (0x000000c8)
+#define HW_TVENC_COLORSUB0_TOG (0x000000cc)
+
+#define BP_TVENC_COLORSUB0_PHASE_INC 0
+#define BM_TVENC_COLORSUB0_PHASE_INC 0xFFFFFFFF
+#define BF_TVENC_COLORSUB0_PHASE_INC(v) (v)
+
+#define HW_TVENC_COLORSUB1 (0x000000d0)
+#define HW_TVENC_COLORSUB1_SET (0x000000d4)
+#define HW_TVENC_COLORSUB1_CLR (0x000000d8)
+#define HW_TVENC_COLORSUB1_TOG (0x000000dc)
+
+#define BP_TVENC_COLORSUB1_PHASE_OFFSET 0
+#define BM_TVENC_COLORSUB1_PHASE_OFFSET 0xFFFFFFFF
+#define BF_TVENC_COLORSUB1_PHASE_OFFSET(v) (v)
+
+#define HW_TVENC_COPYPROTECT (0x000000e0)
+#define HW_TVENC_COPYPROTECT_SET (0x000000e4)
+#define HW_TVENC_COPYPROTECT_CLR (0x000000e8)
+#define HW_TVENC_COPYPROTECT_TOG (0x000000ec)
+
+#define BP_TVENC_COPYPROTECT_RSRVD1 16
+#define BM_TVENC_COPYPROTECT_RSRVD1 0xFFFF0000
+#define BF_TVENC_COPYPROTECT_RSRVD1(v) \
+ (((v) << 16) & BM_TVENC_COPYPROTECT_RSRVD1)
+#define BM_TVENC_COPYPROTECT_WSS_ENBL 0x00008000
+#define BM_TVENC_COPYPROTECT_CGMS_ENBL 0x00004000
+#define BP_TVENC_COPYPROTECT_WSS_CGMS_DATA 0
+#define BM_TVENC_COPYPROTECT_WSS_CGMS_DATA 0x00003FFF
+#define BF_TVENC_COPYPROTECT_WSS_CGMS_DATA(v) \
+ (((v) << 0) & BM_TVENC_COPYPROTECT_WSS_CGMS_DATA)
+
+#define HW_TVENC_CLOSEDCAPTION (0x000000f0)
+#define HW_TVENC_CLOSEDCAPTION_SET (0x000000f4)
+#define HW_TVENC_CLOSEDCAPTION_CLR (0x000000f8)
+#define HW_TVENC_CLOSEDCAPTION_TOG (0x000000fc)
+
+#define BP_TVENC_CLOSEDCAPTION_RSRVD1 20
+#define BM_TVENC_CLOSEDCAPTION_RSRVD1 0xFFF00000
+#define BF_TVENC_CLOSEDCAPTION_RSRVD1(v) \
+ (((v) << 20) & BM_TVENC_CLOSEDCAPTION_RSRVD1)
+#define BP_TVENC_CLOSEDCAPTION_CC_ENBL 18
+#define BM_TVENC_CLOSEDCAPTION_CC_ENBL 0x000C0000
+#define BF_TVENC_CLOSEDCAPTION_CC_ENBL(v) \
+ (((v) << 18) & BM_TVENC_CLOSEDCAPTION_CC_ENBL)
+#define BP_TVENC_CLOSEDCAPTION_CC_FILL 16
+#define BM_TVENC_CLOSEDCAPTION_CC_FILL 0x00030000
+#define BF_TVENC_CLOSEDCAPTION_CC_FILL(v) \
+ (((v) << 16) & BM_TVENC_CLOSEDCAPTION_CC_FILL)
+#define BP_TVENC_CLOSEDCAPTION_CC_DATA 0
+#define BM_TVENC_CLOSEDCAPTION_CC_DATA 0x0000FFFF
+#define BF_TVENC_CLOSEDCAPTION_CC_DATA(v) \
+ (((v) << 0) & BM_TVENC_CLOSEDCAPTION_CC_DATA)
+
+#define HW_TVENC_COLORBURST (0x00000140)
+#define HW_TVENC_COLORBURST_SET (0x00000144)
+#define HW_TVENC_COLORBURST_CLR (0x00000148)
+#define HW_TVENC_COLORBURST_TOG (0x0000014c)
+
+#define BP_TVENC_COLORBURST_NBA 24
+#define BM_TVENC_COLORBURST_NBA 0xFF000000
+#define BF_TVENC_COLORBURST_NBA(v) \
+ (((v) << 24) & BM_TVENC_COLORBURST_NBA)
+#define BP_TVENC_COLORBURST_PBA 16
+#define BM_TVENC_COLORBURST_PBA 0x00FF0000
+#define BF_TVENC_COLORBURST_PBA(v) \
+ (((v) << 16) & BM_TVENC_COLORBURST_PBA)
+#define BP_TVENC_COLORBURST_RSRVD1 12
+#define BM_TVENC_COLORBURST_RSRVD1 0x0000F000
+#define BF_TVENC_COLORBURST_RSRVD1(v) \
+ (((v) << 12) & BM_TVENC_COLORBURST_RSRVD1)
+#define BP_TVENC_COLORBURST_RSRVD2 0
+#define BM_TVENC_COLORBURST_RSRVD2 0x00000FFF
+#define BF_TVENC_COLORBURST_RSRVD2(v) \
+ (((v) << 0) & BM_TVENC_COLORBURST_RSRVD2)
+
+#define HW_TVENC_MACROVISION0 (0x00000150)
+#define HW_TVENC_MACROVISION0_SET (0x00000154)
+#define HW_TVENC_MACROVISION0_CLR (0x00000158)
+#define HW_TVENC_MACROVISION0_TOG (0x0000015c)
+
+#define BP_TVENC_MACROVISION0_DATA 0
+#define BM_TVENC_MACROVISION0_DATA 0xFFFFFFFF
+#define BF_TVENC_MACROVISION0_DATA(v) (v)
+
+#define HW_TVENC_MACROVISION1 (0x00000160)
+#define HW_TVENC_MACROVISION1_SET (0x00000164)
+#define HW_TVENC_MACROVISION1_CLR (0x00000168)
+#define HW_TVENC_MACROVISION1_TOG (0x0000016c)
+
+#define BP_TVENC_MACROVISION1_DATA 0
+#define BM_TVENC_MACROVISION1_DATA 0xFFFFFFFF
+#define BF_TVENC_MACROVISION1_DATA(v) (v)
+
+#define HW_TVENC_MACROVISION2 (0x00000170)
+#define HW_TVENC_MACROVISION2_SET (0x00000174)
+#define HW_TVENC_MACROVISION2_CLR (0x00000178)
+#define HW_TVENC_MACROVISION2_TOG (0x0000017c)
+
+#define BP_TVENC_MACROVISION2_DATA 0
+#define BM_TVENC_MACROVISION2_DATA 0xFFFFFFFF
+#define BF_TVENC_MACROVISION2_DATA(v) (v)
+
+#define HW_TVENC_MACROVISION3 (0x00000180)
+#define HW_TVENC_MACROVISION3_SET (0x00000184)
+#define HW_TVENC_MACROVISION3_CLR (0x00000188)
+#define HW_TVENC_MACROVISION3_TOG (0x0000018c)
+
+#define BP_TVENC_MACROVISION3_DATA 0
+#define BM_TVENC_MACROVISION3_DATA 0xFFFFFFFF
+#define BF_TVENC_MACROVISION3_DATA(v) (v)
+
+#define HW_TVENC_MACROVISION4 (0x00000190)
+#define HW_TVENC_MACROVISION4_SET (0x00000194)
+#define HW_TVENC_MACROVISION4_CLR (0x00000198)
+#define HW_TVENC_MACROVISION4_TOG (0x0000019c)
+
+#define BP_TVENC_MACROVISION4_RSRVD2 24
+#define BM_TVENC_MACROVISION4_RSRVD2 0xFF000000
+#define BF_TVENC_MACROVISION4_RSRVD2(v) \
+ (((v) << 24) & BM_TVENC_MACROVISION4_RSRVD2)
+#define BP_TVENC_MACROVISION4_MACV_TST 16
+#define BM_TVENC_MACROVISION4_MACV_TST 0x00FF0000
+#define BF_TVENC_MACROVISION4_MACV_TST(v) \
+ (((v) << 16) & BM_TVENC_MACROVISION4_MACV_TST)
+#define BP_TVENC_MACROVISION4_RSRVD1 11
+#define BM_TVENC_MACROVISION4_RSRVD1 0x0000F800
+#define BF_TVENC_MACROVISION4_RSRVD1(v) \
+ (((v) << 11) & BM_TVENC_MACROVISION4_RSRVD1)
+#define BP_TVENC_MACROVISION4_DATA 0
+#define BM_TVENC_MACROVISION4_DATA 0x000007FF
+#define BF_TVENC_MACROVISION4_DATA(v) \
+ (((v) << 0) & BM_TVENC_MACROVISION4_DATA)
+
+#define HW_TVENC_DACCTRL (0x000001a0)
+#define HW_TVENC_DACCTRL_SET (0x000001a4)
+#define HW_TVENC_DACCTRL_CLR (0x000001a8)
+#define HW_TVENC_DACCTRL_TOG (0x000001ac)
+
+#define BM_TVENC_DACCTRL_TEST3 0x80000000
+#define BM_TVENC_DACCTRL_RSRVD1 0x40000000
+#define BM_TVENC_DACCTRL_RSRVD2 0x20000000
+#define BM_TVENC_DACCTRL_JACK1_DIS_DET_EN 0x10000000
+#define BM_TVENC_DACCTRL_TEST2 0x08000000
+#define BM_TVENC_DACCTRL_RSRVD3 0x04000000
+#define BM_TVENC_DACCTRL_RSRVD4 0x02000000
+#define BM_TVENC_DACCTRL_JACK1_DET_EN 0x01000000
+#define BM_TVENC_DACCTRL_TEST1 0x00800000
+#define BM_TVENC_DACCTRL_DISABLE_GND_DETECT 0x00400000
+#define BP_TVENC_DACCTRL_JACK_DIS_ADJ 20
+#define BM_TVENC_DACCTRL_JACK_DIS_ADJ 0x00300000
+#define BF_TVENC_DACCTRL_JACK_DIS_ADJ(v) \
+ (((v) << 20) & BM_TVENC_DACCTRL_JACK_DIS_ADJ)
+#define BM_TVENC_DACCTRL_GAINDN 0x00080000
+#define BM_TVENC_DACCTRL_GAINUP 0x00040000
+#define BM_TVENC_DACCTRL_INVERT_CLK 0x00020000
+#define BM_TVENC_DACCTRL_SELECT_CLK 0x00010000
+#define BM_TVENC_DACCTRL_BYPASS_ACT_CASCODE 0x00008000
+#define BM_TVENC_DACCTRL_RSRVD5 0x00004000
+#define BM_TVENC_DACCTRL_RSRVD6 0x00002000
+#define BM_TVENC_DACCTRL_PWRUP1 0x00001000
+#define BM_TVENC_DACCTRL_WELL_TOVDD 0x00000800
+#define BM_TVENC_DACCTRL_RSRVD7 0x00000400
+#define BM_TVENC_DACCTRL_RSRVD8 0x00000200
+#define BM_TVENC_DACCTRL_DUMP_TOVDD1 0x00000100
+#define BM_TVENC_DACCTRL_LOWER_SIGNAL 0x00000080
+#define BP_TVENC_DACCTRL_RVAL 4
+#define BM_TVENC_DACCTRL_RVAL 0x00000070
+#define BF_TVENC_DACCTRL_RVAL(v) \
+ (((v) << 4) & BM_TVENC_DACCTRL_RVAL)
+#define BM_TVENC_DACCTRL_NO_INTERNAL_TERM 0x00000008
+#define BM_TVENC_DACCTRL_HALF_CURRENT 0x00000004
+#define BP_TVENC_DACCTRL_CASC_ADJ 0
+#define BM_TVENC_DACCTRL_CASC_ADJ 0x00000003
+#define BF_TVENC_DACCTRL_CASC_ADJ(v) \
+ (((v) << 0) & BM_TVENC_DACCTRL_CASC_ADJ)
+
+#define HW_TVENC_DACSTATUS (0x000001b0)
+#define HW_TVENC_DACSTATUS_SET (0x000001b4)
+#define HW_TVENC_DACSTATUS_CLR (0x000001b8)
+#define HW_TVENC_DACSTATUS_TOG (0x000001bc)
+
+#define BP_TVENC_DACSTATUS_RSRVD1 13
+#define BM_TVENC_DACSTATUS_RSRVD1 0xFFFFE000
+#define BF_TVENC_DACSTATUS_RSRVD1(v) \
+ (((v) << 13) & BM_TVENC_DACSTATUS_RSRVD1)
+#define BM_TVENC_DACSTATUS_RSRVD2 0x00001000
+#define BM_TVENC_DACSTATUS_RSRVD3 0x00000800
+#define BM_TVENC_DACSTATUS_JACK1_DET_STATUS 0x00000400
+#define BM_TVENC_DACSTATUS_RSRVD4 0x00000200
+#define BM_TVENC_DACSTATUS_RSRVD5 0x00000100
+#define BM_TVENC_DACSTATUS_JACK1_GROUNDED 0x00000080
+#define BM_TVENC_DACSTATUS_RSRVD6 0x00000040
+#define BM_TVENC_DACSTATUS_RSRVD7 0x00000020
+#define BM_TVENC_DACSTATUS_JACK1_DIS_DET_IRQ 0x00000010
+#define BM_TVENC_DACSTATUS_RSRVD8 0x00000008
+#define BM_TVENC_DACSTATUS_RSRVD9 0x00000004
+#define BM_TVENC_DACSTATUS_JACK1_DET_IRQ 0x00000002
+#define BM_TVENC_DACSTATUS_ENIRQ_JACK 0x00000001
+
+#define HW_TVENC_VDACTEST (0x000001c0)
+#define HW_TVENC_VDACTEST_SET (0x000001c4)
+#define HW_TVENC_VDACTEST_CLR (0x000001c8)
+#define HW_TVENC_VDACTEST_TOG (0x000001cc)
+
+#define BP_TVENC_VDACTEST_RSRVD1 14
+#define BM_TVENC_VDACTEST_RSRVD1 0xFFFFC000
+#define BF_TVENC_VDACTEST_RSRVD1(v) \
+ (((v) << 14) & BM_TVENC_VDACTEST_RSRVD1)
+#define BM_TVENC_VDACTEST_ENABLE_PIX_INT_GAIN 0x00002000
+#define BM_TVENC_VDACTEST_BYPASS_PIX_INT 0x00001000
+#define BM_TVENC_VDACTEST_BYPASS_PIX_INT_DROOP 0x00000800
+#define BM_TVENC_VDACTEST_TEST_FIFO_FULL 0x00000400
+#define BP_TVENC_VDACTEST_DATA 0
+#define BM_TVENC_VDACTEST_DATA 0x000003FF
+#define BF_TVENC_VDACTEST_DATA(v) \
+ (((v) << 0) & BM_TVENC_VDACTEST_DATA)
+
+#define HW_TVENC_VERSION (0x000001d0)
+
+#define BP_TVENC_VERSION_MAJOR 24
+#define BM_TVENC_VERSION_MAJOR 0xFF000000
+#define BF_TVENC_VERSION_MAJOR(v) \
+ (((v) << 24) & BM_TVENC_VERSION_MAJOR)
+#define BP_TVENC_VERSION_MINOR 16
+#define BM_TVENC_VERSION_MINOR 0x00FF0000
+#define BF_TVENC_VERSION_MINOR(v) \
+ (((v) << 16) & BM_TVENC_VERSION_MINOR)
+#define BP_TVENC_VERSION_STEP 0
+#define BM_TVENC_VERSION_STEP 0x0000FFFF
+#define BF_TVENC_VERSION_STEP(v) \
+ (((v) << 0) & BM_TVENC_VERSION_STEP)
+#endif /* __ARCH_ARM___TVENC_H */
diff --git a/drivers/video/mxs/tvenc.c b/drivers/video/mxs/tvenc.c
new file mode 100644
index 000000000000..7aaa1fd013b0
--- /dev/null
+++ b/drivers/video/mxs/tvenc.c
@@ -0,0 +1,279 @@
+/*
+ * Freescale STMP378X dvi panel initialization
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * 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:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+/* #define DEBUG */
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <mach/regs-lcdif.h>
+#include <mach/regs-lradc.h>
+#include <mach/regs-pwm.h>
+#include <mach/regs-apbh.h>
+#include <mach/gpio.h>
+#include <mach/lcdif.h>
+#include "regs-tvenc.h"
+
+enum {
+ TVENC_MODE_OFF = 0,
+ TVENC_MODE_NTSC,
+ TVENC_MODE_PAL,
+};
+
+#define REGS_TVENC_BASE (IO_ADDRESS(TVENC_PHYS_ADDR))
+
+/* NTSC 720x480 mode */
+#define NTSC_X_RES 720
+#define NTSC_Y_RES 480
+#define NTSC_H_BLANKING 262
+#define NTSC_V_LINES 525
+
+/* PAL 720x576 mode */
+#define PAL_X_RES 720
+#define PAL_Y_RES 576
+#define PAL_H_BLANKING 274
+#define PAL_V_LINES 625
+
+/* frame size */
+#define DVI_H_BLANKING(m) (m == TVENC_MODE_NTSC ? \
+ NTSC_H_BLANKING : PAL_H_BLANKING)
+#define DVI_V_LINES(m) (m == TVENC_MODE_NTSC ? \
+ NTSC_V_LINES : PAL_V_LINES)
+#define DVI_H_ACTIVE(m) (m == TVENC_MODE_NTSC ? NTSC_X_RES : PAL_X_RES)
+#define DVI_V_ACTIVE(m) (m == TVENC_MODE_NTSC ? NTSC_Y_RES : PAL_Y_RES)
+/* fileds range */
+#define DVI_F1_START(m) 1
+#define DVI_F1_END(m) (DVI_V_LINES(m) / 2)
+#define DVI_F2_START(m) (DVI_F1_END(m) + 1)
+#define DVI_F2_END(m) DVI_V_LINES(m)
+/* blanking range */
+#define DVI_V1_BLANK_START(m) DVI_F1_END(m)
+#define DVI_V1_BLANK_END(m) (DVI_V1_BLANK_START(m) + \
+ (DVI_V_LINES(m) - DVI_V_ACTIVE(m)) / 2)
+#define DVI_V2_BLANK_START(m) DVI_F2_END(m)
+#define DVI_V2_BLANK_END(m) ((DVI_V2_BLANK_START(m) + \
+ (DVI_V_LINES(m) - DVI_V_ACTIVE(m)) / 2 - 1) % \
+ DVI_V_LINES(m))
+
+static struct clk *lcd_clk;
+static struct clk *clk_tv108M_ng;
+static struct clk *clk_tv27M;
+
+static int tvenc_mode;
+
+static void init_tvenc_hw(int mode)
+{
+ /* Reset module */
+ __raw_writel(BM_TVENC_CTRL_SFTRST, REGS_TVENC_BASE + HW_TVENC_CTRL_SET);
+ udelay(10);
+
+ /* Take module out of reset */
+ __raw_writel(BM_TVENC_CTRL_SFTRST | BM_TVENC_CTRL_CLKGATE,
+ REGS_TVENC_BASE + HW_TVENC_CTRL_CLR);
+
+ if (mode == TVENC_MODE_NTSC) {
+ /* Config NTSC-M mode, 8-bit Y/C in, SYNC out */
+ __raw_writel(BM_TVENC_CONFIG_SYNC_MODE |
+ BM_TVENC_CONFIG_PAL_SHAPE |
+ BM_TVENC_CONFIG_YGAIN_SEL |
+ BM_TVENC_CONFIG_CGAIN,
+ REGS_TVENC_BASE + HW_TVENC_CONFIG_CLR);
+ __raw_writel(BM_TVENC_CONFIG_FSYNC_PHS |
+ BF_TVENC_CONFIG_SYNC_MODE(0x4),
+ REGS_TVENC_BASE + HW_TVENC_CONFIG_SET);
+
+ /* 859 pixels/line for NTSC */
+ __raw_writel(857, REGS_TVENC_BASE + HW_TVENC_SYNCOFFSET);
+
+ __raw_writel(0x21F07C1F, REGS_TVENC_BASE + HW_TVENC_COLORSUB0);
+ __raw_writel(BM_TVENC_COLORBURST_NBA |
+ BM_TVENC_COLORBURST_PBA,
+ REGS_TVENC_BASE + HW_TVENC_COLORBURST_CLR);
+ __raw_writel(BF_TVENC_COLORBURST_NBA(0xc8) |
+ BF_TVENC_COLORBURST_PBA(0x0),
+ REGS_TVENC_BASE + HW_TVENC_COLORBURST_SET);
+ } else if (mode == TVENC_MODE_PAL) {
+ /* Config PAL-B mode, 8-bit Y/C in, SYNC out */
+ __raw_writel(BM_TVENC_CONFIG_SYNC_MODE |
+ BM_TVENC_CONFIG_ENCD_MODE |
+ BM_TVENC_CONFIG_YGAIN_SEL |
+ BM_TVENC_CONFIG_CGAIN |
+ BM_TVENC_CONFIG_FSYNC_PHS,
+ REGS_TVENC_BASE + HW_TVENC_CONFIG_CLR);
+ __raw_writel(BM_TVENC_CONFIG_PAL_SHAPE |
+ BF_TVENC_CONFIG_YGAIN_SEL(0x1)
+ | BF_TVENC_CONFIG_CGAIN(0x1)
+ | BF_TVENC_CONFIG_ENCD_MODE(0x1)
+ | BF_TVENC_CONFIG_SYNC_MODE(0x4),
+ REGS_TVENC_BASE + HW_TVENC_CONFIG_SET);
+
+ /* 863 pixels/line for PAL */
+ __raw_writel(863, REGS_TVENC_BASE + HW_TVENC_SYNCOFFSET);
+
+ __raw_writel(0x2A098ACB, REGS_TVENC_BASE + HW_TVENC_COLORSUB0);
+ __raw_writel(BM_TVENC_COLORBURST_NBA |
+ BM_TVENC_COLORBURST_PBA,
+ REGS_TVENC_BASE + HW_TVENC_COLORBURST_CLR);
+ __raw_writel(BF_TVENC_COLORBURST_NBA(0xd6) |
+ BF_TVENC_COLORBURST_PBA(0x2a),
+ REGS_TVENC_BASE + HW_TVENC_COLORBURST_SET);
+ }
+
+ /* Power up DAC */
+ __raw_writel(BM_TVENC_DACCTRL_GAINDN |
+ BM_TVENC_DACCTRL_GAINUP |
+ BM_TVENC_DACCTRL_PWRUP1 |
+ BM_TVENC_DACCTRL_DUMP_TOVDD1 |
+ BF_TVENC_DACCTRL_RVAL(0x3),
+ REGS_TVENC_BASE + HW_TVENC_DACCTRL);
+
+ /* set all to zero is a requirement for NTSC */
+ __raw_writel(0, REGS_TVENC_BASE + HW_TVENC_MACROVISION0);
+ __raw_writel(0, REGS_TVENC_BASE + HW_TVENC_MACROVISION1);
+ __raw_writel(0, REGS_TVENC_BASE + HW_TVENC_MACROVISION2);
+ __raw_writel(0, REGS_TVENC_BASE + HW_TVENC_MACROVISION3);
+ __raw_writel(0, REGS_TVENC_BASE + HW_TVENC_MACROVISION4);
+}
+
+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, "lcdif");
+ clk_enable(lcd_clk);
+ clk_set_rate(lcd_clk, 1000000000 / pentry->cycle_time_ns);/* kHz */
+
+ clk_tv108M_ng = clk_get(NULL, "tv108M_ng");
+ clk_tv27M = clk_get(NULL, "tv27M");
+ clk_enable(clk_tv108M_ng);
+ clk_enable(clk_tv27M);
+
+ tvenc_mode = pentry->x_res == NTSC_Y_RES ? TVENC_MODE_NTSC :
+ TVENC_MODE_PAL;
+
+ init_tvenc_hw(tvenc_mode);
+
+ setup_dvi_panel(DVI_H_ACTIVE(tvenc_mode), DVI_V_ACTIVE(tvenc_mode),
+ DVI_H_BLANKING(tvenc_mode), DVI_V_LINES(tvenc_mode),
+ DVI_V1_BLANK_START(tvenc_mode),
+ DVI_V1_BLANK_END(tvenc_mode),
+ DVI_V2_BLANK_START(tvenc_mode),
+ DVI_V2_BLANK_END(tvenc_mode),
+ DVI_F1_START(tvenc_mode), DVI_F1_END(tvenc_mode),
+ DVI_F2_START(tvenc_mode), DVI_F2_END(tvenc_mode));
+
+ ret = mxs_lcdif_dma_init(dev, phys, memsize);
+ mxs_lcdif_notify_clients(MXS_LCDIF_PANEL_INIT, pentry);
+
+ 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_dvi_panel();
+
+ mxs_lcdif_dma_release();
+
+ clk_disable(clk_tv108M_ng);
+ clk_disable(clk_tv27M);
+ clk_disable(lcd_clk);
+ clk_put(clk_tv108M_ng);
+ clk_put(clk_tv27M);
+ 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);
+
+ /* Wait until current transfer is complete, max 30ms */
+ for (count = 30000; count > 0; 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 ntsc_fb_entry = {
+ .name = "tvenc_ntsc",
+ /* x/y swapped */
+ .x_res = NTSC_Y_RES,
+ .y_res = NTSC_X_RES,
+ .bpp = 32,
+ /* the pix_clk should be near 27Mhz for proper syncronization */
+ .cycle_time_ns = 37,
+ .lcd_type = MXS_LCD_PANEL_DVI,
+ .init_panel = init_panel,
+ .release_panel = release_panel,
+ .blank_panel = blank_panel,
+ .run_panel = mxs_lcdif_run,
+ .pan_display = mxs_lcdif_pan_display,
+};
+
+static struct mxs_platform_fb_entry pal_fb_entry = {
+ .name = "tvenc_pal",
+ /* x/y swapped */
+ .x_res = PAL_Y_RES,
+ .y_res = PAL_X_RES,
+ .bpp = 32,
+ /* the pix_clk should be near 27Mhz for proper syncronization */
+ .cycle_time_ns = 37,
+ .lcd_type = MXS_LCD_PANEL_DVI,
+ .init_panel = init_panel,
+ .release_panel = release_panel,
+ .blank_panel = blank_panel,
+ .run_panel = mxs_lcdif_run,
+ .pan_display = mxs_lcdif_pan_display,
+};
+
+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(&ntsc_fb_entry, pdev->dev.platform_data);
+ mxs_lcd_register_entry(&pal_fb_entry, pdev->dev.platform_data);
+ return 0;
+}
+
+subsys_initcall(register_devices);