From ca3e9cef1625f536a2028cf11268f499bae1e482 Mon Sep 17 00:00:00 2001 From: Huang Jiachai Date: Wed, 27 Jan 2016 19:38:22 +0800 Subject: [PATCH] video: rockchip: add vop config for write back function Change-Id: I8d27bb44fa1e8b30b422f2692a257ac9e0282f5e Signed-off-by: Huang Jiachai (cherry picked from commit e853ac5f48c0d6da970def84c465ce319ab6f1a8) --- drivers/video/rockchip/rk_fb.c | 86 +++++++++++++++++++++++++++++++++- include/linux/rk_fb.h | 41 +++++++++++++++- 2 files changed, 123 insertions(+), 4 deletions(-) diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index 7758ca9ab56f..e8eeda5e0764 100644 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -1513,6 +1513,18 @@ int rk_fb_sysmmu_fault_handler(struct device *dev, 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) { @@ -1536,7 +1548,6 @@ void rk_fb_free_dma_buf(struct rk_lcdc_driver *dev_drv, 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, @@ -1817,6 +1828,9 @@ static void rk_fb_update_reg(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 */ @@ -1853,6 +1867,13 @@ static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv, } 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); @@ -1887,6 +1908,9 @@ static void rk_fb_update_reg(struct rk_lcdc_driver *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); @@ -2046,6 +2070,62 @@ static int rk_fb_config_backup(struct rk_lcdc_driver *dev_drv, 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) @@ -2427,7 +2507,9 @@ static int rk_fb_set_win_config(struct fb_info *info, 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; diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h index d9a34047eabf..9601168822ec 100755 --- a/include/linux/rk_fb.h +++ b/include/linux/rk_fb.h @@ -266,6 +266,20 @@ typedef enum { 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; @@ -328,6 +342,16 @@ struct rk_lcdc_post_cfg { 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; @@ -500,6 +524,7 @@ struct rk_lcdc_drv_ops { 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 { @@ -540,7 +565,17 @@ struct rk_fb_win_cfg_data { 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 { @@ -597,7 +632,7 @@ struct rk_fb_reg_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 { @@ -606,8 +641,10 @@ 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; -- 2.34.1