CR ENGR37631: Adds correct signal handling to the V4L2 input and output
authorQuinn Jensen <quinn.jensen@freescale.com>
Thu, 25 Oct 2007 03:21:01 +0000 (21:21 -0600)
committerQuinn Jensen <quinn.jensen@freescale.com>
Thu, 25 Oct 2007 03:21:01 +0000 (21:21 -0600)
Patch for CR ENGR37631: Adds correct signal handling to the V4L2 input
and output devices. Adds handling of PRP overflow on channel2 under high
system load.  Applies to linux 2.6.22 kernel on MX27 platform.

http://www.bitshrine.org/gpp/linux-2.6.22-mx-CR-ENGR37631-Adds-correct-signal-handling-.patch

drivers/media/video/mxc/capture/mx27_prphw.c
drivers/media/video/mxc/capture/mx27_prpsw.c
drivers/media/video/mxc/capture/mx27_v4l2_capture.c
drivers/media/video/mxc/capture/mxc_v4l2_capture.h
drivers/media/video/mxc/output/mx27_v4l2_output.c

index c56a6df1716e9b93c422882bb680b71ee98b1d4e..7c92fe175bf35f3d3eb942186959bc5bc2598246 100644 (file)
@@ -528,7 +528,8 @@ int prphw_enable(int channel)
        if (channel & PRP_CHANNEL_1)
                val |= PRP_CNTL_CH1EN;
        if (channel & PRP_CHANNEL_2)
-               val |= (PRP_CNTL_CH2EN | PRP_CNTL_CH2_FLOWEN);
+               val |=
+                   (PRP_CNTL_CH2EN | PRP_CNTL_CH2_FLOWEN | PRP_CNTL_AUTODROP);
 
        __raw_writel(val, PRP_CNTL);
 
index 9bf7d92e66f2834bc44e1ce8bb377b2ebeb6a2e3..743551ccf90b5854df1702fa86a6c49e44c2bffc 100644 (file)
@@ -290,14 +290,13 @@ static irqreturn_t prp_isr(int irq, void *dev_id)
                 * They are execlusive.
                 */
        } else if (cam->capture_on) {
-               if (status & PRP_INTRSTAT_CH2OVF)
-               {
-                       //printk(KERN_INFO "prphw_isr - PRP_INTRSTAT_CH2OVF: status: 0x%x\n", status);
+               if (status & PRP_INTRSTAT_CH2OVF) {
                        prphw_disable(PRP_CHANNEL_2);
                        prphw_enable(PRP_CHANNEL_2);
-                       cam->enc_callback(0, cam);
+                       cam->enc_callback(1, cam);
                }
-               else if (status & (PRP_INTRSTAT_CH2BUF1 | PRP_INTRSTAT_CH2BUF2))                {
+               else if (status &
+             (PRP_INTRSTAT_CH2BUF1 | PRP_INTRSTAT_CH2BUF2))            {
                        cam->enc_callback(0, cam);
                }
        }
index 0655d8409ce33a3b45403dd40c218e4fa44ea013..c776bc38d3757e07f54822b3f47d1f916ac13a88 100644 (file)
@@ -653,20 +653,66 @@ 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 == 0)
+               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\n");
+                       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;
+               }
                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);
@@ -685,7 +731,6 @@ static int mxc_v4l_dqueue(cam_data * cam, struct v4l2_buffer *buf)
        buf->bytesused = cam->v2f.fmt.pix.sizeimage;
        buf->index = frame->index;
        buf->flags = frame->buffer.flags;
-
        return retval;
 }
 
@@ -1361,15 +1406,22 @@ 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");
+                       }
 
                        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) {
+                               if ((cam->skip_frame > 0) || (overflow == 1)) {
                                        list_add_tail(&cam->frame[index].queue,
                                                      &cam->working_q);
                                        retval =
@@ -1826,11 +1878,26 @@ static void camera_callback(u32 mask, void *dev)
        if (cam == NULL)
                return;
 
+       if (mask == 1) {
+               cam->overflow = 1;
+       }
+
        if (list_empty(&cam->working_q)) {
                if (empty_wq_cnt == 0) {
-                       printk(KERN_ERR "camera_callback: working queue empty\n");
+                       printk(KERN_ERR "camera_callback: working queue empty %d\n",empty_wq_cnt);
                }
                empty_wq_cnt++;
+           if (list_empty(&cam->ready_q)) {
+                       cam->skip_frame++;
+               } else {
+                       ready_frame =
+                           list_entry(cam->ready_q.next, struct mxc_v4l_frame,
+                                      queue);
+                       list_del(cam->ready_q.next);
+                       list_add_tail(&ready_frame->queue, &cam->working_q);
+                       cam->enc_update_eba(ready_frame->paddress,
+                                           &cam->ping_pong_csi);
+               }
                return;
        }
 
index 44d9d93ace397dedce2a435e5294c67dab36eda3..543a8db4bef6910dd893cc185f713310595bf93f 100644 (file)
@@ -101,6 +101,7 @@ typedef struct _cam_data {
        spinlock_t int_lock;
        struct mxc_v4l_frame frame[FRAME_NUM];
        int skip_frame;
+    int overflow;
        wait_queue_head_t enc_queue;
        int enc_counter;
        dma_addr_t rot_enc_bufs[2];
index 7afac05bf1c3749c8b60535995eff6a402fa758d..7ac39663e2d7727608871ef2851c46ea92e503c2 100644 (file)
@@ -1032,7 +1032,6 @@ mxc_v4l2out_do_ioctl(struct inode *inode, struct file *file,
                                if(dq_intr_cnt == 0)
                                        pr_debug("VIDIOC_DQBUF: interrupt received\n");
                                dq_intr_cnt++;
-                               // vout->state = STATE_STREAM_STOPPING;
                                retval = -ERESTARTSYS;
                                break;
                        }