tiny4412 linux-4.2 移植(十一)LCD驱动移植

简介

tiny4412 lcd屏使用的液晶屏型号是S702,它通过RGB888跟4412进行数据通信。LCD驱动的实现方式有两种,一种是单独写驱动模块,另一种是基于源码s3c-fb.c去修改。
第一种方式可以参考
【TINY4412】LINUX移植笔记:(27)设备树LCD驱动
Exynos4412——LCD驱动
另外一种方式是参考fire brother的github去修改的。
第二种方式的思路是基于友善之臂的linux3.5源码移植过来,然后改成设备树的形式。我这里仅仅是做了移植操作,没有去仔细分析代码,所以我这里仅提供diff。

diff

diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 6085e92..7cf499e 100755
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -722,8 +722,8 @@
             reg = <0x11c00000 0x20000>;
             interrupt-names = "fifo", "vsync", "lcd_sys";
             interrupts = <11 0>, <11 1>, <11 2>;
-            clocks = <&clock CLK_SCLK_FIMD0>, <&clock CLK_FIMD0>;
-            clock-names = "sclk_fimd", "fimd";
+            clocks = <&clock CLK_FIMD0>, <&clock CLK_SCLK_FIMD0>;
+            clock-names = "fimd", "sclk_fimd";
             power-domains = <&pd_lcd0>;
             iommus = <&sysmmu_fimd0>;
             samsung,sysreg = <&sys_reg>;
diff --git a/arch/arm/boot/dts/exynos4412-pinctrl.dtsi b/arch/arm/boot/dts/exynos4412-pinctrl.dtsi
old mode 100644
new mode 100755
index d7d5fdc..8bbb3a8
--- a/arch/arm/boot/dts/exynos4412-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos4412-pinctrl.dtsi
@@ -363,7 +363,7 @@
         samsung,pins = "gpf0-0", "gpf0-1", "gpf0-2", "gpf0-3";
         samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
         samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-        samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
+        samsung,pin-drv = <EXYNOS4_PIN_DRV_LV2>;
     };
     lcd_data16: lcd-data-width16 {
@@ -396,7 +396,7 @@
                 "gpf3-0", "gpf3-1", "gpf3-2", "gpf3-3";
         samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
         samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-        samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
+        samsung,pin-drv = <EXYNOS4_PIN_DRV_LV3>;
     };
     lcd_ldi: lcd-ldi {
diff --git a/arch/arm/boot/dts/exynos4412-tiny4412.dts b/arch/arm/boot/dts/exynos4412-tiny4412.dts
index f6b00a7..92aa0f0 100755
--- a/arch/arm/boot/dts/exynos4412-tiny4412.dts
+++ b/arch/arm/boot/dts/exynos4412-tiny4412.dts
@@ -11,6 +11,8 @@
/dts-v1/;
#include "exynos4412.dtsi"
#include 
+#include <dt-bindings/video/samsung_fimd.h>
+
/ {
     model = "FriendlyARM TINY4412 board based on Exynos4412";
@@ -92,6 +94,147 @@
             clock-frequency = <24000000>;
         };
     };
+    tiny4412_lcd {
+        status = "okay";
+
+        s702{
+            width = <800>;
+            height = <480>;
+            p_width = <155>;
+            p_height = <93>;
+            bpp = <24>;
+            freq = <63>;
+            
+            timing {
+                h_fp = <80>;
+                h_bp = <36>;
+                h_sw = <10>;
+                v_fp = <22>;
+                v_fpe = <1>;
+                v_bp = <15>;
+                v_bpe = <1>;
+                v_sw = <8>;
+            };
+            
+            polarity {
+                rise_vclk;
+                inv_hsync;
+                inv_vsync;
+            };
+        };
+    };
+
+&fimd {
+    compatible = "samsung,exynos4-fb";
+    sclk-fimd-rate = <800000000>;
+    pinctrl-0 = <&lcd_clk &lcd_data24>;
+    pinctrl-names = "lcd0_pin_cfg";
+    sysreg_lcd_blk_cfg_offset = /bits/ 32 <0x0210>;
+    status = "okay";
+    lcd_name = "s702";
+    
+    lcd_default_config {
+        vidcon0 = <VIDCON0_VIDOUT_RGB VIDCON0_PNRMODE_RGB>;
+        vidcon1 = <VIDCON1_INV_HSYNC VIDCON1_INV_VSYNC>;
+        setup_gpio = "exynos4_fimd0_gpio_setup_24bpp";
+    
+        vtiming {
+            left_margin = <9>;
+            right_margin = <9>;
+            upper_margin = <5>;
+            lower_margin = <5>;
+            hsync_len = <2>;
+            vsync_len = <2>;
+            xres = <480>;
+            yres = <800>;
+        };
+        wins_array {
+            win0 {
+                xres = /bits/ 16 <480>;
+                yres = /bits/ 16 <800>;
+                virtual_x = /bits/ 16 <480>;
+                virtual_y = /bits/ 16 <800>;
+                max_bpp     = /bits/ 16 <32>;
+                default_bpp    = /bits/ 16 <24>;
+                width = /bits/ 16 <66>;
+                height = /bits/ 16 <109>;
+            };
+
+            win1 {
+                xres = /bits/ 16 <480>;
+                yres = /bits/ 16 <800>;
+                virtual_x = /bits/ 16 <480>;
+                virtual_y = /bits/ 16 <800>;
+                max_bpp     = /bits/ 16 <32>;
+                default_bpp    = /bits/ 16 <24>;
+                width = /bits/ 16 <66>;
+                height = /bits/ 16 <109>;
+            };
+
+            win2 {
+                xres = /bits/ 16 <480>;
+                yres = /bits/ 16 <800>;
+                virtual_x = /bits/ 16 <480>;
+                virtual_y = /bits/ 16 <800>;
+                max_bpp     = /bits/ 16 <32>;
+                default_bpp    = /bits/ 16 <24>;
+                width = /bits/ 16 <66>;
+                height = /bits/ 16 <109>;
+            };
+
+            win3 {
+                xres = /bits/ 16 <480>;
+                yres = /bits/ 16 <800>;
+                virtual_x = /bits/ 16 <480>;
+                virtual_y = /bits/ 16 <800>;
+                max_bpp     = /bits/ 16 <32>;
+                default_bpp    = /bits/ 16 <24>;
+                width = /bits/ 16 <66>;
+                height = /bits/ 16 <109>;
+            };
+
+            win4 {
+                xres = /bits/ 16 <480>;
+                yres = /bits/ 16 <800>;
+                virtual_x = /bits/ 16 <480>;
+                virtual_y = /bits/ 16 <800>;
+                max_bpp     = /bits/ 16 <32>;
+                default_bpp    = /bits/ 16 <24>;
+                width = /bits/ 16 <66>;
+                height = /bits/ 16 <109>;
+            };
+        };
+        
+    };
+
+    
};
&i2c_0 {
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
index 846b0c9..bf66a1d 100644
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -102,7 +102,7 @@ obj-$(CONFIG_FB_BROADSHEET)       += broadsheetfb.o
obj-$(CONFIG_FB_S1D13XXX)      += s1d13xxxfb.o
obj-$(CONFIG_FB_SH7760)          += sh7760fb.o
obj-$(CONFIG_FB_IMX)              += imxfb.o
-obj-$(CONFIG_FB_S3C)          += s3c-fb.o
+obj-y          += s3c-fb.o
obj-$(CONFIG_FB_S3C2410)      += s3c2410fb.o
obj-$(CONFIG_FB_FSL_DIU)      += fsl-diu-fb.o
obj-$(CONFIG_FB_COBALT)           += cobalt_lcdfb.o
diff --git a/drivers/video/fbdev/s3c-fb.c b/drivers/video/fbdev/s3c-fb.c
old mode 100644
new mode 100755
index 9ec85cc..a343636
--- a/drivers/video/fbdev/s3c-fb.c
+++ b/drivers/video/fbdev/s3c-fb.c
@@ -24,10 +24,17 @@
#include 
#include 
#include 
+#include <linux/dma-buf.h>
+
#include 
#include 
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/gpio.h>
+#include <linux/byteorder/generic.h>
+
/* This driver will export a number of framebuffer interfaces depending
  * on the configuration passed in via the platform data. Each fb instance
  * maps to a hardware window. Currently there is no support for runtime
@@ -54,7 +61,7 @@
/* irq_flags bits */
#define S3C_FB_VSYNC_IRQ_EN    0
-#define VSYNC_TIMEOUT_MSEC 50
+#define VSYNC_TIMEOUT_MSEC 60
struct s3c_fb;
@@ -153,6 +160,13 @@ struct s3c_fb_palette {
     struct fb_bitfield    a;
};
+struct s3c_dma_buf_data {
+    struct dma_buf *dma_buf;
+    struct dma_buf_attachment *attachment;
+    struct sg_table *sg_table;
+    dma_addr_t dma_addr;
+};
+
/**
  * struct s3c_fb_win - per window private data for each framebuffer.
  * @windata: The platform data supplied for the window configuration.
@@ -174,6 +188,13 @@ struct s3c_fb_win {
     u32            *palette_buffer;
     u32             pseudo_palette[16];
     unsigned int         index;
+
+    struct s3c_dma_buf_data dma_buf_data;
+    struct fb_var_screeninfo prev_var;
+    struct fb_fix_screeninfo prev_fix;
+
+    int         fps;
+
};
/**
@@ -221,6 +242,90 @@ struct s3c_fb {
     struct s3c_fb_vsync     vsync_info;
};
+#ifdef CONFIG_OF
+
+typedef struct lcd_io_reg_cfg{
+    struct pinctrl *pctrl;
+    struct pinctrl_state *pin_lcd_cfg;
+    void __iomem *lcd_blk_cfg_reg;
+} lcd_io_reg_cfg;
+
+static struct lcd_io_reg_cfg lcd_io_cfg = {
+    .lcd_blk_cfg_reg = NULL,
+    .pctrl = NULL,
+    .pin_lcd_cfg = NULL,
+};
+
+static const struct of_device_id s3c_fb_of_match[];
+static struct s3c_fb_platdata * of_get_s3_fb_lcd(const struct device_node *node,
+    const char *name);
+static int of_parse_lcd_io_reg_cfg(struct platform_device *pdev,
+    struct lcd_io_reg_cfg *pcfg);
+
+#endif
+
+
+/*
+ * struct s3cfb_lcd_polarity
+ * @rise_vclk:    if 1, video data is fetched at rising edge
+ * @inv_hsync:    if HSYNC polarity is inversed
+ * @inv_vsync:    if VSYNC polarity is inversed
+ * @inv_vden:    if VDEN polarity is inversed
+ */
+struct s3cfb_lcd_polarity {
+    int    rise_vclk;
+    int    inv_hsync;
+    int    inv_vsync;
+    int    inv_vden;
+};
+
+/*
+ * struct s3cfb_lcd_timing
+ * @h_fp:    horizontal front porch
+ * @h_bp:    horizontal back porch
+ * @h_sw:    horizontal sync width
+ * @v_fp:    vertical front porch
+ * @v_fpe:    vertical front porch for even field
+ * @v_bp:    vertical back porch
+ * @v_bpe:    vertical back porch for even field
+ */
+struct s3cfb_lcd_timing {
+    int    h_fp;
+    int    h_bp;
+    int    h_sw;
+    int    v_fp;
+    int    v_fpe;
+    int    v_bp;
+    int    v_bpe;
+    int    v_sw;
+};
+
+
+/*
+ * struct s3cfb_lcd
+ * @width:        horizontal resolution
+ * @height:        vertical resolution
+ * @p_width:    width of lcd in mm
+ * @p_height:    height of lcd in mm
+ * @bpp:        bits per pixel
+ * @freq:        vframe frequency
+ * @timing:        timing values
+ * @polarity:    polarity settings
+ * @init_ldi:    pointer to LDI init function
+ *
+ */
+struct s3cfb_lcd {
+    int    width;
+    int    height;
+    int    p_width;
+    int    p_height;
+    int    bpp;
+    int    freq;
+    struct    s3cfb_lcd_timing timing;
+    struct    s3cfb_lcd_polarity polarity;
+};
+
+
/**
  * s3c_fb_validate_win_bpp - validate the bits-per-pixel for this mode.
  * @win: The device window.
@@ -962,7 +1067,7 @@ static irqreturn_t s3c_fb_irq(int irq, void *dev_id)
     struct s3c_fb *sfb = dev_id;
     void __iomem  *regs = sfb->regs;
     u32 irq_sts_reg;
-
+    printk(KERN_WARNING"s3c_fb_irq do irq!\n");
     spin_lock(&sfb->slock);
     irq_sts_reg = readl(regs + VIDINTCON1);
@@ -1098,21 +1203,25 @@ static int s3c_fb_alloc_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
     size = (real_size > virt_size) ? real_size : virt_size;
     size *= (windata->max_bpp > 16) ? 32 : windata->max_bpp;
-    size /= 8;
+    size >>= 3;
     fbi->fix.smem_len = size;
     size = PAGE_ALIGN(size);
     dev_dbg(sfb->dev, "want %u bytes for window\n", size);
-    fbi->screen_base = dma_alloc_wc(sfb->dev, size, &map_dma, GFP_KERNEL);
-    if (!fbi->screen_base)
+    fbi->screen_base = dma_alloc_writecombine(sfb->dev, size, &map_dma, GFP_KERNEL);
+    printk(KERN_WARNING"s3c_fb_alloc_memory dma addr 0x%08X\n", map_dma);
+    if (!fbi->screen_base){
+        dev_err(sfb->dev, "dma_alloc_writecombine err\n");
         return -ENOMEM;
+    }
+
     dev_dbg(sfb->dev, "mapped %x to %p\n",
         (unsigned int)map_dma, fbi->screen_base);
-    memset(fbi->screen_base, 0x0, size);
+    memset(fbi->screen_base, 0x00, size);
     fbi->fix.smem_start = map_dma;
     return 0;
@@ -1130,7 +1239,7 @@ static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
     struct fb_info *fbi = win->fbinfo;
     if (fbi->screen_base)
-        dma_free_wc(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),
+        dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),
                     fbi->screen_base, fbi->fix.smem_start);
}
@@ -1242,6 +1351,8 @@ static int s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
     initmode.yres = windata->yres;
     fb_videomode_to_var(&fbinfo->var, &initmode);
+    fbinfo->var.width    = windata->width;
+    fbinfo->var.height    = windata->height;
     fbinfo->fix.type    = FB_TYPE_PACKED_PIXELS;
     fbinfo->fix.accel    = FB_ACCEL_NONE;
     fbinfo->var.activate    = FB_ACTIVATE_NOW;
@@ -1314,6 +1425,13 @@ static void s3c_fb_set_rgb_timing(struct s3c_fb *sfb)
         data |= (1 << 5);
     writel(data, regs + VIDCON0);
+    if (sfb->variant.has_blendcon) {
+        data = readl(sfb->regs + BLENDCON);
+        data &= ~BLENDCON_NEW_MASK;
+        data |= BLENDCON_NEW_8BIT_ALPHA_VALUE;
+        writel(data, sfb->regs + BLENDCON);
+    }
+
     data = VIDTCON0_VBPD(vmode->upper_margin - 1) |
            VIDTCON0_VFPD(vmode->lower_margin - 1) |
            VIDTCON0_VSPW(vmode->vsync_len - 1);
@@ -1356,29 +1474,182 @@ static void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
         writel(reg, sfb->regs + SHADOWCON);
     }
}
+static int of_parse_tiny4412_lcd(const char *lcd_name, struct s3cfb_lcd *lcd)
+{
+    struct device_node *lcd_np = NULL;
+    struct device_node *spec_lcd_np = NULL;
+    struct device_node *timing_np = NULL;
+    struct device_node *polar_np = NULL;
+
+    if((NULL == lcd_name) || (NULL == lcd))
+        return -1;
+
+    lcd_np = of_find_node_by_name(NULL, "tiny4412_lcd");
+    
+    if(NULL == lcd_np)
+        return -1;
+
+    spec_lcd_np = of_get_child_by_name(lcd_np, lcd_name);
+
+    if(NULL == spec_lcd_np)
+        return -1;
+
+    of_property_read_u32(spec_lcd_np, "width", &lcd->width);
+    of_property_read_u32(spec_lcd_np, "height", &lcd->height);
+    of_property_read_u32(spec_lcd_np, "p_width", &lcd->p_width);
+    of_property_read_u32(spec_lcd_np, "p_height", &lcd->p_height);
+    of_property_read_u32(spec_lcd_np, "bpp", &lcd->bpp);
+    of_property_read_u32(spec_lcd_np, "freq", &lcd->freq);
+    
+    timing_np = of_get_child_by_name(spec_lcd_np, "timing");
+    of_property_read_u32(timing_np, "h_fp", &lcd->timing.h_fp);
+    of_property_read_u32(timing_np, "h_bp", &lcd->timing.h_bp);
+    of_property_read_u32(timing_np, "h_sw", &lcd->timing.h_sw);
+    of_property_read_u32(timing_np, "v_fp", &lcd->timing.v_fp);
+    of_property_read_u32(timing_np, "v_fpe", &lcd->timing.v_fpe);
+    of_property_read_u32(timing_np, "v_bp", &lcd->timing.v_bp);
+    of_property_read_u32(timing_np, "v_bpe", &lcd->timing.v_bpe);
+    of_property_read_u32(timing_np, "v_sw", &lcd->timing.v_sw);
+    
+    polar_np = of_get_child_by_name(spec_lcd_np, "polarity");
+    memset(&lcd->polarity, 0x00, sizeof(lcd->polarity));
+    if(of_property_read_bool(polar_np, "rise_vclk"))
+        lcd->polarity.rise_vclk = 1;
+
+    if(of_property_read_bool(polar_np, "inv_hsync"))
+        lcd->polarity.inv_hsync = 1;
+
+    if(of_property_read_bool(polar_np, "inv_vsync"))
+        lcd->polarity.inv_vsync = 1;
+
+    if(of_property_read_bool(polar_np, "inv_vden"))
+        lcd->polarity.inv_vden = 1;
+    
+
+    return 0;
+
+}
+
+static void tiny4412_fb_init_pdata(const char *lcd_name, struct s3c_fb_platdata *pd) {
+    struct s3cfb_lcd *lcd = NULL;
+    struct s3c_fb_pd_win *win;
+    struct fb_videomode *mode = pd->vtiming;
+    unsigned long val = 0;
+    u64 pixclk = 1000000000000ULL;
+    u32 div;
+    int i, err;
+
+    if(NULL == lcd_name)
+        return;
+    printk(KERN_WARNING"lcd_name %s\n", lcd_name);
+
+    lcd = kzalloc(sizeof(struct s3cfb_lcd), GFP_KERNEL);
+    err = of_parse_tiny4412_lcd(lcd_name, lcd);
+    if(err < 0){
+        printk(KERN_WARNING"%s of_parse_tiny4412_lcd fail!!\n", lcd_name);
+        goto out;
+    }
+    
+    for (i = 0; i < S3C_FB_MAX_WIN; i++) {
+        if (pd->win[i] == NULL)
+            continue;
+
+        win = pd->win[i];
+        win->xres        = lcd->width;
+        win->yres        = lcd->height;
+        win->default_bpp= lcd->bpp ? : 24;
+        win->virtual_x    = win->xres;
+        win->virtual_y    = win->yres * 3;
+        win->width        = lcd->p_width;
+        win->height        = lcd->p_height;
+    }
+
+    mode->left_margin    = lcd->timing.h_bp;
+    mode->right_margin    = lcd->timing.h_fp;
+    mode->upper_margin    = lcd->timing.v_bp;
+    mode->lower_margin    = lcd->timing.v_fp;
+    mode->hsync_len        = lcd->timing.h_sw;
+    mode->vsync_len        = lcd->timing.v_sw;
+    mode->xres            = lcd->width;
+    mode->yres            = lcd->height;
+
+    /* calculates pixel clock */
+    div  = mode->left_margin + mode->hsync_len + mode->right_margin +
+        mode->xres;
+    div *= mode->upper_margin + mode->vsync_len + mode->lower_margin +
+        mode->yres;
+    div *= lcd->freq ? : 60;
+
+    do_div(pixclk, div);
+
+    mode->pixclock        = pixclk + 386;
+
+    /* initialize signal polarity of RGB interface */
+    if (lcd->polarity.rise_vclk)
+        val |= VIDCON1_INV_VCLK;
+    if (lcd->polarity.inv_hsync)
+        val |= VIDCON1_INV_HSYNC;
+    if (lcd->polarity.inv_vsync)
+        val |= VIDCON1_INV_VSYNC;
+    if (lcd->polarity.inv_vden)
+        val |= VIDCON1_INV_VDEN;
+
+    pd->vidcon1 = val;
+    
+out:
+    if(NULL != lcd){
+        kfree(lcd);
+        lcd = NULL;
+    }
+    
+}
+
static int s3c_fb_probe(struct platform_device *pdev)
{
     const struct platform_device_id *platid;
+    struct of_device_id *of_id = NULL;
+    struct device_node *fimd_root_dn = NULL;
+
     struct s3c_fb_driverdata *fbdrv;
     struct device *dev = &pdev->dev;
     struct s3c_fb_platdata *pd;
     struct s3c_fb *sfb;
+    struct s3c_fb_win *fbwin;
     struct resource *res;
+    const char *lcd_name = NULL;
     int win;
     int ret = 0;
-    u32 reg;
+    u32 reg, clk_rate = 0;
+    printk("s3c_fb_probe\n");
+
+    of_id = of_match_device(s3c_fb_of_match, &pdev->dev);
+    if(NULL != of_id){
+        printk(KERN_WARNING"s3c_fb_probe: of_match_device OK \n");
+        fbdrv = (struct s3c_fb_driverdata *)of_id->data;
+        fimd_root_dn = dev->of_node;
+    }
+    else{
+        platid = platform_get_device_id(pdev);
+        fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
+    }    
-    platid = platform_get_device_id(pdev);
-    fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
     if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) {
         dev_err(dev, "too many windows, cannot attach\n");
         return -EINVAL;
     }
-    pd = dev_get_platdata(&pdev->dev);
-    if (!pd) {
+    if(NULL != fimd_root_dn)
+    {
+        of_parse_lcd_io_reg_cfg(pdev, &lcd_io_cfg);
+        pd = of_get_s3_fb_lcd(fimd_root_dn, "lcd_default_config");
+    }
+    else
+        pd = dev_get_platdata(&pdev->dev);
+    
+    if(!pd){
+
         dev_err(dev, "no platform data specified\n");
         return -EINVAL;
     }
@@ -1388,6 +1659,8 @@ static int s3c_fb_probe(struct platform_device *pdev)
         return -ENOMEM;
     dev_dbg(dev, "allocate new framebuffer %p\n", sfb);
+    of_property_read_string(fimd_root_dn, "lcd_name", &lcd_name);
+    tiny4412_fb_init_pdata(lcd_name, pd);
     sfb->dev = dev;
     sfb->pdata = pd;
@@ -1395,7 +1668,7 @@ static int s3c_fb_probe(struct platform_device *pdev)
     spin_lock_init(&sfb->slock);
-    sfb->bus_clk = devm_clk_get(dev, "lcd");
+    sfb->bus_clk = devm_clk_get(dev, "fimd");
     if (IS_ERR(sfb->bus_clk)) {
         dev_err(dev, "failed to get bus clock\n");
         return PTR_ERR(sfb->bus_clk);
@@ -1410,6 +1683,8 @@ static int s3c_fb_probe(struct platform_device *pdev)
             ret = PTR_ERR(sfb->lcd_clk);
             goto err_bus_clk;
         }
+        of_property_read_u32(fimd_root_dn, "sclk-fimd-rate", &clk_rate);
+        clk_set_rate(sfb->lcd_clk, clk_rate);
         clk_prepare_enable(sfb->lcd_clk);
     }
@@ -1423,13 +1698,12 @@ static int s3c_fb_probe(struct platform_device *pdev)
         goto err_lcd_clk;
     }
-    res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-    if (!res) {
+    sfb->irq_no = platform_get_irq_byname(pdev, "vsync");
+    if (sfb->irq_no < 0) {
         dev_err(dev, "failed to acquire irq resource\n");
         ret = -ENOENT;
         goto err_lcd_clk;
     }
-    sfb->irq_no = res->start;
     ret = devm_request_irq(dev, sfb->irq_no, s3c_fb_irq,
               0, "s3c_fb", sfb);
     if (ret) {
@@ -1478,8 +1752,8 @@ static int s3c_fb_probe(struct platform_device *pdev)
         if (!pd->win[win])
             continue;
-        ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],
-                       &sfb->windows[win]);
+        ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],
+            &sfb->windows[win]);
         if (ret < 0) {
             dev_err(dev, "failed to create window %d\n", win);
             for (; win >= 0; win--)
@@ -1487,9 +1761,17 @@ static int s3c_fb_probe(struct platform_device *pdev)
             goto err_pm_runtime;
         }
     }
+    fbwin = sfb->windows[0];
+
+    if (fb_prepare_logo(fbwin->fbinfo, FB_ROTATE_UR)) {
+        printk("Start display and show logo\n");
+        fb_set_cmap(&fbwin->fbinfo->cmap, fbwin->fbinfo);
+        fb_show_logo(fbwin->fbinfo, FB_ROTATE_UR);
+
+    }
     platform_set_drvdata(pdev, sfb);
-    pm_runtime_put_sync(sfb->dev);
+
     return 0;
@@ -1658,6 +1940,152 @@ static int s3c_fb_runtime_resume(struct device *dev)
}
#endif
+#ifdef CONFIG_OF
+
+
+static int of_parse_lcd_io_reg_cfg(struct platform_device *pdev,
+    struct lcd_io_reg_cfg *pcfg)
+{
+    struct device *dev = NULL;
+    struct device_node *sysreg_node = NULL;
+    u32 sysreg, offset, addr_cells_nr, size_cells_nr;
+    phandle sysreg_ph;
+
+    if((NULL == pdev) || (NULL == pcfg))
+        return -EINVAL;
+    
+    dev = &pdev->dev;
+    of_property_read_u32_index(dev->of_node, "samsung,sysreg", 0, &sysreg_ph);
+    of_property_read_u32(dev->of_node, "sysreg_lcd_blk_cfg_offset", &offset);
+    sysreg_node = of_find_node_by_phandle(sysreg_ph);
+    addr_cells_nr = of_n_addr_cells(sysreg_node);
+    of_property_read_u32_index(sysreg_node, "reg", 0, &sysreg);
+    size_cells_nr = of_n_size_cells(sysreg_node);
+    pcfg->lcd_blk_cfg_reg =  ioremap(sysreg + offset, 4);
+    
+    pcfg->pctrl = devm_pinctrl_get(dev);
+    pcfg->pin_lcd_cfg = pinctrl_lookup_state(pcfg->pctrl, "lcd0_pin_cfg");
+    if((NULL != pcfg->pctrl) && (NULL != pcfg->pin_lcd_cfg))
+        printk(KERN_WARNING"of_parse_lcd_io_reg_cfg pctrl setup OK!\n");
+    
+    return 0;
+}
+static void setup_lcd_pin_cfg(void)
+{
+    u32 reg;
+
+    pinctrl_select_state(lcd_io_cfg.pctrl, lcd_io_cfg.pin_lcd_cfg);
+    /*
+     * Set DISPLAY_CONTROL register for Display path selection.
+     *
+     * DISPLAY_CONTROL[1:0]
+     * ---------------------
+     *  00 | MIE
+     *  01 | MDINE
+     *  10 | FIMD : selected
+     *  11 | FIMD
+     */
+    reg = readl(lcd_io_cfg.lcd_blk_cfg_reg);
+    reg |= (1 << 1);
+    writel(reg, lcd_io_cfg.lcd_blk_cfg_reg);
+    
+}
+
+
+static int of_parse_fimd_def_lcd(const struct device_node * np, struct s3c_fb_platdata *pdata)
+{
+    struct device_node *vt_node;
+    struct device_node *wins_arr_node;
+
+    int i ,cnt;
+    u32 val;
+    
+    if((NULL == np) || (NULL == pdata))
+        return -EINVAL;
+    
+    cnt = of_property_count_elems_of_size(np, "vidcon0", sizeof(u32));
+    for(i = 0; i < cnt; i++)
+    {
+        of_property_read_u32_index(np, "vidcon0", i, &val);
+        pdata->vidcon0 |= val;
+    }
+
+    cnt = of_property_count_elems_of_size(np, "vidcon1", sizeof(u32));
+    for(i = 0; i < cnt; i++)
+    {
+        of_property_read_u32_index(np, "vidcon1", i, &val);
+        pdata->vidcon1 |= val;
+    }
+    vt_node = of_get_child_by_name(np, "vtiming");
+    if(NULL != vt_node)
+    {
+        pdata->vtiming = kzalloc(sizeof(struct fb_videomode), GFP_KERNEL);
+        of_property_read_u32(vt_node, "left_margin", &pdata->vtiming->left_margin);
+        of_property_read_u32(vt_node, "right_margin", &pdata->vtiming->right_margin);
+        of_property_read_u32(vt_node, "upper_margin", &pdata->vtiming->upper_margin);
+        of_property_read_u32(vt_node, "lower_margin", &pdata->vtiming->lower_margin);
+        of_property_read_u32(vt_node, "hsync_len", &pdata->vtiming->hsync_len);
+        of_property_read_u32(vt_node, "vsync_len", &pdata->vtiming->vsync_len);
+        of_property_read_u32(vt_node, "xres", &pdata->vtiming->xres);
+        of_property_read_u32(vt_node, "yres", &pdata->vtiming->yres);
+    }
+    wins_arr_node = of_get_child_by_name(np, "wins_array");
+    if(NULL != wins_arr_node)
+    {
+        struct device_node *child;
+        int j = 0;
+        for_each_child_of_node(wins_arr_node, child)
+        {
+            pdata->win[j] = kzalloc(sizeof(struct s3c_fb_pd_win), GFP_KERNEL);
+            of_property_read_u16(child, "xres", &pdata->win[j]->xres);
+            of_property_read_u16(child, "yres", &pdata->win[j]->yres);
+            of_property_read_u16(child, "virtual_x", &pdata->win[j]->virtual_x);
+            of_property_read_u16(child, "virtual_y", &pdata->win[j]->virtual_y);
+            of_property_read_u16(child, "max_bpp", &pdata->win[j]->max_bpp);
+            of_property_read_u16(child, "default_bpp", &pdata->win[j]->default_bpp);
+            j++;
+        }
+    }
+    
+    pdata->setup_gpio = setup_lcd_pin_cfg;
+        
+    return 0;
+}
+
+static struct s3c_fb_platdata * of_get_s3_fb_lcd(const struct device_node *node,
+        const char *name)
+{
+    struct device_node *def_lcd_node = NULL;
+    struct s3c_fb_platdata *pdata = NULL;
+    int err = 0;
+
+    def_lcd_node = of_get_child_by_name(node, name);
+    if(NULL != def_lcd_node)
+    {
+        pdata = kzalloc(sizeof(struct s3c_fb_platdata), GFP_KERNEL);
+        if(!pdata)
+            goto err_out;
+        
+        err = of_parse_fimd_def_lcd(def_lcd_node, pdata);
+        if(err)
+        {
+            goto err_out;
+        }
+            
+        return pdata;
+    }
+    
+err_out:
+    if(pdata)
+    {
+        kfree(pdata);
+        pdata = NULL;
+    }
+    return NULL;
+}
+
+
+
#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
@@ -1714,6 +2142,64 @@ static int s3c_fb_runtime_resume(struct device *dev)
     },
};
+static struct s3c_fb_win_variant s3c_fb_data_s5p_wins[] = {
+    [0] = {
+        .has_osd_c    = 1,
+        .osd_size_off    = 0x8,
+        .palette_sz    = 256,
+        .valid_bpp    = (VALID_BPP1248 | VALID_BPP(13) |
+                   VALID_BPP(15) | VALID_BPP(16) |
+                   VALID_BPP(18) | VALID_BPP(19) |
+                   VALID_BPP(24) | VALID_BPP(25) |
+                   VALID_BPP(32)),
+    },
+    [1] = {
+        .has_osd_c    = 1,
+        .has_osd_d    = 1,
+        .osd_size_off    = 0xc,
+        .has_osd_alpha    = 1,
+        .palette_sz    = 256,
+        .valid_bpp    = (VALID_BPP1248 | VALID_BPP(13) |
+                   VALID_BPP(15) | VALID_BPP(16) |
+                   VALID_BPP(18) | VALID_BPP(19) |
+                   VALID_BPP(24) | VALID_BPP(25) |
+                   VALID_BPP(32)),
+    },
+    [2] = {
+        .has_osd_c    = 1,
+        .has_osd_d    = 1,
+        .osd_size_off    = 0xc,
+        .has_osd_alpha    = 1,
+        .palette_sz    = 256,
+        .valid_bpp    = (VALID_BPP1248 | VALID_BPP(13) |
+                   VALID_BPP(15) | VALID_BPP(16) |
+                   VALID_BPP(18) | VALID_BPP(19) |
+                   VALID_BPP(24) | VALID_BPP(25) |
+                   VALID_BPP(32)),
+    },
+    [3] = {
+        .has_osd_c    = 1,
+        .has_osd_alpha    = 1,
+        .palette_sz    = 256,
+        .valid_bpp    = (VALID_BPP1248 | VALID_BPP(13) |
+                   VALID_BPP(15) | VALID_BPP(16) |
+                   VALID_BPP(18) | VALID_BPP(19) |
+                   VALID_BPP(24) | VALID_BPP(25) |
+                   VALID_BPP(32)),
+    },
+    [4] = {
+        .has_osd_c    = 1,
+        .has_osd_alpha    = 1,
+        .palette_sz    = 256,
+        .valid_bpp    = (VALID_BPP1248 | VALID_BPP(13) |
+                   VALID_BPP(15) | VALID_BPP(16) |
+                   VALID_BPP(18) | VALID_BPP(19) |
+                   VALID_BPP(24) | VALID_BPP(25) |
+                   VALID_BPP(32)),
+    },
+};
+
+
static struct s3c_fb_driverdata s3c_fb_data_64xx = {
     .variant = {
         .nr_windows    = 5,
@@ -1781,6 +2267,46 @@ static int s3c_fb_runtime_resume(struct device *dev)
                    VALID_BPP(28)),
     },
};
+static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
+    .variant = {
+        .nr_windows = 5,
+        .vidtcon    = VIDTCON0,
+        .wincon     = WINCON(0),
+        .winmap     = WINxMAP(0),
+        .keycon     = WKEYCON,
+        .osd        = VIDOSD_BASE,
+        .osd_stride = 16,
+        .buf_start    = VIDW_BUF_START(0),
+        .buf_size    = VIDW_BUF_SIZE(0),
+        .buf_end    = VIDW_BUF_END(0),
+
+        .palette = {
+            [0] = 0x2400,
+            [1] = 0x2800,
+            [2] = 0x2c00,
+            [3] = 0x3000,
+            [4] = 0x3400,
+        },
+
+        .has_shadowcon    = 1,
+        .has_blendcon    = 1,
+        .has_fixvclk    = 1,
+    },
+    .win[0] = &s3c_fb_data_s5p_wins[0],
+    .win[1] = &s3c_fb_data_s5p_wins[1],
+    .win[2] = &s3c_fb_data_s5p_wins[2],
+    .win[3] = &s3c_fb_data_s5p_wins[3],
+    .win[4] = &s3c_fb_data_s5p_wins[4],
+};
+            
+
+static const struct of_device_id s3c_fb_of_match[] = {
+    { .compatible = "samsung,exynos4-fb",
+      .data = &s3c_fb_data_exynos4 },
+    {},
+};
+MODULE_DEVICE_TABLE(of, s3c_fb_of_match);
+#endif
static const struct platform_device_id s3c_fb_driver_ids[] = {
     {
@@ -1789,6 +2315,9 @@ static int s3c_fb_runtime_resume(struct device *dev)
     }, {
         .name        = "s3c2443-fb",
         .driver_data    = (unsigned long)&s3c_fb_data_s3c2443,
+    },{
+        .name        = "exynos4-fb",
+        .driver_data    = (unsigned long)&s3c_fb_data_exynos4,
     },
     {},
};
@@ -1807,6 +2336,7 @@ static int s3c_fb_runtime_resume(struct device *dev)
     .driver        = {
         .name    = "s3c-fb",
         .pm    = &s3cfb_pm_ops,
+        .of_match_table = s3c_fb_of_match,
     },
};
diff --git a/include/dt-bindings/video/samsung_fimd.h b/include/dt-bindings/video/samsung_fimd.h
new file mode 100644
index 0000000..d8fc96e
--- /dev/null
+++ b/include/dt-bindings/video/samsung_fimd.h
@@ -0,0 +1,477 @@
+/* include/video/samsung_fimd.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      http://armlinux.simtec.co.uk/
+ *      Ben Dooks 
+ *
+ * S3C Platform - new-style fimd and framebuffer register definitions
+ *
+ * This is the register set for the fimd and new style framebuffer interface
+ * found from the S3C2443 onwards into the S3C2416, S3C2450, the
+ * S3C64XX series such as the S3C6400 and S3C6410, and EXYNOS series.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* VIDCON0 */
+
+#define VIDCON0                    0x00
+#define VIDCON0_DSI_EN                (1 << 30)
+#define VIDCON0_INTERLACE            (1 << 29)
+#define VIDCON0_VIDOUT_MASK            (0x7 << 26)
+#define VIDCON0_VIDOUT_SHIFT            26
+#define VIDCON0_VIDOUT_RGB            (0x0 << 26)
+#define VIDCON0_VIDOUT_TV            (0x1 << 26)
+#define VIDCON0_VIDOUT_I80_LDI0            (0x2 << 26)
+#define VIDCON0_VIDOUT_I80_LDI1            (0x3 << 26)
+#define VIDCON0_VIDOUT_WB_RGB            (0x4 << 26)
+#define VIDCON0_VIDOUT_WB_I80_LDI0        (0x6 << 26)
+#define VIDCON0_VIDOUT_WB_I80_LDI1        (0x7 << 26)
+
+#define VIDCON0_L1_DATA_MASK            (0x7 << 23)
+#define VIDCON0_L1_DATA_SHIFT            23
+#define VIDCON0_L1_DATA_16BPP            (0x0 << 23)
+#define VIDCON0_L1_DATA_18BPP16            (0x1 << 23)
+#define VIDCON0_L1_DATA_18BPP9            (0x2 << 23)
+#define VIDCON0_L1_DATA_24BPP            (0x3 << 23)
+#define VIDCON0_L1_DATA_18BPP            (0x4 << 23)
+#define VIDCON0_L1_DATA_16BPP8            (0x5 << 23)
+
+#define VIDCON0_L0_DATA_MASK            (0x7 << 20)
+#define VIDCON0_L0_DATA_SHIFT            20
+#define VIDCON0_L0_DATA_16BPP            (0x0 << 20)
+#define VIDCON0_L0_DATA_18BPP16            (0x1 << 20)
+#define VIDCON0_L0_DATA_18BPP9            (0x2 << 20)
+#define VIDCON0_L0_DATA_24BPP            (0x3 << 20)
+#define VIDCON0_L0_DATA_18BPP            (0x4 << 20)
+#define VIDCON0_L0_DATA_16BPP8            (0x5 << 20)
+
+#define VIDCON0_PNRMODE_MASK            (0x3 << 17)
+#define VIDCON0_PNRMODE_SHIFT            17
+#define VIDCON0_PNRMODE_RGB            (0x0 << 17)
+#define VIDCON0_PNRMODE_BGR            (0x1 << 17)
+#define VIDCON0_PNRMODE_SERIAL_RGB        (0x2 << 17)
+#define VIDCON0_PNRMODE_SERIAL_BGR        (0x3 << 17)
+
+#define VIDCON0_CLKVALUP            (1 << 16)
+#define VIDCON0_CLKVAL_F_MASK            (0xff << 6)
+#define VIDCON0_CLKVAL_F_SHIFT            6
+#define VIDCON0_CLKVAL_F_LIMIT            0xff
+#define VIDCON0_CLKVAL_F(_x)            ((_x) << 6)
+#define VIDCON0_VLCKFREE            (1 << 5)
+#define VIDCON0_CLKDIR                (1 << 4)
+
+#define VIDCON0_CLKSEL_MASK            (0x3 << 2)
+#define VIDCON0_CLKSEL_SHIFT            2
+#define VIDCON0_CLKSEL_HCLK            (0x0 << 2)
+#define VIDCON0_CLKSEL_LCD            (0x1 << 2)
+#define VIDCON0_CLKSEL_27M            (0x3 << 2)
+
+#define VIDCON0_ENVID                (1 << 1)
+#define VIDCON0_ENVID_F                (1 << 0)
+
+#define VIDCON1                    0x04
+#define VIDCON1_LINECNT_MASK            (0x7ff << 16)
+#define VIDCON1_LINECNT_SHIFT            16
+#define VIDCON1_LINECNT_GET(_v)            (((_v) >> 16) & 0x7ff)
+#define VIDCON1_FSTATUS_EVEN            (1 << 15)
+#define VIDCON1_VSTATUS_MASK            (0x3 << 13)
+#define VIDCON1_VSTATUS_SHIFT            13
+#define VIDCON1_VSTATUS_VSYNC            (0x0 << 13)
+#define VIDCON1_VSTATUS_BACKPORCH        (0x1 << 13)
+#define VIDCON1_VSTATUS_ACTIVE            (0x2 << 13)
+#define VIDCON1_VSTATUS_FRONTPORCH        (0x3 << 13)
+#define VIDCON1_VCLK_MASK            (0x3 << 9)
+#define VIDCON1_VCLK_HOLD            (0x0 << 9)
+#define VIDCON1_VCLK_RUN            (0x1 << 9)
+
+#define VIDCON1_INV_VCLK            (1 << 7)
+#define VIDCON1_INV_HSYNC            (1 << 6)
+#define VIDCON1_INV_VSYNC            (1 << 5)
+#define VIDCON1_INV_VDEN            (1 << 4)
+
+/* VIDCON2 */
+
+#define VIDCON2                    0x08
+#define VIDCON2_EN601                (1 << 23)
+#define VIDCON2_TVFMTSEL_SW            (1 << 14)
+
+#define VIDCON2_TVFMTSEL1_MASK            (0x3 << 12)
+#define VIDCON2_TVFMTSEL1_SHIFT            12
+#define VIDCON2_TVFMTSEL1_RGB            (0x0 << 12)
+#define VIDCON2_TVFMTSEL1_YUV422        (0x1 << 12)
+#define VIDCON2_TVFMTSEL1_YUV444        (0x2 << 12)
+
+#define VIDCON2_ORGYCbCr            (1 << 8)
+#define VIDCON2_YUVORDCrCb            (1 << 7)
+
+/* PRTCON (S3C6410)
+ * Might not be present in the S3C6410 documentation,
+ * but tests prove it's there almost for sure; shouldn't hurt in any case.
+ */
+#define PRTCON                    0x0c
+#define PRTCON_PROTECT                (1 << 11)
+
+/* VIDTCON0 */
+
+#define VIDTCON0                0x10
+#define VIDTCON0_VBPDE_MASK            (0xff << 24)
+#define VIDTCON0_VBPDE_SHIFT            24
+#define VIDTCON0_VBPDE_LIMIT            0xff
+#define VIDTCON0_VBPDE(_x)            ((_x) << 24)
+
+#define VIDTCON0_VBPD_MASK            (0xff << 16)
+#define VIDTCON0_VBPD_SHIFT            16
+#define VIDTCON0_VBPD_LIMIT            0xff
+#define VIDTCON0_VBPD(_x)            ((_x) << 16)
+
+#define VIDTCON0_VFPD_MASK            (0xff << 8)
+#define VIDTCON0_VFPD_SHIFT            8
+#define VIDTCON0_VFPD_LIMIT            0xff
+#define VIDTCON0_VFPD(_x)            ((_x) << 8)
+
+#define VIDTCON0_VSPW_MASK            (0xff << 0)
+#define VIDTCON0_VSPW_SHIFT            0
+#define VIDTCON0_VSPW_LIMIT            0xff
+#define VIDTCON0_VSPW(_x)            ((_x) << 0)
+
+/* VIDTCON1 */
+
+#define VIDTCON1                0x14
+#define VIDTCON1_VFPDE_MASK            (0xff << 24)
+#define VIDTCON1_VFPDE_SHIFT            24
+#define VIDTCON1_VFPDE_LIMIT            0xff
+#define VIDTCON1_VFPDE(_x)            ((_x) << 24)
+
+#define VIDTCON1_HBPD_MASK            (0xff << 16)
+#define VIDTCON1_HBPD_SHIFT            16
+#define VIDTCON1_HBPD_LIMIT            0xff
+#define VIDTCON1_HBPD(_x)            ((_x) << 16)
+
+#define VIDTCON1_HFPD_MASK            (0xff << 8)
+#define VIDTCON1_HFPD_SHIFT            8
+#define VIDTCON1_HFPD_LIMIT            0xff
+#define VIDTCON1_HFPD(_x)            ((_x) << 8)
+
+#define VIDTCON1_HSPW_MASK            (0xff << 0)
+#define VIDTCON1_HSPW_SHIFT            0
+#define VIDTCON1_HSPW_LIMIT            0xff
+#define VIDTCON1_HSPW(_x)            ((_x) << 0)
+
+#define VIDTCON2                0x18
+#define VIDTCON2_LINEVAL_E(_x)            ((((_x) & 0x800) >> 11) << 23)
+#define VIDTCON2_LINEVAL_MASK            (0x7ff << 11)
+#define VIDTCON2_LINEVAL_SHIFT            11
+#define VIDTCON2_LINEVAL_LIMIT            0x7ff
+#define VIDTCON2_LINEVAL(_x)            (((_x) & 0x7ff) << 11)
+
+#define VIDTCON2_HOZVAL_E(_x)            ((((_x) & 0x800) >> 11) << 22)
+#define VIDTCON2_HOZVAL_MASK            (0x7ff << 0)
+#define VIDTCON2_HOZVAL_SHIFT            0
+#define VIDTCON2_HOZVAL_LIMIT            0x7ff
+#define VIDTCON2_HOZVAL(_x)            (((_x) & 0x7ff) << 0)
+
+/* WINCONx */
+
+#define WINCON(_win)                (0x20 + ((_win) * 4))
+#define WINCONx_CSCCON_EQ601            (0x0 << 28)
+#define WINCONx_CSCCON_EQ709            (0x1 << 28)
+#define WINCONx_CSCWIDTH_MASK            (0x3 << 26)
+#define WINCONx_CSCWIDTH_SHIFT            26
+#define WINCONx_CSCWIDTH_WIDE            (0x0 << 26)
+#define WINCONx_CSCWIDTH_NARROW            (0x3 << 26)
+#define WINCONx_ENLOCAL                (1 << 22)
+#define WINCONx_BUFSTATUS            (1 << 21)
+#define WINCONx_BUFSEL                (1 << 20)
+#define WINCONx_BUFAUTOEN            (1 << 19)
+#define WINCONx_BITSWP                (1 << 18)
+#define WINCONx_BYTSWP                (1 << 17)
+#define WINCONx_HAWSWP                (1 << 16)
+#define WINCONx_WSWP                (1 << 15)
+#define WINCONx_YCbCr                (1 << 13)
+#define WINCONx_BURSTLEN_MASK            (0x3 << 9)
+#define WINCONx_BURSTLEN_SHIFT            9
+#define WINCONx_BURSTLEN_16WORD            (0x0 << 9)
+#define WINCONx_BURSTLEN_8WORD            (0x1 << 9)
+#define WINCONx_BURSTLEN_4WORD            (0x2 << 9)
+#define WINCONx_ENWIN                (1 << 0)
+
+#define WINCON0_BPPMODE_MASK            (0xf << 2)
+#define WINCON0_BPPMODE_SHIFT            2
+#define WINCON0_BPPMODE_1BPP            (0x0 << 2)
+#define WINCON0_BPPMODE_2BPP            (0x1 << 2)
+#define WINCON0_BPPMODE_4BPP            (0x2 << 2)
+#define WINCON0_BPPMODE_8BPP_PALETTE        (0x3 << 2)
+#define WINCON0_BPPMODE_16BPP_565        (0x5 << 2)
+#define WINCON0_BPPMODE_16BPP_1555        (0x7 << 2)
+#define WINCON0_BPPMODE_18BPP_666        (0x8 << 2)
+#define WINCON0_BPPMODE_24BPP_888        (0xb << 2)
+
+#define WINCON1_LOCALSEL_CAMIF            (1 << 23)
+#define WINCON1_BLD_PIX                (1 << 6)
+#define WINCON1_BPPMODE_MASK            (0xf << 2)
+#define WINCON1_BPPMODE_SHIFT            2
+#define WINCON1_BPPMODE_1BPP            (0x0 << 2)
+#define WINCON1_BPPMODE_2BPP            (0x1 << 2)
+#define WINCON1_BPPMODE_4BPP            (0x2 << 2)
+#define WINCON1_BPPMODE_8BPP_PALETTE        (0x3 << 2)
+#define WINCON1_BPPMODE_8BPP_1232        (0x4 << 2)
+#define WINCON1_BPPMODE_16BPP_565        (0x5 << 2)
+#define WINCON1_BPPMODE_16BPP_A1555        (0x6 << 2)
+#define WINCON1_BPPMODE_16BPP_I1555        (0x7 << 2)
+#define WINCON1_BPPMODE_18BPP_666        (0x8 << 2)
+#define WINCON1_BPPMODE_18BPP_A1665        (0x9 << 2)
+#define WINCON1_BPPMODE_19BPP_A1666        (0xa << 2)
+#define WINCON1_BPPMODE_24BPP_888        (0xb << 2)
+#define WINCON1_BPPMODE_24BPP_A1887        (0xc << 2)
+#define WINCON1_BPPMODE_25BPP_A1888        (0xd << 2)
+#define WINCON1_BPPMODE_28BPP_A4888        (0xd << 2)
+#define WINCON1_ALPHA_SEL            (1 << 1)
+
+/* S5PV210 */
+#define SHADOWCON                0x34
+#define SHADOWCON_WINx_PROTECT(_win)        (1 << (10 + (_win)))
+/* DMA channels (all windows) */
+#define SHADOWCON_CHx_ENABLE(_win)        (1 << (_win))
+/* Local input channels (windows 0-2) */
+#define SHADOWCON_CHx_LOCAL_ENABLE(_win)    (1 << (5 + (_win)))
+
+/* VIDOSDx */
+
+#define VIDOSD_BASE                0x40
+#define VIDOSDxA_TOPLEFT_X_E(_x)        ((((_x) & 0x800) >> 11) << 23)
+#define VIDOSDxA_TOPLEFT_X_MASK            (0x7ff << 11)
+#define VIDOSDxA_TOPLEFT_X_SHIFT        11
+#define VIDOSDxA_TOPLEFT_X_LIMIT        0x7ff
+#define VIDOSDxA_TOPLEFT_X(_x)            (((_x) & 0x7ff) << 11)
+
+#define VIDOSDxA_TOPLEFT_Y_E(_x)        ((((_x) & 0x800) >> 11) << 22)
+#define VIDOSDxA_TOPLEFT_Y_MASK            (0x7ff << 0)
+#define VIDOSDxA_TOPLEFT_Y_SHIFT        0
+#define VIDOSDxA_TOPLEFT_Y_LIMIT        0x7ff
+#define VIDOSDxA_TOPLEFT_Y(_x)            (((_x) & 0x7ff) << 0)
+
+#define VIDOSDxB_BOTRIGHT_X_E(_x)        ((((_x) & 0x800) >> 11) << 23)
+#define VIDOSDxB_BOTRIGHT_X_MASK        (0x7ff << 11)
+#define VIDOSDxB_BOTRIGHT_X_SHIFT        11
+#define VIDOSDxB_BOTRIGHT_X_LIMIT        0x7ff
+#define VIDOSDxB_BOTRIGHT_X(_x)            (((_x) & 0x7ff) << 11)
+
+#define VIDOSDxB_BOTRIGHT_Y_E(_x)        ((((_x) & 0x800) >> 11) << 22)
+#define VIDOSDxB_BOTRIGHT_Y_MASK        (0x7ff << 0)
+#define VIDOSDxB_BOTRIGHT_Y_SHIFT        0
+#define VIDOSDxB_BOTRIGHT_Y_LIMIT        0x7ff
+#define VIDOSDxB_BOTRIGHT_Y(_x)            (((_x) & 0x7ff) << 0)
+
+/* For VIDOSD[1..4]C */
+#define VIDISD14C_ALPHA0_R(_x)            ((_x) << 20)
+#define VIDISD14C_ALPHA0_G_MASK            (0xf << 16)
+#define VIDISD14C_ALPHA0_G_SHIFT        16
+#define VIDISD14C_ALPHA0_G_LIMIT        0xf
+#define VIDISD14C_ALPHA0_G(_x)            ((_x) << 16)
+#define VIDISD14C_ALPHA0_B_MASK            (0xf << 12)
+#define VIDISD14C_ALPHA0_B_SHIFT        12
+#define VIDISD14C_ALPHA0_B_LIMIT        0xf
+#define VIDISD14C_ALPHA0_B(_x)            ((_x) << 12)
+#define VIDISD14C_ALPHA1_R_MASK            (0xf << 8)
+#define VIDISD14C_ALPHA1_R_SHIFT        8
+#define VIDISD14C_ALPHA1_R_LIMIT        0xf
+#define VIDISD14C_ALPHA1_R(_x)            ((_x) << 8)
+#define VIDISD14C_ALPHA1_G_MASK            (0xf << 4)
+#define VIDISD14C_ALPHA1_G_SHIFT        4
+#define VIDISD14C_ALPHA1_G_LIMIT        0xf
+#define VIDISD14C_ALPHA1_G(_x)            ((_x) << 4)
+#define VIDISD14C_ALPHA1_B_MASK            (0xf << 0)
+#define VIDISD14C_ALPHA1_B_SHIFT        0
+#define VIDISD14C_ALPHA1_B_LIMIT        0xf
+#define VIDISD14C_ALPHA1_B(_x)            ((_x) << 0)
+
+#define VIDW_ALPHA                0x021c
+#define VIDW_ALPHA_R(_x)            ((_x) << 16)
+#define VIDW_ALPHA_G(_x)            ((_x) << 8)
+#define VIDW_ALPHA_B(_x)            ((_x) << 0)
+
+/* Video buffer addresses */
+#define VIDW_BUF_START(_buff)            (0xA0 + ((_buff) * 8))
+#define VIDW_BUF_START_S(_buff)            (0x40A0 + ((_buff) * 8))
+#define VIDW_BUF_START1(_buff)            (0xA4 + ((_buff) * 8))
+#define VIDW_BUF_END(_buff)            (0xD0 + ((_buff) * 8))
+#define VIDW_BUF_END1(_buff)            (0xD4 + ((_buff) * 8))
+#define VIDW_BUF_SIZE(_buff)            (0x100 + ((_buff) * 4))
+
+#define VIDW_BUF_SIZE_OFFSET_E(_x)        ((((_x) & 0x2000) >> 13) << 27)
+#define VIDW_BUF_SIZE_OFFSET_MASK        (0x1fff << 13)
+#define VIDW_BUF_SIZE_OFFSET_SHIFT        13
+#define VIDW_BUF_SIZE_OFFSET_LIMIT        0x1fff
+#define VIDW_BUF_SIZE_OFFSET(_x)        (((_x) & 0x1fff) << 13)
+
+#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x)        ((((_x) & 0x2000) >> 13) << 26)
+#define VIDW_BUF_SIZE_PAGEWIDTH_MASK        (0x1fff << 0)
+#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT        0
+#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT        0x1fff
+#define VIDW_BUF_SIZE_PAGEWIDTH(_x)        (((_x) & 0x1fff) << 0)
+
+/* Interrupt controls and status */
+
+#define VIDINTCON0                0x130
+#define VIDINTCON0_FIFOINTERVAL_MASK        (0x3f << 20)
+#define VIDINTCON0_FIFOINTERVAL_SHIFT        20
+#define VIDINTCON0_FIFOINTERVAL_LIMIT        0x3f
+#define VIDINTCON0_FIFOINTERVAL(_x)        ((_x) << 20)
+
+#define VIDINTCON0_INT_SYSMAINCON        (1 << 19)
+#define VIDINTCON0_INT_SYSSUBCON        (1 << 18)
+#define VIDINTCON0_INT_I80IFDONE        (1 << 17)
+
+#define VIDINTCON0_FRAMESEL0_MASK        (0x3 << 15)
+#define VIDINTCON0_FRAMESEL0_SHIFT        15
+#define VIDINTCON0_FRAMESEL0_BACKPORCH        (0x0 << 15)
+#define VIDINTCON0_FRAMESEL0_VSYNC        (0x1 << 15)
+#define VIDINTCON0_FRAMESEL0_ACTIVE        (0x2 << 15)
+#define VIDINTCON0_FRAMESEL0_FRONTPORCH        (0x3 << 15)
+
+#define VIDINTCON0_FRAMESEL1            (1 << 13)
+#define VIDINTCON0_FRAMESEL1_MASK        (0x3 << 13)
+#define VIDINTCON0_FRAMESEL1_NONE        (0x0 << 13)
+#define VIDINTCON0_FRAMESEL1_BACKPORCH        (0x1 << 13)
+#define VIDINTCON0_FRAMESEL1_VSYNC        (0x2 << 13)
+#define VIDINTCON0_FRAMESEL1_FRONTPORCH        (0x3 << 13)
+
+#define VIDINTCON0_INT_FRAME            (1 << 12)
+#define VIDINTCON0_FIFIOSEL_MASK        (0x7f << 5)
+#define VIDINTCON0_FIFIOSEL_SHIFT        5
+#define VIDINTCON0_FIFIOSEL_WINDOW0        (0x1 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW1        (0x2 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW2        (0x10 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW3        (0x20 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW4        (0x40 << 5)
+
+#define VIDINTCON0_FIFOLEVEL_MASK        (0x7 << 2)
+#define VIDINTCON0_FIFOLEVEL_SHIFT        2
+#define VIDINTCON0_FIFOLEVEL_TO25PC        (0x0 << 2)
+#define VIDINTCON0_FIFOLEVEL_TO50PC        (0x1 << 2)
+#define VIDINTCON0_FIFOLEVEL_TO75PC        (0x2 << 2)
+#define VIDINTCON0_FIFOLEVEL_EMPTY        (0x3 << 2)
+#define VIDINTCON0_FIFOLEVEL_FULL        (0x4 << 2)
+
+#define VIDINTCON0_INT_FIFO_MASK        (0x3 << 0)
+#define VIDINTCON0_INT_FIFO_SHIFT        0
+#define VIDINTCON0_INT_ENABLE            (1 << 0)
+
+#define VIDINTCON1                0x134
+#define VIDINTCON1_INT_I80            (1 << 2)
+#define VIDINTCON1_INT_FRAME            (1 << 1)
+#define VIDINTCON1_INT_FIFO            (1 << 0)
+
+/* Window colour-key control registers */
+#define WKEYCON                    0x140
+
+#define WKEYCON0                0x00
+#define WKEYCON1                0x04
+
+#define WxKEYCON0_KEYBL_EN            (1 << 26)
+#define WxKEYCON0_KEYEN_F            (1 << 25)
+#define WxKEYCON0_DIRCON            (1 << 24)
+#define WxKEYCON0_COMPKEY_MASK            (0xffffff << 0)
+#define WxKEYCON0_COMPKEY_SHIFT            0
+#define WxKEYCON0_COMPKEY_LIMIT            0xffffff
+#define WxKEYCON0_COMPKEY(_x)            ((_x) << 0)
+#define WxKEYCON1_COLVAL_MASK            (0xffffff << 0)
+#define WxKEYCON1_COLVAL_SHIFT            0
+#define WxKEYCON1_COLVAL_LIMIT            0xffffff
+#define WxKEYCON1_COLVAL(_x)            ((_x) << 0)
+
+/* Dithering control */
+#define DITHMODE                0x170
+#define DITHMODE_R_POS_MASK            (0x3 << 5)
+#define DITHMODE_R_POS_SHIFT            5
+#define DITHMODE_R_POS_8BIT            (0x0 << 5)
+#define DITHMODE_R_POS_6BIT            (0x1 << 5)
+#define DITHMODE_R_POS_5BIT            (0x2 << 5)
+#define DITHMODE_G_POS_MASK            (0x3 << 3)
+#define DITHMODE_G_POS_SHIFT            3
+#define DITHMODE_G_POS_8BIT            (0x0 << 3)
+#define DITHMODE_G_POS_6BIT            (0x1 << 3)
+#define DITHMODE_G_POS_5BIT            (0x2 << 3)
+#define DITHMODE_B_POS_MASK            (0x3 << 1)
+#define DITHMODE_B_POS_SHIFT            1
+#define DITHMODE_B_POS_8BIT            (0x0 << 1)
+#define DITHMODE_B_POS_6BIT            (0x1 << 1)
+#define DITHMODE_B_POS_5BIT            (0x2 << 1)
+#define DITHMODE_DITH_EN            (1 << 0)
+
+/* Window blanking (MAP) */
+#define WINxMAP(_win)                (0x180 + ((_win) * 4))
+#define WINxMAP_MAP                (1 << 24)
+#define WINxMAP_MAP_COLOUR_MASK            (0xffffff << 0)
+#define WINxMAP_MAP_COLOUR_SHIFT        0
+#define WINxMAP_MAP_COLOUR_LIMIT        0xffffff
+#define WINxMAP_MAP_COLOUR(_x)            ((_x) << 0)
+
+/* Winodw palette control */
+#define WPALCON                    0x1A0
+#define WPALCON_PAL_UPDATE            (1 << 9)
+#define WPALCON_W4PAL_16BPP_A555        (1 << 8)
+#define WPALCON_W3PAL_16BPP_A555        (1 << 7)
+#define WPALCON_W2PAL_16BPP_A555        (1 << 6)
+#define WPALCON_W1PAL_MASK            (0x7 << 3)
+#define WPALCON_W1PAL_SHIFT            3
+#define WPALCON_W1PAL_25BPP_A888        (0x0 << 3)
+#define WPALCON_W1PAL_24BPP            (0x1 << 3)
+#define WPALCON_W1PAL_19BPP_A666        (0x2 << 3)
+#define WPALCON_W1PAL_18BPP_A665        (0x3 << 3)
+#define WPALCON_W1PAL_18BPP            (0x4 << 3)
+#define WPALCON_W1PAL_16BPP_A555        (0x5 << 3)
+#define WPALCON_W1PAL_16BPP_565            (0x6 << 3)
+#define WPALCON_W0PAL_MASK            (0x7 << 0)
+#define WPALCON_W0PAL_SHIFT            0
+#define WPALCON_W0PAL_25BPP_A888        (0x0 << 0)
+#define WPALCON_W0PAL_24BPP            (0x1 << 0)
+#define WPALCON_W0PAL_19BPP_A666        (0x2 << 0)
+#define WPALCON_W0PAL_18BPP_A665        (0x3 << 0)
+#define WPALCON_W0PAL_18BPP            (0x4 << 0)
+#define WPALCON_W0PAL_16BPP_A555        (0x5 << 0)
+#define WPALCON_W0PAL_16BPP_565            (0x6 << 0)
+
+/* Blending equation control */
+#define BLENDCON                0x260
+#define BLENDCON_NEW_MASK            (1 << 0)
+#define BLENDCON_NEW_8BIT_ALPHA_VALUE        (1 << 0)
+#define BLENDCON_NEW_4BIT_ALPHA_VALUE        (0 << 0)
+
+/* Display port clock control */
+#define DP_MIE_CLKCON                0x27c
+#define DP_MIE_CLK_DISABLE            0x0
+#define DP_MIE_CLK_DP_ENABLE            0x2
+#define DP_MIE_CLK_MIE_ENABLE            0x3
+
+/* Notes on per-window bpp settings
+ *
+ * Value    Win0     Win1      Win2       Win3        Win 4
+ * 0000        1(P)     1(P)      1(P)       1(P)        1(P)
+ * 0001        2(P)     2(P)     2(P)       2(P)        2(P)
+ * 0010        4(P)     4(P)     4(P)       4(P)     -none-
+ * 0011        8(P)     8(P)     -none-   -none-   -none-
+ * 0100        -none-     8(A232)  8(A232)  -none-   -none-
+ * 0101        16(565)     16(565)  16(565)  16(565)   16(565)
+ * 0110        -none-     16(A555) 16(A555) 16(A555)  16(A555)
+ * 0111        16(I555) 16(I565) 16(I555) 16(I555)  16(I555)
+ * 1000        18(666)     18(666)  18(666)  18(666)   18(666)
+ * 1001        -none-     18(A665) 18(A665) 18(A665)  16(A665)
+ * 1010        -none-     19(A666) 19(A666) 19(A666)  19(A666)
+ * 1011        24(888)     24(888)  24(888)  24(888)   24(888)
+ * 1100        -none-     24(A887) 24(A887) 24(A887)  24(A887)
+ * 1101        -none-     25(A888) 25(A888) 25(A888)  25(A888)
+ * 1110        -none-     -none-      -none-   -none-    -none-
+ * 1111        -none-     -none-   -none-   -none-    -none-
+*/
+
+/* FIMD Version 8 register offset definitions */
+#define FIMD_V8_VIDTCON0    0x20010
+#define FIMD_V8_VIDTCON1    0x20014
+#define FIMD_V8_VIDTCON2    0x20018
+#define FIMD_V8_VIDTCON3    0x2001C
+#define FIMD_V8_VIDCON1        0x20004
diff --git a/include/linux/platform_data/video_s3c.h b/include/linux/platform_data/video_s3c.h
old mode 100644
new mode 100755
index dd7747b..48f8687
--- a/include/linux/platform_data/video_s3c.h
+++ b/include/linux/platform_data/video_s3c.h
@@ -23,6 +23,9 @@ struct s3c_fb_pd_win {
     unsigned short        yres;
     unsigned short        virtual_x;
     unsigned short        virtual_y;
+    unsigned short        width;
+    unsigned short        height;
+
};

你可能感兴趣的:(Tiny4412,Linux_4.2移植)