return 0;
}
+void rk_fb_free_wb_buf(struct rk_lcdc_driver *dev_drv,
+ struct rk_fb_reg_wb_data *wb_data)
+{
+ struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
+
+ if (dev_drv->iommu_enabled && wb_data->ion_handle)
+ ion_unmap_iommu(dev_drv->dev, rk_fb->ion_client,
+ wb_data->ion_handle);
+ if (wb_data->ion_handle)
+ ion_free(rk_fb->ion_client, wb_data->ion_handle);
+}
+
void rk_fb_free_dma_buf(struct rk_lcdc_driver *dev_drv,
struct rk_fb_reg_win_data *reg_win_data)
{
if (area_data->acq_fence)
sync_fence_put(area_data->acq_fence);
}
- memset(reg_win_data, 0, sizeof(struct rk_fb_reg_win_data));
}
static void rk_fb_update_win(struct rk_lcdc_driver *dev_drv,
win_data = ®s->reg_win_data[i];
rk_fb_free_dma_buf(dev_drv, win_data);
}
+ if (dev_drv->property.feature & SUPPORT_WRITE_BACK)
+ rk_fb_free_wb_buf(dev_drv, ®s->reg_wb_data);
+ kfree(regs);
return;
}
/* acq_fence wait */
}
dev_drv->ops->ovl_mgr(dev_drv, 0, 1);
+ if (dev_drv->property.feature & SUPPORT_WRITE_BACK) {
+ memcpy(&dev_drv->wb_data, ®s->reg_wb_data,
+ sizeof(struct rk_fb_reg_wb_data));
+ if (dev_drv->ops->set_wb)
+ dev_drv->ops->set_wb(dev_drv);
+ }
+
if (rk_fb_iommu_debug > 0)
pagefault = rk_fb_iommu_page_fault_dump(dev_drv);
win_data = &dev_drv->front_regs->reg_win_data[i];
rk_fb_free_dma_buf(dev_drv, win_data);
}
+ if (dev_drv->property.feature & SUPPORT_WRITE_BACK)
+ rk_fb_free_wb_buf(dev_drv,
+ &dev_drv->front_regs->reg_wb_data);
kfree(dev_drv->front_regs);
mutex_unlock(&dev_drv->front_lock);
return 0;
}
+
+static int rk_fb_set_wb_buffer(struct fb_info *info,
+ struct rk_fb_wb_cfg *wb_cfg,
+ struct rk_fb_reg_wb_data *wb_data)
+{
+ int ret = 0;
+ ion_phys_addr_t phy_addr;
+ size_t len;
+ u8 fb_data_fmt;
+ struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
+ struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
+ struct rk_fb *rk_fb = dev_get_drvdata(info->device);
+
+ if ((wb_cfg->phy_addr == 0) && (wb_cfg->ion_fd == 0)) {
+ wb_data->state = 0;
+ return 0;
+ }
+ if (wb_cfg->phy_addr == 0) {
+ wb_data->ion_handle =
+ ion_import_dma_buf(rk_fb->ion_client,
+ wb_cfg->ion_fd);
+ if (IS_ERR(wb_data->ion_handle)) {
+ pr_info("Could not import handle: %ld\n",
+ (long)wb_data->ion_handle);
+ return -EINVAL;
+ }
+ if (dev_drv->iommu_enabled)
+ ret = ion_map_iommu(dev_drv->dev,
+ rk_fb->ion_client,
+ wb_data->ion_handle,
+ (unsigned long *)&phy_addr,
+ (unsigned long *)&len);
+ else
+ ret = ion_phys(rk_fb->ion_client, wb_data->ion_handle,
+ &phy_addr, &len);
+ if (ret < 0) {
+ pr_err("ion map to get phy addr failed\n");
+ ion_free(rk_fb->ion_client, wb_data->ion_handle);
+ return -ENOMEM;
+ }
+ wb_data->smem_start = phy_addr;
+ } else {
+ wb_data->smem_start = wb_cfg->phy_addr;
+ }
+
+ fb_data_fmt = rk_fb_data_fmt(wb_cfg->data_format, 0);
+ if (IS_YUV_FMT(fb_data_fmt))
+ wb_data->cbr_start = wb_data->smem_start +
+ wb_cfg->xsize * wb_cfg->ysize;
+ wb_data->xsize = wb_cfg->xsize;
+ wb_data->ysize = wb_cfg->ysize;
+ wb_data->state = 1;
+
+ return 0;
+}
+
static int rk_fb_set_win_buffer(struct fb_info *info,
struct rk_fb_win_par *win_par,
struct rk_fb_reg_win_data *reg_win_data)
win_data->win_par[i].win_id);
}
}
-
+ if (dev_drv->property.feature & SUPPORT_WRITE_BACK)
+ rk_fb_set_wb_buffer(info, &win_data->wb_cfg,
+ ®s->reg_wb_data);
if (regs->win_num <= 0)
goto err_null_frame;
UNMASK_PAGE_FAULT = 0x2
} extern_func;
+enum rk_vop_feature {
+ SUPPORT_VOP_IDENTIFY = BIT(0),
+ SUPPORT_IFBDC = BIT(1),
+ SUPPORT_AFBDC = BIT(2),
+ SUPPORT_WRITE_BACK = BIT(3),
+ SUPPORT_YUV420_OUTPUT = BIT(4)
+};
+
+struct rk_vop_property {
+ u32 feature;
+ u32 max_output_x;
+ u32 max_output_y;
+};
+
struct rk_fb_rgb {
struct fb_bitfield red;
struct fb_bitfield green;
u32 ysize;
};
+struct rk_fb_wb_cfg {
+ u8 data_format;
+ short ion_fd;
+ u32 phy_addr;
+ u16 xsize;
+ u16 ysize;
+ u8 reserved0;
+ u32 reversed1;
+};
+
struct rk_lcdc_bcsh {
bool enable;
u16 brightness;
int (*area_support_num)(struct rk_lcdc_driver *dev_drv, unsigned int *area_support);
int (*extern_func)(struct rk_lcdc_driver *dev_drv, int cmd);
int (*wait_frame_start)(struct rk_lcdc_driver *dev_drv, int enable);
+ int (*set_wb)(struct rk_lcdc_driver *dev_drv);
};
struct rk_fb_area_par {
short ret_fence_fd;
short rel_fence_fd[RK_MAX_BUF_NUM];
struct rk_fb_win_par win_par[RK30_MAX_LAYER_SUPPORT];
- struct rk_lcdc_post_cfg post_cfg;
+ struct rk_fb_wb_cfg wb_cfg;
+};
+
+struct rk_fb_reg_wb_data {
+ bool state;
+ u8 data_format;
+ struct ion_handle *ion_handle;
+ unsigned long smem_start;
+ unsigned long cbr_start; /*Cbr memory start address*/
+ u16 xsize;
+ u16 ysize;
};
struct rk_fb_reg_area_data {
int buf_num;
int acq_num;
struct rk_fb_reg_win_data reg_win_data[RK30_MAX_LAYER_SUPPORT];
- struct rk_lcdc_post_cfg post_cfg;
+ struct rk_fb_reg_wb_data reg_wb_data;
};
struct rk_lcdc_driver {
int prop;
struct device *dev;
u32 version;
+ struct rk_vop_property property;
struct rk_lcdc_win *win[RK_MAX_FB_SUPPORT];
+ struct rk_fb_reg_wb_data wb_data;
int lcdc_win_num;
int num_buf; //the num_of buffer
int atv_layer_cnt;