Merge "msm: camera: use ION for stats and userptr buffers in V4L2 driver." into msm-3.0
This commit is contained in:
committed by
QuIC Gerrit Code Review
commit
1900dc06f3
@@ -24,6 +24,7 @@
|
||||
#include <mach/board.h>
|
||||
#include <media/msm_camera.h>
|
||||
#include <mach/msm_subsystem_map.h>
|
||||
#include <linux/ion.h>
|
||||
|
||||
#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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <media/msm_isp.h>
|
||||
#include <mach/camera.h>
|
||||
#include <media/msm_isp.h>
|
||||
#include <linux/ion.h>
|
||||
|
||||
#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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <media/videobuf2-core.h>
|
||||
#include <mach/msm_subsystem_map.h>
|
||||
#include <linux/ion.h>
|
||||
|
||||
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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user