vb->state = VIDEOBUF_ACTIVE;
spin_lock_irqsave(&pcdev->lock, flags);
- list_add_tail(&vb->queue, &pcdev->capture);
+ if (!list_empty(&pcdev->capture)) {
+ list_add_tail(&vb->queue, &pcdev->capture);
+ } else {
+ if (list_entry(pcdev->capture.next, struct videobuf_buffer, queue) != vb)
+ list_add_tail(&vb->queue, &pcdev->capture);
+ else
+ BUG(); /* ddl@rock-chips.com : The same videobuffer queue again */
+ }
if (!pcdev->active) {
pcdev->active = vb;
/* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */
if (read_vip_reg(RK28_VIP_FB_SR) & 0x01) {
- if (pcdev->frame_inval) {
+ if (!pcdev->active)
+ goto RK28_CAMERA_IRQ_END;
+
+ if ((pcdev->frame_inval>0) && (pcdev->frame_inval<=RK28_CAM_FRAME_INVAL)) {
pcdev->frame_inval--;
rk28_videobuf_capture(pcdev->active);
- return IRQ_HANDLED;
+ goto RK28_CAMERA_IRQ_END;
+ } else if (pcdev->frame_inval) {
+ printk("frame_inval : %0x",pcdev->frame_inval);
+ pcdev->frame_inval = 0;
}
vb = pcdev->active;
wake_up(&vb->done);
}
+RK28_CAMERA_IRQ_END:
return IRQ_HANDLED;
}
dev_info(&icd->dev, "RK28 Camera driver attached to camera %d\n",
icd->devnum);
+ pcdev->frame_inval = RK28_CAM_FRAME_INVAL;
+ pcdev->active = NULL;
+ pcdev->icd = NULL;
+ /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
+ * if app havn't dequeue all videobuf before close camera device;
+ */
+ INIT_LIST_HEAD(&pcdev->capture);
+
ret = rk28_camera_activate(pcdev,icd);
if (ret)
goto ebusy;
pcdev->icd = icd;
- pcdev->frame_inval = RK28_CAM_FRAME_INVAL;
-
ebusy:
mutex_unlock(&camera_lock);
dev_info(&icd->dev, "RK28 Camera driver detached from camera %d\n",
icd->devnum);
+ rk28_camera_deactivate(pcdev);
+
/* ddl@rock-chips.com: Call videobuf_mmap_free here for free the struct video_buffer which malloc in videobuf_alloc */
if (pcdev->vb_vidq_ptr) {
videobuf_mmap_free(pcdev->vb_vidq_ptr);
pcdev->vb_vidq_ptr = NULL;
}
-
- rk28_camera_deactivate(pcdev);
-
+ pcdev->active = NULL;
pcdev->icd = NULL;
+ /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
+ * if app havn't dequeue all videobuf before close camera device;
+ */
+ INIT_LIST_HEAD(&pcdev->capture);
+
+ return;
}
static int rk28_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)
set_vip_vsp(VSY_HIGH_ACTIVE);
- vip_ctrl_val |= ENABLE_CAPTURE;
+ /* ddl@rock-chips.com : Don't enable capture here, enable in stream_on */
+ //vip_ctrl_val |= ENABLE_CAPTURE;
write_vip_reg(RK28_VIP_CTRL, vip_ctrl_val);
RK28CAMERA_DG("\n%s..CtrReg=%x \n",__FUNCTION__,read_vip_reg(RK28_VIP_CTRL));
return ret;
}
+static int rk28_camera_s_stream(struct soc_camera_device *icd, int enable)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct rk28_camera_dev *pcdev = ici->priv;
+ int vip_ctrl_val;
+
+ WARN_ON(pcdev->icd != icd);
+
+ vip_ctrl_val = read_vip_reg(RK28_VIP_CTRL);
+ if (enable) {
+ vip_ctrl_val |= ENABLE_CAPTURE;
+ } else {
+ vip_ctrl_val &= ~ENABLE_CAPTURE;
+ }
+ write_vip_reg(RK28_VIP_CTRL, vip_ctrl_val);
+
+ RK28CAMERA_DG("%s.. enable : %d\n", __FUNCTION__, enable);
+ return 0;
+}
+
static struct soc_camera_host_ops rk28_soc_camera_host_ops =
{
.owner = THIS_MODULE,
.poll = rk28_camera_poll,
.querycap = rk28_camera_querycap,
.set_bus_param = rk28_camera_set_bus_param,
+ .s_stream = rk28_camera_s_stream /* ddl@rock-chips.com : Add stream control for host */
};
static int rk28_camera_probe(struct platform_device *pdev)
{
}
#else
- /* ddl@rock-chips.com :
+ /* ddl@rock-chips.com :
Judge queue initialised by Judge icf->vb_vidq.bufs[0] whether is NULL , it is error. */
i = 0;
}
i++;
}
-
+
#endif
ret = soc_camera_set_fmt(icf, f);
struct soc_camera_file *icf = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+ struct soc_camera_host *ici =
+ to_soc_camera_host(icd->dev.parent);
int ret;
WARN_ON(priv != file->private_data);
mutex_lock(&icd->video_lock);
v4l2_subdev_call(sd, video, s_stream, 1);
-
+ if (ici->ops->s_stream)
+ ici->ops->s_stream(icd, 1); /* ddl@rock-chips.com : Add stream control for host */
/* This calls buf_queue from host driver's videobuf_queue_ops */
ret = videobuf_streamon(&icf->vb_vidq);
struct soc_camera_file *icf = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+ struct soc_camera_host *ici =
+ to_soc_camera_host(icd->dev.parent);
WARN_ON(priv != file->private_data);
videobuf_streamoff(&icf->vb_vidq);
v4l2_subdev_call(sd, video, s_stream, 0);
+ if (ici->ops->s_stream)
+ ici->ops->s_stream(icd, 0); /* ddl@rock-chips.com : Add stream control for host */
mutex_unlock(&icd->video_lock);
struct soc_camera_device *icd = icf->icd;
struct v4l2_queryctrl qctrl;
int i,j;
-
+
qctrl.id = qm->id;
if (soc_camera_queryctrl(file,priv, &qctrl) == 0) {
for (i = 0; i < icd->ops->num_menus; i++) {
if (qm->id == icd->ops->menus[i].id) {
for (j=0; j<=(qctrl.maximum - qctrl.minimum); j++) {
-
+
if (qm->index == icd->ops->menus[i].index) {
snprintf(qm->name, sizeof(qm->name), icd->ops->menus[i].name);
qm->reserved = 0;
} else {
i++;
if ( i >= icd->ops->num_menus)
- return -EINVAL;
- }
- }
+ return -EINVAL;
+ }
+ }
}
}
}
-
+
return -EINVAL;
}
{
struct soc_camera_file *icf = file->private_data;
struct soc_camera_device *icd = icf->icd;
- const struct v4l2_queryctrl *qctrl;
+ const struct v4l2_queryctrl *qctrl;
int i;
-
+
WARN_ON(priv != file->private_data);
if (ctrl->ctrl_class != V4L2_CTRL_CLASS_CAMERA)
return -EINVAL;
- for (i=0; i<ctrl->count; i++) {
+ for (i=0; i<ctrl->count; i++) {
qctrl = soc_camera_find_qctrl(icd->ops, ctrl->controls[i].id);
if (!qctrl)
return -EINVAL;
if ((ctrl->controls[i].value < qctrl->minimum) ||(ctrl->controls[i].value > qctrl->minimum))
return -ERANGE;
}
-
+
return 0;
}
/* ddl@rock-chips.com : Add ioctrl -VIDIOC_XXX_ext_ctrl for soc-camera */
struct soc_camera_file *icf = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-
+
WARN_ON(priv != file->private_data);
if (ctrl->ctrl_class != V4L2_CTRL_CLASS_CAMERA)
return -EINVAL;
-
- return v4l2_subdev_call(sd, core, g_ext_ctrls, ctrl);
+
+ return v4l2_subdev_call(sd, core, g_ext_ctrls, ctrl);
}
/* ddl@rock-chips.com : Add ioctrl -VIDIOC_XXX_ext_ctrl for soc-camera */
static int soc_camera_s_ext_ctrl(struct file *file, void *priv,
struct soc_camera_file *icf = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-
+
WARN_ON(priv != file->private_data);
if (ctrl->ctrl_class != V4L2_CTRL_CLASS_CAMERA)
return -EINVAL;
-
- return v4l2_subdev_call(sd, core, s_ext_ctrls, ctrl);
+
+ return v4l2_subdev_call(sd, core, s_ext_ctrls, ctrl);
}
unsigned int (*poll)(struct file *, poll_table *);
const struct v4l2_queryctrl *controls;
int num_controls;
+
+ int (*s_stream)(struct soc_camera_device *, int enable); /* ddl@rock-chips.com : Add stream control for host */
+
};
#define SOCAM_SENSOR_INVERT_PCLK (1 << 0)
int (*resume)(struct soc_camera_device *);
unsigned long (*query_bus_param)(struct soc_camera_device *);
int (*set_bus_param)(struct soc_camera_device *, unsigned long);
- int (*enum_input)(struct soc_camera_device *, struct v4l2_input *);
-
+ int (*enum_input)(struct soc_camera_device *, struct v4l2_input *);
+
const struct v4l2_queryctrl *controls;
const struct v4l2_querymenu *menus; /* ddl@rock-chips.com : Add ioctrl -VIDIOC_QUERYMENU */
int num_controls;
#define SOCAM_DATA_ACTIVE_HIGH (1 << 14)
#define SOCAM_DATA_ACTIVE_LOW (1 << 15)
-#define SOCAM_MCLK_24MHZ (1<<29) /* ddl@rock-chips.com : add */
+#define SOCAM_MCLK_24MHZ (1<<29) /* ddl@rock-chips.com : add */
#define SOCAM_MCLK_27MHZ (1<<30)
#define SOCAM_MCLK_48MHZ (1<<31)