diff options
Diffstat (limited to 'drivers/media/video/samsung/fimc/fimc_dev_u1.c')
-rw-r--r-- | drivers/media/video/samsung/fimc/fimc_dev_u1.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/media/video/samsung/fimc/fimc_dev_u1.c b/drivers/media/video/samsung/fimc/fimc_dev_u1.c index 811ac96..52246a1 100644 --- a/drivers/media/video/samsung/fimc/fimc_dev_u1.c +++ b/drivers/media/video/samsung/fimc/fimc_dev_u1.c @@ -745,6 +745,50 @@ static struct vm_operations_struct fimc_mmap_ops = { }; static inline +int fimc_mmap_own_mem(struct file *filp, struct vm_area_struct *vma) +{ + struct fimc_prv_data *prv_data = + (struct fimc_prv_data *)filp->private_data; + struct fimc_control *ctrl = prv_data->ctrl; + u32 start_phy_addr = 0; + u32 size = vma->vm_end - vma->vm_start; + u32 pfn, idx = vma->vm_pgoff; + u32 buf_length = 0; + + buf_length = ctrl->mem.size; + if (size > PAGE_ALIGN(buf_length)) { + fimc_err("Requested mmap size is too big\n"); + return -EINVAL; + } + + start_phy_addr = ctrl->mem.base + (vma->vm_pgoff << PAGE_SHIFT); + + if (!cma_is_registered_region(start_phy_addr, size)) { + pr_err("[%s] handling non-cma region (%#x@%#x)is prohibited\n", + __func__, buf_length, start_phy_addr); + return -EINVAL; + } + + /* only supports non-cached mmap */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_flags |= VM_RESERVED; + + if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) { + fimc_err("writable mapping must be shared\n"); + return -EINVAL; + } + + pfn = __phys_to_pfn(start_phy_addr); + + if (remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot)) { + fimc_err("mmap fail\n"); + return -EINVAL; + } + + return 0; +} + +static inline int fimc_mmap_out_src(struct file *filp, struct vm_area_struct *vma) { struct fimc_prv_data *prv_data = @@ -829,10 +873,14 @@ static inline int fimc_mmap_out(struct file *filp, struct vm_area_struct *vma) int idx = ctrl->out->ctx[ctx_id].overlay.req_idx; int ret = -1; +#if 0 if (idx >= 0) ret = fimc_mmap_out_dst(filp, vma, idx); else if (idx == FIMC_MMAP_IDX) ret = fimc_mmap_out_src(filp, vma); +#else + ret = fimc_mmap_own_mem(filp, vma); +#endif return ret; } @@ -849,6 +897,12 @@ static inline int fimc_mmap_cap(struct file *filp, struct vm_area_struct *vma) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); vma->vm_flags |= VM_RESERVED; + if (!cma_is_registered_region(ctrl->cap->bufs[idx].base[0], size)) { + pr_err("[%s] handling non-cma region (%#x@%#x)is prohibited\n", + __func__, size, ctrl->cap->bufs[idx].base[0]); + return -EINVAL; + } + /* * page frame number of the address for a source frame * to be stored at. |