camera:fix camera client connect error,because capture videobuf queue may be not...
authorddl <ddl@rock-chips.com>
Tue, 21 Sep 2010 10:15:08 +0000 (18:15 +0800)
committerddl <ddl@rock-chips.com>
Tue, 21 Sep 2010 10:16:11 +0000 (18:16 +0800)
drivers/media/video/rk2818_camera.c
drivers/media/video/soc_camera.c
include/media/soc_camera.h

index 935e299513efc25cba5fada31ace667053d98726..99c22951e612cfec4845f70c50e55157b99ae150 100644 (file)
@@ -308,7 +308,14 @@ static void rk28_videobuf_queue(struct videobuf_queue *vq,
 
     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;
@@ -327,10 +334,16 @@ static irqreturn_t rk28_camera_irq(int irq, void *data)
     /* 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;
@@ -350,6 +363,7 @@ static irqreturn_t rk28_camera_irq(int irq, void *data)
         wake_up(&vb->done);
     }
 
+RK28_CAMERA_IRQ_END:
     return IRQ_HANDLED;
 }
 
@@ -486,6 +500,14 @@ static int rk28_camera_add_device(struct soc_camera_device *icd)
     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;
@@ -500,8 +522,6 @@ static int rk28_camera_add_device(struct soc_camera_device *icd)
 
     pcdev->icd = icd;
 
-    pcdev->frame_inval = RK28_CAM_FRAME_INVAL;
-
 ebusy:
     mutex_unlock(&camera_lock);
 
@@ -517,16 +537,22 @@ static void rk28_camera_remove_device(struct soc_camera_device *icd)
     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)
@@ -560,7 +586,8 @@ 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));
@@ -909,6 +936,26 @@ static int rk28_camera_resume(struct soc_camera_device *icd)
     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,
@@ -926,6 +973,7 @@ static struct soc_camera_host_ops rk28_soc_camera_host_ops =
     .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)
 {
index 0ecbf6b4f36ee0e714ca785d9c11e09422e4af6f..93269b551e32e9c91bcd7f0fc4c697c2d0ce5d5d 100644 (file)
@@ -523,7 +523,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
        }
        #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;
@@ -535,7 +535,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
                }
                i++;
        }
-       
+
        #endif
 
        ret = soc_camera_set_fmt(icf, f);
@@ -605,6 +605,8 @@ static int soc_camera_streamon(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);
+       struct soc_camera_host *ici =
+                    to_soc_camera_host(icd->dev.parent);
        int ret;
 
        WARN_ON(priv != file->private_data);
@@ -615,7 +617,8 @@ static int soc_camera_streamon(struct file *file, void *priv,
        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);
 
@@ -630,6 +633,8 @@ static int soc_camera_streamoff(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);
+    struct soc_camera_host *ici =
+                    to_soc_camera_host(icd->dev.parent);
 
        WARN_ON(priv != file->private_data);
 
@@ -643,6 +648,8 @@ static int soc_camera_streamoff(struct file *file, void *priv,
        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);
 
@@ -689,14 +696,14 @@ static int soc_camera_querymenu(struct file *file, void *priv,
     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;
@@ -705,13 +712,13 @@ static int soc_camera_querymenu(struct file *file, void *priv,
                     } else {
                         i++;
                         if ( i >= icd->ops->num_menus)
-                            return -EINVAL;    
-                    }                    
-                }                
+                            return -EINVAL;
+                    }
+                }
             }
         }
     }
-    
+
     return -EINVAL;
 }
 
@@ -762,15 +769,15 @@ static int soc_camera_try_ext_ctrl(struct file *file, void *priv,
 {
     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;
@@ -778,7 +785,7 @@ static int soc_camera_try_ext_ctrl(struct file *file, void *priv,
         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 */
@@ -788,13 +795,13 @@ static int soc_camera_g_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, 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,
@@ -803,13 +810,13 @@ 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);
 }
 
 
index b7227075f6cd39c60a5824eae457e8194e099480..705c44b33b19a7116fc51dd0052c4694e9fbe9fc 100644 (file)
@@ -89,6 +89,9 @@ struct soc_camera_host_ops {
        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)
@@ -196,8 +199,8 @@ struct soc_camera_ops {
        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;
@@ -259,7 +262,7 @@ static inline struct v4l2_queryctrl const *soc_camera_find_qctrl(
 #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)