msm-camera: configure preview and recording buffers
seperately.
decouple preview and recording path configuration
by configuring the buffers during preview start
and recording start respectively.
Signed-off-by: Kiran Kumar H N <hurlisal@codeaurora.org>
Signed-off-by: Mingcheng Zhu <mingchen@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index b49300d..c7ec849 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -81,6 +81,10 @@
VFE_MSG_SYNC_TIMER1,
VFE_MSG_SYNC_TIMER2,
VFE_MSG_COMMON,
+ VFE_MSG_V32_START,
+ VFE_MSG_V32_START_RECORDING,
+ VFE_MSG_V32_CAPTURE,
+ VFE_MSG_OUTPUT_IRQ,
};
enum vpe_resp_msg {
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 6ded98b..28d8e8a 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -639,7 +639,7 @@
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
- D("%s\n", __func__);
+ D("%s Inst = %p\n", __func__, pcam_inst);
WARN_ON(pctx != f->private_data);
D("%s stored reserved info %d", __func__, pb->reserved);
@@ -679,7 +679,7 @@
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
- D("%s\n", __func__);
+ D("%s Inst %p\n", __func__, pcam_inst);
WARN_ON(pctx != f->private_data);
D("%s Calling videobuf_streamon", __func__);
@@ -707,7 +707,7 @@
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
- D("%s\n", __func__);
+ pr_err("%s Inst %p\n", __func__, pcam_inst);
WARN_ON(pctx != f->private_data);
/* first turn of HW (VFE/sensor) streaming so that buffers are
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 7390f10..89434b3 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -354,7 +354,9 @@
int msm_mctl_init_user_formats(struct msm_cam_v4l2_device *pcam);
int msm_mctl_buf_done(struct msm_cam_media_controller *pmctl,
int msg_type, uint32_t y_phy);
-int msm_mctl_fetch_free_buf(struct msm_cam_media_controller *pmctl,
+int msm_mctl_reserve_free_buf(struct msm_cam_media_controller *pmctl,
+ int path, struct msm_free_buf *free_buf);
+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);
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 480c626..c88e106 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -171,6 +171,11 @@
struct msm_sync *sync =
(struct msm_sync *)v4l2_get_subdev_hostdata(sd);
struct msm_vfe_resp *vdata = (struct msm_vfe_resp *)arg;
+ struct msm_free_buf free_buf;
+ struct msm_camvfe_params vfe_params;
+ struct msm_vfe_cfg_cmd cfgcmd;
+ struct msm_cam_v4l2_device *pcam = sync->pcam_sync;
+ int vfe_id = vdata->evt_msg.msg_id;
if (!sync) {
pr_err("%s: no context in dsp callback.\n", __func__);
@@ -212,13 +217,61 @@
D("%s: qtype %d, general msg, enqueue event_q.\n",
__func__, vdata->type);
break;
+ case VFE_MSG_V32_START:
+ case VFE_MSG_V32_START_RECORDING:
+ D("%s Got V32_START_*: Getting ping addr id = %d",
+ __func__, vfe_id);
+ msm_mctl_reserve_free_buf(&pcam->mctl, vfe_id, &free_buf);
+ cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
+ cfgcmd.value = &vfe_id;
+ vfe_params.vfe_cfg = &cfgcmd;
+ vfe_params.data = (void *)&free_buf;
+ rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
+ msm_mctl_reserve_free_buf(&pcam->mctl, vfe_id, &free_buf);
+ cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
+ cfgcmd.value = &vfe_id;
+ vfe_params.vfe_cfg = &cfgcmd;
+ vfe_params.data = (void *)&free_buf;
+ rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
+ break;
+ case VFE_MSG_V32_CAPTURE:
+ D("%s Got V32_CAPTURE: getting buffer for id = %d",
+ __func__, vfe_id);
+ msm_mctl_reserve_free_buf(&pcam->mctl, vfe_id, &free_buf);
+ cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
+ cfgcmd.value = &vfe_id;
+ vfe_params.vfe_cfg = &cfgcmd;
+ vfe_params.data = (void *)&free_buf;
+ rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
+ /* Write the same buffer into PONG */
+ cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
+ cfgcmd.value = &vfe_id;
+ vfe_params.vfe_cfg = &cfgcmd;
+ vfe_params.data = (void *)&free_buf;
+ rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
+ break;
+ case VFE_MSG_OUTPUT_IRQ:
+ D("%s Got OUTPUT_IRQ: Getting free buf id = %d",
+ __func__, vfe_id);
+ msm_mctl_reserve_free_buf(&pcam->mctl, vfe_id, &free_buf);
+ cfgcmd.cmd_type = CMD_CONFIG_FREE_BUF_ADDR;
+ cfgcmd.value = &vfe_id;
+ vfe_params.vfe_cfg = &cfgcmd;
+ vfe_params.data = (void *)&free_buf;
+ rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
+ break;
default:
D("%s: qtype %d not handled\n", __func__, vdata->type);
/* fall through, send to config. */
}
-
- D("%s: msm_enqueue event_q\n", __func__);
- rc = msm_isp_enqueue(&sync->pcam_sync->mctl, vdata, MSM_CAM_Q_VFE_MSG);
+ if (vdata->type != VFE_MSG_V32_START &&
+ vdata->type != VFE_MSG_V32_START_RECORDING &&
+ vdata->type != VFE_MSG_V32_CAPTURE &&
+ vdata->type != VFE_MSG_OUTPUT_IRQ) {
+ D("%s: msm_enqueue event_q\n", __func__);
+ rc = msm_isp_enqueue(&sync->pcam_sync->mctl,
+ vdata, MSM_CAM_Q_VFE_MSG);
+ }
msm_isp_sync_free(vdata);
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index d084f9c..12f8a2c 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -211,6 +211,9 @@
pcam_inst = vb2_get_drv_priv(vb->vb2_queue);
pcam = pcam_inst->pcam;
buf = container_of(vb, struct msm_frame_buffer, vidbuf);
+ mem = vb2_plane_cookie(vb, 0);
+ if (!mem)
+ return;
D("%s: inst=0x%x, buf=0x%x, idx=%d\n", __func__,
(uint32_t)pcam_inst, (uint32_t)buf, vb->v4l2_buf.index);
vb_phyaddr = (unsigned long) videobuf2_to_pmem_contig(vb, 0);
@@ -238,6 +241,12 @@
static int msm_vb2_ops_stop_streaming(struct vb2_queue *q)
{
+ int rc = 0;
+ struct msm_free_buf *free_buf = NULL;
+ struct msm_cam_v4l2_dev_inst *pcam_inst = vb2_get_drv_priv(q);
+ if (rc != 0)
+ msm_mctl_release_free_buf(&pcam_inst->pcam->mctl,
+ pcam_inst->path, free_buf);
return 0;
}
@@ -247,10 +256,7 @@
struct msm_cam_v4l2_device *pcam = NULL;
unsigned long phyaddr = 0;
unsigned long flags = 0;
- int rc;
struct vb2_queue *vq = vb->vb2_queue;
- struct msm_frame frame;
- struct msm_vfe_cfg_cmd cfgcmd;
struct videobuf2_contig_pmem *mem;
struct msm_frame_buffer *buf;
D("%s\n", __func__);
@@ -268,20 +274,10 @@
/* get the physcial address of the buffer */
phyaddr = (unsigned long) videobuf2_to_pmem_contig(vb, 0);
D("%s buffer type is %d\n", __func__, mem->buffer_type);
- frame.path = pcam_inst->path;
- frame.buffer = 0;
- frame.y_off = mem->y_off;
- frame.cbcr_off = mem->cbcr_off;
- /* now release frame to vfe */
- cfgcmd.cmd_type = CMD_FRAME_BUF_RELEASE;
- cfgcmd.value = (void *)&frame;
spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
+ D("Inst %p, >>>ADD>>> Buf 0x%x index %d into free Q",
+ pcam_inst, (int)phyaddr, vb->v4l2_buf.index);
list_add_tail(&buf->list, &pcam_inst->free_vq);
- /* TBD: need to remove. VFE is going to call
- msm_mctl_fetch_free_buf to get free buf.
- Work with Shuzhen to hash out details tomorrow */
- rc = msm_isp_subdev_ioctl(&pcam->mctl.isp_sdev->sd,
- &cfgcmd, &phyaddr);
spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
}
@@ -375,23 +371,6 @@
return 0;
}
-static int msm_mctl_get_pcam_inst_idx(int out_put_type)
-{
- switch (out_put_type) {
- case OUTPUT_TYPE_T:
- return MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
- case OUTPUT_TYPE_S:
- return MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
- case OUTPUT_TYPE_V:
- return MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
- case OUTPUT_TYPE_P:
- return MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
- default:
- return 0;
- }
-}
-
-
int msm_mctl_buf_done(struct msm_cam_media_controller *pmctl,
int msg_type, uint32_t y_phy)
{
@@ -422,6 +401,9 @@
__func__, (uint32_t)y_phy, (uint32_t)buf_phyaddr);
return -EINVAL;
}
+ D("%s Inst %p, <<<REMOVE<<< buffer 0x%x, index %d"
+ " from free Q", __func__, pcam_inst,
+ buf_phyaddr, buf->vidbuf.v4l2_buf.index);
list_del(&buf->list);
buf->vidbuf.v4l2_buf.sequence++;
spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
@@ -436,27 +418,29 @@
return 0;
}
-int msm_mctl_fetch_free_buf(struct msm_cam_media_controller *pmctl,
- int path, struct msm_free_buf *free_buf)
+int msm_mctl_reserve_free_buf(struct msm_cam_media_controller *pmctl,
+ int msg_type, struct msm_free_buf *free_buf)
{
struct msm_cam_v4l2_dev_inst *pcam_inst;
struct videobuf2_contig_pmem *mem;
- int idx = msm_mctl_get_pcam_inst_idx(path);
unsigned long flags = 0;
struct msm_frame_buffer *buf = NULL;
- int rc = -1;
+ int rc = -EINVAL, idx;
+ idx = msm_mctl_out_type_to_inst_index(pmctl->sync.pcam_sync, msg_type);
pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
list_for_each_entry(buf, &pcam_inst->free_vq, list) {
if (buf->inuse == 0) {
mem = vb2_plane_cookie(&buf->vidbuf, 0);
+ if (!mem)
+ continue;
free_buf->paddr =
(uint32_t) videobuf2_to_pmem_contig(&buf->vidbuf, 0);
free_buf->y_off = mem->y_off;
free_buf->cbcr_off = mem->cbcr_off;
- D("%s path=%d,inst=0x%p,idx=%d,paddr=0x%x, "
- "y_off=%d,cbcroff=%d\n", __func__, path,
+ D("%s idx=%d,inst=0x%p,idx=%d,paddr=0x%x, "
+ "y_off=%d,cbcroff=%d\n", __func__, idx,
pcam_inst, buf->vidbuf.v4l2_buf.index,
free_buf->paddr, free_buf->y_off,
free_buf->cbcr_off);
@@ -466,6 +450,45 @@
break;
}
}
+ if (rc != 0) {
+ free_buf->paddr = 0;
+ pr_err("No free buffer available ");
+ }
spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
return rc;
}
+
+int msm_mctl_release_free_buf(struct msm_cam_media_controller *pmctl,
+ int msg_type, struct msm_free_buf *free_buf)
+{
+ struct msm_cam_v4l2_dev_inst *pcam_inst;
+ unsigned long flags = 0;
+ struct msm_frame_buffer *buf = NULL;
+ uint32_t buf_phyaddr = 0;
+ int rc = -EINVAL, idx;
+
+ if (!free_buf)
+ return rc;
+
+ idx = msm_mctl_out_type_to_inst_index(pmctl->sync.pcam_sync, msg_type);
+ pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+ spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
+ list_for_each_entry(buf, &pcam_inst->free_vq, list) {
+ buf_phyaddr =
+ (uint32_t) videobuf2_to_pmem_contig(&buf->vidbuf, 0);
+ if (free_buf->paddr == buf_phyaddr) {
+ D("%s buf = 0x%x ", __func__, free_buf->paddr);
+ /* mark it free */
+ buf->inuse = 0;
+ rc = 0;
+ break;
+ }
+ }
+
+ if (rc != 0)
+ pr_err("%s invalid buffer address ", __func__);
+
+ spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+ return rc;
+}
+
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 946f823..8df366f 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -34,6 +34,24 @@
} \
}
+#define VFE32_AXI_OFFSET 0x0050
+#define vfe32_get_ch_ping_addr(chn) \
+ (msm_io_r(vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn)))
+#define vfe32_get_ch_pong_addr(chn) \
+ (msm_io_r(vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn) + 4))
+#define vfe32_get_ch_addr(ping_pong, chn) \
+ (((ping_pong) & (1 << (chn))) == 0 ? \
+ vfe32_get_ch_pong_addr(chn) : vfe32_get_ch_ping_addr(chn))
+
+#define vfe32_put_ch_ping_addr(chn, addr) \
+ (msm_io_w((addr), vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn)))
+#define vfe32_put_ch_pong_addr(chn, addr) \
+ (msm_io_w((addr), vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn) + 4))
+#define vfe32_put_ch_addr(ping_pong, chn, addr) \
+ (((ping_pong) & (1 << (chn))) == 0 ? \
+ vfe32_put_ch_pong_addr((chn), (addr)) : \
+ vfe32_put_ch_ping_addr((chn), (addr)))
+
static struct vfe32_ctrl_type *vfe32_ctrl;
static struct msm_camera_io_clk camio_clk;
static void *vfe_syncdata;
@@ -576,82 +594,28 @@
vfe32_ctrl->vfebase + VFE_GLOBAL_RESET);
}
-static int vfe32_enqueue_free_buf(struct vfe32_output_ch *outch,
- uint32_t paddr, uint32_t y_off, uint32_t cbcr_off)
+static void vfe32_subdev_notify(int id, int path)
{
- struct vfe32_free_buf *free_buf = NULL;
+ struct msm_vfe_resp *rp;
unsigned long flags = 0;
- free_buf = kmalloc(sizeof(struct vfe32_free_buf), GFP_KERNEL);
- if (!free_buf)
- return -ENOMEM;
-
- spin_lock_irqsave(&outch->free_buf_lock, flags);
- free_buf->paddr = paddr;
- free_buf->y_off = y_off;
- free_buf->cbcr_off = cbcr_off;
- list_add_tail(&free_buf->node, &outch->free_buf_queue);
- CDBG("%s: free_buf paddr = 0x%x, y_off = %d, cbcr_off = %d\n",
- __func__, free_buf->paddr, free_buf->y_off,
- free_buf->cbcr_off);
- spin_unlock_irqrestore(&outch->free_buf_lock, flags);
- return 0;
-}
-
-static struct vfe32_free_buf *vfe32_dequeue_free_buf(
- struct vfe32_output_ch *outch)
-{
- unsigned long flags = 0;
- struct vfe32_free_buf *free_buf = NULL;
- spin_lock_irqsave(&outch->free_buf_lock, flags);
- if (!list_empty(&outch->free_buf_queue)) {
- free_buf = list_first_entry(&outch->free_buf_queue,
- struct vfe32_free_buf, node);
- if (free_buf)
- list_del_init(&free_buf->node);
+ spin_lock_irqsave(&vfe32_ctrl->sd_notify_lock, flags);
+ rp = msm_isp_sync_alloc(sizeof(struct msm_vfe_resp),
+ vfe32_ctrl->syncdata, GFP_ATOMIC);
+ if (!rp) {
+ CDBG("rp: cannot allocate buffer\n");
+ return;
}
- spin_unlock_irqrestore(&outch->free_buf_lock, flags);
- return free_buf;
-}
-
-static void vfe32_reset_free_buf_queue(
- struct vfe32_output_ch *outch)
-{
- unsigned long flags = 0;
- struct vfe32_free_buf *free_buf = NULL;
- spin_lock_irqsave(&outch->free_buf_lock, flags);
- while (!list_empty(&outch->free_buf_queue)) {
- free_buf = list_first_entry(&outch->free_buf_queue,
- struct vfe32_free_buf, node);
- if (free_buf) {
- list_del_init(&free_buf->node);
- kfree(free_buf);
- }
- }
- spin_unlock_irqrestore(&outch->free_buf_lock, flags);
-}
-
-static void vfe32_init_free_buf_queues(void)
-{
- INIT_LIST_HEAD(&vfe32_ctrl->outpath.out0.free_buf_queue);
- INIT_LIST_HEAD(&vfe32_ctrl->outpath.out1.free_buf_queue);
- INIT_LIST_HEAD(&vfe32_ctrl->outpath.out2.free_buf_queue);
- spin_lock_init(&vfe32_ctrl->outpath.out0.free_buf_lock);
- spin_lock_init(&vfe32_ctrl->outpath.out1.free_buf_lock);
- spin_lock_init(&vfe32_ctrl->outpath.out2.free_buf_lock);
-}
-
-static void vfe32_reset_free_buf_queues(void)
-{
- vfe32_reset_free_buf_queue(&vfe32_ctrl->outpath.out0);
- vfe32_reset_free_buf_queue(&vfe32_ctrl->outpath.out1);
- vfe32_reset_free_buf_queue(&vfe32_ctrl->outpath.out2);
+ CDBG("vfe32_subdev_notify : msgId = %d\n", id);
+ rp->evt_msg.type = MSM_CAMERA_MSG;
+ rp->evt_msg.msg_id = path;
+ rp->type = id;
+ v4l2_subdev_notify(vfe32_ctrl->subdev, NOTIFY_VFE_MSG_EVT, rp);
+ spin_unlock_irqrestore(&vfe32_ctrl->sd_notify_lock, flags);
}
static int vfe32_config_axi(int mode, struct axidata *ad, uint32_t *ao)
{
- int ret;
- int i;
- uint32_t *p, *p1, *p2;
+ uint32_t *p, *p1;
int32_t *ch_info;
struct vfe32_output_ch *outp1, *outp2;
struct msm_pmem_region *regp1 = NULL;
@@ -676,7 +640,6 @@
CDBG("vfe32_config_axi: mode = %d, bufnum1 = %d, bufnum2 = %d\n",
mode, ad->bufnum1, ad->bufnum2);
-
switch (mode) {
case OUTPUT_2: {
@@ -686,21 +649,6 @@
outp1 = &(vfe32_ctrl->outpath.out0);
vfe32_ctrl->outpath.output_mode |= VFE32_OUTPUT_MODE_PT;
- for (i = 0; i < 2; i++) {
- p1 = ao + 6 + i; /* wm0 for y */
- *p1 = (regp1->paddr + regp1->info.y_off);
-
- p1 = ao + 12 + i; /* wm1 for cbcr */
- *p1 = (regp1->paddr + regp1->info.cbcr_off);
- regp1++;
- }
- for (i = 2; i < ad->bufnum2; i++) {
- ret = vfe32_enqueue_free_buf(outp1, regp1->paddr,
- regp1->info.y_off, regp1->info.cbcr_off);
- if (ret < 0)
- return ret;
- regp1++;
- }
}
break;
@@ -718,62 +666,6 @@
regp2 = &(ad->region[ad->bufnum1]);
outp1 = &(vfe32_ctrl->outpath.out0);
outp2 = &(vfe32_ctrl->outpath.out1); /* snapshot */
-
- /* Parse the buffers!!! */
- if (ad->bufnum2 == 1) { /* assuming bufnum1 = bufnum2 */
- p1 = ao + 6; /* wm0 ping */
- *p1++ = (regp1->paddr + regp1->info.y_off);
- /* this is to duplicate ping address to pong.*/
- *p1 = (regp1->paddr + regp1->info.y_off);
- p1 = ao + 30; /* wm4 ping */
- *p1++ = (regp1->paddr + regp1->info.cbcr_off);
- /* this is to duplicate ping address to pong.*/
- *p1 = (regp1->paddr + regp1->info.cbcr_off);
- p1 = ao + 12; /* wm1 ping */
- *p1++ = (regp2->paddr + regp2->info.y_off);
- /* pong = ping,*/
- *p1 = (regp2->paddr + regp2->info.y_off);
- p1 = ao + 36; /* wm5 */
- *p1++ = (regp2->paddr + regp2->info.cbcr_off);
- *p1 = (regp2->paddr + regp2->info.cbcr_off);
-
- } else { /* more than one snapshot */
- /* first fill ping & pong */
- for (i = 0; i < 2; i++) {
- p1 = ao + 6 + i; /* wm0 for y */
- *p1 = (regp1->paddr + regp1->info.y_off);
- p1 = ao + 30 + i; /* wm4 for cbcr */
- *p1 = (regp1->paddr + regp1->info.cbcr_off);
- regp1++;
- }
-
- for (i = 0; i < 2; i++) {
- p2 = ao + 12 + i; /* wm1 for y */
- *p2 = (regp2->paddr + regp2->info.y_off);
- p2 = ao + 36 + i; /* wm5 for cbcr */
- *p2 = (regp2->paddr + regp2->info.cbcr_off);
- regp2++;
- }
-
- for (i = 2; i < ad->bufnum1; i++) {
- ret = vfe32_enqueue_free_buf(outp1,
- regp1->paddr,
- regp1->info.y_off,
- regp1->info.cbcr_off);
- if (ret < 0)
- return ret;
- regp1++;
- }
- for (i = 2; i < ad->bufnum2; i++) {
- ret = vfe32_enqueue_free_buf(outp2,
- regp2->paddr,
- regp2->info.y_off,
- regp2->info.cbcr_off);
- if (ret < 0)
- return ret;
- regp2++;
- }
- }
break;
case OUTPUT_1_AND_3:
@@ -791,40 +683,6 @@
outp1 = &(vfe32_ctrl->outpath.out0); /* preview */
outp2 = &(vfe32_ctrl->outpath.out2); /* video */
-
- for (i = 0; i < 2; i++) {
- p1 = ao + 6 + i; /* wm0 for y */
- *p1 = (regp1->paddr + regp1->info.y_off);
-
- p1 = ao + 30 + i; /* wm1 for cbcr */
- *p1 = (regp1->paddr + regp1->info.cbcr_off);
- regp1++;
- }
-
- for (i = 0; i < 2; i++) {
- p2 = ao + 12 + i; /* wm0 for y */
- *p2 = (regp2->paddr + regp2->info.y_off);
-
- p2 = ao + 36 + i; /* wm1 for cbcr */
- *p2 = (regp2->paddr + regp2->info.cbcr_off);
- regp2++;
- }
- for (i = 2; i < ad->bufnum1; i++) {
- ret = vfe32_enqueue_free_buf(outp1, regp1->paddr,
- regp1->info.y_off,
- regp1->info.cbcr_off);
- if (ret < 0)
- return ret;
- regp1++;
- }
- for (i = 2; i < ad->bufnum2; i++) {
- ret = vfe32_enqueue_free_buf(outp2, regp2->paddr,
- regp2->info.y_off,
- regp2->info.cbcr_off);
- if (ret < 0)
- return ret;
- regp2++;
- }
break;
case CAMIF_TO_AXI_VIA_OUTPUT_2: { /* use wm0 only */
if (ad->bufnum2 < 1)
@@ -898,7 +756,6 @@
static void vfe32_reset(void)
{
uint32_t vfe_version;
- vfe32_reset_free_buf_queues();
vfe32_reset_internal_variables();
vfe_version = msm_io_r(vfe32_ctrl->vfebase);
CDBG("vfe_version = 0x%x\n", vfe_version);
@@ -1056,18 +913,6 @@
#define ENQUEUED_BUFFERS 3
static int vfe32_start_recording(void)
{
- /* Clear out duplicate entries in free_buf qeueue,
- * because the same number of the buffers were programmed
- * during AXI config and then enqueued before recording.
- * TODO: Do AXI config separately for recording at the
- * time of enqueue */
- int i;
- for (i = 0; i < ENQUEUED_BUFFERS; ++i) {
- struct vfe32_free_buf *free_buf = NULL;
- free_buf = vfe32_dequeue_free_buf(&vfe32_ctrl->outpath.out2);
- kfree(free_buf);
- }
-
vfe32_ctrl->req_start_video_rec = TRUE;
/* Mask with 0x7 to extract the pixel pattern*/
switch (msm_io_r(vfe32_ctrl->vfebase + VFE_CFG) & 0x7) {
@@ -1320,7 +1165,66 @@
}
vfe32_program_dmi_cfg(NO_MEM_SELECTED);
}
+static struct msm_free_buf *vfe32_check_free_buffer(int id, int path)
+{
+ struct vfe32_output_ch *outch = NULL;
+ struct msm_free_buf *b = NULL;
+ vfe32_subdev_notify(id, path);
+ switch (path) {
+ case VFE_MSG_OUTPUT_P:
+ case VFE_MSG_OUTPUT_T:
+ outch = &vfe32_ctrl->outpath.out0;
+ break;
+ case VFE_MSG_OUTPUT_S:
+ outch = &vfe32_ctrl->outpath.out1;
+ break;
+ case VFE_MSG_OUTPUT_V:
+ outch = &vfe32_ctrl->outpath.out2;
+ break;
+ }
+ if (outch->free_buf.paddr)
+ b = &outch->free_buf;
+ return b;
+}
+static int vfe32_configure_pingpong_buffers(int id, int path)
+{
+ struct vfe32_output_ch *outch = NULL;
+ int rc = 0;
+ vfe32_subdev_notify(id, path);
+ switch (path) {
+ case VFE_MSG_OUTPUT_P:
+ case VFE_MSG_OUTPUT_T:
+ outch = &vfe32_ctrl->outpath.out0;
+ break;
+ case VFE_MSG_OUTPUT_S:
+ outch = &vfe32_ctrl->outpath.out1;
+ break;
+ case VFE_MSG_OUTPUT_V:
+ outch = &vfe32_ctrl->outpath.out2;
+ break;
+ }
+ if (outch->ping.paddr && outch->pong.paddr) {
+ /* Configure Preview Ping Pong */
+ pr_err("%s Configure ping/pong address for %d", __func__, path);
+ vfe32_put_ch_ping_addr(outch->ch0,
+ outch->ping.paddr + outch->ping.y_off);
+ vfe32_put_ch_ping_addr(outch->ch1,
+ outch->ping.paddr + outch->ping.cbcr_off);
+ vfe32_put_ch_pong_addr(outch->ch0,
+ outch->pong.paddr + outch->pong.y_off);
+ vfe32_put_ch_pong_addr(outch->ch1,
+ outch->pong.paddr + outch->pong.cbcr_off);
+
+ /* avoid stale info */
+ outch->ping.paddr = 0;
+ outch->pong.paddr = 0;
+ } else {
+ pr_err("%s ping/pong addr is null!!", __func__);
+ rc = -EINVAL;
+ }
+ return rc;
+}
static int vfe32_proc_general(struct msm_vfe32_cmd *cmd)
{
@@ -1341,6 +1245,14 @@
case V32_START:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
+ rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_START,
+ VFE_MSG_OUTPUT_P);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for preview", __func__);
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
rc = vfe32_start();
break;
case V32_UPDATE:
@@ -1354,11 +1266,35 @@
rc = -EFAULT;
goto proc_general_done;
}
+ rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
+ VFE_MSG_OUTPUT_S);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for preview", __func__);
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
+ VFE_MSG_OUTPUT_T);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for preview", __func__);
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
rc = vfe32_capture(snapshot_cnt);
break;
case V32_START_RECORDING:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
+ rc = vfe32_configure_pingpong_buffers(
+ VFE_MSG_V32_START_RECORDING, VFE_MSG_OUTPUT_V);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for recording", __func__);
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
rc = vfe32_start_recording();
break;
case V32_STOP_RECORDING:
@@ -2280,23 +2216,6 @@
pr_err("vfe32_irq: axi error\n");
}
-#define VFE32_AXI_OFFSET 0x0050
-#define vfe32_get_ch_ping_addr(chn) \
- (msm_io_r(vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn)))
-#define vfe32_get_ch_pong_addr(chn) \
- (msm_io_r(vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn) + 4))
-#define vfe32_get_ch_addr(ping_pong, chn) \
- (((ping_pong) & (1 << (chn))) == 0 ? \
- vfe32_get_ch_pong_addr(chn) : vfe32_get_ch_ping_addr(chn))
-
-#define vfe32_put_ch_ping_addr(chn, addr) \
- (msm_io_w((addr), vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn)))
-#define vfe32_put_ch_pong_addr(chn, addr) \
- (msm_io_w((addr), vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn) + 4))
-#define vfe32_put_ch_addr(ping_pong, chn, addr) \
- (((ping_pong) & (1 << (chn))) == 0 ? \
- vfe32_put_ch_pong_addr((chn), (addr)) : \
- vfe32_put_ch_ping_addr((chn), (addr)))
static void vfe32_process_output_path_irq_0(void)
{
@@ -2306,8 +2225,16 @@
uint32_t pyaddr_ping, pcbcraddr_ping, pyaddr_pong, pcbcraddr_pong;
#endif
uint8_t out_bool = 0;
- struct vfe32_free_buf *free_buf = NULL;
- free_buf = vfe32_dequeue_free_buf(&vfe32_ctrl->outpath.out0);
+ struct msm_free_buf *free_buf = NULL;
+ if (vfe32_ctrl->operation_mode ==
+ VFE_MODE_OF_OPERATION_SNAPSHOT)
+ free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_T);
+ else
+ free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_P);
+ if (!free_buf)
+ pr_err(" Output IRQ 0: NO FREE BUFF");
/* we render frames in the following conditions:
1. Continuous mode and the free buffer is avaialable.
2. In snapshot shot mode, free buffer is not always available.
@@ -2343,7 +2270,6 @@
vfe32_put_ch_addr(ping_pong,
vfe32_ctrl->outpath.out0.ch1,
free_buf->paddr + free_buf->cbcr_off);
- kfree(free_buf);
}
if (vfe32_ctrl->operation_mode ==
VFE_MODE_OF_OPERATION_SNAPSHOT) {
@@ -2408,9 +2334,11 @@
#endif
/* this must be snapshot main image output. */
uint8_t out_bool = 0;
- struct vfe32_free_buf *free_buf = NULL;
- free_buf = vfe32_dequeue_free_buf(&vfe32_ctrl->outpath.out1);
-
+ struct msm_free_buf *free_buf = NULL;
+ free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_S);
+ if (!free_buf)
+ pr_err(" Output IRQ 1: NO FREE BUFF");
/* we render frames in the following conditions:
1. Continuous mode and the free buffer is avaialable.
2. In snapshot shot mode, free buffer is not always available.
@@ -2445,7 +2373,6 @@
vfe32_put_ch_addr(ping_pong,
vfe32_ctrl->outpath.out1.ch1,
free_buf->paddr + free_buf->cbcr_off);
- kfree(free_buf);
}
if (vfe32_ctrl->operation_mode ==
VFE_MODE_OF_OPERATION_SNAPSHOT ||
@@ -2505,9 +2432,11 @@
uint32_t pyaddr_ping, pcbcraddr_ping, pyaddr_pong, pcbcraddr_pong;
#endif
uint8_t out_bool = 0;
- struct vfe32_free_buf *free_buf = NULL;
- free_buf = vfe32_dequeue_free_buf(&vfe32_ctrl->outpath.out2);
-
+ struct msm_free_buf *free_buf = NULL;
+ free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_V);
+ if (!free_buf)
+ pr_err(" Output IRQ 2: NO FREE BUFF");
/* we render frames in the following conditions:
1. Continuous mode and the free buffer is avaialable.
2. In snapshot shot mode, free buffer is not always available.
@@ -2545,7 +2474,6 @@
vfe32_put_ch_addr(ping_pong,
vfe32_ctrl->outpath.out2.ch1,
free_buf->paddr + free_buf->cbcr_off);
- kfree(free_buf);
}
vfe_send_outmsg(MSG_ID_OUTPUT_V, pyaddr, pcbcraddr);
} else {
@@ -3033,8 +2961,8 @@
spin_lock_init(&vfe32_ctrl->aec_ack_lock);
spin_lock_init(&vfe32_ctrl->awb_ack_lock);
spin_lock_init(&vfe32_ctrl->af_ack_lock);
+ spin_lock_init(&vfe32_ctrl->sd_notify_lock);
INIT_LIST_HEAD(&vfe32_ctrl->tasklet_q);
- vfe32_init_free_buf_queues();
vfe32_ctrl->syncdata = sdata;
vfe32_ctrl->vfemem = vfemem;
@@ -3066,6 +2994,9 @@
struct msm_pmem_region *regptr = NULL;
struct vfe_cmd_stats_ack *sack = NULL;
if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE &&
+ cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
+ cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
+ cmd->cmd_type != CMD_CONFIG_FREE_BUF_ADDR &&
cmd->cmd_type != CMD_STATS_AEC_BUF_RELEASE &&
cmd->cmd_type != CMD_STATS_AWB_BUF_RELEASE &&
cmd->cmd_type != CMD_STATS_IHIST_BUF_RELEASE &&
@@ -3081,7 +3012,10 @@
}
} else {
/* here eith stats release or frame release. */
- if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE) {
+ if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE &&
+ cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
+ cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
+ cmd->cmd_type != CMD_CONFIG_FREE_BUF_ADDR) {
/* then must be stats release. */
if (!data)
return -EFAULT;
@@ -3176,7 +3110,51 @@
break;
}
- rc = vfe32_enqueue_free_buf(outch, p, b->y_off, b->cbcr_off);
+ }
+ break;
+
+ case CMD_CONFIG_PING_ADDR: {
+ struct vfe32_output_ch *outch = NULL;
+ int path = *((int *)cmd->value);
+ if ((path == VFE_MSG_OUTPUT_P)
+ || (path == VFE_MSG_OUTPUT_T))
+ outch = &vfe32_ctrl->outpath.out0;
+ else if (path == VFE_MSG_OUTPUT_S)
+ outch = &vfe32_ctrl->outpath.out1;
+ else if (path == VFE_MSG_OUTPUT_V)
+ outch = &vfe32_ctrl->outpath.out2;
+
+ outch->ping = *((struct msm_free_buf *)data);
+ }
+ break;
+
+ case CMD_CONFIG_PONG_ADDR: {
+ struct vfe32_output_ch *outch = NULL;
+ int path = *((int *)cmd->value);
+ if ((path == VFE_MSG_OUTPUT_P)
+ || (path == VFE_MSG_OUTPUT_T))
+ outch = &vfe32_ctrl->outpath.out0;
+ else if (path == VFE_MSG_OUTPUT_S)
+ outch = &vfe32_ctrl->outpath.out1;
+ else if (path == VFE_MSG_OUTPUT_V)
+ outch = &vfe32_ctrl->outpath.out2;
+
+ outch->pong = *((struct msm_free_buf *)data);
+ }
+ break;
+
+ case CMD_CONFIG_FREE_BUF_ADDR: {
+ struct vfe32_output_ch *outch = NULL;
+ int path = *((int *)cmd->value);
+ if ((path == VFE_MSG_OUTPUT_P)
+ || (path == VFE_MSG_OUTPUT_T))
+ outch = &vfe32_ctrl->outpath.out0;
+ else if (path == VFE_MSG_OUTPUT_S)
+ outch = &vfe32_ctrl->outpath.out1;
+ else if (path == VFE_MSG_OUTPUT_V)
+ outch = &vfe32_ctrl->outpath.out2;
+
+ outch->free_buf = *((struct msm_free_buf *)data);
}
break;
@@ -3360,7 +3338,6 @@
{
struct resource *vfemem, *vfeio;
- vfe32_reset_free_buf_queues();
CDBG("%s, free_irq\n", __func__);
free_irq(vfe32_ctrl->vfeirq, 0);
tasklet_kill(&vfe32_tasklet);
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 4d48c6b..4008c68 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -895,6 +895,9 @@
int8_t ch2;
uint32_t capture_cnt;
uint32_t frame_drop_cnt;
+ struct msm_free_buf ping;
+ struct msm_free_buf pong;
+ struct msm_free_buf free_buf;
};
/* no error irq in mask 0 */
@@ -1082,6 +1085,7 @@
/* v4l2 subdev */
struct v4l2_subdev *subdev;
+ spinlock_t sd_notify_lock;
};
#define statsAeNum 0
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 4544a67..e6d7c20 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -305,6 +305,9 @@
#define CMD_AXI_CFG_ZSL 43
#define CMD_AXI_CFG_SNAP_VPE 44
#define CMD_AXI_CFG_SNAP_THUMB_VPE 45
+#define CMD_CONFIG_PING_ADDR 46
+#define CMD_CONFIG_PONG_ADDR 47
+#define CMD_CONFIG_FREE_BUF_ADDR 48
/* vfe config command: config command(from config thread)*/
struct msm_vfe_cfg_cmd {