mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
rk3288 lcdc: add support iommu
This commit is contained in:
@@ -45,12 +45,10 @@
|
||||
|
||||
#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
|
||||
#define H_USE_FENCE 1
|
||||
static int hdmi_switch_complete;
|
||||
static struct platform_device *fb_pdev;
|
||||
@@ -61,6 +59,8 @@ 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_first_buf = 1;
|
||||
|
||||
static struct rk_fb_trsm_ops *trsm_lvds_ops;
|
||||
static struct rk_fb_trsm_ops *trsm_edp_ops;
|
||||
@@ -997,59 +997,19 @@ void rk_fd_fence_wait(struct rk_lcdc_driver *dev_drv,
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_IOMMU
|
||||
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)
|
||||
unsigned long fault_addr,unsigned int status)
|
||||
{
|
||||
/*struct fb_info *fbi = dev_get_drvdata(dev);
|
||||
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);
|
||||
fault_addr, pgtable_base,status);
|
||||
dev_drv->ops->dump_reg(dev_drv);
|
||||
pr_err("Generating Kernel OOPS... because it is unrecoverable.\n");
|
||||
BUG();*/
|
||||
BUG();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1060,22 +1020,13 @@ void rk_fb_free_dma_buf(struct device *dev,struct rk_fb_reg_win_data *reg_win_da
|
||||
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
|
||||
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;
|
||||
#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
|
||||
#ifdef CONFIG_ROCKCHIP_IOMMU
|
||||
ion_unmap_iommu(dev, rk_fb->ion_client, area_data->ion_handle);
|
||||
#endif
|
||||
if(area_data->ion_handle != NULL)
|
||||
ion_free(rk_fb->ion_client, area_data->ion_handle);
|
||||
}
|
||||
@@ -1152,7 +1103,6 @@ static void rk_fb_update_driver(struct rk_lcdc_win *win,struct rk_fb_reg_win_dat
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void rk_fb_update_reg(struct rk_lcdc_driver * dev_drv,struct rk_fb_reg_data *regs)
|
||||
{
|
||||
int i,j,ret=0;
|
||||
@@ -1264,9 +1214,16 @@ ext_win_exit:
|
||||
#ifdef H_USE_FENCE
|
||||
sw_sync_timeline_inc(dev_drv->timeline, 1);
|
||||
#endif
|
||||
for(i=0;i<regs->win_num;i++){
|
||||
rk_fb_free_dma_buf(dev_drv->dev,®s->reg_win_data[i]);
|
||||
if(!g_first_buf){
|
||||
for(i=0;i<regs->win_num;i++){
|
||||
rk_fb_free_dma_buf(dev_drv->dev,&g_reg_win_data[i]);
|
||||
}
|
||||
}
|
||||
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_first_buf = 0;
|
||||
|
||||
if (dev_drv->wait_fs == 1)
|
||||
kfree(regs);
|
||||
}
|
||||
@@ -1344,11 +1301,8 @@ static int rk_fb_set_win_buffer(struct fb_info *info,
|
||||
u16 uv_x_off,uv_y_off,uv_y_act;
|
||||
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;
|
||||
#endif
|
||||
|
||||
reg_win_data->reg_area_data[0].smem_start = -1;
|
||||
reg_win_data->area_num = 0;
|
||||
if(win_par->area_par[0].phy_addr == 0){
|
||||
@@ -1364,19 +1318,13 @@ static int rk_fb_set_win_buffer(struct fb_info *info,
|
||||
}
|
||||
reg_win_data->area_num++;
|
||||
reg_win_data->reg_area_data[i].ion_handle = hdl;
|
||||
#ifndef USE_ION_MMU
|
||||
#ifndef CONFIG_ROCKCHIP_IOMMU
|
||||
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;
|
||||
ion_map_iommu(dev_drv->dev, rk_fb->ion_client, hdl,
|
||||
(unsigned long *)&phy_addr, (unsigned long *)&len);
|
||||
#endif
|
||||
reg_win_data->reg_area_data[i].smem_start = phy_addr;
|
||||
reg_win_data->area_buf_num++;
|
||||
reg_win_data->reg_area_data[i].index_buf = 1;
|
||||
}
|
||||
@@ -1537,7 +1485,7 @@ static int rk_fb_set_win_buffer(struct fb_info *info,
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#ifdef USE_ION_MMU
|
||||
#ifdef CONFIG_ROCKCHIP_IOMMU
|
||||
err_share_dma_buf:
|
||||
ion_free(rk_fb->ion_client, hdl);
|
||||
return -ENOMEM;
|
||||
@@ -2247,6 +2195,18 @@ static int fb_setcolreg(unsigned regno,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
||||
{
|
||||
struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
|
||||
int win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
|
||||
struct rk_lcdc_win *win;
|
||||
win = dev_drv->win[win_id];
|
||||
|
||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
||||
|
||||
return dma_buf_mmap(win->area[0].dma_buf, vma, 0);
|
||||
}
|
||||
|
||||
static struct fb_ops fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_open = rk_fb_open,
|
||||
@@ -2626,11 +2586,7 @@ static int rk_fb_alloc_buffer(struct fb_info *fbi, int fb_id)
|
||||
#if defined(CONFIG_ION_ROCKCHIP)
|
||||
struct ion_handle *handle;
|
||||
ion_phys_addr_t phy_addr;
|
||||
#ifdef USE_ION_MMU
|
||||
struct dma_buf *buf;
|
||||
#else
|
||||
size_t len;
|
||||
#endif
|
||||
#endif
|
||||
win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
|
||||
if (win_id < 0)
|
||||
@@ -2647,26 +2603,25 @@ static int rk_fb_alloc_buffer(struct fb_info *fbi, int fb_id)
|
||||
dev_err(fbi->device, "failed to ion_alloc:%ld\n",PTR_ERR(handle));
|
||||
return -ENOMEM;
|
||||
}
|
||||
win->area[0].dma_buf = ion_share_dma_buf(rk_fb->ion_client, handle);
|
||||
if (IS_ERR_OR_NULL(win->area[0].dma_buf)) {
|
||||
printk("ion_share_dma_buf() failed\n");
|
||||
goto err_share_dma_buf;
|
||||
}
|
||||
win->area[0].ion_hdl = handle;
|
||||
fbi->screen_base = ion_map_kernel(rk_fb->ion_client, handle);
|
||||
#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%lx\n",phy_addr);
|
||||
#ifndef CONFIG_ROCKCHIP_IOMMU
|
||||
ion_phys(rk_fb->ion_client, handle, &phy_addr, &len);
|
||||
#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);
|
||||
ion_phys(rk_fb->ion_client, handle, &phy_addr, &len);
|
||||
printk("ion_phys: %x,%x\n", phy_addr, len);
|
||||
ion_map_iommu(dev_drv->dev, rk_fb->ion_client, handle,
|
||||
(unsigned long *)&phy_addr, (unsigned long *)&len);
|
||||
printk("%s: ion_map_iommu: %x,%x\n", __func__, phy_addr, len);
|
||||
#endif
|
||||
|
||||
fbi->fix.smem_start = phy_addr;
|
||||
fbi->fix.smem_len = len;
|
||||
printk(KERN_INFO "alloc_buffer:ion_phy_addr=0x%lx\n",phy_addr);
|
||||
#else
|
||||
dma_addr_t fb_mem_phys;
|
||||
void *fb_mem_virt;
|
||||
@@ -2714,11 +2669,11 @@ static int rk_fb_alloc_buffer(struct fb_info *fbi, int fb_id)
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -2845,7 +2800,7 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
|
||||
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
|
||||
#ifdef CONFIG_ROCKCHIP_IOMMU
|
||||
struct device *mmu_dev = NULL;
|
||||
#endif
|
||||
if (rk_fb->num_lcdc == RK30_MAX_LCDC_SUPPORT)
|
||||
@@ -2884,17 +2839,20 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
|
||||
fbi->var.width = dev_drv->cur_screen->width;
|
||||
fbi->var.height = dev_drv->cur_screen->height;
|
||||
fbi->var.pixclock = dev_drv->pixclock;
|
||||
#ifdef CONFIG_ROCKCHIP_IOMMU
|
||||
fb_ops.fb_mmap = rk_fb_mmap;
|
||||
#endif
|
||||
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*/
|
||||
#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);
|
||||
#ifdef CONFIG_ROCKCHIP_IOMMU
|
||||
mmu_dev = rockchip_get_sysmmu_device_by_compatible("iommu,vopl_mmu");
|
||||
if (mmu_dev) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
#define Y_MIRROR 2
|
||||
#define X_Y_MIRROR 3
|
||||
|
||||
/*#define USE_ION_MMU 1*/
|
||||
//#define USE_ION_MMU 1
|
||||
#if defined(CONFIG_ION_ROCKCHIP)
|
||||
extern struct ion_client *rockchip_ion_client_create(const char * name);
|
||||
#endif
|
||||
@@ -284,6 +284,7 @@ struct rk_lcdc_win_area{
|
||||
#if defined(CONFIG_ION_ROCKCHIP)
|
||||
struct ion_handle *ion_hdl;
|
||||
int dma_buf_fd;
|
||||
struct dma_buf *dma_buf;
|
||||
#endif
|
||||
u32 dsp_stx;
|
||||
u32 dsp_sty;
|
||||
|
||||
Reference in New Issue
Block a user