mdss: fb: Add backward compatibility to fb memory
In the current implementation, contiguous memory allocation during bootup is removed and related changes were made in frame buffer driver which is not backward compatible. With this change, add backward compatibility to map to physically contiguous memory when available which is allocated at bootup. Change-Id: Ib1a595f2426dda8d3e1c5e50c71c35d3f45854b6 Signed-off-by: Jeevan Shriram <jshriram@codeaurora.org>
This commit is contained in:
parent
c7dfe421a1
commit
915c2f85a0
2 changed files with 151 additions and 13 deletions
|
@ -92,6 +92,8 @@ static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
|
|||
unsigned long arg);
|
||||
static int mdss_fb_fbmem_ion_mmap(struct fb_info *info,
|
||||
struct vm_area_struct *vma);
|
||||
static int mdss_fb_alloc_fb_ion_memory(struct msm_fb_data_type *mfd,
|
||||
size_t size);
|
||||
static void mdss_fb_release_fences(struct msm_fb_data_type *mfd);
|
||||
static int __mdss_fb_sync_buf_done_callback(struct notifier_block *p,
|
||||
unsigned long val, void *data);
|
||||
|
@ -1123,11 +1125,11 @@ void mdss_fb_free_fb_ion_memory(struct msm_fb_data_type *mfd)
|
|||
}
|
||||
|
||||
ion_free(mfd->fb_ion_client, mfd->fb_ion_handle);
|
||||
mfd->fb_ion_handle = NULL;
|
||||
}
|
||||
|
||||
int mdss_fb_alloc_fb_ion_memory(struct msm_fb_data_type *mfd)
|
||||
int mdss_fb_alloc_fb_ion_memory(struct msm_fb_data_type *mfd, size_t fb_size)
|
||||
{
|
||||
size_t size;
|
||||
unsigned long buf_size;
|
||||
int rc;
|
||||
void *vaddr;
|
||||
|
@ -1145,10 +1147,8 @@ int mdss_fb_alloc_fb_ion_memory(struct msm_fb_data_type *mfd)
|
|||
}
|
||||
}
|
||||
|
||||
size = mfd->fbi->fix.line_length * mfd->fbi->var.yres * MDSS_FB_NUM;
|
||||
pr_debug("size for mmap = %d", (int) size);
|
||||
|
||||
mfd->fb_ion_handle = ion_alloc(mfd->fb_ion_client, size, SZ_4K,
|
||||
pr_debug("size for mmap = %zu", fb_size);
|
||||
mfd->fb_ion_handle = ion_alloc(mfd->fb_ion_client, fb_size, SZ_4K,
|
||||
ION_HEAP(ION_SYSTEM_HEAP_ID), 0);
|
||||
if (IS_ERR_OR_NULL(mfd->fb_ion_handle)) {
|
||||
pr_err("unable to alloc fbmem from ion - %ld\n",
|
||||
|
@ -1181,11 +1181,11 @@ int mdss_fb_alloc_fb_ion_memory(struct msm_fb_data_type *mfd)
|
|||
goto fb_mmap_failed;
|
||||
}
|
||||
|
||||
pr_debug("alloc 0x%zuB vaddr = %p (%pa iova) for fb%d\n", size, vaddr,
|
||||
&mfd->iova, mfd->index);
|
||||
pr_debug("alloc 0x%zuB vaddr = %p (%pa iova) for fb%d\n", fb_size,
|
||||
vaddr, &mfd->iova, mfd->index);
|
||||
|
||||
mfd->fbi->screen_base = (char *) vaddr;
|
||||
mfd->fbi->fix.smem_len = size;
|
||||
mfd->fbi->fix.smem_len = fb_size;
|
||||
|
||||
return rc;
|
||||
|
||||
|
@ -1232,7 +1232,7 @@ static int mdss_fb_fbmem_ion_mmap(struct fb_info *info,
|
|||
}
|
||||
|
||||
if (!mfd->fbi->screen_base) {
|
||||
rc = mdss_fb_alloc_fb_ion_memory(mfd);
|
||||
rc = mdss_fb_alloc_fb_ion_memory(mfd, fb_size);
|
||||
if (rc < 0) {
|
||||
pr_err("fb mmap failed!!!!");
|
||||
return rc;
|
||||
|
@ -1292,6 +1292,69 @@ static int mdss_fb_fbmem_ion_mmap(struct fb_info *info,
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* mdss_fb_physical_mmap() - Custom fb mmap() function for MSM driver.
|
||||
*
|
||||
* @info - Framebuffer info.
|
||||
* @vma - VM area which is part of the process virtual memory.
|
||||
*
|
||||
* This framebuffer mmap function differs from standard mmap() function as
|
||||
* map to framebuffer memory from the CMA memory which is allocated during
|
||||
* bootup.
|
||||
*
|
||||
* Return: virtual address is returned through vma
|
||||
*/
|
||||
static int mdss_fb_physical_mmap(struct fb_info *info,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
/* Get frame buffer memory range. */
|
||||
unsigned long start = info->fix.smem_start;
|
||||
u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
|
||||
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
|
||||
|
||||
if (!start) {
|
||||
pr_warn("No framebuffer memory is allocated\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Set VM flags. */
|
||||
start &= PAGE_MASK;
|
||||
if ((vma->vm_end <= vma->vm_start) ||
|
||||
(off >= len) ||
|
||||
((vma->vm_end - vma->vm_start) > (len - off)))
|
||||
return -EINVAL;
|
||||
off += start;
|
||||
if (off < start)
|
||||
return -EINVAL;
|
||||
vma->vm_pgoff = off >> PAGE_SHIFT;
|
||||
/* This is an IO map - tell maydump to skip this VMA */
|
||||
vma->vm_flags |= VM_IO;
|
||||
|
||||
/* Remap the frame buffer I/O range */
|
||||
if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot))
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mdss_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
||||
{
|
||||
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
||||
int rc = 0;
|
||||
|
||||
if (!info->fix.smem_start && !mfd->fb_ion_handle)
|
||||
rc = mdss_fb_fbmem_ion_mmap(info, vma);
|
||||
else
|
||||
rc = mdss_fb_physical_mmap(info, vma);
|
||||
|
||||
if (rc < 0)
|
||||
pr_err("fb mmap failed with rc = %d", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct fb_ops mdss_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_open = mdss_fb_open,
|
||||
|
@ -1304,14 +1367,89 @@ static struct fb_ops mdss_fb_ops = {
|
|||
#ifdef CONFIG_COMPAT
|
||||
.fb_compat_ioctl = mdss_fb_compat_ioctl,
|
||||
#endif
|
||||
.fb_mmap = mdss_fb_fbmem_ion_mmap,
|
||||
.fb_mmap = mdss_fb_mmap,
|
||||
};
|
||||
|
||||
static int mdss_fb_alloc_fbmem_iommu(struct msm_fb_data_type *mfd, int dom)
|
||||
{
|
||||
void *virt = NULL;
|
||||
phys_addr_t phys = 0;
|
||||
size_t size = 0;
|
||||
struct platform_device *pdev = mfd->pdev;
|
||||
int rc = 0;
|
||||
struct device_node *fbmem_pnode = NULL;
|
||||
|
||||
if (!pdev || !pdev->dev.of_node) {
|
||||
pr_err("Invalid device node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
fbmem_pnode = of_parse_phandle(pdev->dev.of_node,
|
||||
"linux,contiguous-region", 0);
|
||||
if (!fbmem_pnode) {
|
||||
pr_debug("fbmem is not reserved for %s\n", pdev->name);
|
||||
mfd->fbi->screen_base = NULL;
|
||||
mfd->fbi->fix.smem_start = 0;
|
||||
mfd->fbi->fix.smem_len = 0;
|
||||
return 0;
|
||||
} else {
|
||||
const u32 *addr;
|
||||
u64 len;
|
||||
|
||||
addr = of_get_address(fbmem_pnode, 0, &len, NULL);
|
||||
if (!addr) {
|
||||
pr_err("fbmem size is not specified\n");
|
||||
of_node_put(fbmem_pnode);
|
||||
return -EINVAL;
|
||||
}
|
||||
size = (size_t)len;
|
||||
of_node_put(fbmem_pnode);
|
||||
}
|
||||
|
||||
pr_debug("%s frame buffer reserve_size=0x%zx\n", __func__, size);
|
||||
|
||||
if (size < PAGE_ALIGN(mfd->fbi->fix.line_length *
|
||||
mfd->fbi->var.yres_virtual))
|
||||
pr_warn("reserve size is smaller than framebuffer size\n");
|
||||
|
||||
virt = dma_alloc_coherent(&pdev->dev, size, &phys, GFP_KERNEL);
|
||||
if (!virt) {
|
||||
pr_err("unable to alloc fbmem size=%zx\n", size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (MDSS_LPAE_CHECK(phys)) {
|
||||
pr_warn("fb mem phys %pa > 4GB is not supported.\n", &phys);
|
||||
dma_free_coherent(&pdev->dev, size, &virt, GFP_KERNEL);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
rc = msm_iommu_map_contig_buffer(phys, dom, 0, size, SZ_4K, 0,
|
||||
&mfd->iova);
|
||||
if (rc)
|
||||
pr_warn("Cannot map fb_mem %pa to IOMMU. rc=%d\n", &phys, rc);
|
||||
|
||||
pr_debug("alloc 0x%zxB @ (%pa phys) (0x%p virt) (%pa iova) for fb%d\n",
|
||||
size, &phys, virt, &mfd->iova, mfd->index);
|
||||
|
||||
mfd->fbi->screen_base = virt;
|
||||
mfd->fbi->fix.smem_start = phys;
|
||||
mfd->fbi->fix.smem_len = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mdss_fb_alloc_fbmem(struct msm_fb_data_type *mfd)
|
||||
{
|
||||
|
||||
if (mfd->mdp.fb_mem_alloc_fnc) {
|
||||
return mfd->mdp.fb_mem_alloc_fnc(mfd);
|
||||
} else if (mfd->mdp.fb_mem_get_iommu_domain) {
|
||||
int dom = mfd->mdp.fb_mem_get_iommu_domain();
|
||||
if (dom >= 0)
|
||||
return mdss_fb_alloc_fbmem_iommu(mfd, dom);
|
||||
else
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
pr_err("no fb memory allocator function defined\n");
|
||||
return -ENOMEM;
|
||||
|
@ -1814,7 +1952,8 @@ static int mdss_fb_release_all(struct fb_info *info, bool release_all)
|
|||
mfd->index, task->comm, pid);
|
||||
}
|
||||
|
||||
mdss_fb_free_fb_ion_memory(mfd);
|
||||
if (mfd->fb_ion_handle)
|
||||
mdss_fb_free_fb_ion_memory(mfd);
|
||||
|
||||
ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info,
|
||||
mfd->op_enable);
|
||||
|
|
|
@ -269,7 +269,6 @@ void mdss_fb_signal_timeline(struct msm_sync_pt_data *sync_pt_data);
|
|||
struct sync_fence *mdss_fb_sync_get_fence(struct sw_sync_timeline *timeline,
|
||||
const char *fence_name, int val);
|
||||
int mdss_fb_register_mdp_instance(struct msm_mdp_interface *mdp);
|
||||
int mdss_fb_alloc_fb_ion_memory(struct msm_fb_data_type *mfd);
|
||||
int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state);
|
||||
int mdss_fb_suspres_panel(struct device *dev, void *data);
|
||||
int mdss_fb_do_ioctl(struct fb_info *info, unsigned int cmd,
|
||||
|
|
Loading…
Add table
Reference in a new issue