camera_v1: Fix the post-processor

This implementation was mismatched with userspace, resulting in the
inability to handle frames. Fixit by restoring an older version

Change-Id: I92f053ec03f4e4cce5cf18b0177b81352fd262a0
This commit is contained in:
Ricardo Cerqueira 2013-12-29 16:50:00 +00:00
parent d613a6ae5c
commit f0864c039b
11 changed files with 446 additions and 185 deletions

View File

@ -340,7 +340,7 @@ int32_t msm_camera_i2c_write_tbl(struct msm_camera_i2c_client *client,
struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint16_t size,
enum msm_camera_i2c_data_type data_type)
{
int i, j;
int i;
int32_t rc = -EFAULT;
if (client->cci_client) {
struct msm_camera_cci_ctrl cci_ctrl;
@ -361,15 +361,7 @@ int32_t msm_camera_i2c_write_tbl(struct msm_camera_i2c_client *client,
reg_conf_tbl->reg_addr,
reg_conf_tbl->reg_data,
reg_conf_tbl->dt);
} else if (reg_conf_tbl->cmd_type == MSM_CAMERA_I2C_CMD_SEQ_WRITE) {
for(j = 0 ; j < reg_conf_tbl->num_byte ; j += 1){
rc = msm_camera_i2c_write(
client,
(reg_conf_tbl->reg_addr) + 2*j,
reg_conf_tbl->data[j], data_type);
}
}
else {
} else {
if (reg_conf_tbl->dt == 0)
dt = data_type;
else

View File

@ -205,10 +205,36 @@ struct msm_isp_color_fmt {
enum v4l2_colorspace colorspace;
};
struct msm_cam_return_frame_info {
int dirty;
int node_type;
struct timeval timestamp;
};
struct msm_cam_timestamp {
uint8_t present;
struct timeval timestamp;
};
struct msm_cam_buf_map_info {
int fd;
uint32_t data_offset;
unsigned long paddr;
unsigned long len;
struct file *file;
struct ion_handle *handle;
};
struct msm_cam_meta_frame {
struct msm_pp_frame frame;
/* Mapping information per plane */
struct msm_cam_buf_map_info map[VIDEO_MAX_PLANES];
};
struct msm_mctl_pp_frame_info {
int user_cmd;
struct msm_pp_frame src_frame;
struct msm_pp_frame dest_frame;
struct msm_cam_meta_frame src_frame;
struct msm_cam_meta_frame dest_frame;
struct msm_mctl_pp_frame_cmd pp_frame_cmd;
struct msm_cam_media_controller *p_mctl;
};
@ -604,7 +630,8 @@ int msm_mctl_buf_done(struct msm_cam_media_controller *pmctl,
uint32_t frame_id);
int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
struct msm_cam_buf_handle *buf_handle,
struct msm_free_buf *frame, int dirty, int node_type);
struct msm_free_buf *frame,
struct msm_cam_return_frame_info *ret_frame);
int msm_mctl_reserve_free_buf(struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst,
struct msm_cam_buf_handle *buf_handle,
@ -638,7 +665,7 @@ int msm_isp_subdev_ioctl(struct v4l2_subdev *sd,
struct msm_vfe_cfg_cmd *cfgcmd, void *data);
int msm_vpe_subdev_init(struct v4l2_subdev *sd);
int msm_gemini_subdev_init(struct v4l2_subdev *gemini_sd);
void msm_vpe_subdev_release(void);
void msm_vpe_subdev_release(struct v4l2_subdev *sd);
void msm_gemini_subdev_release(struct v4l2_subdev *gemini_sd);
int msm_mctl_is_pp_msg_type(struct msm_cam_media_controller *p_mctl,
int msg_type);
@ -683,6 +710,10 @@ struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
struct msm_cam_buf_handle *buf_handle);
int msm_mctl_buf_return_buf(struct msm_cam_media_controller *pmctl,
int image_mode, struct msm_frame_buffer *buf);
int msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
struct ion_client *client, int domain_num);
int msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
struct ion_client *client, int domain_num);
int msm_mctl_pp_mctl_divert_done(struct msm_cam_media_controller *p_mctl,
void __user *arg);
void msm_release_ion_client(struct kref *ref);

View File

@ -61,7 +61,6 @@ static uint32_t sensor_mount_angle[MSM_MAX_CAMERA_SENSORS];
struct ion_client *client_for_ion;
#ifdef CONFIG_MSM_CAMERA_DEBUG
static const char *vfe_config_cmd[] = {
"CMD_GENERAL", /* 0 */
"CMD_AXI_CFG_OUT1",
@ -109,7 +108,6 @@ static const char *vfe_config_cmd[] = {
"CMD_AXI_CFG_SNAP_VPE",
"CMD_AXI_CFG_SNAP_THUMB_VPE",
};
#endif
#define __CONTAINS(r, v, l, field) ({ \
typeof(r) __r = r; \
typeof(v) __v = v; \

View File

@ -422,22 +422,19 @@ static int msm_mctl_cmd(struct msm_cam_media_controller *p_mctl,
rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
VIDIOC_MSM_AXI_CFG, (void __user *)arg);
else
rc = p_mctl->isp_sdev->isp_config(p_mctl, cmd, arg);
if ((p_mctl) && (p_mctl->isp_sdev) && (p_mctl->isp_sdev->isp_config))
rc = p_mctl->isp_sdev->isp_config(p_mctl, cmd, arg);
break;
case MSM_CAM_IOCTL_ISPIF_IO_CFG:
rc = v4l2_subdev_call(p_mctl->ispif_sdev,
core, ioctl, VIDIOC_MSM_ISPIF_CFG, argp);
break;
default:
if ((p_mctl) && (p_mctl->isp_sdev) && (p_mctl->isp_sdev->isp_config)) {
/* ISP config*/
D("%s:%d: go to default. Calling msm_isp_config\n",
__func__, __LINE__);
/* ISP config*/
D("%s:%d: go to default. Calling msm_isp_config\n",
__func__, __LINE__);
if ((p_mctl) && (p_mctl->isp_sdev) && (p_mctl->isp_sdev->isp_config))
rc = p_mctl->isp_sdev->isp_config(p_mctl, cmd, arg);
} else {
rc = -EINVAL;
pr_err("%s: media controller is null\n", __func__);
}
break;
}
D("%s: !!! cmd = %d, rc = %d\n",

View File

@ -430,7 +430,8 @@ int msm_mctl_buf_done_proc(
struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst,
struct msm_free_buf *fbuf,
uint32_t *frame_id, int gen_timestamp)
uint32_t *frame_id,
struct msm_cam_timestamp *cam_ts)
{
struct msm_frame_buffer *buf = NULL;
int del_buf = 1;
@ -441,11 +442,15 @@ int msm_mctl_buf_done_proc(
__func__, fbuf->ch_paddr[0]);
return -EINVAL;
}
if (gen_timestamp) {
if (!cam_ts->present) {
if (frame_id)
buf->vidbuf.v4l2_buf.sequence = *frame_id;
msm_mctl_gettimeofday(
&buf->vidbuf.v4l2_buf.timestamp);
} else {
D("%s Copying timestamp as %ld.%ld", __func__,
cam_ts->timestamp.tv_sec, cam_ts->timestamp.tv_usec);
buf->vidbuf.v4l2_buf.timestamp = cam_ts->timestamp;
}
vb2_buffer_done(&buf->vidbuf, VB2_BUF_STATE_DONE);
return 0;
@ -461,6 +466,7 @@ int msm_mctl_buf_done(struct msm_cam_media_controller *p_mctl,
int idx, rc;
int pp_divert_type = 0, pp_type = 0;
uint32_t image_mode;
struct msm_cam_timestamp cam_ts;
if (!p_mctl || !buf_handle || !fbuf) {
pr_err("%s Invalid argument. ", __func__);
@ -501,7 +507,11 @@ int msm_mctl_buf_done(struct msm_cam_media_controller *p_mctl,
if (idx > MSM_DEV_INST_MAX) {
idx = GET_VIDEO_INST_IDX(
buf_handle->inst_handle);
BUG_ON(idx > MSM_DEV_INST_MAX);
if (idx > MSM_DEV_INST_MAX) {
pr_err("%s Invalid idx %d ", __func__,
idx);
return -EINVAL;
}
pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
} else {
pcam_inst = p_mctl->pcam_ptr->mctl_node.
@ -526,8 +536,9 @@ int msm_mctl_buf_done(struct msm_cam_media_controller *p_mctl,
__func__);
return -EINVAL;
}
memset(&cam_ts, 0, sizeof(cam_ts));
rc = msm_mctl_buf_done_proc(p_mctl, pcam_inst,
fbuf, &frame_id, 1);
fbuf, &frame_id, &cam_ts);
}
return rc;
}
@ -632,7 +643,10 @@ struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
idx = GET_MCTLPP_INST_IDX(buf_handle->inst_handle);
if (idx > MSM_DEV_INST_MAX) {
idx = GET_VIDEO_INST_IDX(buf_handle->inst_handle);
BUG_ON(idx > MSM_DEV_INST_MAX);
if (idx > MSM_DEV_INST_MAX) {
pr_err("%s Invalid idx %d ", __func__, idx);
return NULL;
}
pcam_inst = pcam->dev_inst[idx];
} else {
pcam_inst = pcam->mctl_node.dev_inst[idx];
@ -797,12 +811,14 @@ int msm_mctl_release_free_buf(struct msm_cam_media_controller *pmctl,
int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
struct msm_cam_buf_handle *buf_handle,
struct msm_free_buf *frame, int dirty, int node_type)
struct msm_free_buf *frame,
struct msm_cam_return_frame_info *ret_frame)
{
struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
int rc = 0, idx;
struct msm_cam_timestamp cam_ts;
if (!pmctl || !buf_handle) {
if (!pmctl || !buf_handle || !ret_frame) {
pr_err("%s Invalid argument ", __func__);
return -EINVAL;
}
@ -811,20 +827,23 @@ int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
idx = GET_MCTLPP_INST_IDX(buf_handle->inst_handle);
if (idx > MSM_DEV_INST_MAX) {
idx = GET_VIDEO_INST_IDX(buf_handle->inst_handle);
BUG_ON(idx > MSM_DEV_INST_MAX);
if (idx > MSM_DEV_INST_MAX) {
pr_err("%s Invalid idx %d ", __func__, idx);
return -EINVAL;
}
pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
} else {
pcam_inst = pmctl->pcam_ptr->mctl_node.dev_inst[idx];
}
} else if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_IMG_MODE) {
idx = msm_mctl_img_mode_to_inst_index(pmctl,
buf_handle->image_mode, node_type);
buf_handle->image_mode, ret_frame->node_type);
if (idx < 0) {
pr_err("%s Invalid instance, buffer not released\n",
__func__);
return idx;
}
if (node_type)
if (ret_frame->node_type)
pcam_inst = pmctl->pcam_ptr->mctl_node.dev_inst[idx];
else
pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
@ -836,12 +855,15 @@ int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
}
D("%s:inst=0x%p, paddr=0x%x, dirty=%d",
__func__, pcam_inst, frame->ch_paddr[0], dirty);
if (dirty)
__func__, pcam_inst, frame->ch_paddr[0], ret_frame->dirty);
cam_ts.present = 1;
cam_ts.timestamp = ret_frame->timestamp;
if (ret_frame->dirty)
/* the frame is dirty, not going to disptach to app */
rc = msm_mctl_release_free_buf(pmctl, pcam_inst, frame);
else
rc = msm_mctl_buf_done_proc(pmctl, pcam_inst, frame, NULL, 0);
rc = msm_mctl_buf_done_proc(pmctl, pcam_inst, frame,
NULL, &cam_ts);
return rc;
}
@ -885,3 +907,199 @@ int msm_mctl_buf_return_buf(struct msm_cam_media_controller *pmctl,
spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
return -EINVAL;
}
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
/* Unmap using ION APIs */
static void __msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
struct ion_client *client, int domain_num)
{
int i = 0;
for (i = 0; i < meta_frame->frame.num_planes; i++) {
D("%s Plane %d handle %p", __func__, i,
meta_frame->map[i].handle);
ion_unmap_iommu(client, meta_frame->map[i].handle,
domain_num, 0);
ion_free(client, meta_frame->map[i].handle);
}
}
/* Map using ION APIs */
static int __msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
struct ion_client *client, int domain_num)
{
unsigned long paddr = 0;
unsigned long len = 0;
int i = 0, j = 0;
for (i = 0; i < meta_frame->frame.num_planes; i++) {
meta_frame->map[i].handle = ion_import_dma_buf(client,
meta_frame->frame.mp[i].fd);
if (IS_ERR_OR_NULL(meta_frame->map[i].handle)) {
pr_err("%s: ion_import failed for plane = %d fd = %d",
__func__, i, meta_frame->frame.mp[i].fd);
/* Roll back previous plane mappings, if any */
for (j = i-1; j >= 0; j--) {
ion_unmap_iommu(client,
meta_frame->map[j].handle,
domain_num, 0);
ion_free(client, meta_frame->map[j].handle);
}
return -EACCES;
}
D("%s Mapping fd %d plane %d handle %p", __func__,
meta_frame->frame.mp[i].fd, i,
meta_frame->map[i].handle);
if (ion_map_iommu(client, meta_frame->map[i].handle,
domain_num, 0, SZ_4K,
0, &paddr, &len, 0, 0) < 0) {
pr_err("%s: cannot map address plane %d", __func__, i);
ion_free(client, meta_frame->map[i].handle);
/* Roll back previous plane mappings, if any */
for (j = i-1; j >= 0; j--) {
if (meta_frame->map[j].handle) {
ion_unmap_iommu(client,
meta_frame->map[j].handle,
domain_num, 0);
ion_free(client,
meta_frame->map[j].handle);
}
}
return -EFAULT;
}
/* Validate the offsets with the mapped length. */
if ((meta_frame->frame.mp[i].addr_offset > len) ||
(meta_frame->frame.mp[i].data_offset +
meta_frame->frame.mp[i].length > len)) {
pr_err("%s: Invalid offsets A %d D %d L %d len %ld",
__func__, meta_frame->frame.mp[i].addr_offset,
meta_frame->frame.mp[i].data_offset,
meta_frame->frame.mp[i].length, len);
/* Roll back previous plane mappings, if any */
for (j = i; j >= 0; j--) {
if (meta_frame->map[j].handle) {
ion_unmap_iommu(client,
meta_frame->map[j].handle,
domain_num, 0);
ion_free(client,
meta_frame->map[j].handle);
}
}
return -EINVAL;
}
meta_frame->map[i].data_offset =
meta_frame->frame.mp[i].data_offset;
/* Add the addr_offset to the paddr here itself. The addr_offset
* will be non-zero only if the user has allocated a buffer with
* a single fd, but logically partitioned it into
* multiple planes or buffers.*/
paddr += meta_frame->frame.mp[i].addr_offset;
meta_frame->map[i].paddr = paddr;
meta_frame->map[i].len = len;
D("%s Plane %d fd %d handle %p paddr %x", __func__,
i, meta_frame->frame.mp[i].fd,
meta_frame->map[i].handle,
(uint32_t)meta_frame->map[i].paddr);
}
D("%s Frame mapped successfully ", __func__);
return 0;
}
#else
/* Unmap using PMEM APIs */
static int __msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
struct ion_client *client, int domain_num)
{
int i = 0, rc = 0;
for (i = 0; i < meta_frame->frame.num_planes; i++) {
D("%s Plane %d handle %p", __func__, i,
meta_frame->map[i].handle);
put_pmem_file(meta_frame->map[i].file);
}
}
/* Map using PMEM APIs */
static int __msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
struct ion_client *client, int domain_num)
{
unsigned long kvstart = 0;
unsigned long paddr = 0;
struct file *file = NULL;
unsigned long len;
int i = 0, j = 0;
for (i = 0; i < meta_frame->frame.num_planes; i++) {
rc = get_pmem_file(meta_frame->frame.mp[i].fd,
&paddr, &kvstart, &len, &file);
if (rc < 0) {
pr_err("%s: get_pmem_file fd %d error %d\n",
__func__, meta_frame->frame.mp[i].fd, rc);
/* Roll back previous plane mappings, if any */
for (j = i-1; j >= 0; j--)
if (meta_frame->map[j].file)
put_pmem_file(meta_frame->map[j].file);
return -EACCES;
}
D("%s Got pmem file for fd %d plane %d as %p", __func__,
meta_frame->frame.mp[i].fd, i, file);
meta_frame->map[i].file = file;
/* Validate the offsets with the mapped length. */
if ((meta_frame->frame.mp[i].addr_offset > len) ||
(meta_frame->frame.mp[i].data_offset +
meta_frame->frame.mp[i].length > len)) {
pr_err("%s: Invalid offsets A %d D %d L %d len %ld",
__func__, meta_frame->frame.mp[i].addr_offset,
meta_frame->frame.mp[i].data_offset,
meta_frame->frame.mp[i].length, len);
/* Roll back previous plane mappings, if any */
for (j = i; j >= 0; j--)
if (meta_frame->map[j].file)
put_pmem_file(meta_frame->map[j].file);
return -EINVAL;
}
meta_frame->map[i].data_offset =
meta_frame->frame.mp[i].data_offset;
/* Add the addr_offset to the paddr here itself. The addr_offset
* will be non-zero only if the user has allocated a buffer with
* a single fd, but logically partitioned it into
* multiple planes or buffers.*/
paddr += meta_frame->frame.mp[i].addr_offset;
meta_frame->map[i].paddr = paddr;
meta_frame->map[i].len = len;
D("%s Plane %d fd %d handle %p paddr %x", __func__,
i, meta_frame->frame.mp[i].fd,
meta_frame->map[i].handle,
(uint32_t)meta_frame->map[i].paddr);
}
D("%s Frame mapped successfully ", __func__);
return 0;
}
#endif
int msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
struct ion_client *client, int domain_num)
{
if ((NULL == meta_frame) || (NULL == client)) {
pr_err("%s Invalid input ", __func__);
return -EINVAL;
}
memset(&meta_frame->map[0], 0,
sizeof(struct msm_cam_buf_map_info) * VIDEO_MAX_PLANES);
return __msm_mctl_map_user_frame(meta_frame, client, domain_num);
}
int msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
struct ion_client *client, int domain_num)
{
if ((NULL == meta_frame) || (NULL == client)) {
pr_err("%s Invalid input ", __func__);
return -EINVAL;
}
__msm_mctl_unmap_user_frame(meta_frame, client, domain_num);
return 0;
}

View File

@ -385,49 +385,6 @@ static int msm_mctl_pp_get_phy_addr(
return 0;
}
static int msm_mctl_pp_copy_timestamp_and_frame_id(
uint32_t src_handle, uint32_t dest_handle)
{
struct msm_frame_buffer *src_vb;
struct msm_frame_buffer *dest_vb;
src_vb = (struct msm_frame_buffer *)src_handle;
dest_vb = (struct msm_frame_buffer *)dest_handle;
dest_vb->vidbuf.v4l2_buf.timestamp =
src_vb->vidbuf.v4l2_buf.timestamp;
dest_vb->vidbuf.v4l2_buf.sequence =
src_vb->vidbuf.v4l2_buf.sequence;
D("%s: timestamp=%ld:%ld,frame_id=0x%x", __func__,
dest_vb->vidbuf.v4l2_buf.timestamp.tv_sec,
dest_vb->vidbuf.v4l2_buf.timestamp.tv_usec,
dest_vb->vidbuf.v4l2_buf.sequence);
return 0;
}
static int msm_mctl_pp_path_to_inst_index(struct msm_cam_v4l2_device *pcam,
int out_type)
{
int image_mode;
switch (out_type) {
case OUTPUT_TYPE_P:
image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
break;
case OUTPUT_TYPE_V:
image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
break;
case OUTPUT_TYPE_S:
image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
break;
default:
image_mode = -1;
break;
}
if ((image_mode >= 0) && pcam->dev_inst_map[image_mode])
return pcam->dev_inst_map[image_mode]->my_index;
else
return -EINVAL;
}
static int msm_mctl_pp_path_to_img_mode(int path)
{
switch (path) {
@ -636,6 +593,7 @@ int msm_mctl_pp_done(
struct msm_free_buf buf;
unsigned long flags;
struct msm_cam_buf_handle buf_handle;
struct msm_cam_return_frame_info ret_frame;
if (copy_from_user(&frame, arg, sizeof(frame))) {
ERR_COPY_FROM_USER();
@ -678,7 +636,11 @@ int msm_mctl_pp_done(
buf.ch_paddr[0] = frame.sp.phy_addr + frame.sp.y_off;
}
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, dirty, 0);
ret_frame.dirty = dirty;
ret_frame.node_type = 0;
ret_frame.timestamp = frame.timestamp;
rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, &ret_frame);
return rc;
}
@ -688,10 +650,10 @@ int msm_mctl_pp_divert_done(
{
struct msm_pp_frame frame;
int msg_type, image_mode, rc = 0;
int dirty = 0;
struct msm_free_buf buf;
unsigned long flags;
struct msm_cam_buf_handle buf_handle;
struct msm_cam_return_frame_info ret_frame;
D("%s enter\n", __func__);
@ -739,9 +701,12 @@ int msm_mctl_pp_divert_done(
buf.ch_paddr[0] = frame.sp.phy_addr + frame.sp.y_off;
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
ret_frame.dirty = 0;
ret_frame.node_type = frame.node_type;
ret_frame.timestamp = frame.timestamp;
D("%s Frame done id: %d\n", __func__, frame.frame_id);
rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle,
&buf, dirty, frame.node_type);
rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, &ret_frame);
return rc;
err:
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
@ -776,54 +741,3 @@ int msm_mctl_pp_mctl_divert_done(
return rc;
}
int msm_mctl_pp_get_vpe_buf_info(struct msm_mctl_pp_frame_info *zoom)
{
struct msm_cam_media_controller *p_mctl;
struct msm_cam_v4l2_dev_inst *pcam_inst;
int rc = 0, idx;
if (!zoom || !zoom->p_mctl) {
pr_err("%s Invalid input, not sending buffer to VPE ",
__func__);
return -EINVAL;
}
p_mctl = zoom->p_mctl;
idx = msm_mctl_pp_path_to_inst_index(p_mctl->pcam_ptr,
zoom->pp_frame_cmd.path);
if (idx < 0) {
pr_err("%s Invalid path, returning\n", __func__);
return idx;
}
pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
if (!pcam_inst) {
pr_err("%s Invalid instance, returning\n", __func__);
return -EINVAL;
}
rc = msm_mctl_pp_get_phy_addr(pcam_inst,
zoom->pp_frame_cmd.src_buf_handle, &zoom->src_frame);
if (rc) {
pr_err("%s Error getting buffer address for src frame\n",
__func__);
return rc;
}
rc = msm_mctl_pp_get_phy_addr(pcam_inst,
zoom->pp_frame_cmd.dest_buf_handle, &zoom->dest_frame);
if (rc) {
pr_err("%s Error getting buffer address for dest frame\n",
__func__);
return rc;
}
rc = msm_mctl_pp_copy_timestamp_and_frame_id(
zoom->pp_frame_cmd.src_buf_handle,
zoom->pp_frame_cmd.dest_buf_handle);
if (rc < 0) {
pr_err("%s Error copying timestamp info\n",
__func__);
return rc;
}
return rc;
}

View File

@ -36,8 +36,8 @@
#define D(fmt, args...) do {} while (0)
#endif
static int vpe_enable(uint32_t);
static int vpe_disable(void);
static int vpe_enable(uint32_t, struct msm_cam_media_controller *);
static int vpe_disable(struct msm_cam_media_controller *);
static int vpe_update_scaler(struct msm_pp_crop *pcrop);
struct vpe_ctrl_type *vpe_ctrl;
static atomic_t vpe_init_done = ATOMIC_INIT(0);
@ -425,29 +425,37 @@ static int msm_send_frame_to_vpe(void)
int rc = 0;
unsigned long flags;
unsigned long srcP0, srcP1, outP0, outP1;
struct msm_mctl_pp_frame_info *frame = vpe_ctrl->pp_frame_info;
struct msm_mctl_pp_frame_info *frame_info = vpe_ctrl->pp_frame_info;
if (!frame_info) {
pr_err("%s Invalid frame", __func__);
return -EINVAL;
}
spin_lock_irqsave(&vpe_ctrl->lock, flags);
if (frame->src_frame.num_planes > 1) {
srcP0 = vpe_ctrl->pp_frame_info->src_frame.mp[0].phy_addr +
vpe_ctrl->pp_frame_info->src_frame.mp[0].data_offset;
srcP1 = vpe_ctrl->pp_frame_info->src_frame.mp[1].phy_addr +
vpe_ctrl->pp_frame_info->src_frame.mp[1].data_offset;
outP0 = vpe_ctrl->pp_frame_info->dest_frame.mp[0].phy_addr +
vpe_ctrl->pp_frame_info->dest_frame.mp[0].data_offset;
outP1 = vpe_ctrl->pp_frame_info->dest_frame.mp[1].phy_addr +
vpe_ctrl->pp_frame_info->dest_frame.mp[1].data_offset;
if (frame_info->src_frame.frame.num_planes > 1) {
srcP0 = frame_info->src_frame.map[0].paddr +
frame_info->src_frame.map[0].data_offset;
srcP1 = frame_info->src_frame.map[1].paddr +
frame_info->src_frame.map[1].data_offset;
outP0 = frame_info->dest_frame.map[0].paddr +
frame_info->dest_frame.map[0].data_offset;
outP1 = frame_info->dest_frame.map[1].paddr +
frame_info->dest_frame.map[1].data_offset;
} else {
srcP0 = vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
vpe_ctrl->pp_frame_info->src_frame.sp.y_off;
srcP1 = vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
vpe_ctrl->pp_frame_info->src_frame.sp.cbcr_off;
outP0 = vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
vpe_ctrl->pp_frame_info->dest_frame.sp.y_off;
outP1 = vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
vpe_ctrl->pp_frame_info->dest_frame.sp.cbcr_off;
srcP0 = frame_info->src_frame.map[0].paddr;
srcP1 = frame_info->src_frame.map[0].paddr +
frame_info->src_frame.map[0].data_offset;
outP0 = frame_info->dest_frame.map[0].paddr;
outP1 = frame_info->dest_frame.map[0].paddr +
frame_info->dest_frame.map[0].data_offset;
}
D("%s VPE Configured with Src %x, %x Dest %x, %x",
__func__, (uint32_t)srcP0, (uint32_t)srcP1,
(uint32_t)outP0, (uint32_t)outP1);
msm_camera_io_w(srcP0, vpe_ctrl->vpebase + VPE_SRCP0_ADDR_OFFSET);
msm_camera_io_w(srcP1, vpe_ctrl->vpebase + VPE_SRCP1_ADDR_OFFSET);
msm_camera_io_w(outP0, vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET);
@ -518,7 +526,7 @@ static struct msm_cam_clk_info vpe_clk_info[] = {
{"vpe_pclk", -1},
};
int vpe_enable(uint32_t clk_rate)
int vpe_enable(uint32_t clk_rate, struct msm_cam_media_controller *mctl)
{
int rc = 0;
unsigned long flags = 0;
@ -547,8 +555,27 @@ int vpe_enable(uint32_t clk_rate)
if (rc < 0)
goto vpe_clk_failed;
#ifdef CONFIG_MSM_IOMMU
rc = iommu_attach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
if (rc < 0) {
pr_err("%s: Device attach failed\n", __func__);
goto src_attach_failed;
}
rc = iommu_attach_device(mctl->domain, vpe_ctrl->iommu_ctx_dst);
if (rc < 0) {
pr_err("%s: Device attach failed\n", __func__);
goto dst_attach_failed;
}
#endif
return rc;
#ifdef CONFIG_MSM_IOMMU
dst_attach_failed:
iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
src_attach_failed:
#endif
msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
vpe_ctrl->vpe_clk, ARRAY_SIZE(vpe_clk_info), 0);
vpe_clk_failed:
if (vpe_ctrl->fs_vpe)
regulator_disable(vpe_ctrl->fs_vpe);
@ -558,7 +585,7 @@ vpe_fs_failed:
return rc;
}
int vpe_disable(void)
int vpe_disable(struct msm_cam_media_controller *mctl)
{
int rc = 0;
unsigned long flags = 0;
@ -570,7 +597,10 @@ int vpe_disable(void)
return rc;
}
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
#ifdef CONFIG_MSM_IOMMU
iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_dst);
iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
#endif
disable_irq(vpe_ctrl->vpeirq->start);
tasklet_kill(&vpe_tasklet);
msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
@ -601,8 +631,8 @@ static int msm_vpe_do_pp(struct msm_mctl_pp_frame_info *pp_frame_info)
msm_vpe_cfg_update(
&vpe_ctrl->pp_frame_info->pp_frame_cmd.crop);
D("%s Sending frame idx %d id %d to VPE ", __func__,
pp_frame_info->src_frame.buf_idx,
pp_frame_info->src_frame.frame_id);
pp_frame_info->src_frame.frame.buf_idx,
pp_frame_info->src_frame.frame.frame_id);
rc = msm_send_frame_to_vpe();
return rc;
}
@ -653,23 +683,25 @@ vpe_unmap_mem_region:
return rc; /* this rc should have error code. */
}
void msm_vpe_subdev_release(void)
void msm_vpe_subdev_release(struct v4l2_subdev *sd)
{
struct msm_cam_media_controller *mctl;
mctl = v4l2_get_subdev_hostdata(sd);
if (!atomic_read(&vpe_init_done)) {
/* no VPE object created */
pr_err("%s: no VPE object to release", __func__);
return;
}
vpe_reset();
vpe_disable();
vpe_disable(mctl);
iounmap(vpe_ctrl->vpebase);
vpe_ctrl->vpebase = NULL;
atomic_set(&vpe_init_done, 0);
}
EXPORT_SYMBOL(msm_vpe_subdev_release);
static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd)
static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd,
struct msm_cam_media_controller *mctl)
{
int rc = 0;
@ -792,21 +824,36 @@ static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd)
zoom->user_cmd = vpe_cmd->cmd_type;
zoom->p_mctl = v4l2_get_subdev_hostdata(&vpe_ctrl->subdev);
D("%s: src=0x%x, dest=0x%x,cookie=0x%x,action=0x%x,path=0x%x",
__func__, zoom->pp_frame_cmd.src_buf_handle,
zoom->pp_frame_cmd.dest_buf_handle,
zoom->pp_frame_cmd.cookie,
D("%s: cookie=0x%x,action=0x%x,path=0x%x",
__func__, zoom->pp_frame_cmd.cookie,
zoom->pp_frame_cmd.vpe_output_action,
zoom->pp_frame_cmd.path);
rc = msm_mctl_pp_get_vpe_buf_info(zoom);
D("%s Mapping Source frame ", __func__);
zoom->src_frame.frame = zoom->pp_frame_cmd.src_frame;
rc = msm_mctl_map_user_frame(&zoom->src_frame,
zoom->p_mctl->client, mctl->domain_num);
if (rc < 0) {
pr_err("%s Error getting buffer info from mctl rc = %d",
pr_err("%s Error mapping source buffer rc = %d",
__func__, rc);
kfree(zoom);
break;
}
D("%s Mapping Destination frame ", __func__);
zoom->dest_frame.frame = zoom->pp_frame_cmd.dest_frame;
rc = msm_mctl_map_user_frame(&zoom->dest_frame,
zoom->p_mctl->client, mctl->domain_num);
if (rc < 0) {
pr_err("%s Error mapping dest buffer rc = %d",
__func__, rc);
msm_mctl_unmap_user_frame(&zoom->src_frame,
zoom->p_mctl->client, mctl->domain_num);
kfree(zoom);
break;
}
rc = msm_vpe_do_pp(zoom);
kfree(zoom);
break;
}
@ -826,13 +873,13 @@ static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd)
return -EFAULT;
}
turbo_mode = (int)clk_rate.rate;
rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE) :
vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE);
rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE, mctl) :
vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE, mctl);
break;
}
case VPE_CMD_DISABLE:
rc = vpe_disable();
rc = vpe_disable(mctl);
break;
default:
@ -847,7 +894,8 @@ static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd,
{
struct msm_vpe_cfg_cmd *vpe_cmd;
int rc = 0;
struct msm_cam_media_controller *mctl;
mctl = v4l2_get_subdev_hostdata(sd);
switch (cmd) {
case VIDIOC_MSM_VPE_INIT: {
msm_vpe_subdev_init(sd);
@ -855,12 +903,12 @@ static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd,
}
case VIDIOC_MSM_VPE_RELEASE:
msm_vpe_subdev_release();
msm_vpe_subdev_release(sd);
break;
case MSM_CAM_V4L2_IOCTL_CFG_VPE: {
vpe_cmd = (struct msm_vpe_cfg_cmd *)arg;
rc = msm_vpe_process_vpe_cmd(vpe_cmd);
rc = msm_vpe_process_vpe_cmd(vpe_cmd, mctl);
if (rc < 0) {
pr_err("%s Error processing VPE cmd %d ",
__func__, vpe_cmd->cmd_type);
@ -882,6 +930,14 @@ static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd,
return -EFAULT;
}
pp_frame_info = event_qcmd->command;
D("%s Unmapping source and destination buffers ",
__func__);
msm_mctl_unmap_user_frame(&pp_frame_info->src_frame,
pp_frame_info->p_mctl->client, mctl->domain_num);
msm_mctl_unmap_user_frame(&pp_frame_info->dest_frame,
pp_frame_info->p_mctl->client, mctl->domain_num);
pp_event_info.event = MCTL_PP_EVENT_CMD_ACK;
pp_event_info.ack.cmd = pp_frame_info->user_cmd;
pp_event_info.ack.status = 0;
@ -890,10 +946,9 @@ static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd,
pp_event_info.ack.cmd, pp_event_info.ack.status,
pp_event_info.ack.cookie);
if (copy_to_user((void __user *)v4l2_ioctl->ioctl_ptr,
&pp_event_info,
sizeof(struct msm_mctl_pp_event_info)))
pr_err("%s EVENTPAYLOAD Copy to user failed ",
__func__);
&pp_event_info, sizeof(struct msm_mctl_pp_event_info)))
pr_err("%s PAYLOAD Copy to user failed ", __func__);
kfree(pp_frame_info);
event_qcmd->command = NULL;
free_qcmd(event_qcmd);
@ -949,12 +1004,23 @@ static int msm_vpe_subdev_close(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh)
{
struct vpe_ctrl_type *vpe_ctrl = v4l2_get_subdevdata(sd);
struct msm_mctl_pp_frame_info *frame_info = vpe_ctrl->pp_frame_info;
struct msm_cam_media_controller *mctl;
mctl = v4l2_get_subdev_hostdata(sd);
if (atomic_read(&vpe_ctrl->active) == 0) {
pr_err("%s already closed\n", __func__);
return -EINVAL;
}
D("%s E ", __func__);
if (frame_info) {
D("%s Unmap the pending item from the queue ", __func__);
msm_mctl_unmap_user_frame(&frame_info->src_frame,
frame_info->p_mctl->client, mctl->domain_num);
msm_mctl_unmap_user_frame(&frame_info->dest_frame,
frame_info->p_mctl->client, mctl->domain_num);
}
vpe_ctrl->pp_frame_info = NULL;
/* Drain the payload queue. */
msm_queue_drain(&vpe_ctrl->eventData_q, list_eventdata);
atomic_dec(&vpe_ctrl->active);
@ -1034,6 +1100,19 @@ static int __devinit msm_vpe_probe(struct platform_device *pdev)
disable_irq(vpe_ctrl->vpeirq->start);
#ifdef CONFIG_MSM_IOMMU
/*get device context for IOMMU*/
vpe_ctrl->iommu_ctx_src = msm_iommu_get_ctx("vpe_src"); /*re-confirm*/
vpe_ctrl->iommu_ctx_dst = msm_iommu_get_ctx("vpe_dst"); /*re-confirm*/
if (!vpe_ctrl->iommu_ctx_src || !vpe_ctrl->iommu_ctx_dst) {
release_mem_region(vpe_ctrl->vpemem->start,
resource_size(vpe_ctrl->vpemem));
pr_err("%s: No iommu fw context found\n", __func__);
rc = -ENODEV;
goto vpe_no_resource;
}
#endif
atomic_set(&vpe_ctrl->active, 0);
vpe_ctrl->pdev = pdev;
sd_info.sdev_type = VPE_DEV;

View File

@ -2636,6 +2636,10 @@ static int msm_open_config(struct inode *inode, struct file *fp)
pr_err("%s: nonseekable_open error %d\n", __func__, rc);
return rc;
}
if (!g_server_dev.pcam_active[config_cam->dev_num])
return -ENODEV;
config_cam->use_count++;
/* assume there is only one active camera possible*/

View File

@ -4949,7 +4949,6 @@ fs_failed:
iounmap(axi_ctrl->share_ctrl->vfebase);
axi_ctrl->share_ctrl->vfebase = NULL;
remap_failed:
disable_irq(axi_ctrl->vfeirq->start);
mctl_failed:
return rc;
}

View File

@ -1926,6 +1926,30 @@ struct msm_ver_num_info {
uint32_t rev;
};
#ifdef CONFIG_MSM_CAMERA
struct msm_pp_crop {
uint32_t src_x;
uint32_t src_y;
uint32_t src_w;
uint32_t src_h;
uint32_t dst_x;
uint32_t dst_y;
uint32_t dst_w;
uint32_t dst_h;
uint8_t update_flag;
};
struct msm_mctl_pp_frame_cmd
{
uint32_t cookie;
uint8_t vpe_output_action;
struct msm_pp_frame src_frame;
struct msm_pp_frame dest_frame;
struct msm_pp_crop crop;
int path;
};
#endif
#define VIDIOC_MSM_CPP_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE, struct msm_camera_v4l2_ioctl_t)

View File

@ -322,6 +322,8 @@ struct msm_mctl_pp_divert_pp {
struct msm_vpe_clock_rate {
uint32_t rate;
};
#ifdef CONFIG_MSMB_CAMERA
struct msm_pp_crop {
uint32_t src_x;
uint32_t src_y;
@ -333,8 +335,6 @@ struct msm_pp_crop {
uint32_t dst_h;
uint8_t update_flag;
};
#define MSM_MCTL_PP_VPE_FRAME_ACK (1<<0)
#define MSM_MCTL_PP_VPE_FRAME_TO_APP (1<<1)
struct msm_mctl_pp_frame_cmd {
uint32_t cookie;
@ -345,6 +345,11 @@ struct msm_mctl_pp_frame_cmd {
int path;
/* TBD: 3D related */
};
#endif
#define MSM_MCTL_PP_VPE_FRAME_ACK (1<<0)
#define MSM_MCTL_PP_VPE_FRAME_TO_APP (1<<1)
#define VFE_OUTPUTS_MAIN_AND_PREVIEW BIT(0)
#define VFE_OUTPUTS_MAIN_AND_VIDEO BIT(1)