}
static int rk3036_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv,
- int win_id)
+ int win_id,
+ int area_id)
{
return dev_drv->win[win_id]->state;
}
}
static int rk3036_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,
- unsigned int *dsp_addr)
+ unsigned int dsp_addr[][4])
{
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);
+ dsp_addr[0][0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
+ dsp_addr[1][0] = lcdc_readl(lcdc_dev, WIN1_MST);
}
return 0;
}
return win_id;
}
-static int rk312x_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv, int win_id)
+static int rk312x_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv,
+ int win_id,
+ int area_id)
{
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
}
static int rk312x_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,
- unsigned int *dsp_addr)
+ unsigned int dsp_addr[][4])
{
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[0][0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
if (lcdc_dev->soc_type == VOP_RK3036)
- dsp_addr[1] = lcdc_readl(lcdc_dev, WIN1_MST);
+ dsp_addr[1][0] = lcdc_readl(lcdc_dev, WIN1_MST);
else if (lcdc_dev->soc_type == VOP_RK312X)
- dsp_addr[1] = lcdc_readl(lcdc_dev, WIN1_MST_RK312X);
+ dsp_addr[1][0] = lcdc_readl(lcdc_dev, WIN1_MST_RK312X);
}
return 0;
}
return 0;
}
-static int rk3188_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv, int win_id)
+static int rk3188_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv,
+ int win_id,
+ int area_id)
{
return 0;
}
}
-static int rk3188_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,unsigned int *dsp_addr)
+static int rk3188_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,unsigned int dsp_addr[][4])
{
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_MST0);
- dsp_addr[1] = lcdc_readl(lcdc_dev, WIN1_MST);
+ dsp_addr[0][0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST0);
+ dsp_addr[1][0] = lcdc_readl(lcdc_dev, WIN1_MST);
}
return 0;
}
return 0;
}
-static int rk3288_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv, int win_id)
-{
- struct lcdc_device *lcdc_dev =
- container_of(dev_drv, struct lcdc_device, driver);
- int win_status = 0;
- if (win_id == 0)
- win_status = lcdc_read_bit(lcdc_dev, WIN0_CTRL0, m_WIN0_EN);
- else if (win_id == 1)
- win_status = lcdc_read_bit(lcdc_dev, WIN1_CTRL0, m_WIN1_EN);
- else if (win_id == 2)
- win_status = lcdc_read_bit(lcdc_dev, WIN2_CTRL0, m_WIN2_EN);
- else if (win_id == 3)
- win_status = lcdc_read_bit(lcdc_dev, WIN3_CTRL0, m_WIN3_EN);
- else if (win_id == 4)
- win_status = lcdc_read_bit(lcdc_dev, HWC_CTRL0, m_HWC_EN);
- else
- pr_err("!!!%s,win_id :%d,unsupport!!!\n",__func__,win_id);
-
- return win_status;
+static int rk3288_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv,
+ int win_id, int area_id)
+{
+ struct lcdc_device *lcdc_dev =
+ container_of(dev_drv, struct lcdc_device, driver);
+ u32 win_ctrl = 0;
+ u32 area_status = 0;
+
+ switch (win_id) {
+ case 0:
+ win_ctrl = lcdc_readl(lcdc_dev, WIN0_CTRL0);
+ area_status = win_ctrl & m_WIN0_EN;
+ break;
+ case 1:
+ win_ctrl = lcdc_readl(lcdc_dev, WIN1_CTRL0);
+ area_status = win_ctrl & m_WIN1_EN;
+ break;
+ case 2:
+ win_ctrl = lcdc_readl(lcdc_dev, WIN2_CTRL0);
+ if (area_id == 0)
+ area_status = win_ctrl & m_WIN2_MST0_EN;
+ if (area_id == 1)
+ area_status = win_ctrl & m_WIN2_MST1_EN;
+ if (area_id == 2)
+ area_status = win_ctrl & m_WIN2_MST2_EN;
+ if (area_id == 3)
+ area_status = win_ctrl & m_WIN2_MST3_EN;
+ break;
+ case 3:
+ win_ctrl = lcdc_readl(lcdc_dev, WIN3_CTRL0);
+ if (area_id == 0)
+ area_status = win_ctrl & m_WIN3_MST0_EN;
+ if (area_id == 1)
+ area_status = win_ctrl & m_WIN3_MST1_EN;
+ if (area_id == 2)
+ area_status = win_ctrl & m_WIN3_MST2_EN;
+ if (area_id == 3)
+ area_status = win_ctrl & m_WIN3_MST3_EN;
+ break;
+ case 4:
+ win_ctrl = lcdc_readl(lcdc_dev, HWC_CTRL0);
+ area_status = win_ctrl & m_HWC_EN;
+ break;
+ default:
+ pr_err("!!!%s,win[%d]area[%d],unsupport!!!\n",__func__,win_id,area_id);
+ break;
+ }
+ return area_status;
+}
+
+static int rk3288_lcdc_get_area_num(struct rk_lcdc_driver *dev_drv,
+ unsigned int *area_support)
+{
+ area_support[0] = 1;
+ area_support[1] = 1;
+ area_support[2] = 4;
+ area_support[3] = 4;
+
+ return 0;
}
/*overlay will be do at regupdate*/
return ret;
}
-static int rk3288_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,unsigned int *dsp_addr)
+
+static int rk3288_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,
+ unsigned int dsp_addr[][4])
{
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
spin_lock(&lcdc_dev->reg_lock);
- if(lcdc_dev->clk_on){
- dsp_addr[0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
- dsp_addr[1] = lcdc_readl(lcdc_dev, WIN1_YRGB_MST);
- dsp_addr[2] = lcdc_readl(lcdc_dev, WIN2_MST0);
- dsp_addr[3] = lcdc_readl(lcdc_dev, WIN3_MST0);
+ if (lcdc_dev->clk_on) {
+ dsp_addr[0][0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
+ dsp_addr[1][0] = lcdc_readl(lcdc_dev, WIN1_YRGB_MST);
+ dsp_addr[2][0] = lcdc_readl(lcdc_dev, WIN2_MST0);
+ dsp_addr[2][1] = lcdc_readl(lcdc_dev, WIN2_MST1);
+ dsp_addr[2][2] = lcdc_readl(lcdc_dev, WIN2_MST2);
+ dsp_addr[2][3] = lcdc_readl(lcdc_dev, WIN2_MST3);
+ dsp_addr[3][0] = lcdc_readl(lcdc_dev, WIN3_MST0);
+ dsp_addr[3][1] = lcdc_readl(lcdc_dev, WIN3_MST1);
+ dsp_addr[3][2] = lcdc_readl(lcdc_dev, WIN3_MST2);
+ dsp_addr[3][3] = lcdc_readl(lcdc_dev, WIN3_MST3);
}
spin_unlock(&lcdc_dev->reg_lock);
return 0;
.suspend = rk3288_lcdc_early_suspend,
.resume = rk3288_lcdc_early_resume,
.get_win_state = rk3288_lcdc_get_win_state,
+ .area_support_num = rk3288_lcdc_get_area_num,
.ovl_mgr = rk3288_lcdc_ovl_mgr,
.get_disp_info = rk3288_lcdc_get_disp_info,
.fps_mgr = rk3288_lcdc_fps_mgr,
return win_data;
}
+static int rk_fb_reg_effect(struct rk_lcdc_driver *dev_drv,
+ struct rk_fb_reg_data *regs,
+ int count)
+{
+ struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
+ int i, j, wait_for_vsync = false;
+ unsigned int dsp_addr[5][4];
+ unsigned int area_support[5] = {1, 1, 1, 1, 1};
+ int win_status = 0;
+
+ if (dev_drv->ops->get_dsp_addr)
+ dev_drv->ops->get_dsp_addr(dev_drv, dsp_addr);
+
+ if (dev_drv->ops->area_support_num)
+ dev_drv->ops->area_support_num(dev_drv, area_support);
+
+ for (i = 0; i < dev_drv->lcdc_win_num; i++) {
+ if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
+ (!strcmp(dev_drv->win[i]->name, "hwc")))
+ continue;
+
+ for (j = 0;j < RK_WIN_MAX_AREA; j++) {
+ if ((j > 0) && (area_support[i] == 1)) {
+ continue;
+ }
+ if (dev_drv->win[i]->area[j].state == 1) {
+ u32 new_start =
+ dev_drv->win[i]->area[j].smem_start +
+ dev_drv->win[i]->area[j].y_offset;
+ u32 reg_start = dsp_addr[i][j];
+ if ((rk_fb->disp_policy ==
+ DISPLAY_POLICY_BOX) &&
+ (dev_drv->suspend_flag))
+ continue;
+ if (unlikely(new_start != reg_start)) {
+ wait_for_vsync = true;
+ dev_info(dev_drv->dev,
+ "win%d:new_addr:0x%08x cur_addr:0x%08x--%d\n",
+ i, new_start, reg_start, 101 - count);
+ break;
+ }
+ } else if (dev_drv->win[i]->area[j].state == 0) {
+ if (dev_drv->ops->get_win_state) {
+ win_status =
+ dev_drv->ops->get_win_state(dev_drv, i, j);
+ if (win_status)
+ wait_for_vsync = true;
+ }
+ } else {
+ pr_err("!!!win[%d]state:%d,error!!!\n",
+ i, dev_drv->win[i]->state);
+ }
+ }
+ }
+
+ return wait_for_vsync;
+}
+
static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv,
struct rk_fb_reg_data *regs)
{
struct rk_fb_reg_win_data *win_data;
bool wait_for_vsync;
int count = 100;
- unsigned int dsp_addr[4];
long timeout;
- int win_status = 0;
/* acq_fence wait */
for (i = 0; i < regs->win_num; i++) {
ktime_compare(dev_drv->vsync_info.timestamp, timestamp) > 0,
msecs_to_jiffies(25));
- 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 (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
- (!strcmp(dev_drv->win[i]->name, "hwc")))
- continue;
- if (dev_drv->win[i]->state == 1) {
- u32 new_start =
- dev_drv->win[i]->area[0].smem_start +
- dev_drv->win[i]->area[0].y_offset;
- u32 reg_start = dsp_addr[i];
-
- if ((rk_fb->disp_policy ==
- DISPLAY_POLICY_BOX) &&
- (dev_drv->suspend_flag))
- continue;
- if (unlikely(new_start != reg_start)) {
- wait_for_vsync = true;
- dev_info(dev_drv->dev,
- "win%d:new_addr:0x%08x cur_addr:0x%08x--%d\n",
- i, new_start, reg_start, 101 - count);
- break;
- }
- } else if (dev_drv->win[i]->state == 0) {
- if (dev_drv->ops->get_win_state) {
- win_status =
- dev_drv->ops->get_win_state(dev_drv, i);
- if (win_status)
- wait_for_vsync = true;
- }
- } else {
- pr_err("!!!win[%d]state:%d,error!!!\n",
- i, dev_drv->win[i]->state);
- }
- }
+ wait_for_vsync = rk_fb_reg_effect(dev_drv, regs, count);
} while (wait_for_vsync && count--);
#ifdef H_USE_FENCE
sw_sync_timeline_inc(dev_drv->timeline, 1);
#endif
+
if (dev_drv->front_regs) {
#if defined(CONFIG_ROCKCHIP_IOMMU)
if (dev_drv->iommu_enabled) {
int num_buf; /* buffer_number */
int ret;
struct rk_fb_win_cfg_data win_data;
- unsigned int dsp_addr[4];
+ unsigned int dsp_addr[4][4];
int list_stat;
int win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
dev_drv->ops->open(dev_drv, win_id, enable);
break;
case RK_FBIOGET_ENABLE:
- enable = dev_drv->ops->get_win_state(dev_drv, win_id);
+ enable = dev_drv->ops->get_win_state(dev_drv, win_id, 0);
if (copy_to_user(argp, &enable, sizeof(enable)))
return -EFAULT;
break;
struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
- int state = dev_drv->ops->get_win_state(dev_drv, win_id);
+ int state = dev_drv->ops->get_win_state(dev_drv, win_id, 0);
return snprintf(buf, PAGE_SIZE, "%s\n", state ? "enabled" : "disabled");
}
int (*post_dspbuf)(struct rk_lcdc_driver *dev_drv, u32 rgb_mst,
int format, u16 xact, u16 yact, u16 xvir);
- int (*get_win_state) (struct rk_lcdc_driver *dev_drv, int layer_id);
+ int (*get_win_state) (struct rk_lcdc_driver *dev_drv, int layer_id, int area_id);
int (*ovl_mgr) (struct rk_lcdc_driver *dev_drv, int swap, bool set); /*overlay manager*/
int (*fps_mgr) (struct rk_lcdc_driver *dev_drv, int fps, bool set);
int (*fb_get_win_id) (struct rk_lcdc_driver *dev_drv, const char *id); /*find layer for fb*/
int (*dpi_open) (struct rk_lcdc_driver *dev_drv, bool open);
int (*dpi_win_sel) (struct rk_lcdc_driver *dev_drv, int layer_id);
int (*dpi_status) (struct rk_lcdc_driver *dev_drv);
- int (*get_dsp_addr)(struct rk_lcdc_driver *dev_drv,unsigned int *dsp_addr);
+ int (*get_dsp_addr)(struct rk_lcdc_driver *dev_drv, unsigned int dsp_addr[][4]);
int (*set_dsp_cabc) (struct rk_lcdc_driver *dev_drv, int mode, int calc, int up, int down, int global);
int (*set_dsp_bcsh_hue) (struct rk_lcdc_driver *dev_drv,int sin_hue, int cos_hue);
int (*set_dsp_bcsh_bcs)(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode,int value);
struct overscan *overscan);
int (*dsp_black) (struct rk_lcdc_driver *dev_drv, int enable);
int (*backlight_close)(struct rk_lcdc_driver *dev_drv, int enable);
+ int (*area_support_num)(struct rk_lcdc_driver *dev_drv, unsigned int *area_support);
};
struct rk_fb_area_par {