Merge branch 'develop-3.10' of ssh://10.10.10.29/rk/kernel into develop-3.10
authorhuang zhibao <hzb@rock-chips.com>
Wed, 8 Oct 2014 09:38:14 +0000 (17:38 +0800)
committerhuang zhibao <hzb@rock-chips.com>
Wed, 8 Oct 2014 09:38:14 +0000 (17:38 +0800)
arch/arm/boot/dts/rk3128-sdk.dts
drivers/mmc/host/rk_sdmmc.c
drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_hw.c
drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.c
drivers/video/rockchip/hdmi/rk_hdmi.h
drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c
drivers/video/rockchip/lcdc/rk312x_lcdc.c
drivers/video/rockchip/lcdc/rk312x_lcdc.h
drivers/video/rockchip/rk_fb.c
include/linux/rk_fb.h

index e7ddcd54d16c463aa6efddbde2ea217440ddf9a9..1c8a39ac9af854387952a1d638a92dd8f0b1139d 100755 (executable)
@@ -3,7 +3,7 @@
 
 / {
         compatible = "rockchip,rk3128";
-        backlight {
+        backlight: backlight {
                 compatible = "pwm-backlight";
                 pwms = <&pwm0 0 25000>;
                 brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255>;
@@ -40,6 +40,7 @@
 &lcdc {
        status = "okay";
 
+       backlight = <&backlight>;
        pinctrl-names = "default", "gpio";
        pinctrl-0 = <&lcdc0_lcdc>;
        pinctrl-1 = <&lcdc0_gpio>;
index 4d3cf7c6786204e9465d0da9db12af41671a887a..553d780e0e24dff9041ad78d523430cbf7dd9c69 100755 (executable)
@@ -1198,7 +1198,7 @@ static void dw_mci_wait_unbusy(struct dw_mci *host)
                                 if((host->cmd->arg & (0x1 << 31)) == 1) /* secure erase */
                                         se_flag = 0x1;
 
-                                if (((this_card->ext_csd.erase_group_def) & 0x1) == 1) ;
+                                if (((this_card->ext_csd.erase_group_def) & 0x1) == 1)
                                         se_flag ? (timeout = (this_card->ext_csd.hc_erase_timeout) *
                                                         300000 * (this_card->ext_csd.sec_erase_mult)) :
                                                         (timeout = (this_card->ext_csd.hc_erase_timeout) * 300000);
@@ -2961,7 +2961,7 @@ static void dw_mci_work_routine_card(struct work_struct *work)
 
                 /* Stop edma when rountine card triggered */
                 if(cpu_is_rk3036() || cpu_is_rk312x())
-                       if(host->dma_ops->stop)
+                       if(host->dma_ops && host->dma_ops->stop)
                                host->dma_ops->stop(host);
 
                while (present != slot->last_detect_state) {
@@ -4097,17 +4097,9 @@ int dw_mci_suspend(struct dw_mci *host)
         /*only for sdmmc controller*/
         if (host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) {
                 host->mmc->rescan_disable = 1;
-                if (!(cpu_is_rk312x() || cpu_is_rk3036())) {
-                        if (cancel_delayed_work_sync(&host->mmc->detect))
-                               wake_unlock(&host->mmc->detect_wake_lock);
-                } else {
-                        /* we find dpm suspend timeout for mmc cancel this work sync way,
-                           actually just workaround this for low end platform with
-                           gpio-debounce detect method.
-                        */
-                        if (cancel_delayed_work(&host->mmc->detect))
-                                wake_unlock(&host->mmc->detect_wake_lock);
-                }
+
+                if(cancel_delayed_work(&host->mmc->detect))
+                        wake_unlock(&host->mmc->detect_wake_lock);
 
                 disable_irq(host->irq);
                 if (pinctrl_select_state(host->pinctrl, host->pins_idle) < 0)
index df65daa3c4cbbec4ea3b063149141e8e59815937..d4ee596fe1a962e79088ebcee620d4ee89e18e40 100755 (executable)
@@ -4,7 +4,18 @@
 #include <linux/of_irq.h>
 #include "rk3036_hdmi.h"
 #include "rk3036_hdmi_hw.h"
-
+static unsigned int rk3036_hdmi_support_vic[] = {
+       HDMI_720X480P_60HZ_VIC,
+       HDMI_720X480I_60HZ_VIC,
+       HDMI_720X576P_50HZ_VIC,
+       HDMI_720X576I_50HZ_VIC,
+       HDMI_1280X720P_50HZ_VIC,
+       HDMI_1280X720P_60HZ_VIC,
+       HDMI_1920X1080P_50HZ_VIC,
+       HDMI_1920X1080I_50HZ_VIC,
+       HDMI_1920X1080P_60HZ_VIC,
+       HDMI_1920X1080I_60HZ_VIC
+};
 static int __maybe_unused rk3036_hdmi_show_reg(struct hdmi *hdmi_drv)
 {
        int i = 0;
@@ -202,10 +213,6 @@ int rk3036_hdmi_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
 #endif
                        }
 
-                       /* clear EDID interrupt reg */
-                       hdmi_writel(hdmi_dev, INTERRUPT_STATUS1,
-                                   m_INT_EDID_READY);
-
                        if ((checksum & 0xff) == 0) {
                                ret = 0;
                                hdmi_dbg(hdmi_drv->dev,
@@ -216,6 +223,10 @@ int rk3036_hdmi_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
        }
        /*close edid irq*/
        hdmi_writel(hdmi_dev, INTERRUPT_MASK1, 0);
+       /* clear EDID interrupt reg */
+       hdmi_writel(hdmi_dev, INTERRUPT_STATUS1,
+                   m_INT_EDID_READY);
+
        enable_irq(hdmi_drv->irq);
 
        return ret;
@@ -763,6 +774,12 @@ void rk3036_hdmi_irq(struct hdmi *hdmi_drv)
        struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
                                                       struct rk_hdmi_device,
                                                       driver);
+       hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &interrupt);
+       if(interrupt) {
+               hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, interrupt);
+               dev_info(hdmi_drv->dev, "Clear edid irq.\n");
+       }
+
        hdmi_readl(hdmi_dev, HDMI_STATUS, &interrupt);
        if(interrupt) {
                hdmi_writel(hdmi_dev, HDMI_STATUS, interrupt);
@@ -834,6 +851,8 @@ int rk3036_hdmi_initial(struct hdmi *hdmi_drv)
        hdmi_drv->read_edid = rk3036_hdmi_read_edid;
        hdmi_drv->insert    = rk3036_hdmi_insert;
        hdmi_drv->ops = &hdmi_drv_ops;
+       hdmi_drv->support_vic = rk3036_hdmi_support_vic;
+       hdmi_drv->support_vic_num = ARRAY_SIZE(rk3036_hdmi_support_vic);
 
        if (!hdmi_drv->uboot_logo) {
                rk3036_hdmi_reset_pclk();
index c599106076c7fa61f653534a85d4dd3e9cc8a6c2..4fce93bc457d82700580b4b556ad0873a48473d4 100755 (executable)
@@ -2,6 +2,19 @@
 #include <linux/interrupt.h>
 #include "rk3288_hdmi_hw.h"
 
+static unsigned int rk3288_hdmi_support_vic[] = {
+       HDMI_720X480P_60HZ_VIC,
+       HDMI_720X576P_50HZ_VIC,
+       HDMI_1280X720P_50HZ_VIC,
+       HDMI_1280X720P_60HZ_VIC,
+       HDMI_1920X1080P_50HZ_VIC,
+       HDMI_1920X1080P_60HZ_VIC,
+       HDMI_3840X2160P_24HZ_VIC,
+       HDMI_3840X2160P_25HZ_VIC,
+       HDMI_3840X2160P_30HZ_VIC,
+       HDMI_3840X2160P_50HZ_VIC,
+       HDMI_3840X2160P_60HZ_VIC
+};
 static const struct phy_mpll_config_tab PHY_MPLL_TABLE[] = {   /* opmode: 0:HDMI1.4     1:HDMI2.0 */
 /*      pixclock    pixrepet        colordepth     prepdiv  tmdsmhl opmode  fbdiv2  fbdiv1  ref_cntrl nctrl propctrl intctrl gmpctrl */
        {27000000,      0,      HDMI_COLOR_DEPTH_8BIT,  0,      0,      0,      2,      3,      0,      3,      7,      0,      3},
@@ -1334,6 +1347,8 @@ int rk3288_hdmi_initial(struct hdmi *hdmi_drv)
        hdmi_drv->config_audio = rk3288_hdmi_config_audio;
        hdmi_drv->detect_hotplug = rk3288_hdmi_detect_hotplug;
        hdmi_drv->read_edid = rk3288_hdmi_read_edid;
+       hdmi_drv->support_vic = rk3288_hdmi_support_vic;
+       hdmi_drv->support_vic_num = ARRAY_SIZE(rk3288_hdmi_support_vic);
 
        rk3288_hdmi_reset(hdmi_drv);
 
index ff5bb3d9553b3201ba9487d2eff092cde188014c..d13bed5da6373c6fb3dd553066b22eb6ed1f7c59 100755 (executable)
@@ -391,6 +391,8 @@ struct hdmi {
        void (*cec_set_device_pa)(int);
        int (*cec_enumerate)(void);
        struct rk_hdmi_drv_ops *ops;
+       unsigned int *support_vic;
+       int support_vic_num;
 };
 
 #define hdmi_err(dev, format, arg...)          \
index f41a73a19fabebf9060cf998fc55229fd58f667b..aa6f9ffbc83deaaaf668f971b24cca7967b142b1 100755 (executable)
@@ -377,6 +377,22 @@ static int hdmi_videomode_compare(const struct fb_videomode *mode1,
        }
        return -1;
 }
+int hdmi_check_support_videomode(int vic)
+{
+       int i, support = 0;
+       if (m_hdmi_drv->support_vic_num == 0)
+               return 1;
+
+       for (i=0; i<m_hdmi_drv->support_vic_num; i++) {
+               if (m_hdmi_drv->support_vic[i] == vic) {
+                       support = 1;
+                       break;
+               }
+       }
+       if(i >= m_hdmi_drv->support_vic_num)
+               support = 0;
+       return support;
+}
 
 /**
  * hdmi_add_videomode: adds videomode entry to modelist
@@ -396,7 +412,8 @@ int hdmi_add_videomode(const struct fb_videomode *mode, struct list_head *head)
        for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
                m = (struct fb_videomode *)&hdmi_mode[i];
                if (fb_mode_is_equal(m, mode)) {
-                       found = 1;
+                       if(hdmi_check_support_videomode(m->flag))
+                               found = 1;
                        break;
                }
        }
index b41ab99bfad53ae925f029e26d76789319637dce..2b76b708eab85c8fceb790c8739b9bb70b9969b5 100755 (executable)
@@ -36,6 +36,7 @@
 #include <dt-bindings/clock/rk_system_status.h>
 #include <linux/rockchip-iovmm.h>
 #include "rk312x_lcdc.h"
+#include <linux/rockchip/dvfs.h>
 
 static int dbg_thresd;
 module_param(dbg_thresd, int, S_IRUGO | S_IWUSR);
@@ -750,35 +751,20 @@ static u32 calc_sclk_freq(struct rk_screen *src_screen, struct rk_screen *dst_sc
         return (u32)sclk_freq;
 }
 
-#define SCLK_PLL_LIMIT 594000000
+#define SCLK_PLL_LIMIT         594000000
+#define GPU_FREQ_MAX_LIMIT     297000000
+#define GPU_FREQ_NEED          400000000
+
 static u32 calc_sclk_pll_freq(u32 sclk_freq)
 {
-#define ACCURACY_LEV   100
-       u32 pll_freq = 0;
-       u32 decimal_num = 0;
-       u16 max_multi_num = 0, multi_num = 0, remainder_num = 0;
-       u32 less_delta = 0, greater_delta = 0;
-
-       if (sclk_freq == 0)
-               return 0;
+       u32 multi_num;
 
-       max_multi_num = SCLK_PLL_LIMIT / sclk_freq;
-       decimal_num = (sclk_freq / (1000000 / ACCURACY_LEV)) % ACCURACY_LEV;
-       multi_num = ACCURACY_LEV / decimal_num;
-
-       if (multi_num > max_multi_num) {
-               multi_num = max_multi_num;
-       } else if (decimal_num != 0) {
-               remainder_num = ACCURACY_LEV % decimal_num;
-               if (remainder_num != 0) {
-                       less_delta = ACCURACY_LEV - (decimal_num * multi_num);
-                       greater_delta = decimal_num * (multi_num + 1) - ACCURACY_LEV;
-                       multi_num = (less_delta < greater_delta) ? multi_num : (multi_num + 1);
-               }
+       if (sclk_freq < (SCLK_PLL_LIMIT / 10)) {
+               return (sclk_freq * 10);
+       } else {
+               multi_num = GPU_FREQ_NEED / sclk_freq;
+               return (sclk_freq * multi_num);
        }
-
-       pll_freq = sclk_freq * multi_num;
-       return pll_freq;
 }
 
 static int calc_dsp_frm_vst_hst(struct rk_screen *src,
@@ -824,16 +810,13 @@ static int calc_dsp_frm_vst_hst(struct rk_screen *src,
                T_frm_st = (T_BP_in + T_Delta - T_BP_out);
        else
                T_frm_st = Tin - (T_BP_out - (T_BP_in + T_Delta));
-       printk("T_in=%lld,T_BP_in=%lld,T_Delta=%lld,T_BP_out=%lld\n",Tin,T_BP_in,T_Delta,T_BP_out);
-       printk("T_frm_st=%lld\n",T_frm_st);
-       printk("src_pixclock=%d\n,dst_pixclock=%d\n",src_pixclock,dst_pixclock);
 
        /* (T_frm_st = scl_vst * src_htotal * src_pixclock + scl_hst * src_pixclock) */
-       temp = do_div(T_frm_st, src_htotal * src_pixclock);
+       temp = do_div(T_frm_st, src_pixclock);
+       temp = do_div(T_frm_st, src_htotal);
+       dst->scl_hst = temp - 1;
        dst->scl_vst = T_frm_st;
-       do_div(temp, src_pixclock);
-       dst->scl_hst = temp;
-       printk("dst_frame_hst=%d,dst_frame_vst=%d\n",dst->scl_hst,dst->scl_vst);
+
        return 0;
 }
 
@@ -855,6 +838,7 @@ static int rk312x_lcdc_set_scaler(struct rk_lcdc_driver *dev_drv,
        struct rk_screen *dst;
         struct lcdc_device *lcdc_dev = container_of(dev_drv,
                                                    struct lcdc_device, driver);
+       struct dvfs_node *gpu_clk = clk_get_dvfs_node("clk_gpu");
 
         if (unlikely(!lcdc_dev->clk_on))
                 return 0;
@@ -863,12 +847,21 @@ static int rk312x_lcdc_set_scaler(struct rk_lcdc_driver *dev_drv,
                spin_lock(&lcdc_dev->reg_lock);
                lcdc_msk_reg(lcdc_dev, SCALER_CTRL,
                                m_SCALER_EN | m_SCALER_OUT_ZERO | m_SCALER_OUT_EN,
-                               v_SCALER_EN(0) | v_SCALER_OUT_ZERO(0) | v_SCALER_OUT_EN(0));
+                               v_SCALER_EN(0) | v_SCALER_OUT_ZERO(1) | v_SCALER_OUT_EN(0));
+               lcdc_cfg_done(lcdc_dev);
                spin_unlock(&lcdc_dev->reg_lock);
                if (lcdc_dev->sclk_on) {
                        clk_disable_unprepare(lcdc_dev->sclk);
                        lcdc_dev->sclk_on = false;
                }
+
+               /* switch pll freq as default when sclk is no used */
+               if (clk_get_rate(lcdc_dev->pll_sclk) != GPU_FREQ_NEED) {
+                       dvfs_clk_enable_limit(gpu_clk, GPU_FREQ_MAX_LIMIT,
+                                             GPU_FREQ_MAX_LIMIT);
+                       clk_set_rate(lcdc_dev->pll_sclk, GPU_FREQ_NEED);
+                       dvfs_clk_enable_limit(gpu_clk, 0, -1);
+               }
                dev_dbg(lcdc_dev->dev, "%s: disable\n", __func__);
                return 0;
        }
@@ -889,7 +882,14 @@ static int rk312x_lcdc_set_scaler(struct rk_lcdc_driver *dev_drv,
                clk_prepare_enable(lcdc_dev->sclk);
                lcdc_dev->s_pixclock = calc_sclk_freq(src, dst);
                pll_freq = calc_sclk_pll_freq(lcdc_dev->s_pixclock);
+
+               /* limit gpu freq */
+               dvfs_clk_enable_limit(gpu_clk, GPU_FREQ_MAX_LIMIT, GPU_FREQ_MAX_LIMIT);
+               /* set pll freq */
                clk_set_rate(lcdc_dev->pll_sclk, pll_freq);
+               /* cancel limit gpu freq */
+               dvfs_clk_enable_limit(gpu_clk, 0, -1);
+
                clk_set_rate(lcdc_dev->sclk, lcdc_dev->s_pixclock);
                lcdc_dev->sclk_on = true;
                dev_info(lcdc_dev->dev, "%s:sclk=%d\n", __func__,
@@ -1147,12 +1147,18 @@ static int rk312x_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
                                     v_SW_OVERLAY_MODE(dev_drv->overlay_mode));
                 }
 
-               mask = m_DSP_OUT_FORMAT | m_HSYNC_POL | m_VSYNC_POL |
+               mask = m_HSYNC_POL | m_VSYNC_POL |
                    m_DEN_POL | m_DCLK_POL;
-               val = v_DSP_OUT_FORMAT(face) | v_HSYNC_POL(screen->pin_hsync) |
+               val = v_HSYNC_POL(screen->pin_hsync) |
                    v_VSYNC_POL(screen->pin_vsync) |
                    v_DEN_POL(screen->pin_den) |
                    v_DCLK_POL(screen->pin_dclk);
+
+               if (screen->type != SCREEN_HDMI) {
+                       mask |= m_DSP_OUT_FORMAT;
+                       val |= v_DSP_OUT_FORMAT(face);
+               }
+
                lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
 
                mask = m_BG_COLOR | m_DSP_BG_SWAP | m_DSP_RB_SWAP |
@@ -2199,6 +2205,60 @@ static int rk312x_lcdc_dpi_status(struct rk_lcdc_driver *dev_drv)
        return ovl;
 }
 
+static int rk312x_lcdc_dsp_black(struct rk_lcdc_driver *dev_drv, int enable)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                    struct lcdc_device, driver);
+       struct device_node *backlight;
+
+       if (!lcdc_dev->backlight) {
+               backlight = of_parse_phandle(lcdc_dev->dev->of_node, "backlight", 0);
+               if (backlight) {
+                       lcdc_dev->backlight = of_find_backlight_by_node(backlight);
+                       if (!lcdc_dev->backlight)
+                               dev_info(lcdc_dev->dev, "No find backlight device\n");
+               }
+       }
+
+       if (enable) {
+               /* close the backlight */
+               if (lcdc_dev->backlight) {
+                       lcdc_dev->backlight->props.power = FB_BLANK_POWERDOWN;
+                       backlight_update_status(lcdc_dev->backlight);
+               }
+
+               spin_lock(&lcdc_dev->reg_lock);
+               if (likely(lcdc_dev->clk_on)) {
+                       lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_BLACK_EN,
+                                    v_BLACK_EN(1));
+                       lcdc_cfg_done(lcdc_dev);
+               }
+               spin_unlock(&lcdc_dev->reg_lock);
+
+               if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
+                       dev_drv->trsm_ops->disable();
+       } else {
+               spin_lock(&lcdc_dev->reg_lock);
+               if (likely(lcdc_dev->clk_on)) {
+                       lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_BLACK_EN,
+                                    v_BLACK_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();
+               msleep(100);
+               /* open the backlight */
+               if (lcdc_dev->backlight) {
+                       lcdc_dev->backlight->props.power = FB_BLANK_UNBLANK;
+                       backlight_update_status(lcdc_dev->backlight);
+               }
+       }
+
+       return 0;
+}
+
+
 static struct rk_lcdc_drv_ops lcdc_drv_ops = {
        .open = rk312x_lcdc_open,
        .load_screen = rk312x_load_screen,
@@ -2228,6 +2288,7 @@ static struct rk_lcdc_drv_ops lcdc_drv_ops = {
        .set_screen_scaler = rk312x_lcdc_set_scaler,
        .set_hwc_lut = rk312x_lcdc_set_hwc_lut,
        .set_irq_to_cpu = rk312x_lcdc_set_irq_to_cpu,
+       .dsp_black = rk312x_lcdc_dsp_black,
 };
 #if 0
 static const struct rk_lcdc_drvdata rk3036_lcdc_drvdata = {
@@ -2398,6 +2459,9 @@ static void rk312x_lcdc_shutdown(struct platform_device *pdev)
        rk312x_lcdc_deinit(lcdc_dev);
         rk312x_lcdc_clk_disable(lcdc_dev);
        rk_disp_pwr_disable(&lcdc_dev->driver);
+
+       if (lcdc_dev->backlight)
+               put_device(&lcdc_dev->backlight->dev);
 }
 
 static struct platform_driver rk312x_lcdc_driver = {
index 202b267d8f653b8b45e188ed66c41c77f8814a02..9defd111dfb384c854353554aa91af64e3816e8f 100755 (executable)
@@ -690,6 +690,7 @@ struct lcdc_device {
         u32 s_pixclock;
 
        u32 standby;                    /* 1:standby,0:work */
+       struct backlight_device *backlight;
 };
 
 static inline void lcdc_writel(struct lcdc_device *lcdc_dev, u32 offset, u32 v)
index 41459dd2b9c1226cc2ccab8d560d1bb65704cb9a..cbd86c8204d8d5ac78e34afc3696dbb5d0c6918b 100755 (executable)
@@ -770,9 +770,9 @@ static int rk_fb_close(struct fb_info *info, int user)
        int win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
 
        if (win_id >= 0) {
-               dev_drv->win[win_id]->logicalstate--;
-               if (!dev_drv->win[win_id]->logicalstate) {
-                       win = dev_drv->win[win_id];
+               win = dev_drv->win[win_id];
+               win->logicalstate--;
+               if (!win->logicalstate) {
                        info->fix.smem_start = win->reserved;
                        info->var.xres = dev_drv->screen0->mode.xres;
                        info->var.yres = dev_drv->screen0->mode.yres;
@@ -799,6 +799,7 @@ static int rk_fb_close(struct fb_info *info, int user)
                        info->var.vsync_len = dev_drv->screen0->mode.vsync_len;
                        info->var.hsync_len = dev_drv->screen0->mode.hsync_len;
                }
+               info->var.reserved[0] = (__u32)win->area[0].ion_hdl;
        }
 
        return 0;
@@ -3155,7 +3156,7 @@ static int rk_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
        struct ion_handle *handle = (struct ion_handle *)info->var.reserved[0];
        struct dma_buf *dma_buf = NULL;
 
-       if (IS_ERR(handle)) {
+       if (handle == NULL || IS_ERR(handle)) {
                dev_err(info->device, "failed to get ion handle:%ld\n",
                        PTR_ERR(handle));
                return -ENOMEM;
@@ -3342,8 +3343,8 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
                return 0;
 
        if (rk_fb->disp_mode == ONE_DUAL) {
-               if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
-                       dev_drv->trsm_ops->disable();
+               if (dev_drv->ops->dsp_black)
+                       dev_drv->ops->dsp_black(dev_drv, 1);
                if (dev_drv->ops->set_screen_scaler)
                        dev_drv->ops->set_screen_scaler(dev_drv, dev_drv->screen0, 0);
        }
@@ -3357,8 +3358,18 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
                if (rk_fb->disp_mode == ONE_DUAL) {
                        dev_drv->cur_screen = dev_drv->screen0;
                        dev_drv->ops->load_screen(dev_drv, 1);
-                       if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
-                               dev_drv->trsm_ops->enable();
+
+                       /* force modify dsp size */
+                       info = rk_fb->fb[dev_drv->fb_index_base];
+                       info->var.grayscale &= 0xff;
+                       info->var.grayscale |=
+                               (dev_drv->cur_screen->mode.xres << 8) +
+                               (dev_drv->cur_screen->mode.yres << 20);
+                       info->fbops->fb_set_par(info);
+                       info->fbops->fb_pan_display(&info->var, info);
+
+                       if (dev_drv->ops->dsp_black)
+                               dev_drv->ops->dsp_black(dev_drv, 0);
                } else if (rk_fb->num_lcdc > 1) {
                        /* If there is more than one lcdc device, we disable
                           the layer which attached to this device */
@@ -3400,8 +3411,14 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
                                        load_screen = 1;
                                }
                                info->var.activate |= FB_ACTIVATE_FORCE;
-                               if (rk_fb->disp_mode == DUAL)
+                               if (rk_fb->disp_mode == DUAL) {
                                        rk_fb_update_ext_info(info, pmy_info, 1);
+                               } else if (rk_fb->disp_mode == ONE_DUAL) {
+                                       info->var.grayscale &= 0xff;
+                                       info->var.grayscale |=
+                                               (dev_drv->cur_screen->xsize << 8) +
+                                               (dev_drv->cur_screen->ysize << 20);
+                               }
                                info->fbops->fb_set_par(info);
                                info->fbops->fb_pan_display(&info->var, info);
                        }
@@ -3412,8 +3429,8 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
        if (rk_fb->disp_mode == ONE_DUAL) {
                if (dev_drv->ops->set_screen_scaler)
                        dev_drv->ops->set_screen_scaler(dev_drv, dev_drv->screen0, 1);
-               if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
-                       dev_drv->trsm_ops->enable();
+               if (dev_drv->ops->dsp_black)
+                       dev_drv->ops->dsp_black(dev_drv, 0);
        }
        return 0;
 }
index c5bc747f312201ef901ee9aa1fda2a7d14199ca8..161e987a281fb0eee7d8870f4952743c30174ffa 100755 (executable)
@@ -441,6 +441,7 @@ struct rk_lcdc_drv_ops {
        int (*cfg_done) (struct rk_lcdc_driver *dev_drv);
        int (*set_overscan) (struct rk_lcdc_driver *dev_drv,
                             struct overscan *overscan);
+       int (*dsp_black) (struct rk_lcdc_driver *dev_drv, int enable);
 };
 
 struct rk_fb_area_par {