Loading drivers/video/msm/mdss/mdss_fb.c +151 −12 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; Loading @@ -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", Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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, Loading @@ -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; Loading Loading @@ -1814,6 +1952,7 @@ static int mdss_fb_release_all(struct fb_info *info, bool release_all) mfd->index, task->comm, pid); } if (mfd->fb_ion_handle) mdss_fb_free_fb_ion_memory(mfd); ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info, Loading drivers/video/msm/mdss/mdss_fb.h +0 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
drivers/video/msm/mdss/mdss_fb.c +151 −12 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; Loading @@ -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", Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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, Loading @@ -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; Loading Loading @@ -1814,6 +1952,7 @@ static int mdss_fb_release_all(struct fb_info *info, bool release_all) mfd->index, task->comm, pid); } if (mfd->fb_ion_handle) mdss_fb_free_fb_ion_memory(mfd); ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info, Loading
drivers/video/msm/mdss/mdss_fb.h +0 −1 Original line number Diff line number Diff line Loading @@ -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