aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJavier Martin <javier.martin@vista-silicon.com>2012-02-07 05:14:42 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-03-08 07:41:56 -0500
commitcdc9d6f191d81aa1b1b34db9d3a33f779f5c5ec7 (patch)
tree3223a3fa758c180fdd17e88b48c6c59506410d51
parentfb51cbdd3ec868b903bd706aa7db065c8c36bcd4 (diff)
[media] media i.MX27 camera: improve discard buffer handling
The way discard buffer was previously handled lead to possible races that made a buffer that was not yet ready to be overwritten by new video data. This is easily detected at 25fps just adding "#define DEBUG" to enable the "memset" check and seeing how the image is corrupted. A new "discard" queue and two discard buffers have been added to make them flow trough the pipeline of queues and thus provide suitable event ordering. Signed-off-by: Javier Martin <javier.martin@vista-silicon.com> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/mx2_camera.c287
1 files changed, 161 insertions, 126 deletions
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c
index 2e232092fc10..fc5ffe47c558 100644
--- a/drivers/media/video/mx2_camera.c
+++ b/drivers/media/video/mx2_camera.c
@@ -235,7 +235,8 @@ struct mx2_buffer {
235 struct list_head queue; 235 struct list_head queue;
236 enum mx2_buffer_state state; 236 enum mx2_buffer_state state;
237 237
238 int bufnum; 238 int bufnum;
239 bool discard;
239}; 240};
240 241
241struct mx2_camera_dev { 242struct mx2_camera_dev {
@@ -254,6 +255,7 @@ struct mx2_camera_dev {
254 255
255 struct list_head capture; 256 struct list_head capture;
256 struct list_head active_bufs; 257 struct list_head active_bufs;
258 struct list_head discard;
257 259
258 spinlock_t lock; 260 spinlock_t lock;
259 261
@@ -264,6 +266,7 @@ struct mx2_camera_dev {
264 266
265 u32 csicr1; 267 u32 csicr1;
266 268
269 struct mx2_buffer buf_discard[2];
267 void *discard_buffer; 270 void *discard_buffer;
268 dma_addr_t discard_buffer_dma; 271 dma_addr_t discard_buffer_dma;
269 size_t discard_size; 272 size_t discard_size;
@@ -325,6 +328,29 @@ static struct mx2_fmt_cfg *mx27_emma_prp_get_format(
325 return &mx27_emma_prp_table[0]; 328 return &mx27_emma_prp_table[0];
326}; 329};
327 330
331static void mx27_update_emma_buf(struct mx2_camera_dev *pcdev,
332 unsigned long phys, int bufnum)
333{
334 struct mx2_fmt_cfg *prp = pcdev->emma_prp;
335
336 if (prp->cfg.channel == 1) {
337 writel(phys, pcdev->base_emma +
338 PRP_DEST_RGB1_PTR + 4 * bufnum);
339 } else {
340 writel(phys, pcdev->base_emma +
341 PRP_DEST_Y_PTR - 0x14 * bufnum);
342 if (prp->out_fmt == V4L2_PIX_FMT_YUV420) {
343 u32 imgsize = pcdev->icd->user_height *
344 pcdev->icd->user_width;
345
346 writel(phys + imgsize, pcdev->base_emma +
347 PRP_DEST_CB_PTR - 0x14 * bufnum);
348 writel(phys + ((5 * imgsize) / 4), pcdev->base_emma +
349 PRP_DEST_CR_PTR - 0x14 * bufnum);
350 }
351 }
352}
353
328static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) 354static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev)
329{ 355{
330 unsigned long flags; 356 unsigned long flags;
@@ -373,7 +399,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
373 writel(pcdev->csicr1, pcdev->base_csi + CSICR1); 399 writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
374 400
375 pcdev->icd = icd; 401 pcdev->icd = icd;
376 pcdev->frame_count = -1; 402 pcdev->frame_count = 0;
377 403
378 dev_info(icd->parent, "Camera driver attached to camera %d\n", 404 dev_info(icd->parent, "Camera driver attached to camera %d\n",
379 icd->devnum); 405 icd->devnum);
@@ -393,13 +419,6 @@ static void mx2_camera_remove_device(struct soc_camera_device *icd)
393 419
394 mx2_camera_deactivate(pcdev); 420 mx2_camera_deactivate(pcdev);
395 421
396 if (pcdev->discard_buffer) {
397 dma_free_coherent(ici->v4l2_dev.dev, pcdev->discard_size,
398 pcdev->discard_buffer,
399 pcdev->discard_buffer_dma);
400 pcdev->discard_buffer = NULL;
401 }
402
403 pcdev->icd = NULL; 422 pcdev->icd = NULL;
404} 423}
405 424
@@ -628,7 +647,6 @@ static void mx2_videobuf_release(struct vb2_buffer *vb)
628 */ 647 */
629 648
630 spin_lock_irqsave(&pcdev->lock, flags); 649 spin_lock_irqsave(&pcdev->lock, flags);
631 list_del_init(&buf->queue);
632 if (cpu_is_mx25() && buf->state == MX2_STATE_ACTIVE) { 650 if (cpu_is_mx25() && buf->state == MX2_STATE_ACTIVE) {
633 if (pcdev->fb1_active == buf) { 651 if (pcdev->fb1_active == buf) {
634 pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN; 652 pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN;
@@ -644,6 +662,34 @@ static void mx2_videobuf_release(struct vb2_buffer *vb)
644 spin_unlock_irqrestore(&pcdev->lock, flags); 662 spin_unlock_irqrestore(&pcdev->lock, flags);
645} 663}
646 664
665static void mx27_camera_emma_buf_init(struct soc_camera_device *icd,
666 int bytesperline)
667{
668 struct soc_camera_host *ici =
669 to_soc_camera_host(icd->parent);
670 struct mx2_camera_dev *pcdev = ici->priv;
671 struct mx2_fmt_cfg *prp = pcdev->emma_prp;
672
673 writel((icd->user_width << 16) | icd->user_height,
674 pcdev->base_emma + PRP_SRC_FRAME_SIZE);
675 writel(prp->cfg.src_pixel,
676 pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL);
677 if (prp->cfg.channel == 1) {
678 writel((icd->user_width << 16) | icd->user_height,
679 pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE);
680 writel(bytesperline,
681 pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE);
682 writel(prp->cfg.ch1_pixel,
683 pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL);
684 } else { /* channel 2 */
685 writel((icd->user_width << 16) | icd->user_height,
686 pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE);
687 }
688
689 /* Enable interrupts */
690 writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL);
691}
692
647static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) 693static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
648{ 694{
649 struct soc_camera_device *icd = soc_camera_from_vb2q(q); 695 struct soc_camera_device *icd = soc_camera_from_vb2q(q);
@@ -651,6 +697,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
651 to_soc_camera_host(icd->parent); 697 to_soc_camera_host(icd->parent);
652 struct mx2_camera_dev *pcdev = ici->priv; 698 struct mx2_camera_dev *pcdev = ici->priv;
653 struct mx2_fmt_cfg *prp = pcdev->emma_prp; 699 struct mx2_fmt_cfg *prp = pcdev->emma_prp;
700 struct vb2_buffer *vb;
701 struct mx2_buffer *buf;
702 unsigned long phys;
703 int bytesperline;
654 704
655 if (cpu_is_mx27()) { 705 if (cpu_is_mx27()) {
656 unsigned long flags; 706 unsigned long flags;
@@ -658,6 +708,56 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
658 return -EINVAL; 708 return -EINVAL;
659 709
660 spin_lock_irqsave(&pcdev->lock, flags); 710 spin_lock_irqsave(&pcdev->lock, flags);
711
712 buf = list_entry(pcdev->capture.next,
713 struct mx2_buffer, queue);
714 buf->bufnum = 0;
715 vb = &buf->vb;
716 buf->state = MX2_STATE_ACTIVE;
717
718 phys = vb2_dma_contig_plane_dma_addr(vb, 0);
719 mx27_update_emma_buf(pcdev, phys, buf->bufnum);
720 list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
721
722 buf = list_entry(pcdev->capture.next,
723 struct mx2_buffer, queue);
724 buf->bufnum = 1;
725 vb = &buf->vb;
726 buf->state = MX2_STATE_ACTIVE;
727
728 phys = vb2_dma_contig_plane_dma_addr(vb, 0);
729 mx27_update_emma_buf(pcdev, phys, buf->bufnum);
730 list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
731
732 bytesperline = soc_mbus_bytes_per_line(icd->user_width,
733 icd->current_fmt->host_fmt);
734 if (bytesperline < 0)
735 return bytesperline;
736
737 /*
738 * I didn't manage to properly enable/disable the prp
739 * on a per frame basis during running transfers,
740 * thus we allocate a buffer here and use it to
741 * discard frames when no buffer is available.
742 * Feel free to work on this ;)
743 */
744 pcdev->discard_size = icd->user_height * bytesperline;
745 pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev,
746 pcdev->discard_size, &pcdev->discard_buffer_dma,
747 GFP_KERNEL);
748 if (!pcdev->discard_buffer)
749 return -ENOMEM;
750
751 pcdev->buf_discard[0].discard = true;
752 list_add_tail(&pcdev->buf_discard[0].queue,
753 &pcdev->discard);
754
755 pcdev->buf_discard[1].discard = true;
756 list_add_tail(&pcdev->buf_discard[1].queue,
757 &pcdev->discard);
758
759 mx27_camera_emma_buf_init(icd, bytesperline);
760
661 if (prp->cfg.channel == 1) { 761 if (prp->cfg.channel == 1) {
662 writel(PRP_CNTL_CH1EN | 762 writel(PRP_CNTL_CH1EN |
663 PRP_CNTL_CSIEN | 763 PRP_CNTL_CSIEN |
@@ -692,10 +792,12 @@ static int mx2_stop_streaming(struct vb2_queue *q)
692 struct mx2_camera_dev *pcdev = ici->priv; 792 struct mx2_camera_dev *pcdev = ici->priv;
693 struct mx2_fmt_cfg *prp = pcdev->emma_prp; 793 struct mx2_fmt_cfg *prp = pcdev->emma_prp;
694 unsigned long flags; 794 unsigned long flags;
795 void *b;
695 u32 cntl; 796 u32 cntl;
696 797
697 spin_lock_irqsave(&pcdev->lock, flags);
698 if (cpu_is_mx27()) { 798 if (cpu_is_mx27()) {
799 spin_lock_irqsave(&pcdev->lock, flags);
800
699 cntl = readl(pcdev->base_emma + PRP_CNTL); 801 cntl = readl(pcdev->base_emma + PRP_CNTL);
700 if (prp->cfg.channel == 1) { 802 if (prp->cfg.channel == 1) {
701 writel(cntl & ~PRP_CNTL_CH1EN, 803 writel(cntl & ~PRP_CNTL_CH1EN,
@@ -704,8 +806,18 @@ static int mx2_stop_streaming(struct vb2_queue *q)
704 writel(cntl & ~PRP_CNTL_CH2EN, 806 writel(cntl & ~PRP_CNTL_CH2EN,
705 pcdev->base_emma + PRP_CNTL); 807 pcdev->base_emma + PRP_CNTL);
706 } 808 }
809 INIT_LIST_HEAD(&pcdev->capture);
810 INIT_LIST_HEAD(&pcdev->active_bufs);
811 INIT_LIST_HEAD(&pcdev->discard);
812
813 b = pcdev->discard_buffer;
814 pcdev->discard_buffer = NULL;
815
816 spin_unlock_irqrestore(&pcdev->lock, flags);
817
818 dma_free_coherent(ici->v4l2_dev.dev,
819 pcdev->discard_size, b, pcdev->discard_buffer_dma);
707 } 820 }
708 spin_unlock_irqrestore(&pcdev->lock, flags);
709 821
710 return 0; 822 return 0;
711} 823}
@@ -759,63 +871,6 @@ static int mx27_camera_emma_prp_reset(struct mx2_camera_dev *pcdev)
759 return -ETIMEDOUT; 871 return -ETIMEDOUT;
760} 872}
761 873
762static void mx27_camera_emma_buf_init(struct soc_camera_device *icd,
763 int bytesperline)
764{
765 struct soc_camera_host *ici =
766 to_soc_camera_host(icd->parent);
767 struct mx2_camera_dev *pcdev = ici->priv;
768 struct mx2_fmt_cfg *prp = pcdev->emma_prp;
769 u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width;
770
771 if (prp->cfg.channel == 1) {
772 writel(pcdev->discard_buffer_dma,
773 pcdev->base_emma + PRP_DEST_RGB1_PTR);
774 writel(pcdev->discard_buffer_dma,
775 pcdev->base_emma + PRP_DEST_RGB2_PTR);
776
777 writel((icd->user_width << 16) | icd->user_height,
778 pcdev->base_emma + PRP_SRC_FRAME_SIZE);
779 writel((icd->user_width << 16) | icd->user_height,
780 pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE);
781 writel(bytesperline,
782 pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE);
783 writel(prp->cfg.src_pixel,
784 pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL);
785 writel(prp->cfg.ch1_pixel,
786 pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL);
787 } else { /* channel 2 */
788 writel(pcdev->discard_buffer_dma,
789 pcdev->base_emma + PRP_DEST_Y_PTR);
790 writel(pcdev->discard_buffer_dma,
791 pcdev->base_emma + PRP_SOURCE_Y_PTR);
792
793 if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) {
794 writel(pcdev->discard_buffer_dma + imgsize,
795 pcdev->base_emma + PRP_DEST_CB_PTR);
796 writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4),
797 pcdev->base_emma + PRP_DEST_CR_PTR);
798 writel(pcdev->discard_buffer_dma + imgsize,
799 pcdev->base_emma + PRP_SOURCE_CB_PTR);
800 writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4),
801 pcdev->base_emma + PRP_SOURCE_CR_PTR);
802 }
803
804 writel((icd->user_width << 16) | icd->user_height,
805 pcdev->base_emma + PRP_SRC_FRAME_SIZE);
806
807 writel((icd->user_width << 16) | icd->user_height,
808 pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE);
809
810 writel(prp->cfg.src_pixel,
811 pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL);
812
813 }
814
815 /* Enable interrupts */
816 writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL);
817}
818
819static int mx2_camera_set_bus_param(struct soc_camera_device *icd) 874static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
820{ 875{
821 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 876 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
@@ -898,27 +953,6 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
898 ret = mx27_camera_emma_prp_reset(pcdev); 953 ret = mx27_camera_emma_prp_reset(pcdev);
899 if (ret) 954 if (ret)
900 return ret; 955 return ret;
901
902 if (pcdev->discard_buffer)
903 dma_free_coherent(ici->v4l2_dev.dev,
904 pcdev->discard_size, pcdev->discard_buffer,
905 pcdev->discard_buffer_dma);
906
907 /*
908 * I didn't manage to properly enable/disable the prp
909 * on a per frame basis during running transfers,
910 * thus we allocate a buffer here and use it to
911 * discard frames when no buffer is available.
912 * Feel free to work on this ;)
913 */
914 pcdev->discard_size = icd->user_height * bytesperline;
915 pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev,
916 pcdev->discard_size, &pcdev->discard_buffer_dma,
917 GFP_KERNEL);
918 if (!pcdev->discard_buffer)
919 return -ENOMEM;
920
921 mx27_camera_emma_buf_init(icd, bytesperline);
922 } else if (cpu_is_mx25()) { 956 } else if (cpu_is_mx25()) {
923 writel((bytesperline * icd->user_height) >> 2, 957 writel((bytesperline * icd->user_height) >> 2,
924 pcdev->base_csi + CSIRXCNT); 958 pcdev->base_csi + CSIRXCNT);
@@ -1166,18 +1200,23 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = {
1166static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, 1200static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
1167 int bufnum) 1201 int bufnum)
1168{ 1202{
1169 u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width;
1170 struct mx2_fmt_cfg *prp = pcdev->emma_prp; 1203 struct mx2_fmt_cfg *prp = pcdev->emma_prp;
1171 struct mx2_buffer *buf; 1204 struct mx2_buffer *buf;
1172 struct vb2_buffer *vb; 1205 struct vb2_buffer *vb;
1173 unsigned long phys; 1206 unsigned long phys;
1174 1207
1175 if (!list_empty(&pcdev->active_bufs)) { 1208 buf = list_entry(pcdev->active_bufs.next,
1176 buf = list_entry(pcdev->active_bufs.next, 1209 struct mx2_buffer, queue);
1177 struct mx2_buffer, queue);
1178 1210
1179 BUG_ON(buf->bufnum != bufnum); 1211 BUG_ON(buf->bufnum != bufnum);
1180 1212
1213 if (buf->discard) {
1214 /*
1215 * Discard buffer must not be returned to user space.
1216 * Just return it to the discard queue.
1217 */
1218 list_move_tail(pcdev->active_bufs.next, &pcdev->discard);
1219 } else {
1181 vb = &buf->vb; 1220 vb = &buf->vb;
1182#ifdef DEBUG 1221#ifdef DEBUG
1183 phys = vb2_dma_contig_plane_dma_addr(vb, 0); 1222 phys = vb2_dma_contig_plane_dma_addr(vb, 0);
@@ -1212,29 +1251,25 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
1212 pcdev->frame_count++; 1251 pcdev->frame_count++;
1213 1252
1214 if (list_empty(&pcdev->capture)) { 1253 if (list_empty(&pcdev->capture)) {
1215 if (prp->cfg.channel == 1) { 1254 if (list_empty(&pcdev->discard)) {
1216 writel(pcdev->discard_buffer_dma, pcdev->base_emma + 1255 dev_warn(pcdev->dev, "%s: trying to access empty discard list\n",
1217 PRP_DEST_RGB1_PTR + 4 * bufnum); 1256 __func__);
1218 } else { 1257 return;
1219 writel(pcdev->discard_buffer_dma, pcdev->base_emma +
1220 PRP_DEST_Y_PTR -
1221 0x14 * bufnum);
1222 if (prp->out_fmt == V4L2_PIX_FMT_YUV420) {
1223 writel(pcdev->discard_buffer_dma + imgsize,
1224 pcdev->base_emma + PRP_DEST_CB_PTR -
1225 0x14 * bufnum);
1226 writel(pcdev->discard_buffer_dma +
1227 ((5 * imgsize) / 4), pcdev->base_emma +
1228 PRP_DEST_CR_PTR - 0x14 * bufnum);
1229 }
1230 } 1258 }
1259
1260 buf = list_entry(pcdev->discard.next,
1261 struct mx2_buffer, queue);
1262 buf->bufnum = bufnum;
1263
1264 list_move_tail(pcdev->discard.next, &pcdev->active_bufs);
1265 mx27_update_emma_buf(pcdev, pcdev->discard_buffer_dma, bufnum);
1231 return; 1266 return;
1232 } 1267 }
1233 1268
1234 buf = list_entry(pcdev->capture.next, 1269 buf = list_entry(pcdev->capture.next,
1235 struct mx2_buffer, queue); 1270 struct mx2_buffer, queue);
1236 1271
1237 buf->bufnum = !bufnum; 1272 buf->bufnum = bufnum;
1238 1273
1239 list_move_tail(pcdev->capture.next, &pcdev->active_bufs); 1274 list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
1240 1275
@@ -1242,18 +1277,7 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
1242 buf->state = MX2_STATE_ACTIVE; 1277 buf->state = MX2_STATE_ACTIVE;
1243 1278
1244 phys = vb2_dma_contig_plane_dma_addr(vb, 0); 1279 phys = vb2_dma_contig_plane_dma_addr(vb, 0);
1245 if (prp->cfg.channel == 1) { 1280 mx27_update_emma_buf(pcdev, phys, bufnum);
1246 writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum);
1247 } else {
1248 writel(phys, pcdev->base_emma +
1249 PRP_DEST_Y_PTR - 0x14 * bufnum);
1250 if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) {
1251 writel(phys + imgsize, pcdev->base_emma +
1252 PRP_DEST_CB_PTR - 0x14 * bufnum);
1253 writel(phys + ((5 * imgsize) / 4), pcdev->base_emma +
1254 PRP_DEST_CR_PTR - 0x14 * bufnum);
1255 }
1256 }
1257} 1281}
1258 1282
1259static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) 1283static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
@@ -1261,6 +1285,15 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
1261 struct mx2_camera_dev *pcdev = data; 1285 struct mx2_camera_dev *pcdev = data;
1262 unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS); 1286 unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS);
1263 struct mx2_buffer *buf; 1287 struct mx2_buffer *buf;
1288 unsigned long flags;
1289
1290 spin_lock_irqsave(&pcdev->lock, flags);
1291
1292 if (list_empty(&pcdev->active_bufs)) {
1293 dev_warn(pcdev->dev, "%s: called while active list is empty\n",
1294 __func__);
1295 goto irq_ok;
1296 }
1264 1297
1265 if (status & (1 << 7)) { /* overflow */ 1298 if (status & (1 << 7)) { /* overflow */
1266 u32 cntl; 1299 u32 cntl;
@@ -1277,9 +1310,8 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
1277 pcdev->base_emma + PRP_CNTL); 1310 pcdev->base_emma + PRP_CNTL);
1278 writel(cntl, pcdev->base_emma + PRP_CNTL); 1311 writel(cntl, pcdev->base_emma + PRP_CNTL);
1279 } 1312 }
1280 if ((((status & (3 << 5)) == (3 << 5)) || 1313 if (((status & (3 << 5)) == (3 << 5)) ||
1281 ((status & (3 << 3)) == (3 << 3))) 1314 ((status & (3 << 3)) == (3 << 3))) {
1282 && !list_empty(&pcdev->active_bufs)) {
1283 /* 1315 /*
1284 * Both buffers have triggered, process the one we're expecting 1316 * Both buffers have triggered, process the one we're expecting
1285 * to first 1317 * to first
@@ -1294,6 +1326,8 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
1294 if ((status & (1 << 5)) || (status & (1 << 3))) 1326 if ((status & (1 << 5)) || (status & (1 << 3)))
1295 mx27_camera_frame_done_emma(pcdev, 1); 1327 mx27_camera_frame_done_emma(pcdev, 1);
1296 1328
1329irq_ok:
1330 spin_unlock_irqrestore(&pcdev->lock, flags);
1297 writel(status, pcdev->base_emma + PRP_INTRSTATUS); 1331 writel(status, pcdev->base_emma + PRP_INTRSTATUS);
1298 1332
1299 return IRQ_HANDLED; 1333 return IRQ_HANDLED;
@@ -1403,6 +1437,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
1403 1437
1404 INIT_LIST_HEAD(&pcdev->capture); 1438 INIT_LIST_HEAD(&pcdev->capture);
1405 INIT_LIST_HEAD(&pcdev->active_bufs); 1439 INIT_LIST_HEAD(&pcdev->active_bufs);
1440 INIT_LIST_HEAD(&pcdev->discard);
1406 spin_lock_init(&pcdev->lock); 1441 spin_lock_init(&pcdev->lock);
1407 1442
1408 /* 1443 /*