break;
}
lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
+#ifdef USE_ION_MMU
+ mask = m_MMU_EN;
+ val = v_MMU_EN(1);
+ lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
+ mask = m_AXI_MAX_OUTSTANDING_EN | m_AXI_OUTSTANDING_MAX_NUM;
+ val = v_AXI_OUTSTANDING_MAX_NUM(31) | v_AXI_MAX_OUTSTANDING_EN(1);
+ lcdc_msk_reg(lcdc_dev, SYS_CTRL1, mask, val);
+#endif
#ifndef CONFIG_RK_FPGA
writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_SOC_CON6);
#endif
val = v_WIN0_EMPTY_INTR_EN(1) | v_WIN1_EMPTY_INTR_EN(1) | v_WIN2_EMPTY_INTR_EN(1) |
v_WIN3_EMPTY_INTR_EN(1)| v_HWC_EMPTY_INTR_EN(1) | v_POST_BUF_EMPTY_INTR_EN(1) |
v_PWM_GEN_INTR_EN(1);
- lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);
+ /*lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);*/
#endif
lcdc_cfg_done(lcdc_dev);
val = v_WIN0_EMPTY_INTR_EN(1) | v_WIN1_EMPTY_INTR_EN(1) | v_WIN2_EMPTY_INTR_EN(1) |
v_WIN3_EMPTY_INTR_EN(1)| v_HWC_EMPTY_INTR_EN(1) | v_POST_BUF_EMPTY_INTR_EN(1) |
v_PWM_GEN_INTR_EN(1);
- lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);
+ /*lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);*/
#endif
lcdc_cfg_done(lcdc_dev);
}
return ret;
}
+static int rk3288_lcdc_mmu_en(struct rk_lcdc_driver *dev_drv, bool en)
+{
+ struct lcdc_device *lcdc_dev =
+ container_of(dev_drv, struct lcdc_device, driver);
+ /*close win*/
+ lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_MMU_EN,
+ v_MMU_EN(en));
+ lcdc_cfg_done(lcdc_dev);
+ return 0;
+}
+
+
static int rk3288_lcdc_dpi_open(struct rk_lcdc_driver *dev_drv, bool open)
{
struct lcdc_device *lcdc_dev =
};
static struct rk_lcdc_drv_ops lcdc_drv_ops = {
- .open = rk3288_lcdc_open,
- .load_screen = rk3288_load_screen,
- .set_par = rk3288_lcdc_set_par,
- .pan_display = rk3288_lcdc_pan_display,
- .lcdc_reg_update = rk3288_lcdc_reg_update,
- .blank = rk3288_lcdc_blank,
- .ioctl = rk3288_lcdc_ioctl,
- .suspend = rk3288_lcdc_early_suspend,
- .resume = rk3288_lcdc_early_resume,
- .get_win_state = rk3288_lcdc_get_win_state,
- .ovl_mgr = rk3288_lcdc_ovl_mgr,
- .get_disp_info = rk3288_lcdc_get_disp_info,
- .fps_mgr = rk3288_lcdc_fps_mgr,
- .fb_get_win_id = rk3288_lcdc_get_win_id,
- .fb_win_remap = rk3288_fb_win_remap,
- .set_dsp_lut = rk3288_set_dsp_lut,
- .poll_vblank = rk3288_lcdc_poll_vblank,
- .dpi_open = rk3288_lcdc_dpi_open,
- .dpi_win_sel = rk3288_lcdc_dpi_win_sel,
- .dpi_status = rk3288_lcdc_dpi_status,
- .get_dsp_addr = rk3288_lcdc_get_dsp_addr,
- .set_dsp_cabc = rk3288_lcdc_set_dsp_cabc,
- .set_dsp_hue = rk3288_lcdc_set_hue,
- .set_dsp_bcsh_bcs = rk3288_lcdc_set_bcsh_bcs,
- .dump_reg = rk3288_lcdc_reg_dump,
+ .open = rk3288_lcdc_open,
+ .load_screen = rk3288_load_screen,
+ .set_par = rk3288_lcdc_set_par,
+ .pan_display = rk3288_lcdc_pan_display,
+ .lcdc_reg_update = rk3288_lcdc_reg_update,
+ .blank = rk3288_lcdc_blank,
+ .ioctl = rk3288_lcdc_ioctl,
+ .suspend = rk3288_lcdc_early_suspend,
+ .resume = rk3288_lcdc_early_resume,
+ .get_win_state = rk3288_lcdc_get_win_state,
+ .ovl_mgr = rk3288_lcdc_ovl_mgr,
+ .get_disp_info = rk3288_lcdc_get_disp_info,
+ .fps_mgr = rk3288_lcdc_fps_mgr,
+ .fb_get_win_id = rk3288_lcdc_get_win_id,
+ .fb_win_remap = rk3288_fb_win_remap,
+ .set_dsp_lut = rk3288_set_dsp_lut,
+ .poll_vblank = rk3288_lcdc_poll_vblank,
+ .dpi_open = rk3288_lcdc_dpi_open,
+ .dpi_win_sel = rk3288_lcdc_dpi_win_sel,
+ .dpi_status = rk3288_lcdc_dpi_status,
+ .get_dsp_addr = rk3288_lcdc_get_dsp_addr,
+ .set_dsp_cabc = rk3288_lcdc_set_dsp_cabc,
+ .set_dsp_hue = rk3288_lcdc_set_hue,
+ .set_dsp_bcsh_bcs = rk3288_lcdc_set_bcsh_bcs,
+ .dump_reg = rk3288_lcdc_reg_dump,
+ .mmu_en = rk3288_lcdc_mmu_en,
};
static int rk3288_lcdc_parse_irq(struct lcdc_device *lcdc_dev,unsigned int reg_val)
{
#if 0
intr1_reg = lcdc_readl(lcdc_dev, INTR_CTRL1);
if(intr1_reg != 0){
- rk3288_lcdc_parse_irq(intr1_reg);
+ rk3288_lcdc_parse_irq(lcdc_dev,intr1_reg);
}
#endif
return IRQ_HANDLED;
}
ret = devm_request_irq(dev, lcdc_dev->irq, rk3288_lcdc_isr,
- IRQF_DISABLED, dev_name(dev), lcdc_dev);
+ IRQF_DISABLED | IRQF_SHARED, dev_name(dev), lcdc_dev);
if (ret) {
dev_err(&pdev->dev, "cannot requeset irq %d - err %d\n",
lcdc_dev->irq, ret);
return ret;
}
+#ifdef USE_ION_MMU
+#ifdef CONFIG_RK_FPGA
+ if(lcdc_dev->id == 0){
+ strcpy(dev_drv->mmu_dts_name, "iommu,vopb_mmu");
+ }else{
+ strcpy(dev_drv->mmu_dts_name, "iommu,vopl_mmu");
+ }
+#else
+ if(lcdc_dev->id == 0){
+ strcpy(dev_drv->mmu_dts_name, "iommu,vopl_mmu");
+ }else{
+ strcpy(dev_drv->mmu_dts_name, "iommu,vopb_mmu");
+ }
+#endif
+#endif
ret = rk_fb_register(dev_drv, lcdc_win, lcdc_dev->id);
if (ret < 0) {
#if defined(CONFIG_ION_ROCKCHIP)
#include <linux/rockchip_ion.h>
+#ifdef USE_ION_MMU
+#include <linux/rockchip/iovmm.h>
+#include <linux/rockchip/sysmmu.h>
+#include <linux/dma-buf.h>
+#endif
#endif
-
static int hdmi_switch_complete;
static struct platform_device *fb_pdev;
printk("error waiting on fence\n");
}
+#ifdef USE_ION_MMU
+static unsigned int rk_fb_map_ion_handle(struct fb_info *info,
+ struct rk_fb_reg_area_data *reg_area_data,
+ struct ion_handle *ion_handle,struct dma_buf *buf)
+{
+ struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
+ reg_area_data->dma_buf = buf;
+ reg_area_data->attachment =
+ dma_buf_attach(reg_area_data->dma_buf, dev_drv->dev);
+ if (IS_ERR_OR_NULL(reg_area_data->attachment)) {
+ dev_err(dev_drv->dev, "dma_buf_attach() failed: %ld\n",
+ PTR_ERR(reg_area_data->attachment));
+ goto err_buf_map_attach;
+ }
+
+ reg_area_data->sg_table = dma_buf_map_attachment(reg_area_data->attachment,
+ DMA_BIDIRECTIONAL);
+ if (IS_ERR_OR_NULL(reg_area_data->sg_table)) {
+ dev_err(dev_drv->dev, "dma_buf_map_attachment() failed: %ld\n",
+ PTR_ERR(reg_area_data->sg_table));
+ goto err_buf_map_attachment;
+ }
+
+ reg_area_data->dma_addr = iovmm_map(dev_drv->dev, reg_area_data->sg_table->sgl, 0,
+ buf->size);
+ if (!reg_area_data->dma_addr || IS_ERR_VALUE(reg_area_data->dma_addr)) {
+ dev_err(dev_drv->dev, "iovmm_map() failed: %d\n", reg_area_data->dma_addr);
+ goto err_iovmm_map;
+ }
+ reg_area_data->ion_handle = ion_handle;
+ return reg_area_data->dma_buf->size;
+
+err_iovmm_map:
+ dma_buf_unmap_attachment(reg_area_data->attachment,
+ reg_area_data->sg_table,DMA_BIDIRECTIONAL);
+err_buf_map_attachment:
+ dma_buf_detach(buf, reg_area_data->attachment);
+err_buf_map_attach:
+ return 0;
+}
-void rk_fb_free_dma_buf(struct rk_fb_reg_win_data *reg_win_data)
+int rk_fb_sysmmu_fault_handler(struct device *dev,
+ enum rk_sysmmu_inttype itype, unsigned long pgtable_base,
+ unsigned long fault_addr,unsigned int statu)
{
+ /*struct fb_info *fbi = dev_get_drvdata(dev);
+ struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)fbi->par;
+
+ pr_err("PAGE FAULT occurred at 0x%lx (Page table base: 0x%lx),status=%d\n",
+ fault_addr, pgtable_base,statu);
+ dev_drv->ops->dump_reg(dev_drv);
+ pr_err("Generating Kernel OOPS... because it is unrecoverable.\n");
+ BUG();*/
+
+ return 0;
+}
+#endif
+
+void rk_fb_free_dma_buf(struct device *dev,struct rk_fb_reg_win_data *reg_win_data)
+{
+ int i,index_buf;
+ struct rk_fb_reg_area_data *area_data;
+ struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
#ifdef H_USE_FENCE
- int i;
for(i=0;i<RK_WIN_MAX_AREA;i++){
if(reg_win_data->reg_area_data[i].acq_fence)
sync_fence_put(reg_win_data->reg_area_data[i].acq_fence);
}
#endif
+ for(i=0;i<reg_win_data->area_num;i++){
+ area_data = ®_win_data->reg_area_data[i];
+ index_buf = area_data->index_buf;
+ if(index_buf == 1){
+ #ifdef USE_ION_MMU
+ iovmm_unmap(dev,area_data->dma_addr);
+ dma_buf_unmap_attachment(area_data->attachment, area_data->sg_table,
+ DMA_BIDIRECTIONAL);
+ dma_buf_detach(area_data->dma_buf, area_data->attachment);
+ dma_buf_put(area_data->dma_buf);
+ #endif
+ ion_free(rk_fb->ion_client, area_data->ion_handle);
+ }
+ }
memset(reg_win_data, 0, sizeof(struct rk_fb_reg_win_data));
}
sw_sync_timeline_inc(dev_drv->timeline, 1);
for(i=0;i<regs->win_num;i++){
- rk_fb_free_dma_buf(®s->reg_win_data[i]);
+ rk_fb_free_dma_buf(dev_drv->dev,®s->reg_win_data[i]);
}
}
u32 xoffset,yoffset;
struct ion_handle *hdl;
- ion_phys_addr_t phy_addr;
size_t len;
int index_buf;
u8 fb_data_fmt;
u16 uv_x_off,uv_y_off;
u8 is_pic_yuv=0;
u8 ppixel_a=0,global_a=0;
+#ifdef USE_ION_MMU
+ struct dma_buf *buf;
+#else
+ ion_phys_addr_t phy_addr;
+ size_t len;
+#endif
reg_win_data->area_num = 0;
if(win_par->area_par[0].phy_addr == 0){
for(i=0;i<RK_WIN_MAX_AREA;i++){
}
if(j == i){
hdl = ion_import_dma_buf(rk_fb->ion_client, ion_fd);
- ion_phys(rk_fb->ion_client, hdl, &phy_addr, &len);
- reg_win_data->reg_area_data[i].smem_start = phy_addr;
+ reg_win_data->reg_area_data[i].ion_handle = hdl;
+ #ifndef USE_ION_MMU
+ ion_phys(rk_fb->ion_client, hdl, &phy_addr, &len);
+ reg_win_data->reg_area_data[i].smem_start = phy_addr;
+ #else
+ buf = ion_share_dma_buf(rk_fb->ion_client, hdl);
+ if (IS_ERR_OR_NULL(buf)) {
+ dev_err(info->dev, "ion_share_dma_buf() failed\n");
+ goto err_share_dma_buf;
+ }
+ rk_fb_map_ion_handle(info,®_win_data->reg_area_data[i],hdl,buf);
+ reg_win_data->reg_area_data[i].smem_start =
+ reg_win_data->reg_area_data[i].dma_addr;
+ #endif
reg_win_data->area_buf_num++;
reg_win_data->reg_area_data[i].index_buf = 1;
}else{
uv_stride >> 2;
}
return 0;
+#ifdef USE_ION_MMU
+err_share_dma_buf:
+ ion_free(rk_fb->ion_client, hdl);
+ return -ENOMEM;
+#endif
}
static int rk_fb_set_win_config(struct fb_info *info,
struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
struct rk_fb_reg_data *regs;
struct rk_fb_reg_win_data *reg_win_data;
+#ifdef H_USE_FENCE
struct sync_fence *release_fence[RK_MAX_BUF_NUM];
struct sync_fence *retire_fence;
struct sync_pt *release_sync_pt[RK_MAX_BUF_NUM];
struct sync_pt *retire_sync_pt;
- int ret,i,j=0,fence_fd;
+ int fencd_fd;
char fence_name[20];
+#endif
+ int ret,i,j=0;
//mutex_lock(&dev_drv->output_lock);
regs = kzalloc(sizeof(struct rk_fb_reg_data), GFP_KERNEL);
#if defined(CONFIG_ION_ROCKCHIP)
struct ion_handle *handle;
ion_phys_addr_t phy_addr;
- size_t len;
+#ifdef USE_ION_MMU
+ struct dma_buf *buf;
#else
dma_addr_t fb_mem_phys;
void *fb_mem_virt;
+ size_t len;
+#endif
#endif
win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
if (win_id < 0)
}
win->area[0].ion_hdl = handle;
fbi->screen_base = ion_map_kernel(rk_fb->ion_client, handle);
- ion_phys(rk_fb->ion_client, handle, &phy_addr, &len);
- fbi->fix.smem_start = phy_addr;
- fbi->fix.smem_len = len;
- printk("alloc_buffer:smem_start=0x%x\n",phy_addr);
+ #ifndef USE_ION_MMU
+ ion_phys(rk_fb->ion_client, handle, &phy_addr, &len);
+ fbi->fix.smem_start = phy_addr;
+ fbi->fix.smem_len = len;
+ printk(KERN_INFO "alloc_buffer:ion_phy_addr=0x%x\n",phy_addr);
+ #else
+ buf = ion_share_dma_buf(rk_fb->ion_client, handle);
+ if (IS_ERR_OR_NULL(buf)) {
+ dev_err(fbi->device, "ion_share_dma_buf() failed\n");
+ goto err_share_dma_buf;
+ }
+ rk_fb_map_ion_handle(fbi,&dev_drv->reg_area_data,handle,buf);
+ fbi->fix.smem_start = dev_drv->reg_area_data.dma_addr;
+ fbi->fix.smem_len = buf->size;
+ printk(KERN_INFO "alloc_buffer:kernel_vir_addr=0x%x,mmu_vir_addr=0x%x,len=0x%x\n",
+ fbi->screen_base,fbi->fix.smem_start,fbi->fix.smem_len);
+ #endif
+
#else
fb_mem_virt = dma_alloc_writecombine(fbi->dev, fb_mem_size, &fb_mem_phys,
}
return ret;
+#ifdef USE_ION_MMU
+err_share_dma_buf:
+ ion_free(rk_fb->ion_client, handle);
+ return -ENOMEM;
+#endif
}
static int rk_release_fb_buffer(struct fb_info *fbi)
struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
struct fb_info *fbi;
int i = 0, ret = 0, index = 0;
-
+ #ifdef USE_ION_MMU
+ struct device *mmu_dev = NULL;
+ #endif
if (rk_fb->num_lcdc == RK30_MAX_LCDC_SUPPORT)
return -ENXIO;
fbi->fbops = &fb_ops;
fbi->flags = FBINFO_FLAG_DEFAULT;
fbi->pseudo_palette = dev_drv->win[i]->pseudo_pal;
- if (i == 0) /* only alloc memory for main fb*/
+ if (i == 0){ /* only alloc memory for main fb*/
+ #ifdef USE_ION_MMU
+ mmu_dev =
+ rockchip_get_sysmmu_device_by_compatible(dev_drv->mmu_dts_name);
+ platform_set_sysmmu(mmu_dev, dev_drv->dev);
+ /*rockchip_sysmmu_set_fault_handler(dev_drv->dev,
+ rk_fb_sysmmu_fault_handler);*/
+ iovmm_activate(dev_drv->dev);
+ #endif
rk_fb_alloc_buffer(fbi, rk_fb->num_fb);
+ }
ret = register_framebuffer(fbi);
if (ret < 0) {
dev_err(&fb_pdev->dev, "%s fb%d register_framebuffer fail!\n",