rk30 fb:base version ,can show linux boot logo
authoryxj <yxj@I7-CH.(none)>
Wed, 22 Feb 2012 06:37:53 +0000 (14:37 +0800)
committeryxj <yxj@I7-CH.(none)>
Wed, 22 Feb 2012 06:37:53 +0000 (14:37 +0800)
14 files changed:
arch/arm/mach-rk29/include/mach/board.h
arch/arm/mach-rk30/board-rk30-sdk.c
arch/arm/mach-rk30/devices.c
arch/arm/plat-rk/include/plat/board.h
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/display/Kconfig
drivers/video/display/screen/screen.h
drivers/video/rockchip/Kconfig [new file with mode: 0644]
drivers/video/rockchip/Makefile [new file with mode: 0644]
drivers/video/rockchip/chips/rk30_lcdc.c [new file with mode: 0644]
drivers/video/rockchip/chips/rk30_lcdc.h [new file with mode: 0644]
drivers/video/rockchip/rk_fb.c [new file with mode: 0644]
drivers/video/rockchip/rk_fb.h [new file with mode: 0644]

index 0773e2806b255ce08977828a20281b56ecca7e8f..c63f3f6dfe1b6a293f23d3b21ada8e3e77d5b58e 100755 (executable)
@@ -86,33 +86,6 @@ struct rk29_vmac_platform_data {
 
 #define INVALID_GPIO        -1
 
-struct rk29lcd_info{
-    u32 lcd_id;
-    u32 txd_pin;
-    u32 clk_pin;
-    u32 cs_pin;
-    int (*io_init)(void);
-    int (*io_deinit)(void);
-};
-
-struct rk29_fb_setting_info{
-    u8 data_num;
-    u8 vsync_en;
-    u8 den_en;
-    u8 mcu_fmk_en;
-    u8 disp_on_en;
-    u8 standby_en;
-};
-
-struct rk29fb_info{
-    u32 fb_id;
-    u32 mcu_fmk_pin;
-    struct rk29lcd_info *lcd_info;
-    int (*io_init)(struct rk29_fb_setting_info *fb_setting);
-    int (*io_deinit)(void);
-    int (*io_enable)(void);
-    int (*io_disable)(void);
-};
 
 #ifndef _LINUX_WLAN_PLAT_H_
 struct wifi_platform_data {
index 98066f618d4392678c281bacadd6f03091b77bb3..7e7307175e7e6f34b02b6df310b72fd864ceedf2 100755 (executable)
@@ -49,6 +49,8 @@
 #include "../../../drivers/spi/rk29_spim.h"
 #endif
 
+#define RK30_FB0_MEM_SIZE 8*SZ_1M
+
 
 /*****************************************************************************************
  * xpt2046 touch panel
@@ -290,11 +292,37 @@ static struct mma8452_platform_data mma8452_info = {
 };
 #endif
 
+#ifdef CONFIG_FB_ROCKCHIP
+/* rk30 fb resource */
+ static struct resource resource_fb[] = {
+       [0] = {
+               .name  = "fb0 buf",
+               .start = 0,
+               .end   = 0,//RK30_FB0_MEM_SIZE - 1,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+/*platform_device*/
+struct platform_device device_fb = {
+       .name             = "rk-fb",
+       .id               = -1,
+       .num_resources    = ARRAY_SIZE(resource_fb),
+       .resource         = resource_fb,
+};
+#endif
 
+extern struct platform_device rk30_device_lcdc;
 static struct platform_device *devices[] __initdata = {
 #ifdef CONFIG_BACKLIGHT_RK29_BL
        &rk29_device_backlight,
 #endif 
+#ifdef CONFIG_FB_ROCKCHIP
+       &device_fb,
+#endif
+#ifdef CONFIG_LCDC_RK30
+       &rk30_device_lcdc,
+#endif
 
 };
 
@@ -363,6 +391,8 @@ static void __init machine_rk30_board_init(void)
 
 static void __init rk30_reserve(void)
 {
+       resource_fb[0].start = board_mem_reserve_add("fb0",RK30_FB0_MEM_SIZE);
+       resource_fb[0].end      = resource_fb[0].start + RK30_FB0_MEM_SIZE - 1;
        board_mem_reserved();
 }
 
index 00ba803c04e04e917aaf4240b4af52c3d3c279cd..538020fda41a93576cd25b12a1e287dd344bd28c 100755 (executable)
@@ -687,6 +687,42 @@ static struct platform_device device_nand = {
 };
 #endif
 
+static struct resource resource_lcdc[] = {
+       [0] = {
+               .name  = "lcdc0 reg",
+               .start = RK30_LCDC0_PHYS,
+               .end   = RK30_LCDC0_PHYS + RK30_LCDC0_SIZE - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .name  = "lcdc1 reg",
+               .start = RK30_LCDC1_PHYS,
+               .end   = RK30_LCDC1_PHYS + RK30_LCDC1_SIZE - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       [2] = {
+               .name  = "lcdc0 irq",
+               .start = IRQ_LCDC0,
+               .end   = IRQ_LCDC0,
+               .flags = IORESOURCE_IRQ,
+       },
+       [3] = {
+               .name  = "lcdc1 irq",
+               .start = IRQ_LCDC1,
+               .end   = IRQ_LCDC1,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+/*platform_device*/
+struct platform_device rk30_device_lcdc = {
+       .name             = "rk30-lcdc",
+       .id               = 4,
+       .num_resources    = ARRAY_SIZE(resource_lcdc),
+       .resource         = resource_lcdc,
+};
+
+
 #ifdef CONFIG_KEYS_RK29
 extern struct rk29_keys_platform_data rk29_keys_pdata;
 static struct platform_device device_keys = {
index c445738ea8cf889173a60696f0b49eb4daa9005e..7a3b62e8cc169932d1c07f14a4b279813d579855 100644 (file)
@@ -40,6 +40,34 @@ struct rk29_bl_info {
 #define BOOT_MODE_REBOOT               6
 #define BOOT_MODE_PANIC                        7
 
+struct rk29lcd_info {
+       u32 lcd_id;
+       u32 txd_pin;
+       u32 clk_pin;
+       u32 cs_pin;
+       int (*io_init)(void);
+       int (*io_deinit)(void);
+};
+
+struct rk29_fb_setting_info {
+       u8 data_num;
+       u8 vsync_en;
+       u8 den_en;
+       u8 mcu_fmk_en;
+       u8 disp_on_en;
+       u8 standby_en;
+};
+
+struct rk29_fb_info {
+       u32 fb_id;
+       u32 mcu_fmk_pin;
+       struct rk29lcd_info *lcd_info;
+       int (*io_init)(struct rk_fb_setting_info *fb_setting);
+       int (*io_deinit)(void);
+       int (*io_enable)(void);
+       int (*io_disable)(void);
+};
+
 int board_boot_mode(void);
 
 /* for USB detection */
index ce7ba837987f7b9cf435de5356445aa7158396a3..b4117f636264afd75ab26e5d77a0da99db5c9201 100755 (executable)
@@ -2439,6 +2439,7 @@ source "drivers/video/omap2/Kconfig"
 source "drivers/video/backlight/Kconfig"
 source "drivers/video/display/Kconfig"
 source "drivers/video/hdmi/Kconfig"
+source "drivers/video/rockchip/Kconfig"
 
 if VT
        source "drivers/video/console/Kconfig"
index 2ad17115b39952090ac2d9cf084172668d06e52e..016839ca0b38e52402d9a529373ce624a4ea85e4 100755 (executable)
@@ -126,6 +126,7 @@ obj-$(CONFIG_FB_PNX4008_DUM_RGB)  += pnx4008/
 obj-$(CONFIG_FB_IBM_GXT4500)     += gxt4500.o
 obj-$(CONFIG_FB_PS3)             += ps3fb.o
 obj-$(CONFIG_FB_RK29)             += rk29_fb.o
+obj-$(CONFIG_FB_ROCKCHIP)             += rockchip/
 obj-$(CONFIG_FB_SM501)            += sm501fb.o
 obj-$(CONFIG_FB_UDL)             += udlfb.o
 obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
index 7faf10e5a2c61527cd5cf0a819c92b5aaf82a764..1b497d4c64fb0a75d55165e7e9a4b203cf9007c1 100644 (file)
@@ -6,7 +6,7 @@ menu "Display device support"
 
 config DISPLAY_SUPPORT
        tristate "Display panel/monitor support"
-       depends on FB_RK29
+       depends on FB_RK29 || FB_ROCKCHIP
        ---help---
          This framework adds support for low-level control of a display.
          This includes support for power.
index 761992aa0769b6f4d9527381705e7386f7fdb09d..d07ad0692e7c9fec6243de74b4bc8359957a49ba 100755 (executable)
@@ -34,8 +34,9 @@ typedef enum _MCU_STATUS {
 } MCU_STATUS;
 
 
+
 /* Screen description */
-struct rk29fb_screen {
+typedef struct rk29fb_screen {
     /* screen type & out face */
     u16 type;
     u16 face;
@@ -82,8 +83,7 @@ struct rk29fb_screen {
     int (*scandir)(u16 dir);
     int (*disparea)(u8 area);
 
-};
-
+} rk_screen;
 extern void set_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info);
 extern void set_tv_info(struct rk29fb_screen *screen);
 extern void set_hdmi_info(struct rk29fb_screen *screen);
diff --git a/drivers/video/rockchip/Kconfig b/drivers/video/rockchip/Kconfig
new file mode 100644 (file)
index 0000000..9198783
--- /dev/null
@@ -0,0 +1,13 @@
+config FB_ROCKCHIP
+        tristate "Frame buffer support for Rockchip lcd controller"
+        depends on FB
+        select FB_CFB_FILLRECT
+        select FB_CFB_COPYAREA
+        select FB_CFB_IMAGEBLIT
+        ---help---
+          Framebuffer driver for rochip based  Platform
+config LCDC_RK30
+        tristate "Frame buffer driver support for rk30 lcdc "
+        depends on FB_ROCKCHIP
+        help
+          Frame buffer driver for rk30 lcdc based boards.
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
new file mode 100644 (file)
index 0000000..184952b
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_FB_ROCKCHIP) += rk_fb.o
+obj-$(CONFIG_LCDC_RK30) += chips/rk30_lcdc.o  
diff --git a/drivers/video/rockchip/chips/rk30_lcdc.c b/drivers/video/rockchip/chips/rk30_lcdc.c
new file mode 100644 (file)
index 0000000..a340759
--- /dev/null
@@ -0,0 +1,644 @@
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/backlight.h>
+#include <linux/timer.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/earlysuspend.h>
+#include <linux/cpufreq.h>
+#include <linux/wakelock.h>
+#include <linux/fb.h>
+
+#include <mach/board.h>
+#include <mach/pmu.h>
+#include <mach/iomux.h>
+#include <mach/gpio.h>
+#include <asm/cacheflush.h>
+#include "../../display/screen/screen.h"
+#include "../rk_fb.h"
+#include "rk30_lcdc.h"
+
+
+
+
+static int dbg_thresd = 0;
+#define DBG(x...) do { if(unlikely(dbg_thresd)) printk(KERN_INFO x); } while (0)
+
+
+static struct platform_device * g_lcdc_pdev;
+static  rk_screen * to_screen(struct rk30_lcdc_device *lcdc_dev)
+{
+       return &(lcdc_dev->driver->screen);
+}
+
+
+static int init_rk30_lcdc(struct lcdc_info *info)
+{
+       struct rk30_lcdc_device * lcdc_dev = &info->lcdc0;
+       struct rk30_lcdc_device * lcdc_dev1 = &info->lcdc1;
+       info->lcdc0.hclk = clk_get(NULL,"hclk_lcdc0"); 
+       info->lcdc0.aclk = clk_get(NULL,"aclk_lcdc0");
+       info->lcdc0.dclk = clk_get(NULL,"dclk_lcdc0");
+       
+       info->lcdc1.hclk = clk_get(NULL,"hclk_lcdc1"); 
+       info->lcdc1.aclk = clk_get(NULL,"aclk_lcdc1");
+       info->lcdc1.dclk = clk_get(NULL,"dclk_lcdc1");
+       if ((IS_ERR(info->lcdc0.aclk)) ||(IS_ERR(info->lcdc0.dclk)) || (IS_ERR(info->lcdc0.hclk))||
+               (IS_ERR(info->lcdc1.aclk)) ||(IS_ERR(info->lcdc1.dclk)) || (IS_ERR(info->lcdc1.hclk)))
+    {
+        printk(KERN_ERR "failed to get lcdc_hclk source\n");
+        return PTR_ERR(info->lcdc0.aclk);
+    }
+       clk_enable(info->lcdc0.hclk);  //enable aclk for register config
+       clk_enable(info->lcdc1.hclk);
+       
+       LcdSetBit(lcdc_dev,DSP_CTRL0, m_LCDC_AXICLK_AUTO_ENABLE);//eanble axi-clk auto gating for low power
+       LcdSetBit(lcdc_dev1,DSP_CTRL0, m_LCDC_AXICLK_AUTO_ENABLE);
+       return 0;
+}
+
+int rk30_lcdc_deinit(void)
+{
+    return 0;
+}
+
+void rk30_load_screen(struct rk30_lcdc_device*lcdc_dev, bool initscreen)
+{
+    int ret = -EINVAL;
+    rk_screen *screen = to_screen(lcdc_dev);
+    u16 face;
+    u16 mcu_total, mcu_rwstart, mcu_csstart, mcu_rwend, mcu_csend;
+    u16 right_margin = screen->right_margin;
+       u16 lower_margin = screen->lower_margin;
+    u16 x_res = screen->x_res, y_res = screen->y_res;
+    u32 aclk_rate = 150000000;
+
+    // set the rgb or mcu
+
+       if(screen->type==SCREEN_MCU)
+       {
+       LcdMskReg(lcdc_dev, MCU_CTRL, m_MCU_OUTPUT_SELECT,v_MCU_OUTPUT_SELECT(1));
+               // set out format and mcu timing
+                mcu_total  = (screen->mcu_wrperiod*150*1000)/1000000;
+       if(mcu_total>31)    mcu_total = 31;
+               if(mcu_total<3)     mcu_total = 3;
+       mcu_rwstart = (mcu_total+1)/4 - 1;
+       mcu_rwend = ((mcu_total+1)*3)/4 - 1;
+       mcu_csstart = (mcu_rwstart>2) ? (mcu_rwstart-3) : (0);
+       mcu_csend = (mcu_rwend>15) ? (mcu_rwend-1) : (mcu_rwend);
+
+       DBG(">> mcu_total=%d, mcu_rwstart=%d, mcu_csstart=%d, mcu_rwend=%d, mcu_csend=%d \n",
+        mcu_total, mcu_rwstart, mcu_csstart, mcu_rwend, mcu_csend);
+
+               // set horizontal & vertical out timing
+       
+           right_margin = x_res/6; 
+               screen->pixclock = 150000000; //mcu fix to 150 MHz
+       
+       }
+
+       
+
+       // set synchronous pin polarity and data pin swap rule
+       switch (screen->face)
+       {
+        case OUT_P565:
+            face = OUT_P565;
+            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0));
+            break;
+        case OUT_P666:
+            face = OUT_P666;
+            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1));
+            break;
+        case OUT_D888_P565:
+            face = OUT_P888;
+            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0));
+            break;
+        case OUT_D888_P666:
+            face = OUT_P888;
+            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1));
+            break;
+        case OUT_P888:
+            face = OUT_P888;
+            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_UP_EN, v_DITHER_UP_EN(1));
+            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(0) | v_DITHER_DOWN_MODE(0));
+            break;
+        default:
+            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_UP_EN, v_DITHER_UP_EN(0));
+            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(0) | v_DITHER_DOWN_MODE(0));
+            face = screen->face;
+            break;
+    }
+
+       //use default overlay,set vsyn hsync den dclk polarity
+     LcdMskReg(lcdc_dev, DSP_CTRL0,m_DISPLAY_FORMAT | m_HSYNC_POLARITY | m_VSYNC_POLARITY 
+               | m_DEN_POLARITY |m_DCLK_POLARITY,
+        v_DISPLAY_FORMAT(face) | v_HSYNC_POLARITY(screen->pin_hsync) | v_VSYNC_POLARITY(screen->pin_vsync) |
+        v_DEN_POLARITY(screen->pin_den) | v_DCLK_POLARITY(screen->pin_dclk));
+
+       //set background color to black,set swap according to the screen panel
+     LcdMskReg(lcdc_dev, DSP_CTRL1, m_BG_COLOR | m_OUTPUT_RB_SWAP | m_OUTPUT_RG_SWAP | m_DELTA_SWAP | 
+               m_DUMMY_SWAP,  v_BG_COLOR(0x000000) | v_OUTPUT_RB_SWAP(screen->swap_rb) | 
+               v_OUTPUT_RG_SWAP(screen->swap_rg) | v_DELTA_SWAP(screen->swap_delta) | v_DUMMY_SWAP(screen->swap_dumy) );
+
+       
+    LcdWrReg(lcdc_dev, DSP_HTOTAL_HS_END,v_HSYNC(screen->hsync_len) |
+             v_HORPRD(screen->hsync_len + screen->left_margin + x_res + right_margin));
+    LcdWrReg(lcdc_dev, DSP_HACT_ST_END, v_HAEP(screen->hsync_len + screen->left_margin + x_res) |
+             v_HASP(screen->hsync_len + screen->left_margin));
+
+    LcdWrReg(lcdc_dev, DSP_VTOTAL_VS_END, v_VSYNC(screen->vsync_len) |
+              v_VERPRD(screen->vsync_len + screen->upper_margin + y_res + lower_margin));
+    LcdWrReg(lcdc_dev, DSP_VACT_ST_END,  v_VAEP(screen->vsync_len + screen->upper_margin+y_res)|
+              v_VASP(screen->vsync_len + screen->upper_margin));
+       // let above to take effect
+    LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01);
+                                                        
+    if(initscreen == 0)    //not init
+    {
+        clk_disable(lcdc_dev->dclk);
+      //  clk_disable(inf->aclk);
+    }
+
+
+  //  ret = clk_set_rate(lcdc_dev->dclk, screen->pixclock);
+    if(ret)
+    {
+        printk(KERN_ERR ">>>>>> set lcdc dclk failed\n");
+    }
+    lcdc_dev->driver->pixclock = lcdc_dev->pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
+    if(initscreen)
+    {
+        //ret = clk_set_parent(lcdc_dev->aclk, lcdc_dev->aclk_parent);
+        if(screen->lcdc_aclk){
+           aclk_rate = screen->lcdc_aclk;
+        }
+       // ret = clk_set_rate(lcdc_dev->aclk, aclk_rate);
+        if(ret){
+            printk(KERN_ERR ">>>>>> set lcdc aclk failed\n");
+        }
+        clk_enable(lcdc_dev->aclk);
+    }
+  
+    clk_enable(lcdc_dev->dclk);
+   
+    if(screen->init)
+    {
+       screen->init();
+    }
+       printk("%s>>>>>ok!\n",__func__);
+}
+
+static int mcu_refresh(struct rk30_lcdc_device *lcdc_dev)
+{
+   
+    return 0;
+}
+
+static int win0_blank(int blank_mode,struct rk30_lcdc_device *lcdc_dev)
+{
+       switch(blank_mode)
+       {
+               case FB_BLANK_UNBLANK:
+               LcdMskReg(lcdc_dev, SYS_CTRL1, m_W0_EN, v_W0_EN(1));
+               break;
+       case FB_BLANK_NORMAL:
+               LcdMskReg(lcdc_dev, SYS_CTRL1, m_W0_EN, v_W0_EN(0));
+               break;
+       default:
+               LcdMskReg(lcdc_dev, SYS_CTRL1, m_W0_EN, v_W1_EN(1));
+               break;
+       }
+       mcu_refresh(lcdc_dev);
+    return 0;
+}
+
+static int win1_blank(int blank_mode, struct rk30_lcdc_device *lcdc_dev)
+{
+       printk(KERN_INFO "%s>>>>>>>>>>mode:%d\n",__func__,blank_mode);
+       switch(blank_mode)
+    {
+    case FB_BLANK_UNBLANK:
+        LcdMskReg(lcdc_dev, SYS_CTRL1, m_W1_EN, v_W1_EN(1));
+        break;
+    case FB_BLANK_NORMAL:
+         LcdMskReg(lcdc_dev, SYS_CTRL1, m_W1_EN, v_W1_EN(0));
+            break;
+    default:
+        LcdMskReg(lcdc_dev, SYS_CTRL1, m_W1_EN, v_W1_EN(0));
+        break;
+    }
+    
+       //mcu_refresh(inf);
+    return 0;
+}
+static int rk30_lcdc_blank(struct rk_fb_device_driver*fb_drv,int layer_id,int blank_mode)
+{
+       struct rk30_lcdc_device * lcdc_dev = NULL;
+       struct lcdc_info * info = platform_get_drvdata(g_lcdc_pdev);
+       if(!strcmp(fb_drv->name,"lcdc0"))
+       {
+               lcdc_dev =  &(info->lcdc0); 
+       }
+       else if(!strcmp(fb_drv->name,"lcdc1"))
+       {
+               lcdc_dev = &(info->lcdc1);
+       }
+       if(layer_id==0)
+       {
+               win0_blank(blank_mode,lcdc_dev);
+       }
+       else if(layer_id==1)
+       {
+               win1_blank(blank_mode,lcdc_dev);
+       }
+
+       LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01);
+    return 0;
+}
+
+static  int win0_set_par(struct rk30_lcdc_device *lcdc_dev,rk_screen *screen,
+       struct layer_par *par )
+{
+    u32 xact, yact, xvir, yvir, xpos, ypos;
+    u32 ScaleYrgbX,ScaleYrgbY, ScaleCbrX, ScaleCbrY;
+    u32 y_addr,uv_addr;
+
+    xact = par->xact;                      /*active (origin) picture window width/height               */
+    yact = par->yact;
+    xvir = par->xres_virtual;          /* virtual resolution           */
+    yvir = par->yres_virtual;
+    xpos = par->xpos+screen->left_margin + screen->hsync_len;
+    ypos = par->ypos+screen->upper_margin + screen->vsync_len;
+    y_addr = par->smem_start + par->y_offset;
+    switch (par->format)
+    {
+       case RGB888:
+       case RGB565:
+            ScaleYrgbX = CalScale(xact, par->xsize);
+           ScaleYrgbY = CalScale(yact, par->ysize);
+            break;
+       case YUV422:// yuv422
+            ScaleCbrX=  CalScale((xact/2), par->xsize);
+            ScaleCbrY = CalScale(yact, par->ysize);
+                   break;
+       case YUV420: // yuv420
+           ScaleCbrX= CalScale(xact/2, par->xsize);
+           ScaleCbrY =  CalScale(yact/2, par->ysize);
+           break;
+       case YUV444:// yuv444
+           ScaleCbrX= CalScale(xact, par->xsize);
+           ScaleCbrY = CalScale(yact, par->ysize);
+           break;
+       default:
+           break;
+    }
+
+       DBG("%s>>format:%d>>>xact:%d>>yact:%d>>xvir:%d>>yvir:%d>>ypos:%d>>y_addr:0x%x\n",
+               __func__,par->format,xact,yact,xvir,yvir,ypos,y_addr);
+    LcdWrReg(lcdc_dev, WIN0_YRGB_MST0, y_addr);
+    LcdMskReg(lcdc_dev,SYS_CTRL1,  m_W0_FORMAT , v_W0_FORMAT(par->format));            //(inf->video_mode==0)
+    LcdWrReg(lcdc_dev, WIN0_ACT_INFO,v_ACT_WIDTH(xact) | v_ACT_HEIGHT(yact));
+    LcdWrReg(lcdc_dev, WIN0_DSP_ST, v_DSP_STX(xpos) | v_DSP_STY(ypos));
+    LcdWrReg(lcdc_dev, WIN0_DSP_INFO, v_DSP_WIDTH(par->xsize) | v_DSP_HEIGHT(par->ysize));
+    LcdWrReg(lcdc_dev, WIN0_SCL_FACTOR_YRGB, v_X_SCL_FACTOR(ScaleYrgbX) | v_Y_SCL_FACTOR(ScaleYrgbY));
+       LcdWrReg(lcdc_dev, WIN0_SCL_FACTOR_CBR,  v_X_SCL_FACTOR(ScaleCbrX) | v_Y_SCL_FACTOR(ScaleCbrY));
+    switch(par->format)
+    {
+       case RGB888:  //rgb888
+            LcdMskReg(lcdc_dev, WIN0_VIR, m_WORDLO, v_RGB888_VIRWIDTH(xvir));
+                    break;
+       case RGB565:  //rgb565
+            LcdMskReg(lcdc_dev, WIN0_VIR, m_WORDLO, v_YUV_VIRWIDTH(xvir));
+             break;
+       case YUV420:   
+            LcdMskReg(lcdc_dev, WIN0_VIR, m_WORDLO,v_RGB565_VIRWIDTH(xvir));
+             break;
+       default:
+               LcdMskReg(lcdc_dev, WIN0_VIR, m_WORDLO, v_RGB888_VIRWIDTH(xvir));
+            break;
+    }
+
+    LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01);
+       printk(KERN_INFO "%s>>>>done!\n",__func__);
+       
+    return 0;
+
+}
+
+static int win1_set_par(struct rk30_lcdc_device *lcdc_dev,rk_screen *screen,
+       struct layer_par *par )
+
+{
+       u32 xact, yact, xvir, yvir, xpos, ypos,xres_virtual;
+    u32 ScaleYrgbX,ScaleYrgbY, ScaleCbrX, ScaleCbrY;
+    u32 addr;
+    xact = par->xact;                      /* visible resolution               */
+    yact = par->yact;
+    xvir = par->xres_virtual;          /* virtual resolution           */
+    yvir = par->yres_virtual;
+    xpos = par->xpos+screen->left_margin + screen->hsync_len;
+    ypos = par->ypos+screen->upper_margin + screen->vsync_len;
+       addr = par->smem_start + par->y_offset;
+
+       
+       switch (par->format)
+       {
+               case RGB888:
+               case RGB565:
+                       ScaleYrgbX = CalScale(xact, par->xsize);
+                       ScaleYrgbY = CalScale(yact, par->ysize);
+                       break;
+               case YUV422:// yuv422
+                       ScaleCbrX=      CalScale((xact/2), par->xsize);
+                       ScaleCbrY = CalScale(yact, par->ysize);
+                       break;
+               case YUV420: // yuv420
+                       ScaleCbrX= CalScale(xact/2, par->xsize);
+                       ScaleCbrY =     CalScale(yact/2, par->ysize);
+                       break;
+               case YUV444:// yuv444
+                       ScaleCbrX= CalScale(xact, par->xsize);
+                       ScaleCbrY = CalScale(yact, par->ysize);
+                       break;
+               default:
+                       break;
+       }
+       
+       LcdWrReg(lcdc_dev, WIN1_SCL_FACTOR_YRGB, v_X_SCL_FACTOR(ScaleYrgbX) | v_Y_SCL_FACTOR(ScaleYrgbY));
+       LcdWrReg(lcdc_dev, WIN1_SCL_FACTOR_CBR,  v_X_SCL_FACTOR(ScaleCbrX) | v_Y_SCL_FACTOR(ScaleCbrY));
+    LcdMskReg(lcdc_dev, SYS_CTRL1, m_W1_EN|m_W1_FORMAT, v_W1_EN(1)|v_W1_FORMAT(par->format));
+    LcdWrReg(lcdc_dev, WIN1_YRGB_MST, addr);
+    LcdWrReg(lcdc_dev, WIN1_DSP_ST,v_DSP_STX(xpos) | v_DSP_STY(ypos));
+    LcdWrReg(lcdc_dev, WIN1_DSP_INFO,v_DSP_WIDTH(par->xsize) | v_DSP_HEIGHT(par->ysize));
+     // enable win1 color key and set the color to black(rgb=0)
+    LcdMskReg(lcdc_dev, WIN1_COLOR_KEY_CTRL, m_COLORKEY_EN | m_KEYCOLOR, v_COLORKEY_EN(1) | v_KEYCOLOR(0));
+       switch(par->format)
+    {
+       case RGB888:  //rgb888
+            LcdMskReg(lcdc_dev, WIN1_VIR, m_WORDLO, v_RGB888_VIRWIDTH(xvir));
+                    break;
+       case RGB565:  //rgb565
+            LcdMskReg(lcdc_dev, WIN1_VIR, m_WORDLO, v_YUV_VIRWIDTH(xvir));
+             break;
+       case YUV420:   
+            LcdMskReg(lcdc_dev, WIN1_VIR, m_WORDLO,v_RGB565_VIRWIDTH(xvir));
+             break;
+       default:
+               LcdMskReg(lcdc_dev, WIN1_VIR, m_WORDLO, v_RGB888_VIRWIDTH(xvir));
+               break;
+    }
+    
+       LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01);
+    
+
+    return 0;
+}
+
+static int rk30_lcdc_set_par(struct rk_fb_device_driver *fb_drv,int layer_id)
+{
+       struct rk30_lcdc_device *lcdc_dev=NULL;
+       struct layer_par *par = &fb_drv->layer_par[0];
+       rk_screen *screen = &fb_drv->screen;
+       struct lcdc_info * info = platform_get_drvdata(g_lcdc_pdev);
+       if(!strcmp(fb_drv->name,"lcdc0"))
+       {
+               lcdc_dev =  &(info->lcdc0); 
+       }
+       else if(!strcmp(fb_drv->name,"lcdc1"))
+       {
+               lcdc_dev = &(info->lcdc1);
+       }
+       
+       if(!screen)
+       {
+               printk(KERN_ERR "screen is null!\n");
+       }
+       if(layer_id==0)
+       {
+         win0_set_par(lcdc_dev,screen,par);
+       }
+       else if(layer_id==1)
+       {
+               win1_set_par(lcdc_dev,screen,&(fb_drv->layer_par[1]));
+       }
+       
+       return 0;
+}
+int rk30_lcdc_pan(struct rk_fb_device_driver * dev_drv,int layer_id)
+{
+       
+    return 0;
+}
+
+int rk30_lcdc_ioctl(unsigned int cmd, unsigned long arg,struct layer_par *layer_par)
+{
+   return 0;
+}
+
+int rk30_lcdc_suspend(struct layer_par *layer_par)
+{
+    return 0;
+}
+
+
+int rk30_lcdc_resume(struct layer_par *layer_par)
+{  
+    
+    return 0;
+}
+
+static struct layer_par lcdc0_layer[] = {
+       [0] = {
+               .name           = "win0",
+               .id                     = 0,
+               .support_3d     = true,
+       },
+       [1] = {
+        .name                  = "win1",
+               .id                     = 1,
+               .support_3d     = false,
+       },
+};
+static struct layer_par lcdc1_layer[] = {
+       [0] = {
+               .name           = "win0",
+               .id                     = 0,
+               .support_3d     = true,
+       },
+       [1] = {
+        .name                  = "win1",
+               .id                     = 1,
+               .support_3d     = false,
+       },
+};
+
+static struct rk_fb_device_driver lcdc0_driver = {
+       .name                   = "lcdc0",
+       .layer_par              = lcdc0_layer,
+       .num_layer              = ARRAY_SIZE(lcdc0_layer),
+       .ioctl                  = rk30_lcdc_ioctl,
+       .suspend                = rk30_lcdc_suspend,
+       .resume                 = rk30_lcdc_resume,
+       .set_par       = rk30_lcdc_set_par,
+       .blank         = rk30_lcdc_blank,
+       .pan           = rk30_lcdc_pan,
+};
+static struct rk_fb_device_driver lcdc1_driver = {
+       .name                   = "lcdc1",
+       .layer_par              = lcdc1_layer,
+       .num_layer              = ARRAY_SIZE(lcdc1_layer),
+       .ioctl                  = rk30_lcdc_ioctl,
+       .suspend                = rk30_lcdc_suspend,
+       .resume                 = rk30_lcdc_resume,
+       .set_par       = rk30_lcdc_set_par,
+       .blank         = rk30_lcdc_blank,
+       .pan           = rk30_lcdc_pan,
+};
+
+static int __devinit rk30_lcdc_probe (struct platform_device *pdev)
+{
+       struct lcdc_info *inf = NULL;
+       struct resource *res = NULL;
+       struct resource *mem;
+       int ret = 0;
+       
+       g_lcdc_pdev = pdev; //set g_pdev
+
+       /*************Malloc rk30lcdc_inf and set it to pdev for drvdata**********/
+       inf = kmalloc(sizeof(struct lcdc_info), GFP_KERNEL);
+    if(!inf)
+    {
+        dev_err(&pdev->dev, ">>rk30 lcdc inf kmalloc fail!");
+        ret = -ENOMEM;
+    }
+       memset(inf, 0, sizeof(struct lcdc_info));
+       platform_set_drvdata(pdev, inf);
+
+       /****************       get lcdc0 reg           *************************/
+        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lcdc0 reg");
+    if (res == NULL)
+    {
+        dev_err(&pdev->dev, "failed to get memory registers\n");
+        ret = -ENOENT;
+               //goto release_drvdata;
+    }
+    inf->lcdc0.reg_phy_base = res->start;
+    inf->lcdc0.len = (res->end - res->start) + 1;
+    mem = request_mem_region(inf->lcdc0.reg_phy_base, inf->lcdc0.len, pdev->name);
+    if (mem == NULL)
+    {
+        dev_err(&pdev->dev, "failed to get memory region\n");
+        ret = -ENOENT;
+               //goto release_drvdata;
+    }
+    inf->lcdc0.reg_vir_base = ioremap(inf->lcdc0.reg_phy_base, inf->lcdc0.len);
+    if (inf->lcdc0.reg_vir_base == NULL)
+    {
+        dev_err(&pdev->dev, "ioremap() of registers failed\n");
+        ret = -ENXIO;
+               //goto release_drvdata;
+    }
+    inf->lcdc0.preg = (LCDC_REG*)inf->lcdc0.reg_vir_base;
+       printk("lcdc0 reg_phy_base = 0x%08x,reg_vir_base:0x%p\n", inf->lcdc0.reg_phy_base, inf->lcdc0.preg);
+       /****************       get lcdc1 reg           *************************/
+        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lcdc1 reg");
+    if (res == NULL)
+    {
+        dev_err(&pdev->dev, "failed to get memory registers\n");
+        ret = -ENOENT;
+               //goto release_drvdata;
+    }
+    inf->lcdc1.reg_phy_base = res->start;
+    inf->lcdc1.len = (res->end - res->start) + 1;
+    mem = request_mem_region(inf->lcdc1.reg_phy_base, inf->lcdc1.len, pdev->name);
+    if (mem == NULL)
+    {
+        dev_err(&pdev->dev, "failed to get memory region\n");
+        ret = -ENOENT;
+               //goto release_drvdata;
+    }
+    inf->lcdc1.reg_vir_base = ioremap(inf->lcdc1.reg_phy_base, inf->lcdc1.len);
+    if (inf->lcdc1.reg_vir_base == NULL)
+    {
+        dev_err(&pdev->dev, "ioremap() of registers failed\n");
+        ret = -ENXIO;
+               //goto release_drvdata;
+    }
+    inf->lcdc1.preg = (LCDC_REG*)inf->lcdc1.reg_vir_base;
+       printk("lcdc1 reg_phy_base = 0x%08x,reg_vir_base:0x%p\n", inf->lcdc1.reg_phy_base, inf->lcdc1.preg);
+       /*****************       LCDC driver            ********/
+       inf->lcdc0.driver = &lcdc0_driver;
+       inf->lcdc0.driver->dev=&pdev->dev;
+       inf->lcdc1.driver = &lcdc1_driver;
+       inf->lcdc1.driver->dev=&pdev->dev;
+       /*****************      set lcdc screen ********/
+       set_lcd_info(&inf->lcdc0.driver->screen, NULL);
+       set_lcd_info(&inf->lcdc1.driver->screen, NULL);
+       /*****************      INIT LCDC               ********/
+       init_rk30_lcdc(inf);
+       rk30_load_screen(&inf->lcdc0,1);
+       //rk30_load_screen(&inf->lcdc1,1);
+       /*****************      lcdc register           ********/
+       rk_fb_register(&lcdc0_driver);
+       //rk_fb_register(&lcdc1_driver);
+
+       
+       printk("rk30 lcdc probe ok!\n");
+       return 0;
+    
+}
+static int __devexit rk30_lcdc_remove(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static void rk30_lcdc_shutdown(struct platform_device *pdev)
+{
+
+}
+
+
+static struct platform_driver rk30lcdc_driver = {
+       .probe          = rk30_lcdc_probe,
+       .remove         = __devexit_p(rk30_lcdc_remove),
+       .driver         = {
+               .name   = "rk30-lcdc",
+               .owner  = THIS_MODULE,
+       },
+       .shutdown   = rk30_lcdc_shutdown,
+};
+
+static int __init rk30_lcdc_init(void)
+{
+       //wake_lock_init(&idlelock, WAKE_LOCK_IDLE, "fb");
+    return platform_driver_register(&rk30lcdc_driver);
+}
+
+static void __exit rk30_lcdc_exit(void)
+{
+    platform_driver_unregister(&rk30lcdc_driver);
+}
+
+
+
+fs_initcall(rk30_lcdc_init);
+module_exit(rk30_lcdc_exit);
+
+
+
diff --git a/drivers/video/rockchip/chips/rk30_lcdc.h b/drivers/video/rockchip/chips/rk30_lcdc.h
new file mode 100644 (file)
index 0000000..4e98c10
--- /dev/null
@@ -0,0 +1,503 @@
+#ifndef RK30_LCDC_H_
+#define RK30_LCDC_H_
+
+#define LcdReadBit(inf, addr, msk)      ((inf->regbak.addr=inf->preg->addr)&(msk))
+#define LcdWrReg(inf, addr, val)        inf->preg->addr=inf->regbak.addr=(val)
+#define LcdRdReg(inf, addr)             (inf->preg->addr)
+#define LcdSetBit(inf, addr, msk)       inf->preg->addr=((inf->regbak.addr) |= (msk))
+#define LcdClrBit(inf, addr, msk)       inf->preg->addr=((inf->regbak.addr) &= ~(msk))
+#define LcdSetRegBit(inf, addr, msk)    inf->preg->addr=((inf->preg->addr) |= (msk))
+#define LcdMskReg(inf, addr, msk, val)  (inf->regbak.addr)&=~(msk);   inf->preg->addr=(inf->regbak.addr|=(val))
+
+/********************************************************************
+**                          ½á¹¹¶¨Òå                                *
+********************************************************************/
+/* LCDCµÄ¼Ä´æÆ÷½á¹¹ */
+
+typedef volatile struct tagLCDC_REG
+{
+    /* offset 0x00~0xc0 */
+    unsigned int SYS_CTRL0;               //0x00 system control register 0
+    unsigned int SYS_CTRL1;                              //0x04 system control register 1
+    unsigned int DSP_CTRL0;                             //0x08 display control register 0
+    unsigned int DSP_CTRL1;                             //0x0c display control register 1
+    unsigned int INT_STATUS;             //0x10 Interrupt status register
+    unsigned int MCU_CTRL ;                             //0x14 MCU mode contol register
+    unsigned int BLEND_CTRL;             //0x18 Blending control register
+    unsigned int WIN0_COLOR_KEY_CTRL;     //0x1c Win0 blending control register
+    unsigned int WIN1_COLOR_KEY_CTRL;     //0x20 Win1 blending control register
+    unsigned int WIN2_COLOR_KEY_CTRL;     //0x24 Win2 blending control register
+    unsigned int WIN0_YRGB_MST0;           //0x28 Win0 active YRGB memory start address0
+    unsigned int WIN0_CBR_MST0;            //0x2c Win0 active Cbr memory start address0
+    unsigned int WIN0_YRGB_MST1;           //0x30 Win0 active YRGB memory start address1
+    unsigned int WIN0_CBR_MST1;            //0x34 Win0 active Cbr memory start address1
+    unsigned int WIN0_VIR;                //0x38 WIN0 virtual display width/height
+    unsigned int WIN0_ACT_INFO;           //0x3C Win0 active window width/height
+    unsigned int WIN0_DSP_INFO;           //0x40 Win0 display width/height on panel
+    unsigned int WIN0_DSP_ST;             //0x44 Win0 display start point on panel
+    unsigned int WIN0_SCL_FACTOR_YRGB;    //0x48Win0 YRGB scaling  factor setting
+    unsigned int WIN0_SCL_FACTOR_CBR;     //0x4c Win0 YRGB scaling factor setting
+    unsigned int WIN0_SCL_OFFSET;         //0x50 Win0 Cbr scaling start point offset
+    unsigned int WIN1_YRGB_MST;           //0x54 Win1 active YRGB memory start address
+    unsigned int WIN1_CBR_MST;            //0x58 Win1 active Cbr memory start address
+       unsigned int WIN1_VIR;                //0x5c WIN1 virtual display width/height
+    unsigned int WIN1_ACT_INFO;           //0x60 Win1 active window width/height
+    unsigned int WIN1_DSP_INFO;           //0x64 Win1 display width/height on panel
+    unsigned int WIN1_DSP_ST;             //0x68 Win1 display start point on panel
+    unsigned int WIN1_SCL_FACTOR_YRGB;    //0x6c Win1 YRGB scaling  factor setting
+    unsigned int WIN1_SCL_FACTOR_CBR;     //0x70 Win1 YRGB scaling factor setting
+    unsigned int WIN1_SCL_OFFSET;         //0x74 Win1 Cbr scaling start point offset
+       unsigned int WIN2_MST;                            //0x78 win2 memort start address
+       unsigned int WIM2_VIR;                            //0x7c win2 virtual stride
+       unsigned int WIN2_DSP_INFO;           //0x80 Win2 display width/height on panel
+    unsigned int WIN2_DSP_ST;             //0x84 Win2 display start point on panel
+    unsigned int HWC_MST;                 //0x88 HWC memory start address
+    unsigned int HWC_DSP_ST;              //0x8C HWC display start point on panel
+       unsigned int HWC_COLOR_LUT0;          //0x90 Hardware cursor color 2¡¯b01 look up table 0
+    unsigned int HWC_COLOR_LUT1;          //0x94 Hardware cursor color 2¡¯b10 look up table 1
+    unsigned int HWC_COLOR_LUT2;          //0x98 Hardware cursor color 2¡¯b11 look up table 2
+       unsigned int DSP_HTOTAL_HS_END;       //0x9c Panel scanning horizontal width and hsync pulse end point
+       unsigned int DSP_HACT_ST_END;         //0xa0 Panel active horizontal scanning start/end point
+       unsigned int DSP_VTOTAL_VS_END;       //0xa4 Panel scanning vertical height and vsync pulse end point
+    unsigned int DSP_VACT_ST_END;         //0xa8 Panel active vertical scanning start/end point
+       unsigned int DSP_VS_ST_END_F1;        //0xac Vertical scanning start point and vsync pulse end point of even filed in interlace mode
+    unsigned int DSP_VACT_ST_END_F1;      //0xb0 Vertical scanning active start/end point of even filed in interlace mode
+    unsigned int reserved0[(0xc0-0xb4)/4];
+       unsigned int REG_CFG_DONE;            //0xc0 REGISTER CONFIG FINISH
+       unsigned int reserved1[(0x100-0xc4)/4];
+       unsigned int MCU_BYPASS_WPORT;         //0x100 MCU BYPASS MODE, DATA Write Only Port
+       unsigned int reserved2[(0x200-0x104)/4];
+    unsigned int MCU_BYPASS_RPORT;         //0x200 MCU BYPASS MODE, DATA Read Only Port   
+  
+} LCDC_REG, *pLCDC_REG;
+
+
+/* SYS_CONFIG */
+
+#define m_LCDC_DMA_STOP              (1<<0)
+#define m_LCDC_STANDBY               (1<<1)
+#define m_HWC_RELOAD_EN                 (1<<2)
+#define m_W0_AXI_OUTSTANDING_DISABLE (1<<3)
+#define m_W1_AXI_OUTSTANDING_DISABLE (1<<4)
+#define m_W2_AXI_OUTSTANDING_DISABLE (1<<5)
+#define m_DMA_BURST_LENGTH                      (3<<6)
+
+#define v_LCDC_DMA_STOP(x)              (((x)&1)<<0)
+#define v_LCDC_STANDBY(x)              (((x)&1)<<1)
+#define v_HWC_RELOAD_EN(x)                 (((x)&1)<<2)
+#define v_W0_AXI_OUTSTANDING_DISABLE(x) (((x)&1)<<3)
+#define v_W1_AXI_OUTSTANDING_DISABLE(x) (((x)&1)<<4)
+#define v_W2_AXI_OUTSTANDING_DISABLE(x) (((x)&1)<<5)
+#define v_DMA_BURST_LENGTH(x)                   (((x)&3)<<6)
+
+
+
+//LCDC_SYS_CTRL1
+#define m_W0_EN          (1<<0)
+#define m_W1_EN          (1<<1)
+#define m_W2_EN         (1<<2)
+#define m_HWC_EN         (1<<3)
+#define m_W0_FORMAT          (7<<4)
+#define m_W1_FORMAT          (7<<7)
+#define m_W2_FORMAT          (7<<10)
+#define m_HWC_COLOR_MODE     (1<<13)
+#define m_HWC_SIZE_SELET     (1<<14)
+#define m_W0_3D_MODE_EN      (1<<15)
+#define m_W0_3D_MODE_SELET    (7<<16)
+#define m_W0_RGB_RB_SWAP      (1<<19)
+#define m_W0_RGB_ALPHA_SWAP   (1<<20)
+#define m_W0_YRGB_M8_SWAP     (1<<21)
+#define m_W0_CBCR_SWAP        (1<<22)
+#define m_W1_RGB_RB_SWAP      (1<<23)
+#define m_W1_RGB_ALPHA_SWAP   (1<<24)
+#define m_W1_YRGB_M8_SWAP     (1<<25)
+#define m_W1_CBCR_SWAP        (1<<26)
+#define m_W2_RGB_RB_SWAP      (1<<27)
+#define m_W2_RGB_ALPHA_SWAP   (1<<28)
+#define m_W2_8pp_PALETTE_ENDIAN_SELECT (1<<29)
+#define m_W2_LUT_RAM_EN       (1<<30)
+#define m_DSP_LUT_RAM_EN      (1<<31)
+
+#define v_W0_EN(x)          (((x)&1)<<0)
+#define v_W1_EN(x)          (((x)&1)<<1)
+#define v_W2_EN(x)          (((x)&1)<<2)
+#define v_HWC_EN(x)         (((x)&1)<<3)
+#define v_W0_FORMAT(x)      (((x)&7)<<4)
+#define v_W1_FORMAT(x)      (((x)&7)<<7)
+#define v_W2_FORMAT(x)      (((x)&7)<<10)
+#define v_HWC_COLOR_MODE(x)     (((x)&1)<<13)
+#define v_HWC_SIZE_SELET(x)     (((x)&1)<<14)
+#define v_W0_3D_MODE_EN(x)     (((x)&1)<<15)
+#define v_W0_3D_MODE_SELET(x)    (((x)&3)<<16)
+#define v_W0_RGB_RB_SWAP(x)      (((x)&1)<<19)
+#define v_W0_RGB_ALPHA_SWAP(x)   (((x)&1)<<20)
+#define v_W0_YRGB_M8_SWAP(x)     (((x)&1)<<21)
+#define v_W0_CBCR_SWAP(x)       (((x)&1)<<22)
+#define v_W1_RGB_RB_SWAP(x)      (((x)&1)<<23)
+#define v_W1_RGB_ALPHA_SWAP(x)   (((x)&1)<<24)
+#define v_W1_YRGB_M8_SWAP(x)     (((x)&1)<<25)
+#define v_W1_CBCR_SWAP(x)       (((x)&1)<<26)
+#define v_W2_RGB_RB_SWAP(x)      (((x)&1)<<27)
+#define v_W2_RGB_ALPHA_SWAP(x)   (((x)&1)<<28)
+#define v_W2_8pp_PALETTE_ENDIAN_SELECT (((x)&1)<<29)
+#define v_W2_LUT_RAM_EN(x)      (((x)&1)<<30)
+#define v_DSP_LUT_RAM_EN(x)¡¡¡¡¡¡(((x)&1)<<31)
+
+
+//LCDC_DSP_CTRL_REG0
+#define m_DISPLAY_FORMAT             (0x0f<<0)
+#define m_HSYNC_POLARITY             (1<<4)
+#define m_VSYNC_POLARITY             (1<<5)
+#define m_DEN_POLARITY               (1<<6)
+#define m_DCLK_POLARITY              (1<<7)
+#define m_W0W1_POSITION_SWAP         (1<<8)
+#define m_DITHER_UP_EN               (1<<9)
+#define m_DITHER_DOWN_MODE           (1<<10)
+#define m_DITHER_DOWN_EN             (1<<11)
+#define m_INTERLACE_DSP_EN           (1<<12)
+#define m_INTERLACE_FIELD_POLARITY   (1<<13)
+#define m_W0_INTERLACE_READ_MODE     (1<<14)
+#define m_W1_INTERLACE_READ_MODE     (1<<15)
+#define m_W2_INTERLACE_READ_MODE     (1<<16)
+#define m_W0_YRGB_DEFLICK_MODE       (1<<17)
+#define m_W0_CBR_DEFLICK_MODE        (1<<18)
+#define m_W1_YRGB_DEFLICK_MODE       (1<<19)
+#define m_W1_CBR_DEFLICK_MODE        (1<<20)
+#define m_W0_ALPHA_MODE              (1<<21)
+#define m_W1_ALPHA_MODE              (1<<22)
+#define m_W2_ALPHA_MODE              (1<<23)
+#define m_W0_COLOR_SPACE_CONVERSION  (3<<24)
+#define m_W1_COLOR_SPACE_CONVERSION  (3<<26)
+#define m_W2_COLOR_SPACE_CONVERSION  (1<<28)
+#define m_YCRCB_CLIP_EN              (1<<29)
+#define m_CBR_FILTER_656             (1<<30)
+#define m_LCDC_AXICLK_AUTO_ENABLE      (1<<31) //eanble for low power
+
+#define v_DISPLAY_FORMAT(x)            (((x)&0xf)<<0)
+#define v_HSYNC_POLARITY(x)             (((x)&1)<<4)
+#define v_VSYNC_POLARITY(x)             (((x)&1)<<5)
+#define v_DEN_POLARITY(x)               (((x)&1)<<6)
+#define v_DCLK_POLARITY(x)              (((x)&1)<<7)
+#define v_W0W1_POSITION_SWAP(x)                        (((x)&1)<<8)            
+#define v_DITHER_UP_EN(x)               (((x)&1)<<9)
+#define v_DITHER_DOWN_MODE(x)           (((x)&1)<<10)
+#define v_DITHER_DOWN_EN(x)             (((x)&1)<<11)
+#define v_INTERLACE_DSP_EN(x)             (((x)&1)<<12)
+#define v_INTERLACE_FIELD_POLARITY(x)   (((x)&1)<<13)
+#define v_W0_INTERLACE_READ_MODE(x)     (((x)&1)<<14)
+#define v_W1_INTERLACE_READ_MODE(x)     (((x)&1)<<15)
+#define v_W2_INTERLACE_READ_MODE(x)     (((x)&1)<<16)
+#define v_W0_YRGB_DEFLICK_MODE(x)       (((x)&1)<<17)
+#define v_W0_CBR_DEFLICK_MODE(x)        (((x)&1)<<18)
+#define v_W1_YRGB_DEFLICK_MODE(x)       (((x)&1)<<19)
+#define v_W1_CBR_DEFLICK_MODE(x)        (((x)&1)<<20)
+#define v_W0_ALPHA_MODE(x)             (((x)&1)<<21)
+#define v_W1_ALPHA_MODE(x)              (((x)&1)<<22)
+#define v_W2_ALPHA_MODE(x)             (((x)&1)<<23)
+#define v_W0_COLOR_SPACE_CONVERSION(x)  (((x)&3)<<24)
+#define v_W1_COLOR_SPACE_CONVERSION(x)  (((x)&3)<<26)
+#define v_W2_COLOR_SPACE_CONVERSION(x)  (((x)&1)<<28)
+#define v_YCRCB_CLIP_EN(x)            (((x)&1)<<29)
+#define v_CBR_FILTER_656(x)             (((x)&1)<<30)
+#define v_LCDC_AXICLK_AUTO_ENABLE(x)   (((x)&1)<<31) //eanble for low power
+
+//LCDC_DSP_CTRL_REG1
+#define m_BG_COLOR                    (0xffffff<<0)
+#define m_BG_B                        (0xff<<0)
+#define m_BG_G                        (0xff<<8)
+#define m_BG_R                        (0xff<<16)
+#define m_BLANK_MODE                  (1<<24)
+#define m_BLACK_MODE                  (1<<25)
+#define m_OUTPUT_BG_SWAP                 (1<<26)
+#define m_OUTPUT_RB_SWAP                 (1<<27)
+#define m_OUTPUT_RG_SWAP                 (1<<28)
+#define m_DELTA_SWAP                     (1<<29)
+#define m_DUMMY_SWAP                     (1<<30)
+
+#define v_BG_COLOR(x)                 (((x)&0xffffff)<<0)
+#define v_BG_B(x)                     (((x)&0xff)<<0)
+#define v_BG_G(x)                     (((x)&0xff)<<8)
+#define v_BG_R(x)                     (((x)&0xff)<<16)
+#define v_BLANK_MODE(x)               (((x)&1)<<24)
+#define v_BLACK_MODE(x)               (((x)&1)<<25)
+#define v_OUTPUT_BG_SWAP(x)              (((x)&1)<<26)
+#define v_OUTPUT_RB_SWAP(x)              (((x)&1)<<27)
+#define v_OUTPUT_RG_SWAP(x)              (((x)&1)<<28)
+#define v_DELTA_SWAP(x)                  (((x)&1)<<29)
+#define v_DUMMY_SWAP(x)                  (((x)&1)<<30)
+
+
+//LCDC_INT_STATUS
+#define m_HOR_START         (1<<0)
+#define m_FRM_START         (1<<1)
+#define m_SCANNING_FLAG     (1<<2)
+#define m_HOR_STARTMASK     (1<<3)
+#define m_FRM_STARTMASK     (1<<4)
+#define m_SCANNING_MASK     (1<<5)
+#define m_HOR_STARTCLEAR    (1<<6)
+#define m_FRM_STARTCLEAR    (1<<7)
+#define m_SCANNING_CLEAR    (1<<8)
+#define m_SCAN_LINE_NUM     (0x7ff<<9)
+#define v_HOR_START(x)         (((x)&1)<<0)
+#define v_FRM_START(x)         (((x)&1)<<1)
+#define v_SCANNING_FLAG(x)     (((x)&1)<<2)
+#define v_HOR_STARTMASK(x)     (((x)&1)<<3)
+#define v_FRM_STARTMASK(x)     (((x)&1)<<4)
+#define v_SCANNING_MASK(x)     (((x)&1)<<5)
+#define v_HOR_STARTCLEAR(x)    (((x)&1)<<6)
+#define v_FRM_STARTCLEAR(x)    (((x)&1)<<7)
+#define v_SCANNING_CLEAR(x)    (((x)&1)<<8)
+#define v_SCAN_LINE_NUM(x)     (((x)&0x7ff)<<9)
+
+
+//LCDC_MCU_TIMING_CTRL
+#define m_MCU_WRITE_PERIOD      (31<<0)
+#define m_MCU_CS_ST             (31<<5)
+#define m_MCU_CS_END            (31<<10)
+#define m_MCU_RW_ST             (31<<15)
+#define m_MCU_RW_END            (31<<20)
+#define m_MCU_HOLDMODE_SELECT     (1<<27)
+#define m_MCU_HOLDMODE_FRAME_ST   (1<<28)
+#define m_MCU_RS_SELECT            (1<<29)
+#define m_MCU_BYPASSMODE_SELECT   (1<<30)
+#define m_MCU_OUTPUT_SELECT        (1<<31)
+#define v_MCU_WRITE_PERIOD(x)      (((x)&31)<<0)
+#define v_MCU_CS_ST(x)          (((x)&31)<<5)
+#define v_MCU_CS_END(x)         (((x)&31)<<10)
+#define v_MCU_RW_ST(x)          (((x)&31)<<15)
+#define v_MCU_RW_END(x)         (((x)&31)<<20)
+#define v_MCU_HOLD_STATUS(x)          (((x)&1)<<26)
+#define v_MCU_HOLDMODE_SELECT(x)     (((x)&1)<<27)
+#define v_MCU_HOLDMODE_FRAME_ST(x)   (((x)&1)<<28)
+#define v_MCU_RS_SELECT(x)            (((x)&1)<<29)
+#define v_MCU_BYPASSMODE_SELECT(x)   (((x)&1)<<30)
+#define v_MCU_OUTPUT_SELECT(x)        (((x)&1)<<31)
+
+//LCDC_ BLEND_CTRL
+#define m_HWC_BLEND_EN         (1<<0)
+#define m_W2_BLEND_EN          (1<<1)
+#define m_W1_BLEND_EN          (1<<2)
+#define m_W0_BLEND_EN          (1<<3)
+#define m_HWC_BLEND_FACTOR     (15<<4)
+#define m_W2_BLEND_FACTOR     (0xff<<8)
+#define m_W1_BLEND_FACTOR     (0xff<<16)
+#define m_W0_BLEND_FACTOR     (0xff<<24)
+
+#define v_HWC_BLEND_EN(x)         (((x)&1)<<0)
+#define v_W2_BLEND_EN(x)          (((x)&1)<<1)
+#define v_W1_BLEND_EN(x)          (((x)&1)<<2)
+#define v_W0_BLEND_EN(x)          (((x)&1)<<3)
+#define v_HWC_BLEND_FACTOR(x)    (((x)&15)<<4)
+#define v_W2_BLEND_FACTOR(x)     (((x)&0xff)<<8)
+#define v_W1_BLEND_FACTOR(x)     (((x)&0xff)<<16)
+#define v_W0_BLEND_FACTOR(x)     (((x)&0xff)<<24)
+
+
+//LCDC_WIN0_COLOR_KEY_CTRL / LCDC_WIN1_COLOR_KEY_CTRL
+#define m_KEYCOLOR          (0xffffff<<0)
+#define m_KEYCOLOR_B          (0xff<<0)
+#define m_KEYCOLOR_G          (0xff<<8)
+#define m_KEYCOLOR_R          (0xff<<16)
+#define m_COLORKEY_EN         (1<<24)
+#define v_KEYCOLOR(x)          (((x)&0xffffff)<<0)
+#define v_KEYCOLOR_B(x)          (((x)&0xff)<<0)
+#define v_KEYCOLOR_G(x)         (((x)&0xff)<<8)
+#define v_KEYCOLOR_R(x)          (((x)&0xff)<<16)
+#define v_COLORKEY_EN(x)         (((x)&1)<<24)
+
+//LCDC_DEFLICKER_SCL_OFFSET
+#define m_W0_YRGB_VSD_OFFSET      (0xff<<0)
+#define m_W0_YRGB_VSP_OFFSET      (0xff<<8)
+#define m_W1_VSD_OFFSET           (0xff<<16)
+#define m_W1_VSP_OFFSET           (0xff<<24)
+#define v_W0_YRGB_VSD_OFFSET(x)      (((x)&0xff)<<0)
+#define v_W0_YRGB_VSP_OFFSET(x)      (((x)&0xff)<<8)
+#define v_W1_VSD_OFFSET(x)           (((x)&0xff)<<16)
+#define v_W1_VSP_OFFSET(x)           (((x)&0xff)<<24)
+
+
+
+
+
+//AXI MS ID
+#define m_W0_YRGB_CH_ID        (0xF<<0)
+#define m_W0_CBR_CH_ID         (0xF<<4)
+#define m_W1_YRGB_CH_ID        (0xF<<8)
+#define m_W2_CH_ID             (0xF<<12)
+#define m_HWC_CH_ID            (0xF<<16)
+#define v_W0_YRGB_CH_ID(x)        (((x)&0xF)<<0)
+#define v_W0_CBR_CH_ID(x)         (((x)&0xF)<<4)
+#define v_W1_YRGB_CH_ID(x)        (((x)&0xF)<<8)
+#define v_W2_CH_ID(x)             (((x)&0xF)<<12)
+#define v_HWC_CH_ID(x)            (((x)&0xF)<<16)
+
+
+/* Low Bits Mask */
+#define m_WORDLO            (0xffff<<0)
+#define m_WORDHI            (0xffff<<16)
+#define v_WORDLO(x)         (((x)&0xffff)<<0)
+#define v_WORDHI(x)         (((x)&0xffff)<<16)
+
+
+//LCDC_WINx_SCL_FACTOR_Y/CBCR
+#define v_X_SCL_FACTOR(x)  ((x)<<0)
+#define v_Y_SCL_FACTOR(x)  ((x)<<16)
+
+//LCDC_DSP_HTOTAL_HS_END
+#define v_HSYNC(x)  ((x)<<0)   //hsync pulse width
+#define v_HORPRD(x) ((x)<<16)   //horizontal period
+
+
+//LCDC_DSP_HACT_ST_END
+#define v_HAEP(x) ((x)<<0)  //horizontal active end point
+#define v_HASP(x) ((x)<<16) //horizontal active start point
+
+//LCDC_DSP_VTOTAL_VS_END
+#define v_VSYNC(x) ((x)<<0)
+#define v_VERPRD(x) ((x)<<16)
+
+//LCDC_DSP_VACT_ST_END
+#define v_VAEP(x) ((x)<<0)
+#define v_VASP(x) ((x)<<16)
+
+
+
+#define v_RGB888_VIRWIDTH(x) (((x*3)>>2)+((x)%3))
+#define v_RGB565_VIRWIDTH(x) ((x)>>1)
+#define v_YUV_VIRWIDTH(x)    ((x)>>1)
+
+#define m_ACTWIDTH       (0xffff<<0)
+#define m_ACTHEIGHT      (0xffff<<16)
+#define v_ACTWIDTH(x)       (((x)&0xffff)<<0)
+#define v_ACTHEIGHT(x)      (((x)&0xffff)<<16)
+
+#define m_VIRST_X      (0xffff<<0)
+#define m_VIRST_Y      (0xffff<<16)
+#define v_VIRST_X(x)      (((x)&0xffff)<<0)
+#define v_VIRST_Y(x)      (((x)&0xffff)<<16)
+
+#define m_PANELST_X      (0x3ff<<0)
+#define m_PANELST_Y      (0x3ff<<16)
+#define v_PANELST_X(x)      (((x)&0x3ff)<<0)
+#define v_PANELST_Y(x)      (((x)&0x3ff)<<16)
+
+#define m_PANELWIDTH       (0x3ff<<0)
+#define m_PANELHEIGHT      (0x3ff<<16)
+#define v_PANELWIDTH(x)       (((x)&0x3ff)<<0)
+#define v_PANELHEIGHT(x)      (((x)&0x3ff)<<16)
+
+#define m_HWC_B                 (0xff<<0)
+#define m_HWC_G                 (0xff<<8)
+#define m_HWC_R                 (0xff<<16)
+#define m_W0_YRGB_HSP_OFFSET    (0xff<<24)
+#define m_W0_YRGB_HSD_OFFSET    (0xff<<24)
+#define v_HWC_B(x)                 (((x)&0xff)<<0)
+#define v_HWC_G(x)                 (((x)&0xff)<<8)
+#define v_HWC_R(x)                 (((x)&0xff)<<16)
+#define v_W0_YRGB_HSP_OFFSET(x)    (((x)&0xff)<<24)
+#define v_W0_YRGB_HSD_OFFSET(x)    (((x)&0xff)<<24)
+
+//LCDC_WIN0_ACT_INFO
+#define v_ACT_WIDTH(x)     ((x-1)<<0)
+#define v_ACT_HEIGHT(x)    ((x-1)<<16)
+
+//LCDC_WIN0_DSP_INFO
+#define v_DSP_WIDTH(x)     ((x-1)<<0)
+#define v_DSP_HEIGHT(x)    ((x-1)<<16)
+
+//LCDC_WIN0_DSP_ST    //x,y start point of the panel scanning
+#define v_DSP_STX(x)      (x<<0)
+#define v_DSP_STY(x)      (x<<16)
+
+//Panel display scanning
+#define m_PANEL_HSYNC_WIDTH             (0x3ff<<0)
+#define m_PANEL_HORIZONTAL_PERIOD       (0x3ff<<16)
+#define v_PANEL_HSYNC_WIDTH(x)             (((x)&0x3ff)<<0)
+#define v_PANEL_HORIZONTAL_PERIOD(x)       (((x)&0x3ff)<<16)
+
+#define m_PANEL_END              (0x3ff<<0)
+#define m_PANEL_START            (0x3ff<<16)
+#define v_PANEL_END(x)              (((x)&0x3ff)<<0)
+#define v_PANEL_START(x)            (((x)&0x3ff)<<16)
+
+#define m_PANEL_VSYNC_WIDTH             (0x3ff<<0)
+#define m_PANEL_VERTICAL_PERIOD       (0x3ff<<16)
+#define v_PANEL_VSYNC_WIDTH(x)             (((x)&0x3ff)<<0)
+#define v_PANEL_VERTICAL_PERIOD(x)       (((x)&0x3ff)<<16)
+//-----------
+
+#define m_HSCALE_FACTOR        (0xffff<<0)
+#define m_VSCALE_FACTOR        (0xffff<<16)
+#define v_HSCALE_FACTOR(x)        (((x)&0xffff)<<0)
+#define v_VSCALE_FACTOR(x)        (((x)&0xffff)<<16)
+
+#define m_W0_CBR_HSD_OFFSET   (0xff<<0)
+#define m_W0_CBR_HSP_OFFSET   (0xff<<8)
+#define m_W0_CBR_VSD_OFFSET   (0xff<<16)
+#define m_W0_CBR_VSP_OFFSET   (0xff<<24)
+#define v_W0_CBR_HSD_OFFSET(x)   (((x)&0xff)<<0)
+#define v_W0_CBR_HSP_OFFSET(x)   (((x)&0xff)<<8)
+#define v_W0_CBR_VSD_OFFSET(x)   (((x)&0xff)<<16)
+#define v_W0_CBR_VSP_OFFSET(x)   (((x)&0xff)<<24)
+
+
+
+#define CalScale(x, y)              (((u32)x*0x1000)/y)
+struct rk30_lcdc_device{
+       struct rk_fb_device_driver *driver;
+       /* LCDC reg base address and backup reg */
+    LCDC_REG *preg;
+    LCDC_REG regbak;
+
+       void __iomem *reg_vir_base;  // virtual basic address of lcdc register
+       u32 reg_phy_base;       // physical basic address of lcdc register
+       u32 len;               // physical map length of lcdc register
+       
+       struct clk              *hclk;                          //lcdc AHP clk
+       struct clk              *dclk;                          //lcdc dclk
+       struct clk              *aclk;                          //lcdc share memory frequency
+       struct clk              *aclk_parent;           //lcdc aclk divider frequency source
+       struct clk              *aclk_ddr_lcdc;         //DDR LCDC AXI clock disable.
+       struct clk              *aclk_disp_matrix;      //DISPLAY matrix AXI clock disable.
+       struct clk              *hclk_cpu_display;      //CPU DISPLAY AHB bus clock disable.
+       struct clk              *pd_display;            // display power domain
+       u32     pixclock;
+};
+
+
+struct lcdc_info{
+/*LCD CLK*/
+       struct rk30_lcdc_device lcdc0;
+       struct rk30_lcdc_device lcdc1;
+
+};
+
+
+struct win_set {
+       volatile u32 y_offset;
+       volatile u32 c_offset;
+};
+
+struct win0_par {
+    u32 refcount;
+    u32        pseudo_pal[16];
+    u32 y_offset;
+    u32 c_offset;
+    u32 xpos;         //size in panel
+    u32 ypos;
+    u32 xsize;        //start point in panel
+    u32 ysize;
+    enum data_format format;
+
+    wait_queue_head_t wait;
+    struct win_set mirror;
+    struct win_set displ;
+    struct win_set done;
+
+    u8 par_seted;
+    u8 addr_seted;
+};
+
+#endif
+
+
diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c
new file mode 100644 (file)
index 0000000..5c5a817
--- /dev/null
@@ -0,0 +1,522 @@
+/*
+ * drivers/video/rk30_fb.c
+ *
+ * Copyright (C) 2012 ROCKCHIP, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/backlight.h>
+#include <linux/timer.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/earlysuspend.h>
+#include <linux/cpufreq.h>
+#include <linux/wakelock.h>
+
+#include <asm/io.h>
+#include <asm/div64.h>
+#include <asm/uaccess.h>
+#include <asm/cacheflush.h>
+
+#include <mach/iomux.h>
+#include <mach/gpio.h>
+#include <mach/board.h>
+#include <mach/pmu.h>
+
+#include "../display/screen/screen.h"
+#include "rk_fb.h"
+
+#if 0
+       #define fbprintk(msg...)        printk(msg);
+#else
+       #define fbprintk(msg...)
+#endif
+
+#if 0
+#define CHK_SUSPEND(inf)       \
+       if(inf->in_suspend)     {       \
+               fbprintk(">>>>>> fb is in suspend! return! \n");        \
+               return -EPERM;  \
+       }
+#else
+#define CHK_SUSPEND(inf)
+#endif
+
+static struct platform_device *g_fb_pdev;
+
+static struct rk_fb_rgb def_rgb_16 = {
+     red:    { offset: 11, length: 5, },
+     green:  { offset: 5,  length: 6, },
+     blue:   { offset: 0,  length: 5, },
+     transp: { offset: 0,  length: 0, },
+};
+
+static int fb0_blank(int blank_mode, struct fb_info *info)
+{
+       struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
+       struct rk_fb_device_driver *rk_fb_dev_drv = fb_inf->rk_lcdc_device[0];
+        fb_inf->rk_lcdc_device[0]->blank(rk_fb_dev_drv,0,blank_mode);
+
+    return 0;
+}
+
+static int fb0_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       struct rk_fb_inf *inf = dev_get_drvdata(info->device);
+       rk_screen *screen = &inf->rk_lcdc_device[0]->screen;
+        u16 xpos = (var->nonstd>>8) & 0xfff;
+        u16 ypos = (var->nonstd>>20) & 0xfff;
+        u16 xlcd = screen->x_res;
+        u16 ylcd = screen->y_res;
+        //fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__);
+        CHK_SUSPEND(inf);
+        if( 0==var->xres_virtual || 0==var->yres_virtual ||
+                0==var->xres || 0==var->yres || var->xres<16 ||
+                ((16!=var->bits_per_pixel)&&(32!=var->bits_per_pixel)) )
+        {
+                printk(">>>>>> fb0_check_var fail 1!!! \n");
+                printk(">>>>>> 0==%d || 0==%d ", var->xres_virtual,var->yres_virtual);
+                printk("0==%d || 0==%d || %d<16 || ", var->xres,var->yres,var->xres<16);
+                printk("bits_per_pixel=%d \n", var->bits_per_pixel);
+                return -EINVAL;
+        }
+        if( (var->xoffset+var->xres)>var->xres_virtual ||
+                (var->yoffset+var->yres)>var->yres_virtual*2 )
+        {
+                printk(">>>>>> fb0_check_var fail 2!!! \n");
+                printk(">>>>>> (%d+%d)>%d || ", var->xoffset,var->xres,var->xres_virtual);
+                printk("(%d+%d)>%d || ", var->yoffset,var->yres,var->yres_virtual);
+                printk("(%d+%d)>%d || (%d+%d)>%d \n", xpos,var->xres,xlcd,ypos,var->yres,ylcd);
+                return -EINVAL;
+        }
+        switch(var->bits_per_pixel)
+        {
+        case 16:        // rgb565
+                var->xres_virtual = (var->xres_virtual + 0x1) & (~0x1);
+                var->xres = (var->xres + 0x1) & (~0x1);
+                var->xoffset = (var->xoffset) & (~0x1);
+                break;
+        default:        // rgb888
+                var->bits_per_pixel = 32;
+                break;
+        }
+    return 0;
+}
+
+
+static int fb0_set_par(struct fb_info *info)
+{
+       struct rk_fb_inf *inf =  platform_get_drvdata(g_fb_pdev);
+       struct fb_var_screeninfo *var = &info->var;
+       struct fb_fix_screeninfo *fix = &info->fix;
+       struct rk_fb_device_driver *rk_fb_dev_drv = inf->rk_lcdc_device[0];
+       struct layer_par *par = &rk_fb_dev_drv->layer_par[0];
+       rk_screen *screen = &rk_fb_dev_drv->screen;
+       
+       u32 offset=0,  smem_len=0;
+    u16 xres_virtual = var->xres_virtual;      //virtual screen size
+    u16 xpos_virtual = var->xoffset;           //visiable offset in virtual screen
+    u16 ypos_virtual = var->yoffset;
+
+        switch(var->bits_per_pixel)
+     {
+       case 16:    // rgb565
+               par->format = RGB565;
+                       fix->line_length = 2 * xres_virtual;  
+                       offset = (ypos_virtual*xres_virtual + xpos_virtual)*2;
+               break;
+       case 32:    // rgb888
+       default:
+               par->format = RGB888;
+               fix->line_length = 4 * xres_virtual;
+               offset = (ypos_virtual*xres_virtual + xpos_virtual)*4;
+        
+               if(ypos_virtual >= 2*var->yres)
+               {
+               par->format = RGB565;
+               if(ypos_virtual == 3*var->yres)
+               {            
+                       offset -= var->yres * var->xres *2;
+               }
+               }
+               break;
+     }
+
+        smem_len = fix->line_length * var->yres_virtual;
+     if (smem_len > fix->smem_len)     // buffer need realloc
+     {
+        printk("%s sorry!!! win0 buf is not enough\n",__FUNCTION__);
+        printk("line_length = %d, yres_virtual = %d, win0_buf only = %dB\n",fix->line_length,var->yres_virtual,fix->smem_len);
+        printk("you can change buf size MEM_FB_SIZE in board-xxx.c \n");
+               return 0;
+     }
+         par->smem_start = fix->smem_start;
+         par->y_offset = offset;
+      par->xpos = 0;
+      par->ypos = 0;
+         par->xact = var->xres;
+         par->yact = var->yres;
+         par->xres_virtual = var->xres_virtual;                /* virtual resolution           */
+         par->yres_virtual = var->yres_virtual;
+      par->xsize = screen->x_res;
+      par->ysize = screen->y_res;
+      inf->rk_lcdc_device[0]->set_par(rk_fb_dev_drv,0);
+       return 0;
+}
+
+static int fb0_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
+    return 0;
+}
+
+static int fb0_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+       struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
+    return 0;
+}
+
+static int fb1_blank(int blank_mode, struct fb_info *info)
+{
+       struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
+   return 0;
+}
+
+static int fb1_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+    return 0;
+}
+
+static int fb1_set_par(struct fb_info *info)
+{
+ struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
+   return 0;
+    return 0;
+}
+
+static int fb1_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
+    return 0;
+}
+
+static int fb1_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+  struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
+    return 0;
+}
+int fb1_open(struct fb_info *info, int user)
+{
+  return 0; 
+}
+
+int fb1_release(struct fb_info *info, int user)
+{
+  
+    return 0;
+}
+
+static inline unsigned int chan_to_field(unsigned int chan,
+                                        struct fb_bitfield *bf)
+{
+       chan &= 0xffff;
+       chan >>= 16 - bf->length;
+       return chan << bf->offset;
+}
+
+static int fb_setcolreg(unsigned regno,
+                              unsigned red, unsigned green, unsigned blue,
+                              unsigned transp, struct fb_info *info)
+{
+       unsigned int val;
+//     fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__);
+
+       switch (info->fix.visual) {
+       case FB_VISUAL_TRUECOLOR:
+               /* true-colour, use pseudo-palette */
+               if (regno < 16) {
+                       u32 *pal = info->pseudo_palette;
+                       val  = chan_to_field(red,   &info->var.red);
+                       val |= chan_to_field(green, &info->var.green);
+                       val |= chan_to_field(blue,  &info->var.blue);
+                       pal[regno] = val;
+               }
+               break;
+       default:
+               return -1;      /* unknown type */
+       }
+
+       return 0;
+}
+
+static struct fb_ops fb1_ops = {
+       .owner          = THIS_MODULE,
+       .fb_open    = fb1_open,
+       .fb_release = fb1_release,
+       .fb_check_var   = fb1_check_var,
+       .fb_set_par     = fb1_set_par,
+       .fb_blank       = fb1_blank,
+    .fb_pan_display = fb1_pan_display,
+    .fb_ioctl = fb1_ioctl,
+       .fb_setcolreg   = fb_setcolreg,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+};
+
+static struct fb_ops fb0_ops = {
+       .owner          = THIS_MODULE,
+       .fb_check_var   = fb0_check_var,
+       .fb_set_par = fb0_set_par,
+       .fb_blank   = fb0_blank,
+       .fb_pan_display = fb0_pan_display,
+    .fb_ioctl = fb0_ioctl,
+       .fb_setcolreg   = fb_setcolreg,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+       //.fb_cursor      = rk29_set_cursor,
+};
+int rk_fb_register(struct rk_fb_device_driver *fb_device_driver)
+{
+       struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
+       int i=0;
+       if(NULL==fb_device_driver){
+               printk("rk_fb_register lcdc register fail");
+               return -ENOENT;
+               }
+       for(i=0;i<RK30_MAX_LCDC_SUPPORT;i++){
+               if(NULL==fb_inf->rk_lcdc_device[i]){
+               fb_inf->rk_lcdc_device[i] = fb_device_driver;
+               fb_inf->rk_lcdc_device[i]->id = i;
+               fb_inf->num_lcdc++;
+               break;
+               }
+       }
+       if(i==RK30_MAX_LCDC_SUPPORT){
+               printk("rk_fb_register lcdc out of support %d",i);
+               return -ENOENT;
+       }
+       printk("%s>>>%s registered\n",__func__,fb_inf->rk_lcdc_device[i]->name);
+       /************fb0 set ***********/
+       fb_inf->fb0->fix.type        = FB_TYPE_PACKED_PIXELS;
+    fb_inf->fb0->fix.type_aux    = 0;
+    fb_inf->fb0->fix.xpanstep    = 1;
+    fb_inf->fb0->fix.ypanstep    = 1;
+    fb_inf->fb0->fix.ywrapstep   = 0;
+    fb_inf->fb0->fix.accel       = FB_ACCEL_NONE;
+    fb_inf->fb0->fix.visual      = FB_VISUAL_TRUECOLOR;
+
+    fb_inf->fb0->var.xres = fb_inf->rk_lcdc_device[0]->screen.x_res;
+    fb_inf->fb0->var.yres = fb_inf->rk_lcdc_device[0]->screen.y_res;
+    fb_inf->fb0->var.bits_per_pixel = 16;
+    //fb_inf->fb0_color_deepth = 0;
+    fb_inf->fb0->var.xres_virtual = fb_inf->rk_lcdc_device[0]->screen.x_res;
+    fb_inf->fb0->var.yres_virtual = fb_inf->rk_lcdc_device[0]->screen.y_res;
+    fb_inf->fb0->var.width = fb_inf->rk_lcdc_device[0]->screen.width;
+    fb_inf->fb0->var.height = fb_inf->rk_lcdc_device[0]->screen.height;
+    fb_inf->fb0->var.pixclock =fb_inf->rk_lcdc_device[0]->pixclock;
+    fb_inf->fb0->var.left_margin = fb_inf->rk_lcdc_device[0]->screen.left_margin;
+    fb_inf->fb0->var.right_margin = fb_inf->rk_lcdc_device[0]->screen.right_margin;
+    fb_inf->fb0->var.upper_margin = fb_inf->rk_lcdc_device[0]->screen.upper_margin;
+    fb_inf->fb0->var.lower_margin = fb_inf->rk_lcdc_device[0]->screen.lower_margin;
+    fb_inf->fb0->var.vsync_len = fb_inf->rk_lcdc_device[0]->screen.vsync_len;
+    fb_inf->fb0->var.hsync_len = fb_inf->rk_lcdc_device[0]->screen.hsync_len;
+    fb_inf->fb0->var.red    = def_rgb_16.red;
+    fb_inf->fb0->var.green  = def_rgb_16.green;
+    fb_inf->fb0->var.blue   = def_rgb_16.blue;
+    fb_inf->fb0->var.transp = def_rgb_16.transp;
+
+    fb_inf->fb0->var.nonstd      = 0;  //win1 format & ypos & xpos (ypos<<20 + xpos<<8 + format)
+    fb_inf->fb0->var.grayscale   = 0;  //win1 transprent mode & value(mode<<8 + value)
+    fb_inf->fb0->var.activate    = FB_ACTIVATE_NOW;
+    fb_inf->fb0->var.accel_flags = 0;
+    fb_inf->fb0->var.vmode       = FB_VMODE_NONINTERLACED;
+
+    fb_inf->fb0->fbops           = &fb0_ops;
+    fb_inf->fb0->flags           = FBINFO_FLAG_DEFAULT;
+    fb_inf->fb0->pseudo_palette  = fb_inf->rk_lcdc_device[0]->layer_par[0].pseudo_pal;
+
+
+       /************fb1 set ****************/
+       fb_inf->fb1->fix.type        = FB_TYPE_PACKED_PIXELS;
+    fb_inf->fb1->fix.type_aux    = 0;
+    fb_inf->fb1->fix.xpanstep    = 1;
+    fb_inf->fb1->fix.ypanstep    = 1;
+    fb_inf->fb1->fix.ywrapstep   = 0;
+    fb_inf->fb1->fix.accel       = FB_ACCEL_NONE;
+    fb_inf->fb1->fix.visual      = FB_VISUAL_TRUECOLOR;
+
+    fb_inf->fb1->var.xres = fb_inf->rk_lcdc_device[0]->screen.x_res;
+    fb_inf->fb1->var.yres = fb_inf->rk_lcdc_device[0]->screen.y_res;
+    fb_inf->fb1->var.bits_per_pixel = 16;
+    //fb_inf->fb1_color_deepth = 0;
+    fb_inf->fb1->var.xres_virtual = fb_inf->rk_lcdc_device[0]->screen.x_res;
+    fb_inf->fb1->var.yres_virtual = fb_inf->rk_lcdc_device[0]->screen.y_res;
+    fb_inf->fb1->var.width = fb_inf->rk_lcdc_device[0]->screen.width;
+    fb_inf->fb1->var.height = fb_inf->rk_lcdc_device[0]->screen.height;
+    //fb_inf->fb1->var.pixclock = div_u64(1000000000000llu, screen.pixclock);
+    fb_inf->fb1->var.left_margin = fb_inf->rk_lcdc_device[0]->screen.left_margin;
+    fb_inf->fb1->var.right_margin = fb_inf->rk_lcdc_device[0]->screen.right_margin;
+    fb_inf->fb1->var.upper_margin = fb_inf->rk_lcdc_device[0]->screen.upper_margin;
+    fb_inf->fb1->var.lower_margin = fb_inf->rk_lcdc_device[0]->screen.lower_margin;
+    fb_inf->fb1->var.vsync_len = fb_inf->rk_lcdc_device[0]->screen.vsync_len;
+    fb_inf->fb1->var.hsync_len = fb_inf->rk_lcdc_device[0]->screen.hsync_len;
+    fb_inf->fb1->var.red    = def_rgb_16.red;
+    fb_inf->fb1->var.green  = def_rgb_16.green;
+    fb_inf->fb1->var.blue   = def_rgb_16.blue;
+    fb_inf->fb1->var.transp = def_rgb_16.transp;
+
+    fb_inf->fb1->var.nonstd      = 0;  //win1 format & ypos & xpos (ypos<<20 + xpos<<8 + format)
+    fb_inf->fb1->var.grayscale   = 0;  //win1 transprent mode & value(mode<<8 + value)
+    fb_inf->fb1->var.activate    = FB_ACTIVATE_NOW;
+    fb_inf->fb1->var.accel_flags = 0;
+    fb_inf->fb1->var.vmode       = FB_VMODE_NONINTERLACED;
+
+    fb_inf->fb1->fbops           = &fb1_ops;
+    fb_inf->fb1->flags           = FBINFO_FLAG_DEFAULT;
+    fb_inf->fb1->pseudo_palette  = fb_inf->rk_lcdc_device[0]->layer_par[0].pseudo_pal;
+    fb_inf->fb1->screen_base     = 0;
+
+#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
+    fb0_set_par(fb_inf->fb0);
+    if (fb_prepare_logo(fb_inf->fb0, FB_ROTATE_UR)) {
+        /* Start display and show logo on boot */
+        fb_set_cmap(&fb_inf->fb0->cmap, fb_inf->fb0);
+        fb_show_logo(fb_inf->fb0, FB_ROTATE_UR);
+        fb0_blank(FB_BLANK_UNBLANK, fb_inf->fb0);
+    }
+#endif
+       return 0;
+       
+       
+}
+int rk_fb_unregister(struct rk_fb_device_driver *fb_device_driver)
+{
+
+       struct rk_fb_inf *fb_inf = platform_get_drvdata(g_fb_pdev);
+       int i=0;
+       if(NULL==fb_device_driver){
+               printk("rk_fb_register lcdc register fail");
+               return -ENOENT;
+               }
+       for(i=0;i<RK30_MAX_LCDC_SUPPORT;i++){
+               if(fb_inf->rk_lcdc_device[i]->id == i ){
+               fb_inf->rk_lcdc_device[i] = NULL;
+               fb_inf->num_lcdc--;
+               break;
+               }
+       }
+       if(i==RK30_MAX_LCDC_SUPPORT){
+               printk("rk_fb_unregister lcdc out of support %d",i);
+               return -ENOENT;
+       }
+       
+
+       return 0;
+}
+
+static int __devinit rk_fb_probe (struct platform_device *pdev)
+{
+       struct resource *res = NULL;
+       struct rk_fb_inf *fb_inf        = NULL;
+       int ret = 0;
+       g_fb_pdev=pdev;
+    /* Malloc rk29fb_inf and set it to pdev for drvdata */
+    fb_inf = kmalloc(sizeof(struct rk_fb_inf), GFP_KERNEL);
+    if(!fb_inf)
+    {
+        dev_err(&pdev->dev, ">>fb inf kmalloc fail!");
+        ret = -ENOMEM;
+    }
+    memset(fb_inf, 0, sizeof(struct rk_fb_inf));
+       platform_set_drvdata(pdev, fb_inf);
+       fb_inf->fb0 = framebuffer_alloc(0, &pdev->dev);
+       if(!fb_inf->fb0){
+               dev_err(&pdev->dev,">> fb0 framebuffer_alloc fail!");
+               fb_inf->fb1 = NULL;
+               ret = -ENOMEM;
+       }
+       strcpy(fb_inf->fb0->fix.id, "fb0");
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fb0 buf");
+    if (res == NULL)
+    {
+        dev_err(&pdev->dev, "failed to get win1 memory \n");
+        ret = -ENOENT;
+    }
+    fb_inf->fb0->fix.smem_start = res->start;
+    fb_inf->fb0->fix.smem_len = res->end - res->start + 1;
+    fb_inf->fb0->screen_base = ioremap(res->start, fb_inf->fb0->fix.smem_len);
+    memset(fb_inf->fb0->screen_base, 0, fb_inf->fb0->fix.smem_len);
+       fb_inf->fb1= framebuffer_alloc(0, &pdev->dev);
+       if(!fb_inf->fb1){
+               dev_err(&pdev->dev,">> fb1 framebuffer_alloc fail!");
+               fb_inf->fb1 = NULL;
+               ret = -ENOMEM;
+       }
+       strcpy(fb_inf->fb1->fix.id, "fb1");
+       printk("rk fb probe ok!\n");
+    return 0;
+}
+
+static int __devexit rk_fb_remove(struct platform_device *pdev)
+{
+    return 0;
+}
+
+static void rk_fb_shutdown(struct platform_device *pdev)
+{
+
+}
+
+static struct platform_driver rk_fb_driver = {
+       .probe          = rk_fb_probe,
+       .remove         = __devexit_p(rk_fb_remove),
+       .driver         = {
+               .name   = "rk-fb",
+               .owner  = THIS_MODULE,
+       },
+       .shutdown   = rk_fb_shutdown,
+};
+
+static int __init rk_fb_init(void)
+{
+    return platform_driver_register(&rk_fb_driver);
+}
+
+static void __exit rk_fb_exit(void)
+{
+    platform_driver_unregister(&rk_fb_driver);
+}
+
+fs_initcall(rk_fb_init);
+module_exit(rk_fb_exit);
+
diff --git a/drivers/video/rockchip/rk_fb.h b/drivers/video/rockchip/rk_fb.h
new file mode 100644 (file)
index 0000000..1721f85
--- /dev/null
@@ -0,0 +1,113 @@
+/* drivers/video/rk30_fb.h
+ *
+ * Copyright (C) 2010 ROCKCHIP, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_RK30_FB_H
+#define __ARCH_ARM_MACH_RK30_FB_H
+
+#define RK30_MAX_LCDC_SUPPORT  4
+#define RK30_MAX_LAYER_SUPPORT 4
+
+
+/********************************************************************
+**                            ºê¶¨Òå                                *
+********************************************************************/
+/* ÊäÍùÆÁµÄÊý¾Ý¸ñʽ */
+#define OUT_P888            0
+#define OUT_P666            1    //666µÄÆÁ, ½ÓDATA0-17
+#define OUT_P565            2    //565µÄÆÁ, ½ÓDATA0-15
+#define OUT_S888x           4
+#define OUT_CCIR656         6
+#define OUT_S888            8
+#define OUT_S888DUMY        12
+#define OUT_P16BPP4         24  //Ä£Äⷽʽ,¿ØÖÆÆ÷²¢²»Ö§³Ö
+#define OUT_D888_P666       0x21  //666µÄÆÁ, ½ÓDATA2-7, DATA10-15, DATA18-23
+#define OUT_D888_P565       0x22  //565µÄÆÁ, ½ÓDATA3-7, DATA10-15, DATA19-23
+
+enum data_format{
+       ARGB888 = 0,
+       RGB888,
+       RGB565,
+       YUV422,
+       YUV420,
+       YUV444,
+};
+struct rk_fb_rgb {
+       struct fb_bitfield      red;
+       struct fb_bitfield      green;
+       struct fb_bitfield      blue;
+       struct fb_bitfield      transp;
+};
+
+typedef enum _TRSP_MODE
+{
+    TRSP_CLOSE = 0,
+    TRSP_FMREG,
+    TRSP_FMREGEX,
+    TRSP_FMRAM,
+    TRSP_FMRAMEX,
+    TRSP_MASK,
+    TRSP_INVAL
+} TRSP_MODE;
+
+struct layer_par {
+       u32     pseudo_pal[16];
+    u32 y_offset;
+    u32 c_offset;
+    u32 xpos;         //start point in panel
+    u32 ypos;
+    u16 xsize;        //size of panel
+    u16 ysize;
+       u16 xact;        //act size
+       u16 yact;
+       u16 xres_virtual;
+       u16 yres_virtual;
+       unsigned long smem_start;
+    enum data_format format;
+       
+       bool support_3d;
+       const char *name;
+       int id;
+};
+
+struct rk_fb_device_driver{
+       const char *name;
+       int id;
+       struct device  *dev;
+       
+       struct layer_par *layer_par;
+       int num_layer;
+       rk_screen screen;
+       u32 pixclock;
+       int (*ioctl)(unsigned int cmd, unsigned long arg,struct layer_par *layer_par);
+       int (*suspend)(struct layer_par *layer_par);
+       int (*resume)(struct layer_par *layer_par);
+       int (*blank)(struct rk_fb_device_driver *rk_fb_dev_drv,int layer_id,int blank_mode);
+       int (*set_par)(struct rk_fb_device_driver *rk_fb_dev_drv,int layer_id);
+       int (*pan)(struct rk_fb_device_driver *rk_fb_dev_drv,int layer_id);
+       
+};
+
+struct rk_fb_inf {
+    struct fb_info *fb1;
+    struct fb_info *fb0;
+
+       struct rk_fb_device_driver *rk_lcdc_device[RK30_MAX_LCDC_SUPPORT];
+       
+       int num_lcdc;
+};
+extern int rk_fb_register(struct rk_fb_device_driver *fb_device_driver);
+extern int rk_fb_unregister(struct rk_fb_device_driver *fb_device_driver);
+
+#endif