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 =};
&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 下载。