#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 {
#include "../../../drivers/spi/rk29_spim.h"
#endif
+#define RK30_FB0_MEM_SIZE 8*SZ_1M
+
/*****************************************************************************************
* xpt2046 touch panel
};
#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
};
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();
}
};
#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 = {
#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 */
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"
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
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.
} MCU_STATUS;
+
/* Screen description */
-struct rk29fb_screen {
+typedef struct rk29fb_screen {
/* screen type & out face */
u16 type;
u16 face;
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);
--- /dev/null
+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.
--- /dev/null
+obj-$(CONFIG_FB_ROCKCHIP) += rk_fb.o
+obj-$(CONFIG_LCDC_RK30) += chips/rk30_lcdc.o
--- /dev/null
+
+#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);
+
+
+
--- /dev/null
+#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
+
+
--- /dev/null
+/*
+ * 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);
+
--- /dev/null
+/* 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