From 748a70ad755602593d35eb841b69d0fee35d3132 Mon Sep 17 00:00:00 2001 From: Ankit Premrajka Date: Tue, 1 Nov 2011 08:22:04 -0700 Subject: [PATCH] msm: camera: use ION for stats and userptr buffers in V4L2 driver. Change-Id: Ibc7db3a7355d07f421e63e990354e44e372e79d0 Signed-off-by: Ankit Premrajka --- arch/arm/mach-msm/include/mach/camera.h | 2 + drivers/media/video/msm/msm.c | 12 ++-- drivers/media/video/msm/msm.h | 8 ++- drivers/media/video/msm/msm_mctl_buf.c | 4 +- drivers/media/video/msm/msm_mem.c | 93 +++++++++++++++---------- drivers/media/video/videobuf2-msm-mem.c | 43 +++++++++--- include/media/videobuf2-msm-mem.h | 8 ++- 7 files changed, 115 insertions(+), 55 deletions(-) diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h index 1b6497d612b..1c91d948090 100644 --- a/arch/arm/mach-msm/include/mach/camera.h +++ b/arch/arm/mach-msm/include/mach/camera.h @@ -24,6 +24,7 @@ #include #include #include +#include #define CONFIG_MSM_CAMERA_DEBUG #ifdef CONFIG_MSM_CAMERA_DEBUG @@ -474,6 +475,7 @@ struct msm_pmem_region { struct msm_pmem_info info; struct msm_mapped_buffer *msm_buffer; int subsys_id; + struct ion_handle *handle; }; struct axidata { diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c index 40a273a0108..4b4d235c2b6 100644 --- a/drivers/media/video/msm/msm.c +++ b/drivers/media/video/msm/msm.c @@ -1427,7 +1427,9 @@ static int msm_open(struct file *f) mutex_unlock(&pcam->vid_lock); return rc; } - +#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION + pcam->mctl.client = msm_ion_client_create(-1, "camera"); +#endif /* Should be set to sensor ops if any but right now its OK!! */ if (!pcam->mctl.mctl_open) { D("%s: media contoller is not inited\n", @@ -1603,7 +1605,9 @@ static int msm_close(struct file *f) if (rc < 0) pr_err("mctl_release fails %d\n", rc); } - +#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION + ion_client_destroy(pcam->mctl.client); +#endif dma_release_declared_memory(&pcam->pdev->dev); } mutex_unlock(&pcam->vid_lock); @@ -1903,13 +1907,13 @@ static long msm_ioctl_config(struct file *fp, unsigned int cmd, case MSM_CAM_IOCTL_REGISTER_PMEM: return msm_register_pmem( &config_cam->p_mctl->sync.pmem_stats, - (void __user *)arg); + (void __user *)arg, config_cam->p_mctl->client); break; case MSM_CAM_IOCTL_UNREGISTER_PMEM: return msm_pmem_table_del( &config_cam->p_mctl->sync.pmem_stats, - (void __user *)arg); + (void __user *)arg, config_cam->p_mctl->client); break; case VIDIOC_SUBSCRIBE_EVENT: if (copy_from_user(&temp_sub, diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h index 083fc57769c..f9cf5dea298 100644 --- a/drivers/media/video/msm/msm.h +++ b/drivers/media/video/msm/msm.h @@ -31,6 +31,7 @@ #include #include #include +#include #define MSM_V4L2_DIMENSION_SIZE 96 #define MAX_DEV_NAME_LEN 50 @@ -219,6 +220,7 @@ struct msm_cam_media_controller { struct pm_qos_request_list pm_qos_req_list; struct msm_mctl_pp_info pp_info; + struct ion_client *client; }; /* abstract camera device represents a VFE and connected sensor */ @@ -402,8 +404,10 @@ int msm_mctl_reserve_free_buf(struct msm_cam_media_controller *pmctl, int msm_mctl_release_free_buf(struct msm_cam_media_controller *pmctl, int path, struct msm_free_buf *free_buf); /*Memory(PMEM) functions*/ -int msm_register_pmem(struct hlist_head *ptype, void __user *arg); -int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg); +int msm_register_pmem(struct hlist_head *ptype, void __user *arg, + struct ion_client *client); +int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg, + struct ion_client *client); int msm_pmem_region_get_phy_addr(struct hlist_head *ptype, struct msm_mem_map_info *mem_map, int32_t *phyaddr); uint8_t msm_pmem_region_lookup(struct hlist_head *ptype, diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c index 1bbb029008c..f7e5479736c 100644 --- a/drivers/media/video/msm/msm_mctl_buf.c +++ b/drivers/media/video/msm/msm_mctl_buf.c @@ -115,7 +115,7 @@ static int msm_vb2_ops_buf_init(struct vb2_buffer *vb) rc = videobuf2_pmem_contig_user_get(mem, &offset, buf_type, pcam_inst->buf_offset[buf_idx][i].addr_offset, - pcam_inst->path); + pcam_inst->path, pcam->mctl.client); else rc = videobuf2_pmem_contig_mmap_get(mem, &offset, buf_type, pcam_inst->path); @@ -241,7 +241,7 @@ static void msm_vb2_ops_buf_cleanup(struct vb2_buffer *vb) } for (i = 0; i < vb->num_planes; i++) { mem = vb2_plane_cookie(vb, i); - videobuf2_pmem_contig_user_put(mem); + videobuf2_pmem_contig_user_put(mem, pcam->mctl.client); } buf->state = MSM_BUFFER_STATE_UNUSED; } diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c index 5c64e01d30b..b6dbe875362 100644 --- a/drivers/media/video/msm/msm_mem.c +++ b/drivers/media/video/msm/msm_mem.c @@ -124,49 +124,57 @@ static int check_overlap(struct hlist_head *ptype, } static int msm_pmem_table_add(struct hlist_head *ptype, - struct msm_pmem_info *info) + struct msm_pmem_info *info, struct ion_client *client) { - struct file *file; unsigned long paddr; unsigned int flags; -#ifdef CONFIG_ANDROID_PMEM +#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION unsigned long kvstart; - int rc; + struct file *file; #endif + int rc = -ENOMEM; + unsigned long len; struct msm_pmem_region *region; -#ifdef CONFIG_ANDROID_PMEM + + region = kmalloc(sizeof(struct msm_pmem_region), GFP_KERNEL); + if (!region) + goto out; +#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION + region->handle = ion_import_fd(client, info->fd); + if (IS_ERR_OR_NULL(region->handle)) + goto OUT1; + ion_phys(client, region->handle, &paddr, (size_t *)&len); +#elif CONFIG_ANDROID_PMEM rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file); if (rc < 0) { pr_err("%s: get_pmem_file fd %d error %d\n", - __func__, - info->fd, rc); - return rc; + __func__, info->fd, rc); + goto out1; } - if (!info->len) - info->len = len; - - rc = check_pmem_info(info, len); - if (rc < 0) - return rc; + region->file = file; #else paddr = 0; file = NULL; + kvstart = 0; #endif + if (!info->len) + info->len = len; + rc = check_pmem_info(info, len); + if (rc < 0) + goto out2; paddr += info->offset; len = info->len; - if (check_overlap(ptype, paddr, len) < 0) - return -EINVAL; + if (check_overlap(ptype, paddr, len) < 0) { + rc = -EINVAL; + goto out2; + } CDBG("%s: type %d, active flag %d, paddr 0x%lx, vaddr 0x%lx\n", __func__, info->type, info->active, paddr, (unsigned long)info->vaddr); - region = kmalloc(sizeof(struct msm_pmem_region), GFP_KERNEL); - if (!region) - return -ENOMEM; - INIT_HLIST_NODE(®ion->list); flags = MSM_SUBSYSTEM_MAP_IOVA; region->subsys_id = MSM_SUBSYSTEM_CAMERA; @@ -174,13 +182,12 @@ static int msm_pmem_table_add(struct hlist_head *ptype, flags, &(region->subsys_id), 1); if (IS_ERR((void *)region->msm_buffer)) { pr_err("%s: msm_subsystem_map_buffer failed\n", __func__); - kfree(region); - put_pmem_file(file); - return PTR_ERR((void *)region->msm_buffer); + rc = PTR_ERR((void *)region->msm_buffer); + goto out2; } - region->paddr = region->msm_buffer->iova[0]; + paddr = region->msm_buffer->iova[0]; + region->paddr = paddr; region->len = len; - region->file = file; memcpy(®ion->info, info, sizeof(region->info)); D("%s Adding region to list with type %d\n", __func__, region->info.type); @@ -188,10 +195,20 @@ static int msm_pmem_table_add(struct hlist_head *ptype, hlist_add_head(&(region->list), ptype); return 0; +out2: +#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION + ion_free(client, region->handle); +#elif CONFIG_ANDROID_PMEM + put_pmem_file(region->file); +#endif +out1: + kfree(region); +out: + return rc; } static int __msm_register_pmem(struct hlist_head *ptype, - struct msm_pmem_info *pinfo) + struct msm_pmem_info *pinfo, struct ion_client *client) { int rc = 0; @@ -203,7 +220,7 @@ static int __msm_register_pmem(struct hlist_head *ptype, case MSM_PMEM_CS: case MSM_PMEM_IHIST: case MSM_PMEM_SKIN: - rc = msm_pmem_table_add(ptype, pinfo); + rc = msm_pmem_table_add(ptype, pinfo, client); break; default: @@ -215,7 +232,7 @@ static int __msm_register_pmem(struct hlist_head *ptype, } static int __msm_pmem_table_del(struct hlist_head *ptype, - struct msm_pmem_info *pinfo) + struct msm_pmem_info *pinfo, struct ion_client *client) { int rc = 0; struct msm_pmem_region *region; @@ -235,16 +252,16 @@ static int __msm_pmem_table_del(struct hlist_head *ptype, if (pinfo->type == region->info.type && pinfo->vaddr == region->info.vaddr && pinfo->fd == region->info.fd) { + hlist_del(node); if (msm_subsystem_unmap_buffer (region->msm_buffer) < 0) pr_err( "%s: unmapped stat memory\n", - __func__); - hlist_del(node); -#ifdef CONFIG_ANDROID_PMEM - put_pmem_file(region->file); + __func__); +#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION + ion_free(client, region->handle); #else - + put_pmem_file(region->file); #endif kfree(region); } @@ -381,7 +398,8 @@ unsigned long msm_pmem_stats_ptov_lookup(struct msm_sync *sync, return 0; } -int msm_register_pmem(struct hlist_head *ptype, void __user *arg) +int msm_register_pmem(struct hlist_head *ptype, void __user *arg, + struct ion_client *client) { struct msm_pmem_info info; @@ -390,11 +408,12 @@ int msm_register_pmem(struct hlist_head *ptype, void __user *arg) return -EFAULT; } - return __msm_register_pmem(ptype, &info); + return __msm_register_pmem(ptype, &info, client); } EXPORT_SYMBOL(msm_register_pmem); -int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg) +int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg, + struct ion_client *client) { struct msm_pmem_info info; @@ -403,6 +422,6 @@ int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg) return -EFAULT; } - return __msm_pmem_table_del(ptype, &info); + return __msm_pmem_table_del(ptype, &info, client); } EXPORT_SYMBOL(msm_pmem_table_del); diff --git a/drivers/media/video/videobuf2-msm-mem.c b/drivers/media/video/videobuf2-msm-mem.c index d7652446f75..fa7e3fd7f5c 100644 --- a/drivers/media/video/videobuf2-msm-mem.c +++ b/drivers/media/video/videobuf2-msm-mem.c @@ -151,16 +151,27 @@ EXPORT_SYMBOL_GPL(videobuf2_pmem_contig_mmap_get); int videobuf2_pmem_contig_user_get(struct videobuf2_contig_pmem *mem, struct videobuf2_msm_offset *offset, enum videobuf2_buffer_type buffer_type, - uint32_t addr_offset, int path) + uint32_t addr_offset, int path, + struct ion_client *client) { - unsigned long kvstart; unsigned long len; - int rc; + int rc = 0; +#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION + unsigned long kvstart; +#endif unsigned int flags = 0; - + unsigned long paddr = 0; if (mem->phyaddr != 0) return 0; - +#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION + mem->ion_handle = ion_import_fd(client, (int)mem->vaddr); + if (IS_ERR_OR_NULL(mem->ion_handle)) { + pr_err("%s ION import failed\n", __func__); + return PTR_ERR(mem->ion_handle); + } + rc = ion_phys(client, mem->ion_handle, (ion_phys_addr_t *)&mem->phyaddr, + (size_t *)&len); +#elif CONFIG_ANDROID_PMEM rc = get_pmem_file((int)mem->vaddr, (unsigned long *)&mem->phyaddr, &kvstart, &len, &mem->file); if (rc < 0) { @@ -168,32 +179,48 @@ int videobuf2_pmem_contig_user_get(struct videobuf2_contig_pmem *mem, __func__, (int)mem->vaddr, rc); return rc; } +#else + paddr = 0; + kvstart = 0; +#endif if (offset) mem->offset = *offset; else memset(&mem->offset, 0, sizeof(struct videobuf2_msm_offset)); mem->path = path; mem->buffer_type = buffer_type; + paddr = mem->phyaddr; flags = MSM_SUBSYSTEM_MAP_IOVA; mem->subsys_id = MSM_SUBSYSTEM_CAMERA; mem->msm_buffer = msm_subsystem_map_buffer(mem->phyaddr, len, flags, &(mem->subsys_id), 1); if (IS_ERR((void *)mem->msm_buffer)) { pr_err("%s: msm_subsystem_map_buffer failed\n", __func__); +#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION + ion_free(client, mem->ion_handle); +#elif CONFIG_ANDROID_PMEM put_pmem_file(mem->file); +#endif return PTR_ERR((void *)mem->msm_buffer); } - mem->mapped_phyaddr = mem->msm_buffer->iova[0] + addr_offset; + paddr = mem->msm_buffer->iova[0]; + mem->mapped_phyaddr = paddr + addr_offset; return rc; } EXPORT_SYMBOL_GPL(videobuf2_pmem_contig_user_get); -void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem) +void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem, + struct ion_client *client) { if (msm_subsystem_unmap_buffer(mem->msm_buffer) < 0) D("%s unmapped memory\n", __func__); - if (mem->is_userptr) + if (mem->is_userptr) { +#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION + ion_free(client, mem->ion_handle); +#elif CONFIG_ANDROID_PMEM put_pmem_file(mem->file); +#endif + } mem->is_userptr = 0; mem->phyaddr = 0; mem->size = 0; diff --git a/include/media/videobuf2-msm-mem.h b/include/media/videobuf2-msm-mem.h index ac1575bd69e..916c458e76b 100644 --- a/include/media/videobuf2-msm-mem.h +++ b/include/media/videobuf2-msm-mem.h @@ -17,6 +17,7 @@ #include #include +#include struct videobuf2_mapping { unsigned int count; @@ -58,6 +59,7 @@ struct videobuf2_contig_pmem { struct msm_mapped_buffer *msm_buffer; int subsys_id; unsigned long mapped_phyaddr; + struct ion_handle *ion_handle; }; void videobuf2_queue_pmem_contig_init(struct vb2_queue *q, enum v4l2_buf_type type, @@ -70,8 +72,10 @@ int videobuf2_pmem_contig_mmap_get(struct videobuf2_contig_pmem *mem, int videobuf2_pmem_contig_user_get(struct videobuf2_contig_pmem *mem, struct videobuf2_msm_offset *offset, enum videobuf2_buffer_type, - uint32_t addr_offset, int path); -void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem); + uint32_t addr_offset, int path, + struct ion_client *client); +void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem, + struct ion_client *client); unsigned long videobuf2_to_pmem_contig(struct vb2_buffer *buf, unsigned int plane_no);