diff options
-rw-r--r-- | drivers/media/video/mxc/capture/mx27_prphw.c | 47 | ||||
-rw-r--r-- | drivers/media/video/mxc/capture/mx27_prpsw.c | 10 | ||||
-rw-r--r-- | drivers/media/video/mxc/capture/mx27_v4l2_capture.c | 151 | ||||
-rw-r--r-- | drivers/media/video/mxc/capture/mxc_v4l2_capture.h | 3 |
4 files changed, 89 insertions, 122 deletions
diff --git a/drivers/media/video/mxc/capture/mx27_prphw.c b/drivers/media/video/mxc/capture/mx27_prphw.c index 0e8632573cff..ee90012ea5fc 100644 --- a/drivers/media/video/mxc/capture/mx27_prphw.c +++ b/drivers/media/video/mxc/capture/mx27_prphw.c @@ -361,7 +361,6 @@ static const unsigned char coeftab[] = { 1, 20 }; - /*! * @brief Build PrP coefficient table based on average algorithm * @@ -614,7 +613,7 @@ int prp_scale(scale_t * pscale, int din, int dout, int inv, return -1; } } - + if ((num > MAX_TBL * MAX_TBL) || scale(pscale, num, den) < 0) { pr_debug("Scale err, unsupported ratio %d : %d\n", num, den); return -1; @@ -1067,50 +1066,6 @@ static int prphw_ch2_cfg(emma_prp_cfg * cfg, unsigned long *prp_cntl) __raw_writel((cfg->ch2_width << 16) | cfg->ch2_height, PRP_CH2_OUT_IMAGE_SIZE); - if (cfg->ch2_pix == PRP_PIX2_YUV420) { - u32 size; - - /* Luminanance band start address */ - __raw_writel(cfg->ch2_ptr, PRP_DEST_Y_PTR); - - if ((cfg->in_csi & PRP_CSI_LOOP) == PRP_CSI_LOOP) { - if (!cfg->ch2_ptr2) - __raw_writel(cfg->ch2_ptr, PRP_SOURCE_Y_PTR); - else - __raw_writel(cfg->ch2_ptr2, PRP_SOURCE_Y_PTR); - } - - /* Cb and Cr band start address */ - size = cfg->ch2_width * cfg->ch2_height; - __raw_writel(cfg->ch2_ptr + size, PRP_DEST_CB_PTR); - __raw_writel(cfg->ch2_ptr + size + (size >> 2), - PRP_DEST_CR_PTR); - - if ((cfg->in_csi & PRP_CSI_LOOP) == PRP_CSI_LOOP) { - if (!cfg->ch2_ptr2) { - __raw_writel(cfg->ch2_ptr + size, - PRP_SOURCE_CB_PTR); - __raw_writel(cfg->ch2_ptr + size + (size >> 2), - PRP_SOURCE_CR_PTR); - } else { - __raw_writel(cfg->ch2_ptr2 + size, - PRP_SOURCE_CB_PTR); - __raw_writel(cfg->ch2_ptr2 + size + (size >> 2), - PRP_SOURCE_CR_PTR); - } - } - } else { /* Pixel interleaved YUV422 or YUV444 */ - __raw_writel(cfg->ch2_ptr, PRP_DEST_Y_PTR); - - if ((cfg->in_csi & PRP_CSI_LOOP) == PRP_CSI_LOOP) { - if (!cfg->ch2_ptr2) - __raw_writel(cfg->ch2_ptr, PRP_SOURCE_Y_PTR); - else - __raw_writel(cfg->ch2_ptr2, PRP_SOURCE_Y_PTR); - } - } - *prp_cntl |= PRP_CNTL_CH2B1 | PRP_CNTL_CH2B2; - return 0; } diff --git a/drivers/media/video/mxc/capture/mx27_prpsw.c b/drivers/media/video/mxc/capture/mx27_prpsw.c index b39623f25c1f..b4bfccc745b1 100644 --- a/drivers/media/video/mxc/capture/mx27_prpsw.c +++ b/drivers/media/video/mxc/capture/mx27_prpsw.c @@ -293,12 +293,11 @@ static irqreturn_t prp_isr(int irq, void *dev_id) } else if (cam->capture_on) { if (status & PRP_INTRSTAT_CH2OVF) { prphw_disable(PRP_CHANNEL_2); - prphw_enable(PRP_CHANNEL_2); cam->enc_callback(1, cam); - } - else if (status & - (PRP_INTRSTAT_CH2BUF1 | PRP_INTRSTAT_CH2BUF2)) { - cam->enc_callback(0, cam); + } else if (status & + (PRP_INTRSTAT_CH2BUF1 | PRP_INTRSTAT_CH2BUF2)) { + if (cam->overflow != 1) + cam->enc_callback(0, cam); } } if (cam->overlay_on @@ -1003,7 +1002,6 @@ static int prp_resize_check_ch1(emma_prp_cfg * cfg) } } - pr_debug("Ch1 resize error.\n"); return -1; diff --git a/drivers/media/video/mxc/capture/mx27_v4l2_capture.c b/drivers/media/video/mxc/capture/mx27_v4l2_capture.c index d6d91bda3e98..7d92fbfaa333 100644 --- a/drivers/media/video/mxc/capture/mx27_v4l2_capture.c +++ b/drivers/media/video/mxc/capture/mx27_v4l2_capture.c @@ -44,10 +44,52 @@ static int video_nr = -1; cam_data *g_cam; EXPORT_SYMBOL(g_cam); -static int dq_intr_cnt=0; -static int dq_timeout_cnt=0; -static int empty_wq_cnt=0; +static int dq_intr_cnt = 0; +static int dq_timeout_cnt = 0; +static int empty_wq_cnt = 0; +struct workqueue_struct *v4l2_work; +static void prp_reset(struct work_struct *unused) +{ + struct mxc_v4l_frame *done_frame, *ready_frame, *temp_frame; + + g_cam->ping_pong_csi = 0; + g_cam->enc_enable(g_cam); + if (!list_empty(&g_cam->working_q)) { + done_frame = + list_entry(g_cam->working_q.next, struct mxc_v4l_frame, + queue); + list_del(g_cam->working_q.next); + if (!list_empty(&g_cam->working_q)) { + temp_frame = + list_entry(g_cam->working_q.next, + struct mxc_v4l_frame, queue); + list_del(g_cam->working_q.next); + list_add_tail(&temp_frame->queue, &g_cam->working_q); + g_cam->enc_update_eba(temp_frame->paddress, + &g_cam->ping_pong_csi); + } + list_add_tail(&done_frame->queue, &g_cam->working_q); + g_cam->enc_update_eba(done_frame->paddress, + &g_cam->ping_pong_csi); + pr_debug("prp_reset - working_q\n"); + } else if (list_empty(&g_cam->ready_q)) { + prphw_disable(PRP_CHANNEL_2); + g_cam->skip_frame++; + } else { + ready_frame = + list_entry(g_cam->ready_q.next, struct mxc_v4l_frame, + queue); + list_del(g_cam->ready_q.next); + list_add_tail(&ready_frame->queue, &g_cam->working_q); + g_cam->enc_update_eba(ready_frame->paddress, + &g_cam->ping_pong_csi); + } + g_cam->overflow = 0; + wake_up_interruptible(&g_cam->overflow_queue); +} + +DECLARE_WORK(prp_reset_work, prp_reset); /*! * Free frame buffers * @@ -184,6 +226,7 @@ static int mxc_streamon(cam_data * cam) } cam->ping_pong_csi = 0; + cam->overflow = 0; if (cam->enc_update_eba) { frame = list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue); @@ -684,66 +727,23 @@ static int mxc_v4l_dqueue(cam_data * cam, struct v4l2_buffer *buf) int retval = 0; struct mxc_v4l_frame *frame; - cont: if (!wait_event_interruptible_timeout(cam->enc_queue, cam->enc_counter != 0, 10 * HZ)) { - if( (dq_timeout_cnt & 0x1f) == 0) - printk(KERN_ERR "mxc_v4l_dqueue timeout enc_counter %x\n", + if ((dq_timeout_cnt & 0x1f) == 0) + printk(KERN_ERR + "mxc_v4l_dqueue timeout enc_counter %x\n", cam->enc_counter); dq_timeout_cnt++; - if (cam->overflow == 1) { - cam->enc_enable(cam); - cam->overflow = 0; - if (!list_empty(&cam->ready_q)) { - frame = - list_entry(cam->ready_q.next, - struct mxc_v4l_frame, queue); - list_del(cam->ready_q.next); - list_add_tail(&frame->queue, &cam->working_q); - cam->enc_update_eba(frame->paddress, - &cam->ping_pong_csi); - } - goto cont; - } return -ETIME; } else if (signal_pending(current)) { - if(dq_intr_cnt == 0) - printk(KERN_ERR "mxc_v4l_dqueue() interrupt received %d\n",dq_intr_cnt); - dq_intr_cnt++; - if (cam->overflow == 1) { - cam->enc_enable(cam); - cam->overflow = 0; - if (!list_empty(&cam->ready_q)) { - frame = - list_entry(cam->ready_q.next, - struct mxc_v4l_frame, queue); - list_del(cam->ready_q.next); - list_add_tail(&frame->queue, &cam->working_q); - cam->enc_update_eba(frame->paddress, - &cam->ping_pong_csi); - } - goto cont; - } + if (dq_intr_cnt == 0) + printk(KERN_ERR + "mxc_v4l_dqueue() interrupt received %d\n", + dq_intr_cnt); + dq_intr_cnt++; return -ERESTARTSYS; } - if (cam->overflow == 1) { - cam->enc_enable(cam); - cam->overflow = 0; - if (!list_empty(&cam->ready_q)) { - frame = - list_entry(cam->ready_q.next, struct mxc_v4l_frame, - queue); - list_del(cam->ready_q.next); - list_add_tail(&frame->queue, &cam->working_q); - cam->enc_update_eba(frame->paddress, - &cam->ping_pong_csi); - } - printk(KERN_INFO "mxc_v4l_dqueue - overflow\n"); - - } - - cam->enc_counter--; frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue); @@ -801,9 +801,9 @@ static int mxc_v4l_open(struct inode *inode, struct file *file) cam_data *cam = dev->priv; int err = 0; - dq_intr_cnt = 0; + dq_intr_cnt = 0; dq_timeout_cnt = 0; - empty_wq_cnt = 0; + empty_wq_cnt = 0; if (!cam) { pr_info("Internal error, cam_data not found!\n"); return -ENODEV; @@ -890,6 +890,7 @@ static int mxc_v4l_close(struct inode *inode, struct file *file) err |= mxc_streamoff(cam); cam->capture_on = false; wake_up_interruptible(&cam->enc_queue); + wake_up_interruptible(&cam->overflow_queue); } if (--cam->open_count == 0) { @@ -904,6 +905,7 @@ static int mxc_v4l_close(struct inode *inode, struct file *file) /* capture off */ wake_up_interruptible(&cam->enc_queue); + wake_up_interruptible(&cam->overflow_queue); mxc_free_frames(cam); cam->enc_counter++; prp_exit(cam); @@ -1440,22 +1442,17 @@ mxc_v4l_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_QBUF:{ struct v4l2_buffer *buf = arg; int index = buf->index; - int overflow = 0; pr_debug("VIDIOC_QBUF: %d\n", buf->index); - if (cam->overflow == 1) { - cam->enc_enable(cam); - cam->overflow = 0; - overflow = 1; - printk(KERN_INFO "VIDIOC_QBUF - overflow\n"); - } - + wait_event_interruptible(cam->overflow_queue, + cam->overflow == 0); spin_lock_irqsave(&cam->int_lock, lock_flags); if ((cam->frame[index].buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) { cam->frame[index].buffer.flags |= V4L2_BUF_FLAG_QUEUED; - if ((cam->skip_frame > 0) || (overflow == 1)) { + if (cam->skip_frame > 0) { + prphw_enable(PRP_CHANNEL_2); list_add_tail(&cam->frame[index].queue, &cam->working_q); retval = @@ -1913,15 +1910,22 @@ static void camera_callback(u32 mask, void *dev) return; if (mask == 1) { - cam->overflow = 1; + if (cam->overflow == 0) { + cam->overflow = 1; + queue_work(v4l2_work, &prp_reset_work); + } + return; } if (list_empty(&cam->working_q)) { if (empty_wq_cnt == 0) { - printk(KERN_ERR "camera_callback: working queue empty %d\n",empty_wq_cnt); + printk(KERN_ERR + "camera_callback: working queue empty %d\n", + empty_wq_cnt); } empty_wq_cnt++; - if (list_empty(&cam->ready_q)) { + if (list_empty(&cam->ready_q)) { + prphw_disable(PRP_CHANNEL_2); cam->skip_frame++; } else { ready_frame = @@ -1941,7 +1945,10 @@ static void camera_callback(u32 mask, void *dev) done_frame->buffer.flags |= V4L2_BUF_FLAG_DONE; done_frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED; + list_del(cam->working_q.next); if (list_empty(&cam->ready_q)) { + if (list_empty(&cam->working_q)) + prphw_disable(PRP_CHANNEL_2); cam->skip_frame++; } else { ready_frame = @@ -1954,7 +1961,6 @@ static void camera_callback(u32 mask, void *dev) } /* Added to the done queue */ - list_del(cam->working_q.next); list_add_tail(&done_frame->queue, &cam->done_q); /* Wake up the queue */ @@ -2000,6 +2006,8 @@ static void init_camera_struct(cam_data * cam) init_waitqueue_head(&cam->enc_queue); init_waitqueue_head(&cam->still_queue); + init_waitqueue_head(&cam->overflow_queue); + cam->overflow = 0; /* setup cropping */ cam->crop_bounds.left = 0; @@ -2158,6 +2166,8 @@ static __init int camera_init(void) init_camera_struct(cam); + v4l2_work = create_singlethread_workqueue("v4l2_emma"); + /* Register the I2C device */ err = platform_device_register(&mxc_v4l2_devices); if (err != 0) { @@ -2201,6 +2211,9 @@ static void __exit camera_exit(void) { pr_debug("unregistering video\n"); + flush_workqueue(v4l2_work); + destroy_workqueue(v4l2_work); + video_unregister_device(g_cam->video_dev); platform_driver_unregister(&mxc_v4l2_driver); diff --git a/drivers/media/video/mxc/capture/mxc_v4l2_capture.h b/drivers/media/video/mxc/capture/mxc_v4l2_capture.h index 69cc5189fd16..733bcc66599a 100644 --- a/drivers/media/video/mxc/capture/mxc_v4l2_capture.h +++ b/drivers/media/video/mxc/capture/mxc_v4l2_capture.h @@ -105,7 +105,8 @@ typedef struct _cam_data { spinlock_t int_lock; struct mxc_v4l_frame frame[FRAME_NUM]; int skip_frame; - int overflow; + wait_queue_head_t overflow_queue; + int overflow; wait_queue_head_t enc_queue; int enc_counter; dma_addr_t rot_enc_bufs[2]; |