rk3288 android 4.4.4 双屏异显

kernel\arch\arm\boot\dts\include\dt-bindings\rkfb\rk_fb.h


+#define DUAL_LCD 3
+#define DEFAULT_MODE 0


dts文件

&fb {

rockchip,disp-mode = ;
rockchip,uboot-logo-on = <0>;
};


&rk_screen {
status = "okay";
screen0 {
screen_prop = ;//PRMRY
native-mode = ;
power_ctr {
lcd_en {
rockchip,power_type = ;
gpios = <&gpio7 GPIO_A3 GPIO_ACTIVE_HIGH>;
rockchip,delay = <10>;
};
lcd_cs {
rockchip,power_type = ;
gpios = <&gpio7 GPIO_A4 GPIO_ACTIVE_HIGH>;
rockchip,delay = <10>;
};
};
display-timings {
            native-mode = <&hn116wx1>;
            compatible = "rockchip,display-timings";
            hn116wx1: timing0 {
screen-type = ;
lvds-format = ;
out-face    = ;
clock-frequency = <73000000>;
hactive = <1366>;//720
vactive = <768>;//1280
hback-porch = <70>;
hfront-porch = <70>;
vback-porch = <10>;
vfront-porch = <10>;
hsync-len = <10>;
vsync-len = <2>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <1>;
swap-rb = <0>;
swap-rg = <0>;
swap-gb = <0>;
            };
        };
};
screen1 {
screen_prop = ;//EXTEND
native-mode = ;
power_ctr {
lcd_en {
rockchip,power_type = ;
gpios = <&gpio5 GPIO_B1 GPIO_ACTIVE_HIGH>;
rockchip,delay = <10>;
};
/*lcd_cs {
rockchip,power_type = ;
gpios = <&gpio7 GPIO_A4 GPIO_ACTIVE_HIGH>;
rockchip,delay = <10>;
};*/
};
display-timings {
            native-mode = <&b156htn04>;
            compatible = "rockchip,display-timings";
            b156htn04: timing0 {
screen-type = ;
lvds-format = ;
out-face    = ;
clock-frequency = <142400000>;
hactive = <1920>;  /* Horizontal display area thd 1024       DCLK */
vactive = <1080>;  /* Vertical display area tvd   600 H */
hback-porch = <60>;    /* HS Width +Back Porch   160  160   160  DCLK (Thw+ thbp)*/
hfront-porch = <60>;  /* HS front porch thfp    16   160   216  DCLK */
vback-porch = <20>;  /* VS front porch tvfp 1 12    127  H   */
vfront-porch = <20>;  /* VS Width+Back Porch    23   23    23   H (Tvw+ tvbp) */
hsync-len = <60>;  /* HS Pulse Width thw 1  -    140  DCLK */
vsync-len = <10>;  /* VS Pulse Width tvw 1  - 20  H */
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <1>;
swap-rb = <0>;
swap-rg = <0>;
swap-gb = <0>;
            };
        };
};

};


&lvds {
status = "okay";
prop = ;
};


&edp{
status = "okay";
prop = ;
};


&lcdc1 {
status = "okay";
rockchip,mirror = ;


};


&hdmi {
status = "disabled";
rockchips,hdmi_audio_source = <0>;
};


From c992f04253bd7c1b72b5bb0041cc4cc1e1e1d9d4 Mon Sep 17 00:00:00 2001
From: shen zhi cheng
Date: Sat, 10 Jan 2015 15:21:16 +0800
Subject: [PATCH] android 4.4.4 dual screen kernel


---
 drivers/video/rockchip/hdmi/rk_hdmi_task.c |    1 +
 drivers/video/rockchip/rk_fb.c             |  138 +++++++++++++++++++++++-----
 include/linux/rk_fb.h                      |    2 +
 3 files changed, 120 insertions(+), 21 deletions(-)


diff --git a/drivers/video/rockchip/hdmi/rk_hdmi_task.c b/drivers/video/rockchip/hdmi/rk_hdmi_task.c
index eb3c7db..d99635f 100755
--- a/drivers/video/rockchip/hdmi/rk_hdmi_task.c
+++ b/drivers/video/rockchip/hdmi/rk_hdmi_task.c
@@ -276,6 +276,7 @@ void hdmi_work(struct work_struct *work)
  if (hdmi->uboot_logo) {
  hdmi->state = CONFIG_AUDIO;
  }
+ kobject_uevent_env(&hdmi->ddev->dev->kobj, KOBJ_CHANGE, envp);
  break;
  case CONFIG_VIDEO:
  hdmi->display = HDMI_DISABLE;
diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c
index 66c5045..369e828 100755
--- a/drivers/video/rockchip/rk_fb.c
+++ b/drivers/video/rockchip/rk_fb.c
@@ -58,15 +58,19 @@
 #define H_USE_FENCE 1
 static int hdmi_switch_complete;
 static struct platform_device *fb_pdev;
-struct list_head saved_list;
+//struct list_head saved_list;
+
+//#define HDMI_SET_BY_FB 1
 
 #if defined(CONFIG_FB_MIRRORING)
 int (*video_data_to_mirroring) (struct fb_info *info, u32 yuv_phy[2]);
 EXPORT_SYMBOL(video_data_to_mirroring);
 #endif
 
-struct rk_fb_reg_win_data g_reg_win_data[4];
-static int g_last_win_num;
+struct rk_fb_reg_win_data lcdc0_g_reg_win_data[4];
+static int lcdc0_g_last_win_num;
+struct rk_fb_reg_win_data lcdc1_g_reg_win_data[4];
+static int lcdc1_g_last_win_num;
 static int g_first_buf = 1;
 static struct rk_fb_trsm_ops *trsm_lvds_ops;
 static struct rk_fb_trsm_ops *trsm_edp_ops;
@@ -688,6 +692,7 @@ int rk_fb_set_prmry_screen_status(int status)
  return 0;
 }
 
+#ifdef HDMI_SET_BY_FB
 static struct rk_lcdc_driver *rk_get_extend_lcdc_drv(void)
 {
  struct rk_fb *inf = NULL;
@@ -708,6 +713,7 @@ static struct rk_lcdc_driver *rk_get_extend_lcdc_drv(void)
 
  return dev_drv;
 }
+#endif
 
 u32 rk_fb_get_prmry_screen_pixclock(void)
 {
@@ -1005,6 +1011,7 @@ static void fb_copy_by_ipp(struct fb_info *dst_info,
 
 #endif
 
+#ifdef HDMI_SET_BY_FB
 #if defined(CONFIG_ROCKCHIP_RGA) || defined(CONFIG_ROCKCHIP_RGA2)
 static int get_rga_format(int fmt)
 {
@@ -1195,9 +1202,11 @@ static void fb_copy_by_rga(struct fb_info *dst_info,
  win_copy_by_rga(dst_win, src_win, ext_dev_drv->rotate_mode,
  ext_dev_drv->iommu_enabled);
 }
-
 #endif
+#endif
+
 
+#ifdef HDMI_SET_BY_FB
 static int rk_fb_rotate(struct fb_info *dst_info,
   struct fb_info *src_info)
 {
@@ -1332,6 +1341,8 @@ static int rk_fb_set_ext_win_buffer(struct rk_lcdc_win *ext_win,
 
  return 0;
 }
+#endif
+
 
 static int rk_fb_pan_display(struct fb_var_screeninfo *var,
      struct fb_info *info)
@@ -1474,6 +1485,7 @@ static int rk_fb_pan_display(struct fb_var_screeninfo *var,
 
  dev_drv->ops->pan_display(dev_drv, win_id);
 
+#ifdef HDMI_SET_BY_FB
  if (rk_fb->disp_mode == DUAL) {
  if (extend_info != info && extend_win->state &&
     hdmi_switch_complete) {
@@ -1488,6 +1500,7 @@ static int rk_fb_pan_display(struct fb_var_screeninfo *var,
  extend_dev_drv->ops->cfg_done(extend_dev_drv);
  }
  }
+#endif
 #ifdef CONFIG_FB_MIRRORING
  if (video_data_to_mirroring)
  video_data_to_mirroring(info, NULL);
@@ -1501,7 +1514,7 @@ static int rk_fb_get_list_stat(struct rk_lcdc_driver *dev_drv)
  int i, j;
 
  i = list_empty(&dev_drv->update_regs_list);
- j = list_empty(&saved_list);
+ j = list_empty(&dev_drv->saved_list);
  return i == j ? 0 : 1;
 }
 
@@ -1601,7 +1614,9 @@ void rk_fb_free_dma_buf(struct rk_lcdc_driver *dev_drv,
  struct rk_fb_reg_area_data *area_data;
  struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
 #if defined(CONFIG_ROCKCHIP_IOMMU)
+ #ifdef HDMI_SET_BY_FB
  struct rk_lcdc_driver *ext_dev_drv = rk_get_extend_lcdc_drv();
+ #endif
 #endif
 
  for (i = 0; i < reg_win_data->area_num; i++) {
@@ -1614,6 +1629,7 @@ void rk_fb_free_dma_buf(struct rk_lcdc_driver *dev_drv,
  area_data->ion_handle);
  freed_addr[freed_index++] = area_data->smem_start;
  }
+#ifdef HDMI_SET_BY_FB
  if (rk_fb->disp_mode == DUAL && hdmi_switch_complete) {
  if (ext_dev_drv->iommu_enabled)
  ion_unmap_iommu(ext_dev_drv->dev,
@@ -1621,6 +1637,7 @@ void rk_fb_free_dma_buf(struct rk_lcdc_driver *dev_drv,
  area_data->ion_handle);
  }
 #endif
+#endif
  if (area_data->ion_handle != NULL) {
  ion_unmap_kernel(rk_fb->ion_client,
  area_data->ion_handle);
@@ -1632,6 +1649,7 @@ void rk_fb_free_dma_buf(struct rk_lcdc_driver *dev_drv,
  memset(reg_win_data, 0, sizeof(struct rk_fb_reg_win_data));
 }
 
+#ifdef HDMI_SET_BY_FB
 /*
  * function: update extend win info acorrding to primary win info,
  the function is only used for dual display mode
@@ -1771,6 +1789,7 @@ static int rk_fb_update_ext_win(struct rk_lcdc_driver *ext_dev_drv,
 
  return 0;
 }
+#endif
 
 static void rk_fb_update_win(struct rk_lcdc_driver *dev_drv,
                                 struct rk_lcdc_win *win,
@@ -1908,8 +1927,10 @@ static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv,
  struct rk_lcdc_win *win;
  ktime_t timestamp = dev_drv->vsync_info.timestamp;
  struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
+#ifdef HDMI_SET_BY_FB
  struct rk_lcdc_driver *ext_dev_drv;
  struct rk_lcdc_win *ext_win;
+#endif
  struct rk_fb_reg_win_data *win_data;
  bool wait_for_vsync;
  int count = 100;
@@ -1932,12 +1953,15 @@ static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv,
  win_data = rk_fb_get_win_data(regs, i);
  if (win_data) {
  if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
-     win_data->data_format == YUV420)
+    (win_data->data_format == YUV420 ||
+     win_data->data_format == YUV420_A))
  continue;
+ mutex_lock(&dev_drv->win_config);
  rk_fb_update_win(dev_drv, win, win_data);
  win->state = 1;
  dev_drv->ops->set_par(dev_drv, i);
  dev_drv->ops->pan_display(dev_drv, i);
+ mutex_unlock(&dev_drv->win_config);
 #if defined(CONFIG_ROCKCHIP_IOMMU)
  if (dev_drv->iommu_enabled) {
  g_last_addr[i] = win_data->reg_area_data[0].smem_start +
@@ -1952,6 +1976,8 @@ static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv,
  dev_drv->ops->ovl_mgr(dev_drv, 0, 1);
  if (rk_fb->disp_policy == DISPLAY_POLICY_BOX)
  dev_drv->ops->cfg_done(dev_drv);
+
+#ifdef HDMI_SET_BY_FB
  if ((rk_fb->disp_mode == DUAL)
     && (hdmi_get_hotplug() == HDMI_HPD_ACTIVED)
     && hdmi_switch_complete) {
@@ -1990,6 +2016,8 @@ static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv,
  ext_dev_drv->ops->cfg_done(ext_dev_drv);
  }
 ext_win_exit:
+#endif
+
  dev_drv->ops->cfg_done(dev_drv);
 
  do {
@@ -1997,12 +2025,28 @@ ext_win_exit:
  timeout = wait_event_interruptible_timeout(dev_drv->vsync_info.wait,
  ktime_compare(dev_drv->vsync_info.timestamp, timestamp) > 0,
  msecs_to_jiffies(25));
+ #ifdef HDMI_SET_BY_FB
+ if ((rk_fb->disp_mode == DUAL) &&
+    (hdmi_get_hotplug() == HDMI_HPD_ACTIVED) &&
+    hdmi_switch_complete) {
+ /*
+ * If dual output, we need make sure the extend display
+ * cfg take effect before release fence.
+ */
+ ext_dev_drv = rk_get_extend_lcdc_drv();
+ timeout = wait_event_interruptible_timeout(ext_dev_drv->vsync_info.wait,
+ ktime_compare(ext_dev_drv->vsync_info.timestamp, timestamp) > 0,
+ msecs_to_jiffies(25));
+ }
+ #endif
+
  dev_drv->ops->get_dsp_addr(dev_drv, dsp_addr);
  wait_for_vsync = false;
  for (i = 0; i < dev_drv->lcdc_win_num; i++) {
  if (dev_drv->win[i]->state == 1) {
  if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
     (dev_drv->win[i]->format == YUV420 ||
+     dev_drv->win[i]->format == YUV420_A ||
      !strcmp(dev_drv->win[i]->name, "hwc"))) {
  continue;
  } else {
@@ -2037,19 +2081,50 @@ ext_win_exit:
  g_last_timeout = timeout;
  }
 #endif
- for (i = 0; i < g_last_win_num; i++)
- rk_fb_free_dma_buf(dev_drv, &g_reg_win_data[i]);
+        if(dev_drv->id==0)
+        {
+                for (i = 0; i < lcdc0_g_last_win_num; i++)
+                {
+                        rk_fb_free_dma_buf(dev_drv, &lcdc0_g_reg_win_data[i]);
+                        //printk("----lcdc0 %s rk_fb_free_dma_buf i=%d,g_last_win_num=%d\n",__FUNCTION__,i,lcdc0_g_last_win_num);
+
+                }
+        }
+        else//(dev_drv->id==1)
+        {
+                for (i = 0; i < lcdc1_g_last_win_num; i++)
+                {
+                        rk_fb_free_dma_buf(dev_drv, &lcdc1_g_reg_win_data[i]);
+                        //printk("----lcdc1 %s rk_fb_free_dma_buf i=%d,g_last_win_num=%d\n",__FUNCTION__,i,lcdc1_g_last_win_num);
+                }
+        }
+
 
 #if defined(CONFIG_ROCKCHIP_IOMMU)
  if (dev_drv->iommu_enabled)
  freed_addr[freed_index] = 0xfefefefe;
 #endif
  }
- for (i = 0; i < regs->win_num; i++) {
- memcpy(&g_reg_win_data[i], &(regs->reg_win_data[i]),
-       sizeof(struct rk_fb_reg_win_data));
- }
- g_last_win_num = regs->win_num;
+
+   if(dev_drv->id==0)
+   {
+           for (i = 0; i < regs->win_num; i++) {
+                   memcpy(&lcdc0_g_reg_win_data[i], &(regs->reg_win_data[i]),
+                          sizeof(struct rk_fb_reg_win_data));
+           }
+           lcdc0_g_last_win_num = regs->win_num;
+           //printk("---lcdc0 %s  g_last_win_num =%d\n",__FUNCTION__,lcdc0_g_last_win_num);
+
+   }
+   else
+   {
+           for (i = 0; i < regs->win_num; i++) {
+                   memcpy(&lcdc1_g_reg_win_data[i], &(regs->reg_win_data[i]),
+                          sizeof(struct rk_fb_reg_win_data));
+           }
+           lcdc1_g_last_win_num = regs->win_num;
+           //printk("---lcdc1 %s  g_last_win_num =%d\n",__FUNCTION__,lcdc1_g_last_win_num);
+    }
  g_first_buf = 0;
 }
 
@@ -2061,11 +2136,11 @@ static void rk_fb_update_regs_handler(struct kthread_work *work)
  /* struct list_head saved_list; */
 
  mutex_lock(&dev_drv->update_regs_list_lock);
- saved_list = dev_drv->update_regs_list;
- list_replace_init(&dev_drv->update_regs_list, &saved_list);
+ dev_drv->saved_list = dev_drv->update_regs_list;
+ list_replace_init(&dev_drv->update_regs_list, &dev_drv->saved_list);
  mutex_unlock(&dev_drv->update_regs_list_lock);
 
- list_for_each_entry_safe(data, next, &saved_list, list) {
+ list_for_each_entry_safe(data, next, &dev_drv->saved_list, list) {
  rk_fb_update_reg(dev_drv, data);
  list_del(&data->list);
  kfree(data);
@@ -2449,11 +2524,11 @@ static int rk_fb_set_win_config(struct fb_info *info,
  } else {
  mutex_lock(&dev_drv->update_regs_list_lock);
  list_is_empty = list_empty(&dev_drv->update_regs_list) &&
- list_empty(&saved_list);
+ list_empty(&dev_drv->saved_list);
  mutex_unlock(&dev_drv->update_regs_list_lock);
  if (!list_is_empty) {
  ret = wait_event_timeout(dev_drv->update_regs_wait,
- list_empty(&dev_drv->update_regs_list) && list_empty(&saved_list),
+ list_empty(&dev_drv->update_regs_list) && list_empty(&dev_drv->saved_list),
  msecs_to_jiffies(60));
  if (ret > 0)
  rk_fb_update_reg(dev_drv, regs);
@@ -2692,6 +2767,10 @@ static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd,
  case RK_FBIOSET_ENABLE:
  if (copy_from_user(&enable, argp, sizeof(enable)))
  return -EFAULT;
+ if (enable)
+ fb_par->state++;
+ else
+ fb_par->state--;
  dev_drv->ops->open(dev_drv, win_id, enable);
  break;
  case RK_FBIOGET_ENABLE:
@@ -3008,6 +3087,7 @@ static ssize_t rk_fb_write(struct fb_info *info, const char __user *buf,
  return (cnt) ? cnt : err;
 }
 
+#ifdef HDMI_SET_BY_FB
 /*
  * function: update extend info acorrding to primary info that only used for dual display mode
  * @ext_info: the fb_info of extend screen
@@ -3077,6 +3157,7 @@ static int rk_fb_update_ext_info(struct fb_info *ext_info,
 
  return 0;
 }
+#endif
 
 static int rk_fb_set_par(struct fb_info *info)
 {
@@ -3251,6 +3332,11 @@ static int rk_fb_set_par(struct fb_info *info)
  (win->format == ABGR888)) ? 1 : 0;
  win->g_alpha_val = 0;
 
+ if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
+    (win->format == YUV420 || win->format == YUV420_A))
+    win->state = 1;
+
+ #ifdef HDMI_SET_BY_FB
  if (rk_fb->disp_mode == DUAL) {
  if (extend_win->state && hdmi_switch_complete) {
  if (info != extend_info) {
@@ -3261,6 +3347,7 @@ static int rk_fb_set_par(struct fb_info *info)
  }
  }
  }
+ #endif
  dev_drv->ops->set_par(dev_drv, win_id);
 
  return 0;
@@ -3462,9 +3549,11 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
 {
  struct rk_fb *rk_fb =  platform_get_drvdata(fb_pdev);
  struct fb_info *info = NULL;
- struct fb_info *pmy_info = NULL;
  struct rk_fb_par *fb_par = NULL;
+#ifdef HDMI_SET_BY_FB
+ struct fb_info *pmy_info = NULL;
  struct rk_fb_par *pmy_fb_par = NULL;
+#endif
  struct rk_lcdc_driver *dev_drv = NULL;
  char name[6] = {0};
  int i, win_id, load_screen = 0;
@@ -3525,10 +3614,10 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
  } else if (rk_fb->num_lcdc > 1) {
  /* If there is more than one lcdc device, we disable
    the layer which attached to this device */
- for (i = 0; i < dev_drv->lcdc_win_num; i++) {
+ /*for (i = 0; i < dev_drv->lcdc_win_num; i++) {
  if (dev_drv->win[i] && dev_drv->win[i]->state)
  dev_drv->ops->open(dev_drv, i, 0);
- }
+ }*/
  }
 
  hdmi_switch_complete = 0;
@@ -3548,6 +3637,7 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
  fb_par = (struct rk_fb_par *)info->par;
  win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
  if (dev_drv->win[win_id]) {
+ #ifdef HDMI_SET_BY_FB
  if (rk_fb->disp_mode == DUAL) {
  pmy_info = rk_fb->fb[i];
  if (pmy_info != info) {
@@ -3556,6 +3646,7 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
  fb_par->state = pmy_fb_par->state;
  }
  }
+ #endif
  if (fb_par->state) {
  if (!dev_drv->win[win_id]->state)
  dev_drv->ops->open(dev_drv, win_id, 1);
@@ -3565,7 +3656,9 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
  }
  info->var.activate |= FB_ACTIVATE_FORCE;
  if (rk_fb->disp_mode == DUAL) {
+ #ifdef HDMI_SET_BY_FB
  rk_fb_update_ext_info(info, pmy_info, 1);
+ #endif
  } else if (rk_fb->disp_mode == ONE_DUAL) {
  info->var.grayscale &= 0xff;
  info->var.grayscale |=
@@ -3649,7 +3742,9 @@ int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id)
  dev_drv->cur_screen->xsize = screen_x * scale_x / 100;
  dev_drv->cur_screen->ysize = screen_y * scale_y / 100;
  if (inf->disp_mode == DUAL) {
+ #ifdef HDMI_SET_BY_FB
  rk_fb_update_ext_info(info, pmy_info, 0);
+ #endif
  } else {
  var->nonstd &= 0xff;
  var->nonstd |= (xpos << 8) + (ypos << 20);
@@ -3887,6 +3982,7 @@ static int init_lcdc_device_driver(struct rk_fb *rk_fb,
  init_completion(&dev_drv->frame_done);
  spin_lock_init(&dev_drv->cpl_lock);
  mutex_init(&dev_drv->fb_win_id_mutex);
+ mutex_init(&dev_drv->win_config);
  dev_drv->ops->fb_win_remap(dev_drv, dev_drv->fb_win_map);
  dev_drv->first_frame = 1;
  dev_drv->overscan.left = 100;
diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h
index 1c4ec6d..f847c14 100755
--- a/include/linux/rk_fb.h
+++ b/include/linux/rk_fb.h
@@ -562,6 +562,7 @@ struct rk_lcdc_driver {
 
  struct rk_fb_reg_area_data reg_area_data;
  struct mutex fb_win_id_mutex;
+ struct mutex win_config;
 
  struct completion frame_done;/*sync for pan_display,whe we set a new
   frame address to lcdc register,we must
@@ -575,6 +576,7 @@ struct rk_lcdc_driver {
  int timeline_max;
  int suspend_flag;
  struct list_headupdate_regs_list;
+ struct list_head    saved_list;
  struct mutexupdate_regs_list_lock;
  struct kthread_workerupdate_regs_worker;
  struct task_struct*update_regs_thread;
-- 
1.7.9.5
kernel\drivers\video\rockchip\screen\rk_screen.c



#include
#include
#include "lcd.h"
#include "../hdmi/rk_hdmi.h"


static struct rk_screen *prmry_screen;
static struct rk_screen *extend_screen;


static void rk_screen_info_error(struct rk_screen *screen, int prop)
{
pr_err(">>>>>>>>>>>>>>>>>>>>error<<<<<<<<<<<<<<<<<<<<\n");
pr_err(">>please init %s screen info in dtsi file<<\n",
      (prop == PRMRY) ? "prmry" : "extend");
pr_err(">>>>>>>>>>>>>>>>>>>>error<<<<<<<<<<<<<<<<<<<<\n");
}


int  rk_fb_get_prmry_screen(struct rk_screen *screen)
{
if (unlikely(!prmry_screen) || unlikely(!screen))
return -1;


memcpy(screen, prmry_screen, sizeof(struct rk_screen));
return 0;
}


int rk_fb_get_extend_screen(struct rk_screen *screen)
{
if (unlikely(!extend_screen) || unlikely(!screen))
return -1;

memcpy(screen, extend_screen, sizeof(struct rk_screen));
return 0;
}


int rk_fb_get_screen(struct rk_screen *screen, int prop)
{
struct rk_screen *cur_screen = NULL;
if (unlikely(!screen))
return -1;

if (prop == PRMRY) {
if (unlikely(!prmry_screen)) {
rk_screen_info_error(screen, prop);
return -1;
}
cur_screen = prmry_screen;
} else {
if (unlikely(!extend_screen)) {
rk_screen_info_error(screen, prop);
return -1;
}
cur_screen = extend_screen;
}


memcpy(screen, cur_screen, sizeof(struct rk_screen));

return 0;
}


int rk_fb_set_screen(struct rk_screen *screen, int prop)
{
struct rk_screen *cur_screen = NULL;


if (unlikely(!screen))
return -1;
if (prop == PRMRY) {
if (unlikely(!prmry_screen)) {
rk_screen_info_error(screen, prop);
return -1;
}
cur_screen = prmry_screen;
} else {
if (unlikely(!extend_screen)) {
rk_screen_info_error(screen, prop);
return -1;
}
cur_screen = extend_screen;
}


cur_screen->lcdc_id = screen->lcdc_id;
cur_screen->screen_id = screen->screen_id;
cur_screen->x_mirror = screen->x_mirror;
cur_screen->y_mirror = screen->y_mirror;
cur_screen->overscan.left = screen->overscan.left;
cur_screen->overscan.top = screen->overscan.left;
cur_screen->overscan.right = screen->overscan.left;
cur_screen->overscan.bottom = screen->overscan.left;


return 0;
}


size_t get_fb_size(u8 reserved_fb, struct rk_screen *screen)
{
size_t size = 0;
u32 xres = 0;
u32 yres = 0;


if (unlikely(!screen))
return 0;


xres = screen->mode.xres;
yres = screen->mode.yres;


/* align as 64 bytes(16*4) in an odd number of times */
xres = ALIGN_64BYTE_ODD_TIMES(xres, ALIGN_PIXEL_64BYTE_RGB8888);


if (reserved_fb == 1) {
size = (xres * yres << 2) << 1;/*two buffer*/
} else {
#if defined(CONFIG_THREE_FB_BUFFER)
size = (xres * yres << 2) * 3;/* three buffer */
#else
size = (xres * yres << 2) << 1; /* two buffer */
#endif
}
return ALIGN(size, SZ_1M);
}


#define FB_4K_SIZE      (3840UL*2160UL*2)
size_t get_rotate_fb_size(struct rk_screen *screen)
{
size_t size = 0;
u32 xres = 0;
u32 yres = 0;


if (unlikely(!screen))
return 0;


xres = screen->mode.xres;
yres = screen->mode.yres;


/* align as 64 bytes(16*4) number of times */
xres = ALIGN_N_TIMES(xres, ALIGN_PIXEL_64BYTE_RGB8888);


size = (xres * yres << 2) << 1; /* two buffer */
        size += 2 * FB_4K_SIZE; /* two full RGB size and two 4k size */
return ALIGN(size, SZ_1M);
}


static int rk_screen_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *screen_np;
struct rk_screen *rk_screen;
int ret, screen_prop;


if (!np) {
dev_err(&pdev->dev, "Missing device tree node.\n");
return -EINVAL;
}
for_each_child_of_node(np, screen_np) {
rk_screen = devm_kzalloc(&pdev->dev,
sizeof(struct rk_screen), GFP_KERNEL);
if (!rk_screen) {
dev_err(&pdev->dev, "kmalloc for rk screen fail!");
return  -ENOMEM;
}
rk_screen->pwrlist_head = devm_kzalloc(&pdev->dev,
sizeof(struct list_head), GFP_KERNEL);
if (!rk_screen->pwrlist_head) {
dev_err(&pdev->dev, "kmalloc for rk_screen pwrlist_head fail!");
return  -ENOMEM;
}
of_property_read_u32(screen_np, "screen_prop", &screen_prop);
if (screen_prop == PRMRY)
prmry_screen = rk_screen;
else if (screen_prop == EXTEND)
extend_screen = rk_screen;
else
dev_err(&pdev->dev, "unknow screen prop: %d\n",
screen_prop);
rk_screen->prop = screen_prop;
of_property_read_u32(screen_np, "native-mode", &rk_screen->native_mode);
rk_screen->dev = &pdev->dev;
ret = rk_fb_prase_timing_dt(screen_np, rk_screen);
pr_info("%s screen timing parse %s\n",
(screen_prop == PRMRY) ? "prmry" : "extend",
ret ? "failed" : "success");
ret = rk_disp_pwr_ctr_parse_dt(screen_np, rk_screen);
pr_info("%s screen power ctrl parse %s\n",
(screen_prop == PRMRY) ? "prmry" : "extend",
ret ? "failed" : "success");
}
dev_info(&pdev->dev, "rockchip screen probe success\n");
return 0;
}


static const struct of_device_id rk_screen_dt_ids[] = {
{ .compatible = "rockchip,screen", },
{}
};


static struct platform_driver rk_screen_driver = {
.probe = rk_screen_probe,
.driver = {
.name = "rk-screen",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(rk_screen_dt_ids),
},
};


static int __init rk_screen_init(void)
{
return platform_driver_register(&rk_screen_driver);
}


static void __exit rk_screen_exit(void)
{
platform_driver_unregister(&rk_screen_driver);
}


fs_initcall(rk_screen_init);
module_exit(rk_screen_exit);



其他源码请到 http://download.csdn.net/download/baimingyong007/9931546 下载。


你可能感兴趣的:(rk3288 android 4.4.4 双屏异显)