From ead6bc195e5e508ec2b22151c845b22ac8cd827d Mon Sep 17 00:00:00 2001 From: ddl Date: Tue, 31 Jul 2012 10:46:19 +0800 Subject: [PATCH] camera rk29: fix struct rk29_camera_work may be reentrant, version update to v0.x.f --- drivers/media/video/rk29_camera_oneframe.c | 55 ++++++++++++++++------ 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/rk29_camera_oneframe.c b/drivers/media/video/rk29_camera_oneframe.c index f149776498b7..f7500fd6152b 100755 --- a/drivers/media/video/rk29_camera_oneframe.c +++ b/drivers/media/video/rk29_camera_oneframe.c @@ -140,6 +140,8 @@ module_param(debug, int, S_IRUGO|S_IWUSR|S_IWGRP); * *v0.0.x : this driver is 2.6.32 kernel driver; *v0.1.x : this driver is 3.0.8 kernel driver; +*v0.2.x : this driver is rk30 3.0.8 kernel driver; +*v0.3.x : this driver is camera-isp driver; * *v0.x.1 : this driver first support rk2918; *v0.x.2 : fix this driver support v4l2 format is V4L2_PIX_FMT_NV12 and V4L2_PIX_FMT_NV16,is not V4L2_PIX_FMT_YUV420 @@ -157,8 +159,9 @@ module_param(debug, int, S_IRUGO|S_IWUSR|S_IWGRP); *v0.x.b : fix sensor autofocus thread may in running when reinit sensor if sensor haven't stream on in first init; *v0.x.c : fix work queue havn't been finished after close device; *v0.x.d : fix error when calculate crop left-top point coordinate; +*v0.x.f : fix struct rk29_camera_work may be reentrant. */ -#define RK29_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 0xd) +#define RK29_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 0xf) /* limit to rk29 hardware capabilities */ #define RK29_CAM_BUS_PARAM (SOCAM_MASTER |\ @@ -216,6 +219,8 @@ struct rk29_camera_work struct videobuf_buffer *vb; struct rk29_camera_dev *pcdev; struct work_struct work; + struct list_head queue; + unsigned int index; }; struct rk29_camera_frmivalenum { @@ -284,6 +289,8 @@ struct rk29_camera_dev struct rk29_camera_reg reginfo_suspend; struct workqueue_struct *camera_wq; struct rk29_camera_work *camera_work; + struct list_head camera_work_queue; + spinlock_t camera_work_lock; unsigned int camera_work_count; struct hrtimer fps_timer; struct work_struct camera_reinit_work; @@ -327,6 +334,8 @@ static int rk29_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, icd->current_fmt->host_fmt); int bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width, icd->current_fmt->host_fmt); + int i; + struct rk29_camera_work *wk; dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); @@ -351,16 +360,23 @@ static int rk29_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, if ((pcdev->camera_work_count != *count) && pcdev->camera_work) { kfree(pcdev->camera_work); pcdev->camera_work = NULL; - pcdev->camera_work_count = 0; + pcdev->camera_work_count = 0; } if (pcdev->camera_work == NULL) { - pcdev->camera_work = kmalloc(sizeof(struct rk29_camera_work)*(*count), GFP_KERNEL); + pcdev->camera_work = wk = kzalloc(sizeof(struct rk29_camera_work)*(*count), GFP_KERNEL); if (pcdev->camera_work == NULL) { RK29CAMERA_TR("\n %s kmalloc fail\n", __FUNCTION__); BUG(); } - pcdev->camera_work_count = *count; + INIT_LIST_HEAD(&pcdev->camera_work_queue); + + for (i=0; i<(*count); i++) { + wk->index = i; + list_add_tail(&wk->queue, &pcdev->camera_work_queue); + wk++; + } + pcdev->camera_work_count = (*count); } } @@ -609,6 +625,9 @@ static void rk29_camera_capture_process(struct work_struct *work) do_ipp_err: up(&pcdev->zoominfo.sem); wake_up(&(camera_work->vb->done)); + spin_lock_irqsave(&pcdev->camera_work_lock, flags); + list_add_tail(&camera_work->queue, &pcdev->camera_work_queue); + spin_unlock_irqrestore(&pcdev->camera_work_lock, flags); return; } static irqreturn_t rk29_camera_irq(int irq, void *data) @@ -669,11 +688,14 @@ static irqreturn_t rk29_camera_irq(int irq, void *data) } if (CAM_WORKQUEUE_IS_EN()) { - wk = pcdev->camera_work + vb->i; - INIT_WORK(&(wk->work), rk29_camera_capture_process); - wk->vb = vb; - wk->pcdev = pcdev; - queue_work(pcdev->camera_wq, &(wk->work)); + if (!list_empty(&pcdev->camera_work_queue)) { + wk = list_entry(pcdev->camera_work_queue.next, struct rk29_camera_work, queue); + list_del_init(&wk->queue); + INIT_WORK(&(wk->work), rk29_camera_capture_process); + wk->vb = vb; + wk->pcdev = pcdev; + queue_work(pcdev->camera_wq, &(wk->work)); + } } else { wake_up(&vb->done); } @@ -958,6 +980,7 @@ static void rk29_camera_remove_device(struct soc_camera_device *icd) kfree(pcdev->camera_work); pcdev->camera_work = NULL; pcdev->camera_work_count = 0; + INIT_LIST_HEAD(&pcdev->camera_work_queue); } pcdev->active = NULL; @@ -1122,17 +1145,19 @@ static void rk29_camera_setup_format(struct soc_camera_device *icd, __u32 host_p pcdev->pixfmt = host_pixfmt; break; default: /* ddl@rock-chips.com : vip output format is hold when pixfmt is invalidate */ - vip_ctrl_val |= (read_vip_reg(RK29_VIP_CTRL) & VIPREGYUV422); + if (pcdev->frame_inval != RK29_CAM_FRAME_INVAL_INIT) + pcdev->frame_inval = RK29_CAM_FRAME_INVAL_INIT; + pcdev->pixfmt = host_pixfmt; break; } switch (icd_code) { case V4L2_MBUS_FMT_UYVY8_2X8: - vip_ctrl_val |= SENSOR_UYVY; + vip_ctrl_val |= (SENSOR_UYVY|VIP_YUV); break; case V4L2_MBUS_FMT_YUYV8_2X8: - vip_ctrl_val |= SENSOR_YUYV; + vip_ctrl_val |= (SENSOR_YUYV|VIP_YUV); break; default : vip_ctrl_val |= (read_vip_reg(RK29_VIP_CTRL) & SENSOR_YUYV); @@ -1893,13 +1918,13 @@ int rk29_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_f fival->discrete.denominator,fival->discrete.numerator); } else { if (index == 0) - RK29CAMERA_TR("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(rk29_camdev_info_ptr->icd->pdev), + RK29CAMERA_TR("%s have not catch %dx%d@%c%c%c%c index(%d) framerate\n",dev_name(rk29_camdev_info_ptr->icd->pdev), fival->width,fival->height, fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF, (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24), index); else - RK29CAMERA_DG("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(rk29_camdev_info_ptr->icd->pdev), + RK29CAMERA_DG("%s have not catch %dx%d@%c%c%c%c index(%d) framerate\n",dev_name(rk29_camdev_info_ptr->icd->pdev), fival->width,fival->height, fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF, (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24), @@ -2100,7 +2125,9 @@ static int rk29_camera_probe(struct platform_device *pdev) } #endif INIT_LIST_HEAD(&pcdev->capture); + INIT_LIST_HEAD(&pcdev->camera_work_queue); spin_lock_init(&pcdev->lock); + spin_lock_init(&pcdev->camera_work_lock); sema_init(&pcdev->zoominfo.sem,1); /* -- 2.34.1