rk3036 lcdc: commit driver code, just pass compiling.
authorZheng Yang <zhengyang@rock-chips.com>
Mon, 7 Jul 2014 05:08:04 +0000 (13:08 +0800)
committerZheng Yang <zhengyang@rock-chips.com>
Mon, 7 Jul 2014 05:08:04 +0000 (13:08 +0800)
arch/arm/boot/dts/lcd-box.dtsi [new file with mode: 0755]
arch/arm/boot/dts/rk3036-fpga.dts
arch/arm/boot/dts/rk3036.dtsi
drivers/video/rockchip/lcdc/Kconfig
drivers/video/rockchip/lcdc/Makefile
drivers/video/rockchip/lcdc/rk3036_lcdc.c [new file with mode: 0644]
drivers/video/rockchip/lcdc/rk3036_lcdc.h [new file with mode: 0644]
drivers/video/rockchip/rk_fb.c
drivers/video/rockchip/rkfb_sysfs.c
include/linux/rk_screen.h

diff --git a/arch/arm/boot/dts/lcd-box.dtsi b/arch/arm/boot/dts/lcd-box.dtsi
new file mode 100755 (executable)
index 0000000..8d7710b
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * RockChip. LCD_BOX
+ *
+ */
+
+/ {
+               disp_power_ctr: power_ctr {
+                     /*                        rockchip,debug = <0>;
+                        lcd_en:lcd_en {
+                                rockchip,power_type = <GPIO>;
+                                gpios = <&gpio0 GPIO_B0 GPIO_ACTIVE_HIGH>;
+                                rockchip,delay = <10>;
+                        };
+
+                        bl_en:bl_en {
+                                rockchip,power_type = <GPIO>;
+                                gpios = <&gpio0 GPIO_A2 GPIO_ACTIVE_HIGH>;
+                                rockchip,delay = <10>;
+                        };
+
+                        bl_ctr:bl_ctr {
+                                rockchip,power_type = <GPIO>;
+                                gpios = <&gpio3 GPIO_D6 GPIO_ACTIVE_HIGH>;
+                                rockchip,delay = <10>;
+                        };
+
+                        lcd_rst:lcd_rst {
+                                rockchip,power_type = <REGULATOR>;
+                                rockchip,delay = <5>;
+                        };*/
+
+                };
+
+               disp_timings: display-timings {
+                       native-mode = <&timing0>;
+                       timing0: timing0 {
+                               screen-type = <SCREEN_RGB>;
+                               out-face    = <OUT_P888>;
+                               clock-frequency = <74250000>;
+                               hactive = <1280>;
+                               vactive = <720>;
+                               hback-porch = <220>;
+                               hfront-porch = <110>;
+                               vback-porch = <20>;
+                               vfront-porch = <5>;
+                               hsync-len = <40>;
+                               vsync-len = <5>;
+                               hsync-active = <1>;
+                               vsync-active = <1>;
+                               de-active = <0>;
+                               pixelclk-active = <0>;
+                               swap-rb = <0>;
+                               swap-rg = <0>;
+                               swap-gb = <0>;
+                       };
+                       timing1: timing1 {
+                               screen-type = <SCREEN_RGB>;
+                               out-face    = <OUT_P888>;
+                               clock-frequency = <148500000>;
+                               hactive = <1920>;
+                               vactive = <1080>;
+                               hback-porch = <148>;
+                               hfront-porch = <88>;
+                               vback-porch = <36>;
+                               vfront-porch = <4>;
+                               hsync-len = <44>;
+                               vsync-len = <5>;
+                               hsync-active = <1>;
+                               vsync-active = <1>;
+                               de-active = <0>;
+                               pixelclk-active = <0>;
+                               swap-rb = <0>;
+                               swap-rg = <0>;
+                               swap-gb = <0>;
+                       };
+                       timing2: timing2 {
+                               screen-type = <SCREEN_RGB>;
+                               out-face    = <OUT_P888>;
+                               clock-frequency = <297000000>;
+                               hactive = <3840>;
+                               vactive = <2160>;
+                               hback-porch = <296>;
+                               hfront-porch = <176>;
+                               vback-porch = <72>;
+                               vfront-porch = <8>;
+                               hsync-len = <88>;
+                               vsync-len = <10>;
+                               hsync-active = <1>;
+                               vsync-active = <1>;
+                               de-active = <0>;
+                               pixelclk-active = <0>;
+                               swap-rb = <0>;
+                               swap-rg = <0>;
+                               swap-gb = <0>;
+                       };
+               };
+};
index b78f2805988854cd1c694aac6248fa869abdad2c..c8ae65af314ef998fea12a8b35f05f6480e4945d 100644 (file)
@@ -1,6 +1,7 @@
 /dts-v1/;
 /dts-v1/;
-
+#include <dt-bindings/rkfb/rk_fb.h>
 #include "rk3036.dtsi"
 #include "rk3036.dtsi"
+#include "lcd-box.dtsi"
 
 / {
        compatible = "rockchip,rk3036";
 
 / {
        compatible = "rockchip,rk3036";
index 591da87ea3c6bc3f87ea7517cc55db955614aef4..fcc04c0584a1e7157807a6401fcd87e428b3b379 100755 (executable)
                clocks = <&clk_gates1 6>, <&clk_gates7 3>;
                clock-names = "clk_usbphy1", "hclk_usb1";
        };
                clocks = <&clk_gates1 6>, <&clk_gates7 3>;
                clock-names = "clk_usbphy1", "hclk_usb1";
        };
-         
+       
+       lcdc: lcdc@10118000 {
+               compatible = "rockchip,rk3036-lcdc";
+               reg = <0x10118000 0x4000>;
+               interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+               clocks = <&clk_gates9 6>, <&dclk_lcdc1>, <&clk_gates9 5>;
+               clock-names = "aclk_lcdc", "dclk_lcdc", "hclk_lcdc";
+               rockchip,iommu-enabled = <1>;
+       };
+       
        hdmi: hdmi@20034000 {
                compatible = "rockchip,rk3036-hdmi";
                reg = <0x20034000 0x4000>;
        hdmi: hdmi@20034000 {
                compatible = "rockchip,rk3036-hdmi";
                reg = <0x20034000 0x4000>;
                clock-names = "pclk_hdmi";      
                status = "disabled";
        };
                clock-names = "pclk_hdmi";      
                status = "disabled";
        };
-
+/*
         vpu: vpu_service@10108000 {
                compatible = "vpu_service";
                reg = <0x10108000 0x800>;
         vpu: vpu_service@10108000 {
                compatible = "vpu_service";
                reg = <0x10108000 0x800>;
                clock-names = "aclk_vcodec", "hclk_vcodec", "clk_core", "clk_cabac";
                name = "hevc_service";
                status = "disabled";
                clock-names = "aclk_vcodec", "hclk_vcodec", "clk_core", "clk_cabac";
                name = "hevc_service";
                status = "disabled";
-       
+*/     
        vop_mmu {
                dbgname = "vop";
                compatible = "iommu,vop_mmu";
        vop_mmu {
                dbgname = "vop";
                compatible = "iommu,vop_mmu";
index 04bff9588cb490b328604f320abac8e460bacdcb..6c0d314028a63c922c837315e9c5fce56564b045 100755 (executable)
@@ -31,3 +31,9 @@ config LCDC_RK3288
         depends on DRM_ROCKCHIP || FB_ROCKCHIP 
         help
           Driver for rk3288 lcdc.There are two lcd controllers on rk3288
         depends on DRM_ROCKCHIP || FB_ROCKCHIP 
         help
           Driver for rk3288 lcdc.There are two lcd controllers on rk3288
+
+config LCDC_RK3036
+       bool "rk3036 lcdc support"
+       depends on DRM_ROCKCHIP || FB_ROCKCHIP 
+        help
+          Driver for rk3036 lcdc.
\ No newline at end of file
index c514092848260a73873367f85103d54818f5458b..4c96d38d03285e4dbf0d4b22068e09ee3aab40cb 100644 (file)
@@ -3,3 +3,4 @@ obj-$(CONFIG_LCDC_RK2928) += rk2928_lcdc.o
 obj-$(CONFIG_LCDC_RK3066B) += rk3066b_lcdc.o
 obj-$(CONFIG_LCDC_RK3188) += rk3188_lcdc.o
 obj-$(CONFIG_LCDC_RK3288) += rk3288_lcdc.o
 obj-$(CONFIG_LCDC_RK3066B) += rk3066b_lcdc.o
 obj-$(CONFIG_LCDC_RK3188) += rk3188_lcdc.o
 obj-$(CONFIG_LCDC_RK3288) += rk3288_lcdc.o
+obj-$(CONFIG_LCDC_RK3036) += rk3036_lcdc.o
diff --git a/drivers/video/rockchip/lcdc/rk3036_lcdc.c b/drivers/video/rockchip/lcdc/rk3036_lcdc.c
new file mode 100644 (file)
index 0000000..e78ce2e
--- /dev/null
@@ -0,0 +1,1247 @@
+/*
+ * drivers/video/rockchip/lcdc/rk3036_lcdc.c
+ *
+ * Copyright (C) 2014 ROCKCHIP, Inc.
+ * Author:zhengyang<zhengyang@rock-chips.com>
+ * 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/device.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <asm/div64.h>
+#include <asm/uaccess.h>
+#include <linux/rockchip/cpu.h>
+#include <linux/rockchip/iomap.h>
+#include <linux/rockchip/grf.h>
+#include <linux/rockchip/common.h>
+#include <dt-bindings/clock/rk_system_status.h>
+
+#include "rk3036_lcdc.h"
+
+static int dbg_thresd;
+module_param(dbg_thresd, int, S_IRUGO | S_IWUSR);
+
+#define DBG(level, x...) do {                  \
+       if (unlikely(dbg_thresd >= level))      \
+               printk(KERN_INFO x); } while (0)
+
+static struct rk_lcdc_win lcdc_win[] = {
+       [0] = {
+              .name = "win0",
+              .id = 0,
+              .support_3d = false,
+              },
+       [1] = {
+              .name = "win1",
+              .id = 1,
+              .support_3d = false,
+              },
+       [2] = {
+              .name = "hwc",
+              .id = 2,
+              .support_3d = false,
+              },
+};
+
+static void layer_enable(struct lcdc_device *lcdc_dev, unsigned int win_id, bool open);
+
+static irqreturn_t rk3036_lcdc_isr(int irq, void *dev_id)
+{
+       struct lcdc_device *lcdc_dev =
+           (struct lcdc_device *)dev_id;
+       ktime_t timestamp = ktime_get();
+       u32 int_reg = lcdc_readl(lcdc_dev, INT_STATUS);
+
+       if (int_reg & m_FS_INT_STA) {
+               timestamp = ktime_get();
+               lcdc_msk_reg(lcdc_dev, INT_STATUS, m_FS_INT_CLEAR,
+                            v_FS_INT_CLEAR(1));
+               //if (lcdc_dev->driver.wait_fs) {
+               if (0) {        
+                       spin_lock(&(lcdc_dev->driver.cpl_lock));
+                       complete(&(lcdc_dev->driver.frame_done));
+                       spin_unlock(&(lcdc_dev->driver.cpl_lock));
+               }
+               lcdc_dev->driver.vsync_info.timestamp = timestamp;
+               wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
+
+       } else if (int_reg & m_LF_INT_STA) {
+               lcdc_msk_reg(lcdc_dev, INT_STATUS, m_LF_INT_CLEAR,
+                            v_LF_INT_CLEAR(1));
+       }
+       return IRQ_HANDLED;
+}
+
+static int rk3036_lcdc_clk_enable(struct lcdc_device *lcdc_dev)
+{
+#ifdef CONFIG_RK_FPGA
+       lcdc_dev->clk_on = 1;
+       return 0;
+#endif 
+       if (!lcdc_dev->clk_on) {
+               clk_prepare_enable(lcdc_dev->hclk);
+               clk_prepare_enable(lcdc_dev->dclk);
+               clk_prepare_enable(lcdc_dev->aclk);
+//             clk_prepare_enable(lcdc_dev->pd);
+               spin_lock(&lcdc_dev->reg_lock);
+               lcdc_dev->clk_on = 1;
+               spin_unlock(&lcdc_dev->reg_lock);
+       }
+
+       return 0;
+}
+
+static int rk3036_lcdc_clk_disable(struct lcdc_device *lcdc_dev)
+{
+#ifdef CONFIG_RK_FPGA
+       lcdc_dev->clk_on = 0;
+       return 0;
+#endif 
+       if (lcdc_dev->clk_on) {
+               spin_lock(&lcdc_dev->reg_lock);
+               lcdc_dev->clk_on = 0;
+               spin_unlock(&lcdc_dev->reg_lock);
+               mdelay(25);
+               clk_disable_unprepare(lcdc_dev->dclk);
+               clk_disable_unprepare(lcdc_dev->hclk);
+               clk_disable_unprepare(lcdc_dev->aclk);
+//             clk_disable_unprepare(lcdc_dev->pd);
+       }
+
+       return 0;
+}
+
+static int rk3036_lcdc_enable_irq(struct rk_lcdc_driver *dev_drv)
+{
+       u32 mask, val;
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                       struct lcdc_device, driver);
+       mask = m_FS_INT_CLEAR |m_FS_INT_EN;
+       val = v_FS_INT_CLEAR(1) | v_FS_INT_EN(1);
+       lcdc_msk_reg(lcdc_dev, INT_STATUS, mask, val);
+       return 0;
+}
+
+static int rk3036_lcdc_disable_irq(struct lcdc_device *lcdc_dev)
+{      
+       u32 mask, val;
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               mask = m_FS_INT_CLEAR |m_FS_INT_EN;
+               val = v_FS_INT_CLEAR(0) | v_FS_INT_EN(0);
+               lcdc_msk_reg(lcdc_dev, INT_STATUS, mask, val);
+               spin_unlock(&lcdc_dev->reg_lock);
+       } else {
+               spin_unlock(&lcdc_dev->reg_lock);
+       }
+       mdelay(1);
+       return 0;
+}
+
+static void rk_lcdc_read_reg_defalut_cfg(struct lcdc_device
+                                            *lcdc_dev)
+{
+       int reg = 0;
+       u32 value = 0;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       for (reg = 0; reg < 0xdc; reg += 4) {
+               value = lcdc_readl(lcdc_dev, reg);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+}
+
+/********do basic init*********/
+static int rk3036_lcdc_pre_init(struct rk_lcdc_driver *dev_drv)
+{
+       u32 mask,val;
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                          struct
+                                                          lcdc_device,
+                                                  driver);
+       if (lcdc_dev->pre_init)
+               return 0;
+
+       lcdc_dev->hclk = devm_clk_get(lcdc_dev->dev, "hclk_lcdc");
+       lcdc_dev->aclk = devm_clk_get(lcdc_dev->dev, "aclk_lcdc");
+       lcdc_dev->dclk = devm_clk_get(lcdc_dev->dev, "dclk_lcdc");
+//     lcdc_dev->pd   = devm_clk_get(lcdc_dev->dev, "pd_lcdc");
+       
+       if (/*IS_ERR(lcdc_dev->pd) ||*/ (IS_ERR(lcdc_dev->aclk)) ||
+           (IS_ERR(lcdc_dev->dclk)) || (IS_ERR(lcdc_dev->hclk))) {
+               dev_err(lcdc_dev->dev, "failed to get lcdc%d clk source\n",
+                       lcdc_dev->id);
+       }
+
+       rk_disp_pwr_enable(dev_drv);
+       rk3036_lcdc_clk_enable(lcdc_dev);
+
+       /*backup reg config at uboot*/
+       rk_lcdc_read_reg_defalut_cfg(lcdc_dev);
+
+       mask =  m_AUTO_GATING_EN;
+       val  =  v_AUTO_GATING_EN(0);
+       lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask,val);
+       lcdc_cfg_done(lcdc_dev);
+       if (dev_drv->iommu_enabled) /*disable win0 to workaround iommu pagefault*/
+               layer_enable(lcdc_dev, 0, 0);
+       lcdc_dev->pre_init = true;
+
+       return 0;
+}
+
+static int rk3036_lcdc_alpha_cfg(struct lcdc_device *lcdc_dev)
+{
+       return 0;
+}
+
+static int rk3036_lcdc_reg_update(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       struct rk_lcdc_win *win0 = lcdc_dev->driver.win[0];
+       struct rk_lcdc_win *win1 = lcdc_dev->driver.win[1];
+       int timeout;
+       unsigned long flags;
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
+                            v_LCDC_STANDBY(lcdc_dev->standby));
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL,
+                            m_WIN0_EN | m_WIN1_EN | m_WIN0_RB_SWAP |
+                            m_WIN1_RB_SWAP,
+                            v_WIN0_EN(win0->state) | v_WIN1_EN(win1->state) |
+                            v_WIN0_RB_SWAP(win0->swap_rb) |
+                            v_WIN1_RB_SWAP(win1->swap_rb));
+               lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_YRGB,
+                           v_X_SCL_FACTOR(win0->scale_yrgb_x) |
+                           v_Y_SCL_FACTOR(win0->scale_yrgb_y));
+               lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_CBR,
+                           v_X_SCL_FACTOR(win0->scale_cbcr_x) |
+                           v_Y_SCL_FACTOR(win0->scale_cbcr_y));
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_WIN0_FORMAT, v_WIN0_FORMAT(win0->fmt_cfg));
+               lcdc_writel(lcdc_dev, WIN0_ACT_INFO, v_ACT_WIDTH(win0->area[0].xact) |
+                           v_ACT_HEIGHT(win0->area[0].yact));
+               lcdc_writel(lcdc_dev, WIN0_DSP_ST, v_DSP_STX(win0->area[0].dsp_stx) |
+                           v_DSP_STY(win0->area[0].dsp_sty));
+               lcdc_writel(lcdc_dev, WIN0_DSP_INFO, v_DSP_WIDTH(win0->area[0].xsize) |
+                           v_DSP_HEIGHT(win0->area[0].ysize));
+               lcdc_msk_reg(lcdc_dev, WIN0_VIR, m_YRGB_VIR | m_CBBR_VIR,
+                            v_YRGB_VIR(win0->area[0].y_vir_stride) | v_YRGB_VIR(win0->area[0].uv_vir_stride));
+               lcdc_writel(lcdc_dev, WIN0_YRGB_MST, win0->area[0].y_addr);
+               lcdc_writel(lcdc_dev, WIN0_CBR_MST, win0->area[0].uv_addr);
+               lcdc_writel(lcdc_dev, WIN1_DSP_INFO, v_DSP_WIDTH(win1->area[0].xsize) |
+                           v_DSP_HEIGHT(win1->area[0].ysize));
+               lcdc_writel(lcdc_dev, WIN1_DSP_ST, v_DSP_STX(win1->area[0].dsp_stx) |
+                           v_DSP_STY(win1->area[0].dsp_sty));
+               lcdc_msk_reg(lcdc_dev, WIN1_VIR, m_YRGB_VIR, v_YRGB_VIR(win1->area[0].y_vir_stride));
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_WIN1_FORMAT,
+                            v_WIN1_FORMAT(win1->fmt_cfg));
+               lcdc_writel(lcdc_dev, WIN1_MST, win1->area[0].y_addr);
+               rk3036_lcdc_alpha_cfg(lcdc_dev);
+               lcdc_cfg_done(lcdc_dev);
+
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       //if (dev_drv->wait_fs) {
+       if (0) {
+               spin_lock_irqsave(&dev_drv->cpl_lock, flags);
+               init_completion(&dev_drv->frame_done);
+               spin_unlock_irqrestore(&dev_drv->cpl_lock, flags);
+               timeout = wait_for_completion_timeout(&dev_drv->frame_done,
+                                                     msecs_to_jiffies
+                                                     (dev_drv->cur_screen->ft +
+                                                      5));
+               if (!timeout && (!dev_drv->frame_done.done)) {
+                       dev_warn(lcdc_dev->dev, "wait for new frame start time out!\n");
+                       return -ETIMEDOUT;
+               }
+       }
+       DBG(2, "%s for lcdc%d\n", __func__, lcdc_dev->id);
+       return 0;
+
+}
+
+static void rk3036_lcdc_reg_restore(struct lcdc_device *lcdc_dev)
+{
+       memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0xdc);
+}
+
+static void rk3036_lcdc_mmu_en(struct rk_lcdc_driver *dev_drv)
+{
+       u32 mask,val;
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               mask = m_MMU_EN | m_AXI_MAX_OUTSTANDING_EN | m_AXI_OUTSTANDING_MAX_NUM;;
+               val = v_MMU_EN(1) | v_AXI_OUTSTANDING_MAX_NUM(31) | v_AXI_MAX_OUTSTANDING_EN(1);
+               lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+}
+
+static int rk3036_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv)
+{
+#ifdef CONFIG_RK_FPGA
+       return 0;
+#endif
+       int ret,fps;
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       struct rk_screen *screen = dev_drv->cur_screen;
+
+       ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);
+       if (ret)
+               dev_err(dev_drv->dev, "set lcdc%d dclk failed\n", lcdc_dev->id);
+       lcdc_dev->pixclock =
+                div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
+       lcdc_dev->driver.pixclock = lcdc_dev->pixclock;
+       
+       fps = rk_fb_calc_fps(screen, lcdc_dev->pixclock);
+       screen->ft = 1000 / fps;
+       dev_info(lcdc_dev->dev, "%s: dclk:%lu>>fps:%d ",
+                lcdc_dev->driver.name, clk_get_rate(lcdc_dev->dclk), fps);
+       return 0;
+
+}
+
+static int rk3036_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
+{
+       int ret = -EINVAL;
+       int fps;
+       u16 face = 0;
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                               struct lcdc_device, driver);
+       struct rk_screen *screen = dev_drv->cur_screen;
+       u16 right_margin = screen->mode.right_margin;
+       u16 left_margin = screen->mode.left_margin;
+       u16 lower_margin = screen->mode.lower_margin;
+       u16 upper_margin = screen->mode.upper_margin;
+       u16 x_res = screen->mode.xres;
+       u16 y_res = screen->mode.yres;
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               switch (screen->type) {
+               case SCREEN_HDMI:
+                       mask = m_HDMI_DCLK_EN;
+                       val = v_HDMI_DCLK_EN(1);
+                       if(screen->pixelrepeat) {
+                               mask |= m_CORE_CLK_DIV_EN;
+                               val |= v_CORE_CLK_DIV_EN(1);
+                       }
+                       lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
+                       break;
+               case SCREEN_TVOUT:
+                       mask = m_TVE_DAC_DCLK_EN;
+                       val = v_TVE_DAC_DCLK_EN(1);
+                       if(screen->pixelrepeat) {
+                               mask |= m_CORE_CLK_DIV_EN;
+                               val |= v_CORE_CLK_DIV_EN(1);
+                       }
+                       lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
+                       break;
+               default:
+                       dev_err(lcdc_dev->dev, "un supported interface!\n");
+                       break;
+               }
+
+               mask = m_DSP_OUT_FORMAT | m_HSYNC_POL | m_VSYNC_POL |
+                   m_DEN_POL | m_DCLK_POL;
+               val = v_DSP_OUT_FORMAT(face) | v_HSYNC_POL(screen->pin_hsync) |
+                   v_VSYNC_POL(screen->pin_vsync) | v_DEN_POL(screen->pin_den) |
+                   v_DCLK_POL(screen->pin_dclk);
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
+
+               mask = m_BG_COLOR | m_DSP_BG_SWAP | m_DSP_RB_SWAP |
+                   m_DSP_RG_SWAP | m_DSP_DELTA_SWAP |
+                   m_DSP_DUMMY_SWAP | m_BLANK_EN;
+                   
+               val = v_BG_COLOR(0x000000) | v_DSP_BG_SWAP(screen->swap_gb) |
+                   v_DSP_RB_SWAP(screen->swap_rb) | v_DSP_RG_SWAP(screen->
+                                                                  swap_rg) |
+                   v_DSP_DELTA_SWAP(screen->
+                                    swap_delta) | v_DSP_DUMMY_SWAP(screen->
+                                                                   swap_dumy) |
+                   v_BLANK_EN(0) | v_BLACK_EN(0);
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
+               val =
+                   v_HSYNC(screen->mode.hsync_len) | v_HORPRD(screen->mode.
+                                                              hsync_len +
+                                                              left_margin +
+                                                              x_res +
+                                                              right_margin);
+               lcdc_writel(lcdc_dev, DSP_HTOTAL_HS_END, val);
+               val = v_HAEP(screen->mode.hsync_len + left_margin + x_res) |
+                   v_HASP(screen->mode.hsync_len + left_margin);
+               lcdc_writel(lcdc_dev, DSP_HACT_ST_END, val);
+
+               val =
+                   v_VSYNC(screen->mode.vsync_len) | v_VERPRD(screen->mode.
+                                                              vsync_len +
+                                                              upper_margin +
+                                                              y_res +
+                                                              lower_margin);
+               lcdc_writel(lcdc_dev, DSP_VTOTAL_VS_END, val);
+
+               val = v_VAEP(screen->mode.vsync_len + upper_margin + y_res) |
+                   v_VASP(screen->mode.vsync_len + screen->mode.upper_margin);
+               lcdc_writel(lcdc_dev, DSP_VACT_ST_END, val);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);
+       if (ret)
+               dev_err(dev_drv->dev, "set lcdc%d dclk failed\n", lcdc_dev->id);
+       lcdc_dev->pixclock =
+           div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
+       lcdc_dev->driver.pixclock = lcdc_dev->pixclock;
+
+       fps = rk_fb_calc_fps(screen, lcdc_dev->pixclock);
+       screen->ft = 1000 / fps;
+       dev_info(lcdc_dev->dev, "%s: dclk:%lu>>fps:%d ",
+                lcdc_dev->driver.name, clk_get_rate(lcdc_dev->dclk), fps);
+       if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
+               dev_drv->trsm_ops->enable();
+       if (screen->init)
+               screen->init();
+
+       return 0;
+}
+
+static void layer_enable(struct lcdc_device *lcdc_dev, unsigned int win_id, bool open)
+{
+       spin_lock(&lcdc_dev->reg_lock);
+               if (likely(lcdc_dev->clk_on)) {
+                       if (open) {
+                               if (!lcdc_dev->atv_layer_cnt) {
+                                       dev_info(lcdc_dev->dev, "wakeup from standby!\n");
+                                       lcdc_dev->standby = 0;
+                               }
+                               lcdc_dev->atv_layer_cnt++;
+                       } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
+                               lcdc_dev->atv_layer_cnt--;
+                       }
+                       lcdc_dev->driver.win[win_id]->state = open;
+                       if(win_id == 0)
+                               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_WIN0_EN, v_WIN0_EN(open));
+                       else if(win_id == 1)
+                               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_WIN1_EN, v_WIN1_EN(open));
+                       else
+                               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_HWC_EN, v_HWC_EN(open));
+                       /*if no layer used,disable lcdc*/
+                       if (!lcdc_dev->atv_layer_cnt) {
+                               dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
+                               lcdc_dev->standby = 1;
+                       }
+               }
+               spin_unlock(&lcdc_dev->reg_lock);
+}
+
+static int rk3036_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
+                           bool open)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                       struct lcdc_device, driver);
+
+       /*enable clk,when first layer open */
+       if ((open) && (!lcdc_dev->atv_layer_cnt)) {
+               rk3036_lcdc_pre_init(dev_drv);
+               rk3036_lcdc_clk_enable(lcdc_dev);
+               rk3036_lcdc_reg_restore(lcdc_dev);
+               if (dev_drv->iommu_enabled)
+                       rk3036_lcdc_mmu_en(dev_drv);
+               if ((support_uboot_display()&&(lcdc_dev->prop == PRMRY))) {
+                       rk3036_lcdc_set_dclk(dev_drv);
+                       rk3036_lcdc_enable_irq(dev_drv);
+               } else {
+                       rk3036_load_screen(dev_drv, 1);
+               }
+       }
+       if(win_id < ARRAY_SIZE(lcdc_win)) {
+               layer_enable(lcdc_dev, win_id, open);
+       }
+       else
+               dev_err(lcdc_dev->dev, "invalid win id:%d\n", win_id);
+
+       /*when all layer closed,disable clk */
+       if ((!open) && (!lcdc_dev->atv_layer_cnt)) {
+               rk3036_lcdc_disable_irq(lcdc_dev);
+               rk3036_lcdc_reg_update(dev_drv);
+               rk3036_lcdc_clk_disable(lcdc_dev);
+       }
+       
+       return 0;
+}
+
+static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv,int win_id)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                               struct lcdc_device, driver);
+       struct rk_screen *screen = dev_drv->cur_screen;
+       struct rk_lcdc_win *win = NULL;
+       char fmt[9] = "NULL";
+       
+       if (!screen) {
+               dev_err(dev_drv->dev, "screen is null!\n");
+               return -ENOENT;
+       }
+       
+       if (win_id == 0) {
+               win = dev_drv->win[0];
+       } else if (win_id == 1) {
+               win = dev_drv->win[1];
+       } else {
+               dev_err(dev_drv->dev, "un supported win number:%d\n", win_id);
+               return -EINVAL;
+       }
+       
+       spin_lock(&lcdc_dev->reg_lock);
+       
+       win->area[0].dsp_stx = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len;
+       win->area[0].dsp_sty = win->area[0].ypos + screen->mode.upper_margin + screen->mode.vsync_len;
+       win->scale_yrgb_x = CalScale(win->area[0].xact, win->area[0].xsize);
+       win->scale_yrgb_y = CalScale(win->area[0].yact, win->area[0].ysize);
+       switch (win->format) {
+               case ARGB888:
+                       win->fmt_cfg = VOP_FORMAT_ARGB888;
+                       win->swap_rb = 0;
+                       break;
+               case XBGR888:
+                       win->fmt_cfg = VOP_FORMAT_ARGB888;
+                       win->swap_rb = 1;
+                       break;
+               case ABGR888:
+                       win->fmt_cfg = VOP_FORMAT_ARGB888;
+                       win->swap_rb = 1;
+                       break;
+               case RGB888:
+                       win->fmt_cfg = VOP_FORMAT_RGB888;
+                       win->swap_rb = 0;
+                       break;
+               case RGB565:
+                       win->fmt_cfg = VOP_FORMAT_RGB565;
+                       win->swap_rb = 0;
+                       break;
+               case YUV444:
+                       if(win_id == 0) {
+                               win->fmt_cfg = VOP_FORMAT_YCBCR444;
+                               win->scale_cbcr_x = CalScale(win->area[0].xact, win->area[0].xsize);
+                               win->scale_cbcr_y = CalScale(win->area[0].yact, win->area[0].ysize);
+                               win->swap_rb = 0;
+                       } else {
+                               dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
+                               __func__);
+                       }
+                       break;
+               case YUV422:
+                       if(win_id == 0) {
+                               win->fmt_cfg = VOP_FORMAT_YCBCR422;
+                               win->scale_cbcr_x = CalScale((win->area[0].xact / 2), win->area[0].xsize);
+                               win->scale_cbcr_y = CalScale(win->area[0].yact, win->area[0].ysize);
+                               win->swap_rb = 0;
+                       } else {
+                               dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
+                               __func__);
+                       }
+                       break;
+               case YUV420:
+                       if(win_id == 0) {
+                               win->fmt_cfg = VOP_FORMAT_YCBCR420;
+                               win->scale_cbcr_x = CalScale(win->area[0].xact / 2, win->area[0].xsize);
+                               win->scale_cbcr_y = CalScale(win->area[0].yact / 2, win->area[0].ysize);
+                               win->swap_rb = 0;
+                       }
+                       else {
+                               dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
+                               __func__);
+                       }
+                       break;
+               default:
+                       dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
+                               __func__);
+                       break;
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       
+       if (lcdc_dev->clk_on) {
+               rk3036_lcdc_alpha_cfg(lcdc_dev);
+       }
+       DBG(1, "lcdc%d>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
+               ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id,
+               __func__, get_format_string(win->format, fmt), win->area[0].xact,
+               win->area[0].yact, win->area[0].xsize, win->area[0].ysize, win->area[0].xvir, 
+               win->area[0].yvir, win->area[0].xpos, win->area[0].ypos);
+       return 0;
+}
+
+static int rk3036_lcdc_pan_display(struct rk_lcdc_driver *dev_drv, int win_id)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv, 
+                                               struct lcdc_device, driver);
+       struct rk_lcdc_win *win = NULL;
+       struct rk_screen *screen = dev_drv->cur_screen;
+
+       if (!screen) {
+               dev_err(dev_drv->dev,"screen is null!\n");
+               return -ENOENT;
+       }
+       
+       if (win_id == 0) {
+               win = dev_drv->win[0];
+       } else if(win_id==1) {
+               win = dev_drv->win[1];
+       } else {
+               dev_err(dev_drv->dev,"invalid win number:%d!\n", win_id);
+               return -EINVAL;
+       }
+
+       
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               win->area[0].y_addr = win->area[0].smem_start+win->area[0].y_offset;
+               win->area[0].uv_addr = win->area[0].cbr_start + win->area[0].c_offset;
+               if(win_id == 0) {
+                       lcdc_writel(lcdc_dev, WIN0_YRGB_MST, win->area[0].y_addr); 
+                       lcdc_writel(lcdc_dev, WIN0_CBR_MST, win->area[0].uv_addr);
+               } else
+                       lcdc_writel(lcdc_dev, WIN1_MST, win->area[0].y_addr); 
+               /*lcdc_cfg_done(lcdc_dev);*/
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       DBG(2, "lcdc%d>>%s:y_addr:0x%x>>uv_addr:0x%x>>offset:%d\n",
+           lcdc_dev->id, __func__, win->area[0].y_addr, win->area[0].uv_addr,win->area[0].y_offset);
+        /*this is the first frame of the system ,enable frame start interrupt*/
+       if ((dev_drv->first_frame))  {
+               dev_drv->first_frame = 0;
+               rk3036_lcdc_enable_irq(dev_drv);
+
+       }
+       
+       return 0;
+}
+
+static int rk3036_lcdc_ioctl(struct rk_lcdc_driver *dev_drv, unsigned int cmd,
+                            unsigned long arg, int win_id)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                       struct lcdc_device, driver);
+       u32 panel_size[2];
+       void __user *argp = (void __user *)arg;
+       struct color_key_cfg clr_key_cfg;
+
+       switch (cmd) {
+       case RK_FBIOGET_PANEL_SIZE:
+               panel_size[0] = lcdc_dev->screen->mode.xres;
+               panel_size[1] = lcdc_dev->screen->mode.yres;
+               if (copy_to_user(argp, panel_size, 8))
+                       return -EFAULT;
+               break;
+       case RK_FBIOPUT_COLOR_KEY_CFG:
+               if (copy_from_user(&clr_key_cfg, argp,
+                                  sizeof(struct color_key_cfg)))
+                       return -EFAULT;
+               lcdc_writel(lcdc_dev, WIN0_COLOR_KEY,
+                           clr_key_cfg.win0_color_key_cfg);
+               lcdc_writel(lcdc_dev, WIN1_COLOR_KEY,
+                           clr_key_cfg.win1_color_key_cfg);
+               break;
+
+       default:
+               break;
+       }
+       return 0;
+}
+
+static int rk3036_lcdc_get_win_id(struct rk_lcdc_driver *dev_drv,
+                                 const char *id)
+{
+       int win_id = 0;
+       mutex_lock(&dev_drv->fb_win_id_mutex);
+       if (!strcmp(id, "fb0"))
+               win_id = dev_drv->fb0_win_id;
+       else if (!strcmp(id, "fb1"))
+               win_id = dev_drv->fb1_win_id;
+       else if (!strcmp(id, "fb2"))
+               win_id = dev_drv->fb2_win_id;
+       mutex_unlock(&dev_drv->fb_win_id_mutex);
+
+       return win_id;
+}
+
+static int rk3036_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv, int win_id)
+{
+       return 0;
+}
+
+static int rk3036_lcdc_ovl_mgr(struct rk_lcdc_driver *dev_drv, int swap,
+                              bool set)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       int ovl;
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               if (set) {
+                       lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_WIN0_TOP,
+                                    v_WIN0_TOP(swap));
+                       ovl = swap;
+               } else {
+                       ovl = lcdc_read_bit(lcdc_dev, DSP_CTRL0, m_WIN0_TOP);
+               }
+       } else {
+               ovl = -EPERM;
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       return ovl;
+}
+
+static int rk3036_lcdc_early_suspend(struct rk_lcdc_driver *dev_drv)
+{
+
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                       struct lcdc_device, driver);
+       if (dev_drv->suspend_flag) 
+               return 0;
+       dev_drv->suspend_flag = 1;
+       flush_kthread_worker(&dev_drv->update_regs_worker);
+
+       if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
+               dev_drv->trsm_ops->disable();
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_BLANK_EN,
+                            v_BLANK_EN(1));
+               lcdc_msk_reg(lcdc_dev, INT_STATUS, m_FS_INT_CLEAR,
+                            v_FS_INT_CLEAR(1));
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_OUT_ZERO,
+                            v_DSP_OUT_ZERO(1));
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
+                            v_LCDC_STANDBY(1));
+               lcdc_cfg_done(lcdc_dev);
+               spin_unlock(&lcdc_dev->reg_lock);
+       } else {
+               spin_unlock(&lcdc_dev->reg_lock);
+               return 0;
+       }
+       rk3036_lcdc_clk_disable(lcdc_dev);
+       rk_disp_pwr_disable(dev_drv);
+       return 0;
+}
+
+static int rk3036_lcdc_early_resume(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+
+       if (!dev_drv->suspend_flag)
+               return 0;
+       rk_disp_pwr_enable(dev_drv);
+       dev_drv->suspend_flag = 0;
+
+       if (lcdc_dev->atv_layer_cnt) {
+               rk3036_lcdc_clk_enable(lcdc_dev);
+               rk3036_lcdc_reg_restore(lcdc_dev);
+
+               spin_lock(&lcdc_dev->reg_lock);
+
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_OUT_ZERO,
+                            v_DSP_OUT_ZERO(0));
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
+                            v_LCDC_STANDBY(0));
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_BLANK_EN,
+                            v_BLANK_EN(0));
+               lcdc_cfg_done(lcdc_dev);
+
+               spin_unlock(&lcdc_dev->reg_lock);
+       }
+       
+       if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
+               dev_drv->trsm_ops->enable();
+       return 0;
+}
+
+
+static int rk3036_lcdc_blank(struct rk_lcdc_driver *dev_drv,
+                            int win_id, int blank_mode)
+{
+       switch (blank_mode) {
+       case FB_BLANK_UNBLANK:
+               rk3036_lcdc_early_resume(dev_drv);
+               break;
+       case FB_BLANK_NORMAL:
+               rk3036_lcdc_early_suspend(dev_drv);
+               break;
+       default:
+               rk3036_lcdc_early_suspend(dev_drv);
+               break;
+       }
+       
+       dev_info(dev_drv->dev, "blank mode:%d\n", blank_mode);
+
+       return 0;
+}
+
+static int rk3036_lcdc_cfg_done(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv, 
+                                       struct lcdc_device, driver);
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on)
+               lcdc_cfg_done(lcdc_dev);
+       spin_unlock(&lcdc_dev->reg_lock);
+       return 0;
+}
+
+/*
+       a:[-30~0]:
+           sin_hue = sin(a)*256 +0x100;
+           cos_hue = cos(a)*256;
+       a:[0~30]
+           sin_hue = sin(a)*256;
+           cos_hue = cos(a)*256;
+*/
+static int rk3036_lcdc_get_bcsh_hue(struct rk_lcdc_driver *dev_drv,bcsh_hue_mode mode)
+{
+
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 val;
+                       
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               val = lcdc_readl(lcdc_dev, BCSH_H);
+               switch(mode){
+               case H_SIN:
+                       val &= m_BCSH_SIN_HUE;
+                       break;
+               case H_COS:
+                       val &= m_BCSH_COS_HUE;
+                       val >>= 16;
+                       break;
+               default:
+                       break;
+               }
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       return val;
+}
+
+
+static int rk3036_lcdc_set_bcsh_hue(struct rk_lcdc_driver *dev_drv,int sin_hue, int cos_hue)
+{
+
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               mask = m_BCSH_SIN_HUE | m_BCSH_COS_HUE;
+               val = v_BCSH_SIN_HUE(sin_hue) | v_BCSH_COS_HUE(cos_hue);
+               lcdc_msk_reg(lcdc_dev, BCSH_H, mask, val);
+               lcdc_cfg_done(lcdc_dev);
+       }       
+       spin_unlock(&lcdc_dev->reg_lock);
+       
+       return 0;
+}
+
+static int rk3036_lcdc_set_bcsh_bcs(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode,int value)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 mask, val;
+       
+       spin_lock(&lcdc_dev->reg_lock);
+       if(lcdc_dev->clk_on) {
+               switch (mode) {
+               case BRIGHTNESS:
+               /*from 0 to 255,typical is 128*/
+                       if (value < 0x80)
+                               value += 0x80;
+                       else if (value >= 0x80)
+                               value = value - 0x80;
+                       mask =  m_BCSH_BRIGHTNESS;
+                       val = v_BCSH_BRIGHTNESS(value);
+                       break;
+               case CONTRAST:
+               /*from 0 to 510,typical is 256*/
+                       mask =  m_BCSH_CONTRAST;
+                       val =  v_BCSH_CONTRAST(value);
+                       break;
+               case SAT_CON:
+               /*from 0 to 1015,typical is 256*/
+                       mask = m_BCSH_SAT_CON;
+                       val = v_BCSH_SAT_CON(value);
+                       break;
+               default:
+                       break;
+               }
+               lcdc_msk_reg(lcdc_dev, BCSH_BCS, mask, val);
+               lcdc_cfg_done(lcdc_dev);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       return val;
+}
+
+static int rk3036_lcdc_get_bcsh_bcs(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if(lcdc_dev->clk_on) {
+               val = lcdc_readl(lcdc_dev, BCSH_BCS);
+               switch (mode) {
+               case BRIGHTNESS:
+                       val &= m_BCSH_BRIGHTNESS;
+                       if(val > 0x80)
+                               val -= 0x80;
+                       else
+                               val += 0x80;
+                       break;
+               case CONTRAST:
+                       val &= m_BCSH_CONTRAST;
+                       val >>= 8;
+                       break;
+               case SAT_CON:
+                       val &= m_BCSH_SAT_CON;
+                       val >>= 20;
+                       break;
+               default:
+                       break;
+               }
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       return val;
+}
+
+
+static int rk3036_lcdc_open_bcsh(struct rk_lcdc_driver *dev_drv, bool open)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               if (open) {
+                       lcdc_writel(lcdc_dev,BCSH_COLOR_BAR,0x1);
+                       lcdc_writel(lcdc_dev,BCSH_BCS,0xd0010000);
+                       lcdc_writel(lcdc_dev,BCSH_H,0x01000000);
+               } else {
+                       mask = m_BCSH_EN;
+                       val = v_BCSH_EN(0);
+                       lcdc_msk_reg(lcdc_dev, BCSH_COLOR_BAR, mask, val);
+               }
+               lcdc_cfg_done(lcdc_dev);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       return 0;
+}
+
+static int rk3036_fb_win_remap(struct rk_lcdc_driver *dev_drv,
+                              enum fb_win_map_order order)
+{
+       mutex_lock(&dev_drv->fb_win_id_mutex);
+       if (order == FB_DEFAULT_ORDER)
+               order = FB0_WIN0_FB1_WIN1_FB2_WIN2;
+       dev_drv->fb2_win_id = order / 100;
+       dev_drv->fb1_win_id = (order / 10) % 10;
+       dev_drv->fb0_win_id = order % 10;
+       mutex_unlock(&dev_drv->fb_win_id_mutex);
+
+       return 0;
+}
+
+static int rk3036_lcdc_fps_mgr(struct rk_lcdc_driver *dev_drv, int fps,
+                              bool set)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       struct rk_screen *screen = dev_drv->cur_screen;
+       u64 ft = 0;
+       u32 dotclk;
+       int ret;
+       u32 pixclock;
+       u32 x_total, y_total;
+       if (set) {
+               ft = div_u64(1000000000000llu, fps);
+               x_total =
+                   screen->mode.upper_margin + screen->mode.lower_margin +
+                   screen->mode.yres + screen->mode.vsync_len;
+               y_total =
+                   screen->mode.left_margin + screen->mode.right_margin +
+                   screen->mode.xres + screen->mode.hsync_len;
+               dev_drv->pixclock = div_u64(ft, x_total * y_total);
+               dotclk = div_u64(1000000000000llu, dev_drv->pixclock);
+               ret = clk_set_rate(lcdc_dev->dclk, dotclk);
+       }
+
+       pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
+       dev_drv->pixclock = lcdc_dev->pixclock = pixclock;
+       fps = rk_fb_calc_fps(lcdc_dev->screen, pixclock);
+       screen->ft = 1000 / fps;        /*one frame time in ms */
+
+       if (set)
+               dev_info(dev_drv->dev, "%s:dclk:%lu,fps:%d\n", __func__,
+                        clk_get_rate(lcdc_dev->dclk), fps);
+
+       return fps;
+}
+
+static int rk3036_lcdc_poll_vblank(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 int_reg;
+       int ret;
+
+       if (lcdc_dev->clk_on) {
+               int_reg = lcdc_readl(lcdc_dev, INT_STATUS);
+               if (int_reg & m_LF_INT_STA) {
+                       lcdc_msk_reg(lcdc_dev, INT_STATUS, m_LF_INT_CLEAR,
+                                    v_LF_INT_CLEAR(1));
+                       ret = RK_LF_STATUS_FC;
+               } else
+                       ret = RK_LF_STATUS_FR;
+       } else {
+               ret = RK_LF_STATUS_NC;
+       }
+
+       return ret;
+}
+
+static int rk3036_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,unsigned int *dsp_addr)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+
+       if(lcdc_dev->clk_on){
+               dsp_addr[0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
+               dsp_addr[1] = lcdc_readl(lcdc_dev, WIN1_MST);
+       }
+       return 0;
+}
+
+static ssize_t rk3036_lcdc_get_disp_info(struct rk_lcdc_driver *dev_drv,
+                                        char *buf, int win_id)
+{
+//     struct lcdc_device *lcdc_dev = container_of(dev_drv,
+//                                     struct lcdc_device, driver);
+//     struct rk_screen *screen = dev_drv->cur_screen;
+       struct rk_lcdc_win *win = NULL;
+       char fmt[9] = "NULL";
+       u32     size;
+       
+       if (win_id < ARRAY_SIZE(lcdc_win)) {
+               win = dev_drv->win[win_id];
+       } else {
+               dev_err(dev_drv->dev,"invalid win number:%d!\n", win_id);
+               return 0;
+       }
+       
+       size = snprintf(buf, PAGE_SIZE, "win%d: %s\n", win_id, get_format_string(win->format, fmt));
+       size += snprintf(buf + size, PAGE_SIZE - size, "        xact %d yact %d xvir %d yvir %d\n", 
+               win->area[0].xact, win->area[0].yact, win->area[0].xvir, win->area[0].yvir);
+       size += snprintf(buf + size, PAGE_SIZE - size, "        xpos %d ypos %d xsize %d ysize %d\n", 
+               win->area[0].xpos, win->area[0].ypos, win->area[0].xsize, win->area[0].ysize);
+       size += snprintf(buf + size, PAGE_SIZE - size, "        yaddr 0x%x uvaddr 0x%x\n", 
+               win->area[0].y_addr, win->area[0].uv_addr);
+       return size;
+}
+
+static int rk3036_lcdc_reg_dump(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                               struct lcdc_device,
+                                               driver);
+       int *cbase = (int *)lcdc_dev->regs;
+       int *regsbak = (int *)lcdc_dev->regsbak;
+       int i, j;
+
+       printk("back up reg:\n");
+       for (i = 0; i <= (0x90 >> 4); i++) {
+               for (j = 0; j < 4; j++)
+                       printk("%08x  ", *(regsbak + i * 4 + j));
+               printk("\n");
+       }
+
+       printk("lcdc reg:\n");
+       for (i = 0; i <= (0x90 >> 4); i++) {
+               for (j = 0; j < 4; j++)
+                       printk("%08x  ", readl_relaxed(cbase + i * 4 + j));
+               printk("\n");
+       }
+       return 0;
+}
+
+static struct rk_lcdc_drv_ops lcdc_drv_ops = {
+       .open                   = rk3036_lcdc_open,
+       .load_screen            = rk3036_load_screen,
+       .set_par                = rk3036_lcdc_set_par,
+       .pan_display            = rk3036_lcdc_pan_display,
+       .blank                  = rk3036_lcdc_blank,
+       .ioctl                  = rk3036_lcdc_ioctl,
+       .get_win_state          = rk3036_lcdc_get_win_state,
+       .ovl_mgr                = rk3036_lcdc_ovl_mgr,
+       .get_disp_info          = rk3036_lcdc_get_disp_info,
+       .fps_mgr                = rk3036_lcdc_fps_mgr,
+       .fb_get_win_id          = rk3036_lcdc_get_win_id,
+       .fb_win_remap           = rk3036_fb_win_remap,
+       .poll_vblank            = rk3036_lcdc_poll_vblank,
+       .get_dsp_addr           = rk3036_lcdc_get_dsp_addr,
+       .cfg_done               = rk3036_lcdc_cfg_done,
+       .dump_reg               = rk3036_lcdc_reg_dump,
+       .set_dsp_bcsh_hue       = rk3036_lcdc_set_bcsh_hue,
+       .set_dsp_bcsh_bcs       = rk3036_lcdc_set_bcsh_bcs,
+       .get_dsp_bcsh_hue       = rk3036_lcdc_get_bcsh_hue,
+       .get_dsp_bcsh_bcs       = rk3036_lcdc_get_bcsh_bcs,
+       .open_bcsh              = rk3036_lcdc_open_bcsh,
+};
+
+static int rk3036_lcdc_probe(struct platform_device *pdev)
+{
+       struct lcdc_device *lcdc_dev = NULL;
+       struct rk_lcdc_driver *dev_drv;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       int ret;
+       
+       lcdc_dev = devm_kzalloc(dev,
+                               sizeof(struct lcdc_device), GFP_KERNEL);
+       if (!lcdc_dev) {
+               dev_err(&pdev->dev, "rk3036 lcdc device kmalloc fail!");
+               return -ENOMEM;
+       }
+       platform_set_drvdata(pdev, lcdc_dev);
+       lcdc_dev->dev = dev;
+       
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       lcdc_dev->reg_phy_base = res->start;
+       lcdc_dev->len = resource_size(res);
+       lcdc_dev->regs = devm_ioremap_resource(dev, res);
+       if (IS_ERR(lcdc_dev->regs))
+               return PTR_ERR(lcdc_dev->regs);
+
+       lcdc_dev->regsbak = devm_kzalloc(dev, lcdc_dev->len, GFP_KERNEL);
+       if (IS_ERR(lcdc_dev->regsbak))
+               return PTR_ERR(lcdc_dev->regsbak);
+
+       dev_set_name(lcdc_dev->dev, "lcdc%d", lcdc_dev->id);
+       dev_drv = &lcdc_dev->driver;
+       dev_drv->dev = dev;
+       dev_drv->prop = 0;
+       dev_drv->id = lcdc_dev->id;
+       dev_drv->ops = &lcdc_drv_ops;
+       dev_drv->lcdc_win_num = ARRAY_SIZE(lcdc_win);
+       spin_lock_init(&lcdc_dev->reg_lock);
+       
+       lcdc_dev->irq = platform_get_irq(pdev, 0);
+       if (lcdc_dev->irq < 0) {
+               dev_err(&pdev->dev, "cannot find IRQ for lcdc%d\n",
+                       lcdc_dev->id);
+               return -ENXIO;
+       }
+
+       ret = devm_request_irq(dev, lcdc_dev->irq, rk3036_lcdc_isr,
+                              IRQF_DISABLED, dev_name(dev), lcdc_dev);
+       if (ret) {
+               dev_err(&pdev->dev, "cannot requeset irq %d - err %d\n",
+                       lcdc_dev->irq, ret);
+               return ret;
+       }
+
+       ret = rk_fb_register(dev_drv, lcdc_win, lcdc_dev->id);
+       if (ret < 0) {
+               dev_err(dev, "register fb for lcdc%d failed!\n", lcdc_dev->id);
+               return ret;
+       }
+       lcdc_dev->screen = dev_drv->screen0;
+       
+       dev_info(dev, "lcdc%d probe ok\n", lcdc_dev->id);
+       return 0;
+}
+
+#if defined(CONFIG_PM)
+static int rk3036_lcdc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       return 0;
+}
+
+static int rk3036_lcdc_resume(struct platform_device *pdev)
+{
+       return 0;
+}
+#else
+#define rk3036_lcdc_suspend NULL
+#define rk3036_lcdc_resume  NULL
+#endif
+
+static int rk3036_lcdc_remove(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static void rk3036_lcdc_shutdown(struct platform_device *pdev)
+{
+       
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id rk3036_lcdc_dt_ids[] = {
+       {.compatible = "rockchip,rk3036-lcdc",},
+       {}
+};
+#endif
+
+static struct platform_driver rk3036_lcdc_driver = {
+       .probe = rk3036_lcdc_probe,
+       .remove = rk3036_lcdc_remove,
+       .driver = {
+               .name = "rk3036-lcdc",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(rk3036_lcdc_dt_ids),
+       },
+       .suspend = rk3036_lcdc_suspend,
+       .resume = rk3036_lcdc_resume,
+       .shutdown = rk3036_lcdc_shutdown,
+};
+
+static int __init rk3036_lcdc_module_init(void)
+{
+       return platform_driver_register(&rk3036_lcdc_driver);
+}
+
+static void __exit rk3036_lcdc_module_exit(void)
+{
+       platform_driver_unregister(&rk3036_lcdc_driver);
+}
+
+fs_initcall(rk3036_lcdc_module_init);
+module_exit(rk3036_lcdc_module_exit);
\ No newline at end of file
diff --git a/drivers/video/rockchip/lcdc/rk3036_lcdc.h b/drivers/video/rockchip/lcdc/rk3036_lcdc.h
new file mode 100644 (file)
index 0000000..bb0861a
--- /dev/null
@@ -0,0 +1,546 @@
+#ifndef _RK3036_LCDC_H_
+#define _RK3036_LCDC_H_
+
+#include<linux/rk_fb.h>
+#include<linux/io.h>
+#include<linux/clk.h>
+
+/*******************register definition**********************/
+
+#define SYS_CTRL               (0x00)
+       #define m_WIN0_EN               (1<<0)
+       #define m_WIN1_EN               (1<<1)
+       #define m_HWC_EN                (1<<2)
+       #define m_WIN0_FORMAT           (7<<3)
+       #define m_WIN1_FORMAT           (7<<6)
+       #define m_HWC_LUT_EN            (1<<9)
+       #define m_HWC_SIZE              (1<<10)
+       #define m_WIN0_RB_SWAP          (1<<15)
+       #define m_WIN0_ALPHA_SWAP       (1<<16)
+       #define m_WIN0_Y8_SWAP          (1<<17)
+       #define m_WIN0_UV_SWAP          (1<<18)
+       #define m_WIN1_RB_SWAP          (1<<19)
+       #define m_WIN1_ALPHA_SWAP       (1<<20)
+       #define m_WIN0_OTSD_DISABLE     (1<<22)
+       #define m_WIN1_OTSD_DISABLE     (1<<23)
+       #define m_DMA_BURST_LENGTH      (3<<24)
+       #define m_HWC_LODAD_EN          (1<<26)
+       #define m_DMA_STOP              (1<<29)
+       #define m_LCDC_STANDBY          (1<<30)
+       #define m_AUTO_GATING_EN        (1<<31)
+       
+       #define v_WIN0_EN(x)            (((x)&1)<<0)
+       #define v_WIN1_EN(x)            (((x)&1)<<1)
+       #define v_HWC_EN(x)             (((x)&1)<<2)
+       #define v_WIN0_FORMAT(x)        (((x)&7)<<3)
+       #define v_WIN1_FORMAT(x)        (((x)&7)<<6)
+       #define v_HWC_LUT_EN(x)         (((x)&1)<<9)
+       #define v_HWC_SIZE(x)           (((x)&1)<<10)
+       #define v_WIN0_RB_SWAP(x)       (((x)&1)<<15)
+       #define v_WIN0_ALPHA_SWAP(x)    (((x)&1)<<16)
+       #define v_WIN0_Y8_SWAP(x)       (((x)&1)<<17)
+       #define v_WIN0_UV_SWAP(x)       (((x)&1)<<18)
+       #define v_WIN1_RB_SWAP(x)       (((x)&1)<<19)
+       #define v_WIN1_ALPHA_SWAP(x)    (((x)&1)<<20)
+       #define v_WIN0_OTSD_DISABLE(x)  (((x)&1)<<22)
+       #define v_WIN1_OTSD_DISABLE(x)  (((x)&1)<<23)
+       #define v_DMA_BURST_LENGTH(x)   (((x)&3)<<24)
+       #define v_HWC_LODAD_EN(x)       (((x)&1)<<26)
+       #define v_WIN1_LUT_EN(x)        (((x)&1)<<27)
+       #define v_DMA_STOP(x)           (((x)&1)<<29)
+       #define v_LCDC_STANDBY(x)       (((x)&1)<<30)
+       #define v_AUTO_GATING_EN(x)     (((x)&1)<<31)
+
+#define DSP_CTRL0              (0x04)
+       #define m_DSP_OUT_FORMAT        (0x0f<<0)
+       #define m_HSYNC_POL             (1<<4)
+       #define m_VSYNC_POL             (1<<5)
+       #define m_DEN_POL               (1<<6)
+       #define m_DCLK_POL              (1<<7)
+       #define m_WIN0_TOP              (1<<8)
+       #define m_DITHER_UP_EN          (1<<9)
+       #define m_INTERLACE_DSP_EN      (1<<12)
+       #define m_WIN1_INTERLACE_EN     (1<<15)
+       #define m_WIN0_YRGB_DEFLICK_EN  (1<<16)
+       #define m_WIN0_CBR_DEFLICK_EN   (1<<17)
+       #define m_WIN0_ALPHA_MODE       (1<<18)
+       #define m_WIN1_ALPHA_MODE       (1<<19)
+       #define m_WIN0_CSC_MODE         (3<<20)
+       #define m_WIN0_YUV_CLIP         (1<<23)
+       #define m_TVE_MODE              (1<<25)
+       #define m_HWC_ALPHA_MODE        (1<<28)
+       #define m_PREMUL_ALPHA_ENABLE   (1<<29)
+       #define m_ALPHA_MODE_SEL1       (1<<30)
+       #define m_WIN1_DIFF_DCLK_EN     (1<<31)
+       
+       #define v_DSP_OUT_FORMAT(x)     (((x)&0x0f)<<0)
+       #define v_HSYNC_POL(x)          (((x)&1)<<4)
+       #define v_VSYNC_POL(x)          (((x)&1)<<5)
+       #define v_DEN_POL(x)            (((x)&1)<<6)
+       #define v_DCLK_POL(x)           (((x)&1)<<7)
+       #define v_WIN0_TOP(x)           (((x)&1)<<8)
+       #define v_DITHER_UP_EN(x)       (((x)&1)<<9)
+       #define v_INTERLACE_DSP_EN(x)   (((x)&1)<<12)
+       #define v_WIN1_INTERLACE_EN(x)  (((x)&1)<<15)
+       #define v_WIN0_YRGB_DEFLICK_EN(x)       (((x)&1)<<16)
+       #define v_WIN0_CBR_DEFLICK_EN(x)        (((x)&1)<<17)
+       #define v_WIN0_ALPHA_MODE(x)            (((x)&1)<<18)
+       #define v_WIN1_ALPHA_MODE(x)            (((x)&1)<<19)
+       #define v_WIN0_CSC_MODE(x)              (((x)&3)<<20)
+       #define v_WIN0_YUV_CLIP(x)              (((x)&1)<<23)
+       #define v_TVE_MODE(x)                   (((x)&1)<<25)
+       #define v_HWC_ALPHA_MODE(x)             (((x)&1)<<28)
+       #define v_PREMUL_ALPHA_ENABLE(x)        (((x)&1)<<29)
+       #define v_ALPHA_MODE_SEL1(x)            (((x)&1)<<30)
+       #define v_WIN1_DIFF_DCLK_EN(x)          (((x)&1)<<31)
+
+#define DSP_CTRL1              (0x08)
+       #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_EN              (1<<24)
+       #define m_BLACK_EN              (1<<25)
+       #define m_DSP_BG_SWAP           (1<<26)
+       #define m_DSP_RB_SWAP           (1<<27)
+       #define m_DSP_RG_SWAP           (1<<28)
+       #define m_DSP_DELTA_SWAP        (1<<29)
+       #define m_DSP_DUMMY_SWAP        (1<<30)
+       #define m_DSP_OUT_ZERO          (1<<31)
+       
+       #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_EN(x)           (((x)&1)<<24)
+       #define v_BLACK_EN(x)           (((x)&1)<<25)
+       #define v_DSP_BG_SWAP(x)        (((x)&1)<<26)
+       #define v_DSP_RB_SWAP(x)        (((x)&1)<<27)
+       #define v_DSP_RG_SWAP(x)        (((x)&1)<<28)
+       #define v_DSP_DELTA_SWAP(x)     (((x)&1)<<29)
+       #define v_DSP_DUMMY_SWAP(x)     (((x)&1)<<30)
+       #define v_DSP_OUT_ZERO(x)       (((x)&1)<<31)
+
+#define INT_STATUS             (0x10)
+       #define m_HS_INT_STA            (1<<0)  //status
+       #define m_FS_INT_STA            (1<<1)
+       #define m_LF_INT_STA            (1<<2)
+       #define m_BUS_ERR_INT_STA       (1<<3)
+       #define m_HS_INT_EN             (1<<4)  //enable
+       #define m_FS_INT_EN             (1<<5)
+       #define m_LF_INT_EN             (1<<6)
+       #define m_BUS_ERR_INT_EN        (1<<7)
+       #define m_HS_INT_CLEAR          (1<<8) //auto clear
+       #define m_FS_INT_CLEAR          (1<<9)
+       #define m_LF_INT_CLEAR          (1<<10)
+       #define m_BUS_ERR_INT_CLEAR     (1<<11)
+       #define m_LF_INT_NUM            (0xfff<<12)
+       #define m_WIN0_EMPTY_INT_EN     (1<<24)
+       #define m_WIN1_EMPTY_INT_EN     (1<<25)
+       #define m_WIN0_EMPTY_INT_CLEAR  (1<<26)
+       #define m_WIN1_EMPTY_INT_CLEAR  (1<<27)
+       #define m_WIN0_EMPTY_INT_STA    (1<<28)
+       #define m_WIN1_EMPTY_INT_STA    (1<<29)
+       #define m_FS_RAW_STA            (1<<30)
+       #define m_LF_RAW_STA            (1<<31)
+       
+       #define v_HS_INT_EN(x)                  (((x)&1)<<4)
+       #define v_FS_INT_EN(x)                  (((x)&1)<<5)
+       #define v_LF_INT_EN(x)                  (((x)&1)<<6)
+       #define v_BUS_ERR_INT_EN(x)             (((x)&1)<<7)
+       #define v_HS_INT_CLEAR(x)               (((x)&1)<<8)
+       #define v_FS_INT_CLEAR(x)               (((x)&1)<<9)
+       #define v_LF_INT_CLEAR(x)               (((x)&1)<<10)
+       #define v_BUS_ERR_INT_CLEAR(x)          (((x)&1)<<11)
+       #define v_LF_INT_NUM(x)                 (((x)&0xfff)<<12)
+       #define v_WIN0_EMPTY_INT_EN(x)          (((x)&1)<<24)
+       #define v_WIN1_EMPTY_INT_EN(x)          (((x)&1)<<25)
+       #define v_WIN0_EMPTY_INT_CLEAR(x)       (((x)&1)<<26)
+       #define v_WIN1_EMPTY_INT_CLEAR(x)       (((x)&1)<<27)
+
+
+#define ALPHA_CTRL             (0x14)
+       #define m_WIN0_ALPHA_EN         (1<<0)
+       #define m_WIN1_ALPHA_EN         (1<<1)
+       #define m_HWC_ALPAH_EN          (1<<2)
+       #define m_WIN1_PREMUL_SCALE     (1<<3)
+       #define m_WIN0_ALPHA_VAL        (0xff<<4)
+       #define m_WIN1_ALPHA_VAL        (0xff<<12)
+       #define m_HWC_ALPAH_VAL         (0x0f<<20)
+       
+       #define v_WIN0_ALPHA_EN(x)      (((x)&1)<<0)
+       #define v_WIN1_ALPHA_EN(x)      (((x)&1)<<1)
+       #define v_HWC_ALPAH_EN(x)       (((x)&1)<<2)
+       #define v_WIN1_PREMUL_SCALE(x)  (((x)&1)<<3)
+       #define v_WIN0_ALPHA_VAL(x)     (((x)&0xff)<<4)
+       #define v_WIN1_ALPHA_VAL(x)     (((x)&0xff)<<12)
+       #define v_HWC_ALPAH_VAL(x)      (((x)&0x0f)<<20)
+
+#define WIN0_COLOR_KEY         (0x18)
+#define WIN1_COLOR_KEY         (0x1C)
+       #define m_COLOR_KEY_VAL         (0xffffff<<0)
+       #define m_COLOR_KEY_EN          (1<<24)
+       #define v_COLOR_KEY_VAL(x)      (((x)&0xffffff)<<0)
+       #define v_COLOR_KEY_EN(x)       (((x)&1)<<24)
+
+/* Layer Registers */
+#define WIN0_YRGB_MST          (0x20)
+#define WIN0_CBR_MST           (0x24)
+#define WIN1_MST               (0xa0)
+#define HWC_MST                        (0x58)
+
+#define WIN1_VIR               (0x28)
+#define WIN0_VIR               (0x30)
+       #define m_YRGB_VIR      (0x1fff << 0)
+       #define m_CBBR_VIR      (0x1fff << 16)
+       
+       #define v_YRGB_VIR(x)   ((x & 0x1fff) << 0)
+       #define v_CBBR_VIR(x)   ((x & 0x1fff) << 16)
+       
+       #define v_ARGB888_VIRWIDTH(x)   (((x)&0x1fff)<<0)
+       #define v_RGB888_VIRWIDTH(x)    (((((x*3)>>2)+((x)%3))&0x1fff)<<0)
+       #define v_RGB565_VIRWIDTH(x)    ((DIV_ROUND_UP(x,2)&0x1fff)<<0)
+       #define v_YUV_VIRWIDTH(x)       ((DIV_ROUND_UP(x,4)&0x1fff)<<0)
+       #define v_CBCR_VIR(x)           ((x & 0x1fff) << 16)
+
+#define WIN0_ACT_INFO          (0x34)
+#define WIN1_ACT_INFO          (0xB4)
+       #define m_ACT_WIDTH             (0x1fff<<0)
+       #define m_ACT_HEIGHT            (0x1fff<<16)
+       #define v_ACT_WIDTH(x)          (((x-1)&0x1fff)<<0)
+       #define v_ACT_HEIGHT(x)         (((x-1)&0x1fff)<<16)
+
+#define WIN0_DSP_INFO          (0x38)
+#define WIN1_DSP_INFO          (0xB8)
+       #define v_DSP_WIDTH(x)          (((x-1)&0x7ff)<<0)
+       #define v_DSP_HEIGHT(x)         (((x-1)&0x7ff)<<16)
+       
+#define WIN0_DSP_ST            (0x3C)
+#define WIN1_DSP_ST            (0xBC)
+#define HWC_DSP_ST             (0x5C)
+       #define v_DSP_STX(x)            (((x)&0xfff)<<0)
+       #define v_DSP_STY(x)            (((x)&0xfff)<<16)
+       
+#define WIN0_SCL_FACTOR_YRGB   (0x40)
+#define WIN0_SCL_FACTOR_CBR    (0x44)
+#define WIN1_SCL_FACTOR_YRGB   (0xC0)
+       #define v_X_SCL_FACTOR(x)       (((x)&0xffff)<<0)
+       #define v_Y_SCL_FACTOR(x)       (((x)&0xffff)<<16)
+       
+#define WIN0_SCL_OFFSET                (0x48)
+#define WIN1_SCL_OFFSET                (0xC8)
+
+/* LUT Registers */
+#define WIN1_LUT_ADDR                  (0x0400)
+#define HWC_LUT_ADDR                           (0x0800)
+
+/* Display Infomation Registers */
+#define DSP_HTOTAL_HS_END      (0x6C)
+       #define v_HSYNC(x)              (((x)&0xfff)<<0)   //hsync pulse width
+       #define v_HORPRD(x)             (((x)&0xfff)<<16)   //horizontal period
+
+#define DSP_HACT_ST_END                (0x70)
+       #define v_HAEP(x)               (((x)&0xfff)<<0)  //horizontal active end point
+       #define v_HASP(x)               (((x)&0xfff)<<16) //horizontal active start point
+
+#define DSP_VTOTAL_VS_END      (0x74)
+       #define v_VSYNC(x)              (((x)&0xfff)<<0)
+       #define v_VERPRD(x)             (((x)&0xfff)<<16)
+       
+#define DSP_VACT_ST_END                (0x78)
+       #define v_VAEP(x)               (((x)&0xfff)<<0)
+       #define v_VASP(x)               (((x)&0xfff)<<16)
+
+#define DSP_VS_ST_END_F1       (0x7C)
+#define DSP_VACT_ST_END_F1     (0x80)
+
+/*BCSH Registers*/
+#define BCSH_COLOR_BAR                         (0xD0)
+       #define v_BCSH_EN(x)                    (((x)&1)<<0)
+       #define v_BCSH_COLOR_BAR_Y(x)           (((x)&0x3ff)<<2)
+       #define v_BCSH_COLOR_BAR_U(x)           (((x)&0x3ff)<<12)
+       #define v_BCSH_COLOR_BAR_V(x)           (((x)&0x3ff)<<22)
+
+       #define m_BCSH_EN                       (1<<0)
+       #define m_BCSH_COLOR_BAR_Y              (0x3ff<<2)
+       #define m_BCSH_COLOR_BAR_U              (0x3ff<<12)
+       #define m_BCSH_COLOR_BAR_V              ((u32)0x3ff<<22)
+
+#define BCSH_BCS                       (0xD4)
+       #define v_BCSH_BRIGHTNESS(x)            (((x)&0xff)<<0) 
+       #define v_BCSH_CONTRAST(x)              (((x)&0x1ff)<<8)        
+       #define v_BCSH_SAT_CON(x)               (((x)&0x3ff)<<20)       
+       #define v_BCSH_OUT_MODE(x)              (((x)&0x3)<<30) 
+       
+       #define m_BCSH_BRIGHTNESS               (0xff<<0)       
+       #define m_BCSH_CONTRAST                 (0x1ff<<8)
+       #define m_BCSH_SAT_CON                  (0x3ff<<20)     
+       #define m_BCSH_OUT_MODE                 ((u32)0x3<<30)  
+
+
+#define BCSH_H                                 (0xD8)
+       #define v_BCSH_SIN_HUE(x)               (((x)&0x1ff)<<0)
+       #define v_BCSH_COS_HUE(x)               (((x)&0x1ff)<<16)
+       
+       #define m_BCSH_SIN_HUE                  (0x1ff<<0)
+       #define m_BCSH_COS_HUE                  (0x1ff<<16)
+
+/* Bus Register */
+#define AXI_BUS_CTRL           (0x2C)
+       #define m_IO_PAD_CLK                    (1 << 31)
+       #define m_CORE_CLK_DIV_EN               (1 << 30)
+       #define m_HDMI_DCLK_INVERT              (1 << 23)
+       #define m_HDMI_DCLK_EN                  (1 << 22)
+       #define m_TVE_DAC_DCLK_INVERT           (1 << 21)
+       #define m_TVE_DAC_DCLK_EN               (1 << 20)
+       #define m_HDMI_DCLK_DIV_EN              (1 << 19)
+       #define m_AXI_OUTSTANDING_MAX_NUM       (0x1f << 12)
+       #define m_AXI_MAX_OUTSTANDING_EN        (1 << 11)
+       #define m_MMU_EN                        (1 << 10)
+       #define m_NOC_HURRY_THRESHOLD           (0xf << 6)
+       #define m_NOC_HURRY_VALUE               (3 << 4)
+       #define m_NOC_HURRY_EN                  (1 << 3)
+       #define m_NOC_QOS_VALUE                 (3 << 1)
+       #define m_NOC_QOS_EN                    (1 << 0)
+       
+       #define v_IO_PAD_CLK(x)                 ((x&1) << 31)
+       #define v_CORE_CLK_DIV_EN(x)            ((x&1) << 30)
+       #define v_HDMI_DCLK_INVERT(x)           ((x&1) << 23)
+       #define v_HDMI_DCLK_EN(x)               ((x&1) << 22)
+       #define v_TVE_DAC_DCLK_INVERT(x)        ((x&1) << 21)
+       #define v_TVE_DAC_DCLK_EN(x)            ((x&1) << 20)
+       #define v_HDMI_DCLK_DIV_EN(x)           ((x&1) << 19)
+       #define v_AXI_OUTSTANDING_MAX_NUM(x)    ((x&0x1f) << 12)
+       #define v_AXI_MAX_OUTSTANDING_EN(x)     ((x&1) << 11)
+       #define v_MMU_EN(x)                     ((x&1) << 10)
+       #define v_NOC_HURRY_THRESHOLD(x)        ((x&0xf) << 6)
+       #define v_NOC_HURRY_VALUE(x)            ((x&3) << 4)
+       #define v_NOC_HURRY_EN(x)               ((x&1) << 3)
+       #define v_NOC_QOS_VALUE(x)              ((x&3) << 1)
+       #define v_NOC_QOS_EN(x)                 ((x&1) << 0)
+       
+#define GATHER_TRANSFER                (0x84)
+       #define m_WIN1_AXI_GATHER_NUM           (0xf << 12)
+       #define m_WIN0_CBCR_AXI_GATHER_NUM      (0x7 << 8)
+       #define m_WIN0_YRGB_AXI_GATHER_NUM      (0xf << 4)
+       #define m_WIN1_AXI_GAHTER_EN            (1 << 2)
+       #define m_WIN0_CBCR_AXI_GATHER_EN       (1 << 1)
+       #define m_WIN0_YRGB_AXI_GATHER_EN       (1 << 0)
+       
+       #define v_WIN1_AXI_GATHER_NUM(x)        ((x & 0xf) << 12)
+       #define v_WIN0_CBCR_AXI_GATHER_NUM(x)   ((x & 0x7) << 8)
+       #define v_WIN0_YRGB_AXI_GATHER_NUM(x)   ((x & 0xf) << 4)
+       #define v_WIN1_AXI_GAHTER_EN(x)         ((x & 1) << 2)
+       #define v_WIN0_CBCR_AXI_GATHER_EN(x)    ((x & 1) << 1)
+       #define v_WIN0_YRGB_AXI_GATHER_EN(x)    ((x & 1) << 0)
+       
+#define VERSION_INFO           (0x94)
+       #define m_MAJOR         (0xff << 24)
+       #define m_MINOR         (0xff << 16)
+       #define m_BUILD         (0xffff)
+               
+#define REG_CFG_DONE           (0x90)
+
+/* TV Control Registers */
+#define TV_CTRL                        (0x200)
+#define TV_SYNC_TIMING         (0x204)
+#define TV_ACT_TIMING          (0x208)
+#define TV_ADJ_TIMING          (0x20c)
+#define TV_FREQ_SC             (0x210)
+#define TV_FILTER0             (0x214)
+#define TV_FILTER1             (0x218)
+#define TV_FILTER2             (0x21C)
+#define TV_ACT_ST              (0x234)
+#define TV_ROUTING             (0x238)
+#define TV_SYNC_ADJUST         (0x250)
+#define TV_STATUS              (0x254)
+#define TV_RESET               (0x268)
+#define TV_SATURATION          (0x278)
+#define TV_BW_CTRL             (0x28C)
+#define TV_BRIGHTNESS_CONTRAST (0x290)
+
+
+/* MMU registers */
+#define MMU_DTE_ADDR                   (0x0300)
+       #define v_MMU_DTE_ADDR(x)               (((x)&0xffffffff)<<0)
+       #define m_MMU_DTE_ADDR                  (0xffffffff<<0)
+
+#define MMU_STATUS                     (0x0304)
+       #define v_PAGING_ENABLED(x)             (((x)&1)<<0)
+       #define v_PAGE_FAULT_ACTIVE(x)          (((x)&1)<<1)
+       #define v_STAIL_ACTIVE(x)               (((x)&1)<<2)
+       #define v_MMU_IDLE(x)                   (((x)&1)<<3)
+       #define v_REPLAY_BUFFER_EMPTY(x)        (((x)&1)<<4)
+       #define v_PAGE_FAULT_IS_WRITE(x)        (((x)&1)<<5)
+       #define v_PAGE_FAULT_BUS_ID(x)          (((x)&0x1f)<<6)
+       #define m_PAGING_ENABLED                (1<<0)
+       #define m_PAGE_FAULT_ACTIVE             (1<<1)
+       #define m_STAIL_ACTIVE                  (1<<2)
+       #define m_MMU_IDLE                      (1<<3)
+       #define m_REPLAY_BUFFER_EMPTY           (1<<4)
+       #define m_PAGE_FAULT_IS_WRITE           (1<<5)
+       #define m_PAGE_FAULT_BUS_ID             (0x1f<<6)
+
+#define MMU_COMMAND                    (0x0308)
+       #define v_MMU_CMD(x)                    (((x)&0x3)<<0)
+       #define m_MMU_CMD                       (0x3<<0)
+
+#define MMU_PAGE_FAULT_ADDR            (0x030c)
+       #define v_PAGE_FAULT_ADDR(x)            (((x)&0xffffffff)<<0)
+       #define m_PAGE_FAULT_ADDR               (0xffffffff<<0)
+
+#define MMU_ZAP_ONE_LINE               (0x0310)
+       #define v_MMU_ZAP_ONE_LINE(x)           (((x)&0xffffffff)<<0)
+       #define m_MMU_ZAP_ONE_LINE              (0xffffffff<<0)
+
+#define MMU_INT_RAWSTAT                        (0x0314)
+       #define v_PAGE_FAULT_RAWSTAT(x)         (((x)&1)<<0)
+       #define v_READ_BUS_ERROR_RAWSTAT(x)     (((x)&1)<<1)
+       #define m_PAGE_FAULT_RAWSTAT            (1<<0)
+       #define m_READ_BUS_ERROR_RAWSTAT        (1<<1)
+
+#define MMU_INT_CLEAR                  (0x0318)
+       #define v_PAGE_FAULT_CLEAR(x)           (((x)&1)<<0)
+       #define v_READ_BUS_ERROR_CLEAR(x)       (((x)&1)<<1)
+       #define m_PAGE_FAULT_CLEAR              (1<<0)
+       #define m_READ_BUS_ERROR_CLEAR          (1<<1)
+
+#define MMU_INT_MASK                   (0x031c)
+       #define v_PAGE_FAULT_MASK(x)            (((x)&1)<<0)
+       #define v_READ_BUS_ERROR_MASK(x)        (((x)&1)<<1)
+       #define m_PAGE_FAULT_MASK               (1<<0)
+       #define m_READ_BUS_ERROR_MASK           (1<<1)
+
+#define MMU_INT_STATUS                 (0x0320)
+       #define v_PAGE_FAULT_STATUS(x)          (((x)&1)<<0)
+       #define v_READ_BUS_ERROR_STATUS(x)      (((x)&1)<<1)
+       #define m_PAGE_FAULT_STATUS             (1<<0)
+       #define m_READ_BUS_ERROR_STATUS         (1<<1)
+
+#define MMU_AUTO_GATING                        (0x0324)
+       #define v_MMU_AUTO_GATING(x)            (((x)&1)<<0)
+       #define m_MMU_AUTO_GATING               (1<<0)
+
+enum _vop_dma_burst {
+       DMA_BURST_16 = 0,
+       DMA_BURST_8,
+       DMA_BURST_4
+};
+
+enum _vop_format_e {
+       VOP_FORMAT_ARGB888 = 0,
+       VOP_FORMAT_RGB888,
+       VOP_FORMAT_RGB565,
+       VOP_FORMAT_YCBCR420,
+       VOP_FORMAT_YCBCR422,
+       VOP_FORMAT_YCBCR444
+};
+
+enum _vop_tv_mode {
+       TV_NTSC,
+       TV_PAL,
+};
+
+enum _vop_csc_mode {
+       VOP_CSC_BT601 = 0,
+       VOP_CSC_JPEG,
+       VOP_CSC_BT709
+};
+
+enum _vop_hwc_size {
+       VOP_HWC_SIZE_32,
+       VOP_HWC_SIZE_64
+};
+
+#define CalScale(x, y)              ((((u32)(x-1))*0x1000)/(y-1))
+
+struct lcdc_device{
+       int id;
+       struct rk_lcdc_driver driver;
+       struct device *dev;
+       struct rk_screen *screen;
+
+       void __iomem *regs;
+       void *regsbak;                  /*back up reg*/
+       u32 reg_phy_base;               /* physical basic address of lcdc register*/
+       u32 len;                        /* physical map length of lcdc register*/
+       spinlock_t  reg_lock;           /*one time only one process allowed to config the register*/
+       
+       int __iomem *dsp_lut_addr_base;
+
+
+       int prop;                       /*used for primary or extended display device*/
+       bool pre_init;
+       bool pwr18;                     /*if lcdc use 1.8v power supply*/
+       bool clk_on;                    /*if aclk or hclk is closed ,acess to register is not allowed*/
+       u8 atv_layer_cnt;               /*active layer counter,when  atv_layer_cnt = 0,disable lcdc*/
+       
+
+       unsigned int            irq;
+
+       struct clk              *pd;                            /*lcdc power domain*/
+       struct clk              *hclk;                          /*lcdc AHP clk*/
+       struct clk              *dclk;                          /*lcdc dclk*/
+       struct clk              *aclk;                          /*lcdc share memory frequency*/
+       u32 pixclock;   
+
+       u32 standby;                                            /*1:standby,0:wrok*/
+};
+
+static inline void lcdc_writel(struct lcdc_device *lcdc_dev,u32 offset,u32 v)
+{
+       u32 *_pv = (u32*)lcdc_dev->regsbak;     
+       _pv += (offset >> 2);   
+       *_pv = v;
+       writel_relaxed(v,lcdc_dev->regs+offset);        
+}
+
+static inline u32 lcdc_readl(struct lcdc_device *lcdc_dev,u32 offset)
+{
+       u32 v;
+       u32 *_pv = (u32*)lcdc_dev->regsbak;
+       _pv += (offset >> 2);
+       v = readl_relaxed(lcdc_dev->regs+offset);
+       *_pv = v;
+       return v;
+}
+
+static inline u32 lcdc_read_bit(struct lcdc_device *lcdc_dev,u32 offset,u32 msk) 
+{
+       u32 _v = readl_relaxed(lcdc_dev->regs+offset); 
+       _v &= msk;
+       return (_v?1:0);   
+}
+
+static inline void  lcdc_set_bit(struct lcdc_device *lcdc_dev,u32 offset,u32 msk) 
+{
+       u32* _pv = (u32*)lcdc_dev->regsbak;     
+       _pv += (offset >> 2);                           
+       (*_pv) |= msk;                          
+       writel_relaxed(*_pv,lcdc_dev->regs + offset); 
+} 
+
+static inline void lcdc_clr_bit(struct lcdc_device *lcdc_dev,u32 offset,u32 msk)
+{
+       u32* _pv = (u32*)lcdc_dev->regsbak;     
+       _pv += (offset >> 2);                           
+       (*_pv) &= (~msk);                               
+       writel_relaxed(*_pv,lcdc_dev->regs + offset); 
+} 
+
+static inline void  lcdc_msk_reg(struct lcdc_device *lcdc_dev,u32 offset,u32 msk,u32 v)
+{
+       u32 *_pv = (u32*)lcdc_dev->regsbak;     
+       _pv += (offset >> 2);                   
+       (*_pv) &= (~msk);                               
+       (*_pv) |= v;                            
+       writel_relaxed(*_pv,lcdc_dev->regs+offset);     
+}
+
+static inline void lcdc_cfg_done(struct lcdc_device *lcdc_dev) 
+{
+       writel_relaxed(0x01,lcdc_dev->regs+REG_CFG_DONE); 
+       dsb();  
+} 
+
+#endif /* _RK3036_LCDC_H_ */
\ No newline at end of file
index 3c1b6c917ca9d899b977e172ecf3ec5bfd20f53c..57d6a8631ac0415890c13184e9a9a77a20b2d67c 100755 (executable)
@@ -2832,7 +2832,8 @@ int rk_fb_dpi_open(bool open)
 {
        struct rk_lcdc_driver *dev_drv = NULL;
        dev_drv = rk_get_prmry_lcdc_drv();
 {
        struct rk_lcdc_driver *dev_drv = NULL;
        dev_drv = rk_get_prmry_lcdc_drv();
-       dev_drv->ops->dpi_open(dev_drv, open);
+       if(dev_drv->ops->dpi_open)
+               dev_drv->ops->dpi_open(dev_drv, open);
 
        return 0;
 }
 
        return 0;
 }
@@ -2841,18 +2842,20 @@ int rk_fb_dpi_win_sel(int win_id)
 {
        struct rk_lcdc_driver *dev_drv = NULL;
        dev_drv = rk_get_prmry_lcdc_drv();
 {
        struct rk_lcdc_driver *dev_drv = NULL;
        dev_drv = rk_get_prmry_lcdc_drv();
-       dev_drv->ops->dpi_win_sel(dev_drv, win_id);
+       if(dev_drv->ops->dpi_win_sel)
+               dev_drv->ops->dpi_win_sel(dev_drv, win_id);
 
        return 0;
 }
 
 int rk_fb_dpi_status(void)
 {
 
        return 0;
 }
 
 int rk_fb_dpi_status(void)
 {
-       int ret;
+       int ret = 0;
        struct rk_lcdc_driver *dev_drv = NULL;
        dev_drv = rk_get_prmry_lcdc_drv();
        struct rk_lcdc_driver *dev_drv = NULL;
        dev_drv = rk_get_prmry_lcdc_drv();
-       ret = dev_drv->ops->dpi_status(dev_drv);
-
+       if(dev_drv->ops->dpi_status)
+               ret = dev_drv->ops->dpi_status(dev_drv);
+       
        return ret;
 }
 
        return ret;
 }
 
index af48af11bef0d0189757b5226a69ccdcd8875b6a..fc8b10706e8f51fc21835eb3a0ba6c7685a47db4 100755 (executable)
@@ -330,13 +330,15 @@ static ssize_t show_dsp_bcsh(struct device *dev,
        struct rk_lcdc_driver *dev_drv =
            (struct rk_lcdc_driver *)fbi->par;
        int brightness, contrast, sat_con, sin_hue, cos_hue;
        struct rk_lcdc_driver *dev_drv =
            (struct rk_lcdc_driver *)fbi->par;
        int brightness, contrast, sat_con, sin_hue, cos_hue;
-
-       brightness = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, BRIGHTNESS);
-       contrast = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, CONTRAST);
-       sat_con = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, SAT_CON);
-       sin_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv,H_SIN);
-       cos_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv,H_COS);
-
+       if(dev_drv->ops->get_dsp_bcsh_bcs) {
+               brightness = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, BRIGHTNESS);
+               contrast = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, CONTRAST);
+               sat_con = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, SAT_CON);
+       }
+       if(dev_drv->ops->get_dsp_bcsh_hue) {
+               sin_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv,H_SIN);
+               cos_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv,H_COS);
+       }
        snprintf(buf, PAGE_SIZE, "brightness:%4d,contrast:%4d,sat_con:%4d,"
                                 "sin_hue:%4d,cos_hue:%4d\n",
                                 brightness, contrast,sat_con,sin_hue,cos_hue);
        snprintf(buf, PAGE_SIZE, "brightness:%4d,contrast:%4d,sat_con:%4d,"
                                 "sin_hue:%4d,cos_hue:%4d\n",
                                 brightness, contrast,sat_con,sin_hue,cos_hue);
@@ -350,37 +352,56 @@ static ssize_t set_dsp_bcsh(struct device *dev, struct device_attribute *attr,
        struct rk_lcdc_driver *dev_drv =
            (struct rk_lcdc_driver *)fbi->par;
        int brightness, contrast, sat_con, ret, sin_hue, cos_hue;
        struct rk_lcdc_driver *dev_drv =
            (struct rk_lcdc_driver *)fbi->par;
        int brightness, contrast, sat_con, ret, sin_hue, cos_hue;
+       
        if (!strncmp(buf, "open", 4)) {
        if (!strncmp(buf, "open", 4)) {
-               ret = dev_drv->ops->open_bcsh(dev_drv, 1);
+               if(dev_drv->ops->open_bcsh)
+                       ret = dev_drv->ops->open_bcsh(dev_drv, 1);
+               else
+                       ret = -1;
        } else if (!strncmp(buf, "close", 5)) {
        } else if (!strncmp(buf, "close", 5)) {
-               ret = dev_drv->ops->open_bcsh(dev_drv, 0);
+               if(dev_drv->ops->open_bcsh)
+                       ret = dev_drv->ops->open_bcsh(dev_drv, 0);
+               else
+                       ret = -1;
        } else if (!strncmp(buf, "brightness", 10)) {
                sscanf(buf, "brightness %d", &brightness);
                if (unlikely(brightness > 255)) {
                        dev_err(fbi->dev,"brightness should be [0:255],now=%d\n\n",brightness);
                        brightness = 255;
                }
        } else if (!strncmp(buf, "brightness", 10)) {
                sscanf(buf, "brightness %d", &brightness);
                if (unlikely(brightness > 255)) {
                        dev_err(fbi->dev,"brightness should be [0:255],now=%d\n\n",brightness);
                        brightness = 255;
                }
-               ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv, BRIGHTNESS,brightness);
+               if(dev_drv->ops->set_dsp_bcsh_bcs)
+                       ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv, BRIGHTNESS,brightness);
+               else
+                       ret = -1;
        } else if (!strncmp(buf, "contrast", 8)) {
                sscanf(buf, "contrast %d", &contrast);
                if (unlikely(contrast > 510)) {
                        dev_err(fbi->dev,"contrast should be [0:510],now=%d\n",contrast);
                        contrast = 510;
                }
        } else if (!strncmp(buf, "contrast", 8)) {
                sscanf(buf, "contrast %d", &contrast);
                if (unlikely(contrast > 510)) {
                        dev_err(fbi->dev,"contrast should be [0:510],now=%d\n",contrast);
                        contrast = 510;
                }
-               ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv, CONTRAST,contrast);
+               if(dev_drv->ops->set_dsp_bcsh_bcs)
+                       ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv, CONTRAST,contrast);
+               else
+                       ret = -1;
        } else if (!strncmp(buf, "sat_con", 7)) {
                sscanf(buf, "sat_con %d", &sat_con);
                if (unlikely(sat_con > 1015)) {
                        dev_err(fbi->dev,"sat_con should be [0:1015],now=%d\n",sat_con);
                        sat_con = 1015;
                }
        } else if (!strncmp(buf, "sat_con", 7)) {
                sscanf(buf, "sat_con %d", &sat_con);
                if (unlikely(sat_con > 1015)) {
                        dev_err(fbi->dev,"sat_con should be [0:1015],now=%d\n",sat_con);
                        sat_con = 1015;
                }
-               ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv, SAT_CON,sat_con);
+               if(dev_drv->ops->set_dsp_bcsh_bcs)
+                       ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv, SAT_CON,sat_con);
+               else
+                       ret = -1;
        } else if (!strncmp(buf, "hue", 3)) {
                sscanf(buf, "hue %d %d", &sin_hue,&cos_hue);
                if (unlikely(sin_hue > 511 || cos_hue > 511)) {
                        dev_err(fbi->dev,"sin_hue=%d,cos_hue=%d\n",sin_hue,cos_hue);
                }
        } else if (!strncmp(buf, "hue", 3)) {
                sscanf(buf, "hue %d %d", &sin_hue,&cos_hue);
                if (unlikely(sin_hue > 511 || cos_hue > 511)) {
                        dev_err(fbi->dev,"sin_hue=%d,cos_hue=%d\n",sin_hue,cos_hue);
                }
-               ret = dev_drv->ops->set_dsp_bcsh_hue(dev_drv,sin_hue,cos_hue);
+               if(dev_drv->ops->set_dsp_bcsh_hue)
+                       ret = dev_drv->ops->set_dsp_bcsh_hue(dev_drv,sin_hue,cos_hue);
+               else
+                       ret = -1;
        } else {
                printk("format error\n");
        }
        } else {
                printk("format error\n");
        }
index 4ee4960d49d5529459b2b1104481dfe3917f0e0a..e7f33c1d32a7a600bcda5841c9089b00f61d06a3 100755 (executable)
@@ -74,6 +74,7 @@ struct rk_screen {
        u16 x_mirror;
        u16 y_mirror;
        int interlace;
        u16 x_mirror;
        u16 y_mirror;
        int interlace;
+       int pixelrepeat; //For 480i/576i format, pixel is repeated twice.
        u16 width;
        u16 height;
        u8  ft;
        u16 width;
        u16 height;
        u8  ft;