aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-12-07 06:34:50 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-12-20 06:53:43 -0500
commit875e2e3edf48a206c64195666cf408dd3d119137 (patch)
treed86bf2075ed22fe669af4896afbe41f357f52fcd
parentc3cd257402fdcd650816ec25b83480a24912430a (diff)
[media] omap3isp: Mark next captured frame as faulty when an SBL overflow occurs
Instead of trying to propagate errors down the pipeline manually (and failing to do so properly in all cases), flag SBL errors in the pipeline to which the entity that triggered the error belongs, and use pipeline error flags to mark buffers as faulty when completing them. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/omap3isp/isp.c53
-rw-r--r--drivers/media/video/omap3isp/ispccdc.c9
-rw-r--r--drivers/media/video/omap3isp/ispccdc.h2
-rw-r--r--drivers/media/video/omap3isp/ispccp2.c22
-rw-r--r--drivers/media/video/omap3isp/ispccp2.h3
-rw-r--r--drivers/media/video/omap3isp/ispcsi2.c18
-rw-r--r--drivers/media/video/omap3isp/ispcsi2.h2
-rw-r--r--drivers/media/video/omap3isp/isppreview.c9
-rw-r--r--drivers/media/video/omap3isp/isppreview.h2
-rw-r--r--drivers/media/video/omap3isp/ispresizer.c7
-rw-r--r--drivers/media/video/omap3isp/ispresizer.h1
-rw-r--r--drivers/media/video/omap3isp/ispvideo.c19
-rw-r--r--drivers/media/video/omap3isp/ispvideo.h8
13 files changed, 73 insertions, 82 deletions
diff --git a/drivers/media/video/omap3isp/isp.c b/drivers/media/video/omap3isp/isp.c
index b818cacf420f..5cc15ba6a76a 100644
--- a/drivers/media/video/omap3isp/isp.c
+++ b/drivers/media/video/omap3isp/isp.c
@@ -410,6 +410,7 @@ static inline void isp_isr_dbg(struct isp_device *isp, u32 irqstatus)
410static void isp_isr_sbl(struct isp_device *isp) 410static void isp_isr_sbl(struct isp_device *isp)
411{ 411{
412 struct device *dev = isp->dev; 412 struct device *dev = isp->dev;
413 struct isp_pipeline *pipe;
413 u32 sbl_pcr; 414 u32 sbl_pcr;
414 415
415 /* 416 /*
@@ -423,27 +424,38 @@ static void isp_isr_sbl(struct isp_device *isp)
423 if (sbl_pcr) 424 if (sbl_pcr)
424 dev_dbg(dev, "SBL overflow (PCR = 0x%08x)\n", sbl_pcr); 425 dev_dbg(dev, "SBL overflow (PCR = 0x%08x)\n", sbl_pcr);
425 426
426 if (sbl_pcr & (ISPSBL_PCR_CCDC_WBL_OVF | ISPSBL_PCR_CSIA_WBL_OVF 427 if (sbl_pcr & ISPSBL_PCR_CSIB_WBL_OVF) {
427 | ISPSBL_PCR_CSIB_WBL_OVF)) { 428 pipe = to_isp_pipeline(&isp->isp_ccp2.subdev.entity);
428 isp->isp_ccdc.error = 1; 429 if (pipe != NULL)
429 if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW) 430 pipe->error = true;
430 isp->isp_prev.error = 1; 431 }
431 if (isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER) 432
432 isp->isp_res.error = 1; 433 if (sbl_pcr & ISPSBL_PCR_CSIA_WBL_OVF) {
434 pipe = to_isp_pipeline(&isp->isp_csi2a.subdev.entity);
435 if (pipe != NULL)
436 pipe->error = true;
437 }
438
439 if (sbl_pcr & ISPSBL_PCR_CCDC_WBL_OVF) {
440 pipe = to_isp_pipeline(&isp->isp_ccdc.subdev.entity);
441 if (pipe != NULL)
442 pipe->error = true;
433 } 443 }
434 444
435 if (sbl_pcr & ISPSBL_PCR_PRV_WBL_OVF) { 445 if (sbl_pcr & ISPSBL_PCR_PRV_WBL_OVF) {
436 isp->isp_prev.error = 1; 446 pipe = to_isp_pipeline(&isp->isp_prev.subdev.entity);
437 if (isp->isp_res.input == RESIZER_INPUT_VP && 447 if (pipe != NULL)
438 !(isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER)) 448 pipe->error = true;
439 isp->isp_res.error = 1;
440 } 449 }
441 450
442 if (sbl_pcr & (ISPSBL_PCR_RSZ1_WBL_OVF 451 if (sbl_pcr & (ISPSBL_PCR_RSZ1_WBL_OVF
443 | ISPSBL_PCR_RSZ2_WBL_OVF 452 | ISPSBL_PCR_RSZ2_WBL_OVF
444 | ISPSBL_PCR_RSZ3_WBL_OVF 453 | ISPSBL_PCR_RSZ3_WBL_OVF
445 | ISPSBL_PCR_RSZ4_WBL_OVF)) 454 | ISPSBL_PCR_RSZ4_WBL_OVF)) {
446 isp->isp_res.error = 1; 455 pipe = to_isp_pipeline(&isp->isp_res.subdev.entity);
456 if (pipe != NULL)
457 pipe->error = true;
458 }
447 459
448 if (sbl_pcr & ISPSBL_PCR_H3A_AF_WBL_OVF) 460 if (sbl_pcr & ISPSBL_PCR_H3A_AF_WBL_OVF)
449 omap3isp_stat_sbl_overflow(&isp->isp_af); 461 omap3isp_stat_sbl_overflow(&isp->isp_af);
@@ -471,24 +483,17 @@ static irqreturn_t isp_isr(int irq, void *_isp)
471 IRQ0STATUS_HS_VS_IRQ; 483 IRQ0STATUS_HS_VS_IRQ;
472 struct isp_device *isp = _isp; 484 struct isp_device *isp = _isp;
473 u32 irqstatus; 485 u32 irqstatus;
474 int ret;
475 486
476 irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS); 487 irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
477 isp_reg_writel(isp, irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS); 488 isp_reg_writel(isp, irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
478 489
479 isp_isr_sbl(isp); 490 isp_isr_sbl(isp);
480 491
481 if (irqstatus & IRQ0STATUS_CSIA_IRQ) { 492 if (irqstatus & IRQ0STATUS_CSIA_IRQ)
482 ret = omap3isp_csi2_isr(&isp->isp_csi2a); 493 omap3isp_csi2_isr(&isp->isp_csi2a);
483 if (ret)
484 isp->isp_ccdc.error = 1;
485 }
486 494
487 if (irqstatus & IRQ0STATUS_CSIB_IRQ) { 495 if (irqstatus & IRQ0STATUS_CSIB_IRQ)
488 ret = omap3isp_ccp2_isr(&isp->isp_ccp2); 496 omap3isp_ccp2_isr(&isp->isp_ccp2);
489 if (ret)
490 isp->isp_ccdc.error = 1;
491 }
492 497
493 if (irqstatus & IRQ0STATUS_CCDC_VD0_IRQ) { 498 if (irqstatus & IRQ0STATUS_CCDC_VD0_IRQ) {
494 if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW) 499 if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c
index 9012b57b3cf0..3663834ca94c 100644
--- a/drivers/media/video/omap3isp/ispccdc.c
+++ b/drivers/media/video/omap3isp/ispccdc.c
@@ -1427,8 +1427,11 @@ static void ccdc_lsc_isr(struct isp_ccdc_device *ccdc, u32 events)
1427 unsigned long flags; 1427 unsigned long flags;
1428 1428
1429 if (events & IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ) { 1429 if (events & IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ) {
1430 struct isp_pipeline *pipe =
1431 to_isp_pipeline(&ccdc->subdev.entity);
1432
1430 ccdc_lsc_error_handler(ccdc); 1433 ccdc_lsc_error_handler(ccdc);
1431 ccdc->error = 1; 1434 pipe->error = true;
1432 dev_dbg(to_device(ccdc), "lsc prefetch error\n"); 1435 dev_dbg(to_device(ccdc), "lsc prefetch error\n");
1433 } 1436 }
1434 1437
@@ -1503,7 +1506,7 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
1503 goto done; 1506 goto done;
1504 } 1507 }
1505 1508
1506 buffer = omap3isp_video_buffer_next(&ccdc->video_out, ccdc->error); 1509 buffer = omap3isp_video_buffer_next(&ccdc->video_out);
1507 if (buffer != NULL) { 1510 if (buffer != NULL) {
1508 ccdc_set_outaddr(ccdc, buffer->isp_addr); 1511 ccdc_set_outaddr(ccdc, buffer->isp_addr);
1509 restart = 1; 1512 restart = 1;
@@ -1517,7 +1520,6 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
1517 ISP_PIPELINE_STREAM_SINGLESHOT); 1520 ISP_PIPELINE_STREAM_SINGLESHOT);
1518 1521
1519done: 1522done:
1520 ccdc->error = 0;
1521 return restart; 1523 return restart;
1522} 1524}
1523 1525
@@ -1743,7 +1745,6 @@ static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
1743 */ 1745 */
1744 ccdc_config_vp(ccdc); 1746 ccdc_config_vp(ccdc);
1745 ccdc_enable_vp(ccdc, 1); 1747 ccdc_enable_vp(ccdc, 1);
1746 ccdc->error = 0;
1747 ccdc_print_status(ccdc); 1748 ccdc_print_status(ccdc);
1748 } 1749 }
1749 1750
diff --git a/drivers/media/video/omap3isp/ispccdc.h b/drivers/media/video/omap3isp/ispccdc.h
index 483a19cac1ad..6d0264bab75b 100644
--- a/drivers/media/video/omap3isp/ispccdc.h
+++ b/drivers/media/video/omap3isp/ispccdc.h
@@ -150,7 +150,6 @@ struct ispccdc_lsc {
150 * @input: Active input 150 * @input: Active input
151 * @output: Active outputs 151 * @output: Active outputs
152 * @video_out: Output video node 152 * @video_out: Output video node
153 * @error: A hardware error occurred during capture
154 * @alaw: A-law compression enabled (1) or disabled (0) 153 * @alaw: A-law compression enabled (1) or disabled (0)
155 * @lpf: Low pass filter enabled (1) or disabled (0) 154 * @lpf: Low pass filter enabled (1) or disabled (0)
156 * @obclamp: Optical-black clamp enabled (1) or disabled (0) 155 * @obclamp: Optical-black clamp enabled (1) or disabled (0)
@@ -178,7 +177,6 @@ struct isp_ccdc_device {
178 enum ccdc_input_entity input; 177 enum ccdc_input_entity input;
179 unsigned int output; 178 unsigned int output;
180 struct isp_video video_out; 179 struct isp_video video_out;
181 unsigned int error;
182 180
183 unsigned int alaw:1, 181 unsigned int alaw:1,
184 lpf:1, 182 lpf:1,
diff --git a/drivers/media/video/omap3isp/ispccp2.c b/drivers/media/video/omap3isp/ispccp2.c
index 904ca8c8b17f..70ddbf35b223 100644
--- a/drivers/media/video/omap3isp/ispccp2.c
+++ b/drivers/media/video/omap3isp/ispccp2.c
@@ -556,7 +556,7 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
556 struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity); 556 struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
557 struct isp_buffer *buffer; 557 struct isp_buffer *buffer;
558 558
559 buffer = omap3isp_video_buffer_next(&ccp2->video_in, ccp2->error); 559 buffer = omap3isp_video_buffer_next(&ccp2->video_in);
560 if (buffer != NULL) 560 if (buffer != NULL)
561 ccp2_set_inaddr(ccp2, buffer->isp_addr); 561 ccp2_set_inaddr(ccp2, buffer->isp_addr);
562 562
@@ -567,8 +567,6 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
567 omap3isp_pipeline_set_stream(pipe, 567 omap3isp_pipeline_set_stream(pipe,
568 ISP_PIPELINE_STREAM_SINGLESHOT); 568 ISP_PIPELINE_STREAM_SINGLESHOT);
569 } 569 }
570
571 ccp2->error = 0;
572} 570}
573 571
574/* 572/*
@@ -576,13 +574,11 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
576 * @ccp2: Pointer to ISP CCP2 device 574 * @ccp2: Pointer to ISP CCP2 device
577 * 575 *
578 * This will handle the CCP2 interrupts 576 * This will handle the CCP2 interrupts
579 *
580 * Returns -EIO in case of error, or 0 on success.
581 */ 577 */
582int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2) 578void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
583{ 579{
580 struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
584 struct isp_device *isp = to_isp_device(ccp2); 581 struct isp_device *isp = to_isp_device(ccp2);
585 int ret = 0;
586 static const u32 ISPCCP2_LC01_ERROR = 582 static const u32 ISPCCP2_LC01_ERROR =
587 ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ | 583 ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
588 ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ | 584 ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
@@ -604,19 +600,18 @@ int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
604 ISPCCP2_LCM_IRQSTATUS); 600 ISPCCP2_LCM_IRQSTATUS);
605 /* Errors */ 601 /* Errors */
606 if (lcx_irqstatus & ISPCCP2_LC01_ERROR) { 602 if (lcx_irqstatus & ISPCCP2_LC01_ERROR) {
607 ccp2->error = 1; 603 pipe->error = true;
608 dev_dbg(isp->dev, "CCP2 err:%x\n", lcx_irqstatus); 604 dev_dbg(isp->dev, "CCP2 err:%x\n", lcx_irqstatus);
609 return -EIO; 605 return;
610 } 606 }
611 607
612 if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ) { 608 if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ) {
613 ccp2->error = 1; 609 pipe->error = true;
614 dev_dbg(isp->dev, "CCP2 OCP err:%x\n", lcm_irqstatus); 610 dev_dbg(isp->dev, "CCP2 OCP err:%x\n", lcm_irqstatus);
615 ret = -EIO;
616 } 611 }
617 612
618 if (omap3isp_module_sync_is_stopping(&ccp2->wait, &ccp2->stopping)) 613 if (omap3isp_module_sync_is_stopping(&ccp2->wait, &ccp2->stopping))
619 return 0; 614 return;
620 615
621 /* Frame number propagation */ 616 /* Frame number propagation */
622 if (lcx_irqstatus & ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ) { 617 if (lcx_irqstatus & ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ) {
@@ -629,8 +624,6 @@ int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
629 /* Handle queued buffers on frame end interrupts */ 624 /* Handle queued buffers on frame end interrupts */
630 if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_EOF_IRQ) 625 if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_EOF_IRQ)
631 ccp2_isr_buffer(ccp2); 626 ccp2_isr_buffer(ccp2);
632
633 return ret;
634} 627}
635 628
636/* ----------------------------------------------------------------------------- 629/* -----------------------------------------------------------------------------
@@ -867,7 +860,6 @@ static int ccp2_s_stream(struct v4l2_subdev *sd, int enable)
867 if (enable == ISP_PIPELINE_STREAM_STOPPED) 860 if (enable == ISP_PIPELINE_STREAM_STOPPED)
868 return 0; 861 return 0;
869 atomic_set(&ccp2->stopping, 0); 862 atomic_set(&ccp2->stopping, 0);
870 ccp2->error = 0;
871 } 863 }
872 864
873 switch (enable) { 865 switch (enable) {
diff --git a/drivers/media/video/omap3isp/ispccp2.h b/drivers/media/video/omap3isp/ispccp2.h
index 6674e9de2cd7..76d65f4576ef 100644
--- a/drivers/media/video/omap3isp/ispccp2.h
+++ b/drivers/media/video/omap3isp/ispccp2.h
@@ -82,7 +82,6 @@ struct isp_ccp2_device {
82 struct isp_video video_in; 82 struct isp_video video_in;
83 struct isp_csiphy *phy; 83 struct isp_csiphy *phy;
84 struct regulator *vdds_csib; 84 struct regulator *vdds_csib;
85 unsigned int error;
86 enum isp_pipeline_stream_state state; 85 enum isp_pipeline_stream_state state;
87 wait_queue_head_t wait; 86 wait_queue_head_t wait;
88 atomic_t stopping; 87 atomic_t stopping;
@@ -94,6 +93,6 @@ void omap3isp_ccp2_cleanup(struct isp_device *isp);
94int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2, 93int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
95 struct v4l2_device *vdev); 94 struct v4l2_device *vdev);
96void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2); 95void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2);
97int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2); 96void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2);
98 97
99#endif /* OMAP3_ISP_CCP2_H */ 98#endif /* OMAP3_ISP_CCP2_H */
diff --git a/drivers/media/video/omap3isp/ispcsi2.c b/drivers/media/video/omap3isp/ispcsi2.c
index 0c5f1cb9d99d..fcb5168996a7 100644
--- a/drivers/media/video/omap3isp/ispcsi2.c
+++ b/drivers/media/video/omap3isp/ispcsi2.c
@@ -667,7 +667,7 @@ static void csi2_isr_buffer(struct isp_csi2_device *csi2)
667 667
668 csi2_ctx_enable(isp, csi2, 0, 0); 668 csi2_ctx_enable(isp, csi2, 0, 0);
669 669
670 buffer = omap3isp_video_buffer_next(&csi2->video_out, 0); 670 buffer = omap3isp_video_buffer_next(&csi2->video_out);
671 671
672 /* 672 /*
673 * Let video queue operation restart engine if there is an underrun 673 * Let video queue operation restart engine if there is an underrun
@@ -727,17 +727,15 @@ static void csi2_isr_ctx(struct isp_csi2_device *csi2,
727 727
728/* 728/*
729 * omap3isp_csi2_isr - CSI2 interrupt handling. 729 * omap3isp_csi2_isr - CSI2 interrupt handling.
730 *
731 * Return -EIO on Transmission error
732 */ 730 */
733int omap3isp_csi2_isr(struct isp_csi2_device *csi2) 731void omap3isp_csi2_isr(struct isp_csi2_device *csi2)
734{ 732{
733 struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity);
735 u32 csi2_irqstatus, cpxio1_irqstatus; 734 u32 csi2_irqstatus, cpxio1_irqstatus;
736 struct isp_device *isp = csi2->isp; 735 struct isp_device *isp = csi2->isp;
737 int retval = 0;
738 736
739 if (!csi2->available) 737 if (!csi2->available)
740 return -ENODEV; 738 return;
741 739
742 csi2_irqstatus = isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQSTATUS); 740 csi2_irqstatus = isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQSTATUS);
743 isp_reg_writel(isp, csi2_irqstatus, csi2->regs1, ISPCSI2_IRQSTATUS); 741 isp_reg_writel(isp, csi2_irqstatus, csi2->regs1, ISPCSI2_IRQSTATUS);
@@ -750,7 +748,7 @@ int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
750 csi2->regs1, ISPCSI2_PHY_IRQSTATUS); 748 csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
751 dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ " 749 dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ "
752 "%x\n", cpxio1_irqstatus); 750 "%x\n", cpxio1_irqstatus);
753 retval = -EIO; 751 pipe->error = true;
754 } 752 }
755 753
756 if (csi2_irqstatus & (ISPCSI2_IRQSTATUS_OCP_ERR_IRQ | 754 if (csi2_irqstatus & (ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
@@ -775,11 +773,11 @@ int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
775 ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ) ? 1 : 0, 773 ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ) ? 1 : 0,
776 (csi2_irqstatus & 774 (csi2_irqstatus &
777 ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ) ? 1 : 0); 775 ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ) ? 1 : 0);
778 retval = -EIO; 776 pipe->error = true;
779 } 777 }
780 778
781 if (omap3isp_module_sync_is_stopping(&csi2->wait, &csi2->stopping)) 779 if (omap3isp_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
782 return 0; 780 return;
783 781
784 /* Successful cases */ 782 /* Successful cases */
785 if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0)) 783 if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0))
@@ -787,8 +785,6 @@ int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
787 785
788 if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ) 786 if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
789 dev_dbg(isp->dev, "CSI2: ECC correction done\n"); 787 dev_dbg(isp->dev, "CSI2: ECC correction done\n");
790
791 return retval;
792} 788}
793 789
794/* ----------------------------------------------------------------------------- 790/* -----------------------------------------------------------------------------
diff --git a/drivers/media/video/omap3isp/ispcsi2.h b/drivers/media/video/omap3isp/ispcsi2.h
index 456fb7fb8a0f..885ad79a7678 100644
--- a/drivers/media/video/omap3isp/ispcsi2.h
+++ b/drivers/media/video/omap3isp/ispcsi2.h
@@ -156,7 +156,7 @@ struct isp_csi2_device {
156 atomic_t stopping; 156 atomic_t stopping;
157}; 157};
158 158
159int omap3isp_csi2_isr(struct isp_csi2_device *csi2); 159void omap3isp_csi2_isr(struct isp_csi2_device *csi2);
160int omap3isp_csi2_reset(struct isp_csi2_device *csi2); 160int omap3isp_csi2_reset(struct isp_csi2_device *csi2);
161int omap3isp_csi2_init(struct isp_device *isp); 161int omap3isp_csi2_init(struct isp_device *isp);
162void omap3isp_csi2_cleanup(struct isp_device *isp); 162void omap3isp_csi2_cleanup(struct isp_device *isp);
diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c
index 28a123273a25..6d0fb2c8c26d 100644
--- a/drivers/media/video/omap3isp/isppreview.c
+++ b/drivers/media/video/omap3isp/isppreview.c
@@ -1404,16 +1404,14 @@ static void preview_isr_buffer(struct isp_prev_device *prev)
1404 int restart = 0; 1404 int restart = 0;
1405 1405
1406 if (prev->input == PREVIEW_INPUT_MEMORY) { 1406 if (prev->input == PREVIEW_INPUT_MEMORY) {
1407 buffer = omap3isp_video_buffer_next(&prev->video_in, 1407 buffer = omap3isp_video_buffer_next(&prev->video_in);
1408 prev->error);
1409 if (buffer != NULL) 1408 if (buffer != NULL)
1410 preview_set_inaddr(prev, buffer->isp_addr); 1409 preview_set_inaddr(prev, buffer->isp_addr);
1411 pipe->state |= ISP_PIPELINE_IDLE_INPUT; 1410 pipe->state |= ISP_PIPELINE_IDLE_INPUT;
1412 } 1411 }
1413 1412
1414 if (prev->output & PREVIEW_OUTPUT_MEMORY) { 1413 if (prev->output & PREVIEW_OUTPUT_MEMORY) {
1415 buffer = omap3isp_video_buffer_next(&prev->video_out, 1414 buffer = omap3isp_video_buffer_next(&prev->video_out);
1416 prev->error);
1417 if (buffer != NULL) { 1415 if (buffer != NULL) {
1418 preview_set_outaddr(prev, buffer->isp_addr); 1416 preview_set_outaddr(prev, buffer->isp_addr);
1419 restart = 1; 1417 restart = 1;
@@ -1440,8 +1438,6 @@ static void preview_isr_buffer(struct isp_prev_device *prev)
1440 default: 1438 default:
1441 return; 1439 return;
1442 } 1440 }
1443
1444 prev->error = 0;
1445} 1441}
1446 1442
1447/* 1443/*
@@ -1565,7 +1561,6 @@ static int preview_set_stream(struct v4l2_subdev *sd, int enable)
1565 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW); 1561 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
1566 preview_configure(prev); 1562 preview_configure(prev);
1567 atomic_set(&prev->stopping, 0); 1563 atomic_set(&prev->stopping, 0);
1568 prev->error = 0;
1569 preview_print_status(prev); 1564 preview_print_status(prev);
1570 } 1565 }
1571 1566
diff --git a/drivers/media/video/omap3isp/isppreview.h b/drivers/media/video/omap3isp/isppreview.h
index f54e775c2df4..09686607973c 100644
--- a/drivers/media/video/omap3isp/isppreview.h
+++ b/drivers/media/video/omap3isp/isppreview.h
@@ -157,7 +157,6 @@ struct isptables_update {
157 * @output: Bitmask of the active output 157 * @output: Bitmask of the active output
158 * @video_in: Input video entity 158 * @video_in: Input video entity
159 * @video_out: Output video entity 159 * @video_out: Output video entity
160 * @error: A hardware error occurred during capture
161 * @params: Module configuration data 160 * @params: Module configuration data
162 * @shadow_update: If set, update the hardware configured in the next interrupt 161 * @shadow_update: If set, update the hardware configured in the next interrupt
163 * @underrun: Whether the preview entity has queued buffers on the output 162 * @underrun: Whether the preview entity has queued buffers on the output
@@ -179,7 +178,6 @@ struct isp_prev_device {
179 unsigned int output; 178 unsigned int output;
180 struct isp_video video_in; 179 struct isp_video video_in;
181 struct isp_video video_out; 180 struct isp_video video_out;
182 unsigned int error;
183 181
184 struct prev_params params; 182 struct prev_params params;
185 unsigned int shadow_update:1; 183 unsigned int shadow_update:1;
diff --git a/drivers/media/video/omap3isp/ispresizer.c b/drivers/media/video/omap3isp/ispresizer.c
index 50e593bfcfaf..6958a9e3dc22 100644
--- a/drivers/media/video/omap3isp/ispresizer.c
+++ b/drivers/media/video/omap3isp/ispresizer.c
@@ -1038,7 +1038,7 @@ static void resizer_isr_buffer(struct isp_res_device *res)
1038 /* Complete the output buffer and, if reading from memory, the input 1038 /* Complete the output buffer and, if reading from memory, the input
1039 * buffer. 1039 * buffer.
1040 */ 1040 */
1041 buffer = omap3isp_video_buffer_next(&res->video_out, res->error); 1041 buffer = omap3isp_video_buffer_next(&res->video_out);
1042 if (buffer != NULL) { 1042 if (buffer != NULL) {
1043 resizer_set_outaddr(res, buffer->isp_addr); 1043 resizer_set_outaddr(res, buffer->isp_addr);
1044 restart = 1; 1044 restart = 1;
@@ -1047,7 +1047,7 @@ static void resizer_isr_buffer(struct isp_res_device *res)
1047 pipe->state |= ISP_PIPELINE_IDLE_OUTPUT; 1047 pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
1048 1048
1049 if (res->input == RESIZER_INPUT_MEMORY) { 1049 if (res->input == RESIZER_INPUT_MEMORY) {
1050 buffer = omap3isp_video_buffer_next(&res->video_in, 0); 1050 buffer = omap3isp_video_buffer_next(&res->video_in);
1051 if (buffer != NULL) 1051 if (buffer != NULL)
1052 resizer_set_inaddr(res, buffer->isp_addr); 1052 resizer_set_inaddr(res, buffer->isp_addr);
1053 pipe->state |= ISP_PIPELINE_IDLE_INPUT; 1053 pipe->state |= ISP_PIPELINE_IDLE_INPUT;
@@ -1064,8 +1064,6 @@ static void resizer_isr_buffer(struct isp_res_device *res)
1064 if (restart) 1064 if (restart)
1065 resizer_enable_oneshot(res); 1065 resizer_enable_oneshot(res);
1066 } 1066 }
1067
1068 res->error = 0;
1069} 1067}
1070 1068
1071/* 1069/*
@@ -1154,7 +1152,6 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
1154 1152
1155 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_RESIZER); 1153 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_RESIZER);
1156 resizer_configure(res); 1154 resizer_configure(res);
1157 res->error = 0;
1158 resizer_print_status(res); 1155 resizer_print_status(res);
1159 } 1156 }
1160 1157
diff --git a/drivers/media/video/omap3isp/ispresizer.h b/drivers/media/video/omap3isp/ispresizer.h
index 76abc2e42126..70c1c0e1bbdf 100644
--- a/drivers/media/video/omap3isp/ispresizer.h
+++ b/drivers/media/video/omap3isp/ispresizer.h
@@ -107,7 +107,6 @@ struct isp_res_device {
107 enum resizer_input_entity input; 107 enum resizer_input_entity input;
108 struct isp_video video_in; 108 struct isp_video video_in;
109 struct isp_video video_out; 109 struct isp_video video_out;
110 unsigned int error;
111 110
112 u32 addr_base; /* stored source buffer address in memory mode */ 111 u32 addr_base; /* stored source buffer address in memory mode */
113 u32 crop_offset; /* additional offset for crop in memory mode */ 112 u32 crop_offset; /* additional offset for crop in memory mode */
diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c
index ffe7ce9eb4bc..ffb9f00b391c 100644
--- a/drivers/media/video/omap3isp/ispvideo.c
+++ b/drivers/media/video/omap3isp/ispvideo.c
@@ -580,21 +580,20 @@ static const struct isp_video_queue_operations isp_video_queue_ops = {
580/* 580/*
581 * omap3isp_video_buffer_next - Complete the current buffer and return the next 581 * omap3isp_video_buffer_next - Complete the current buffer and return the next
582 * @video: ISP video object 582 * @video: ISP video object
583 * @error: Whether an error occurred during capture
584 * 583 *
585 * Remove the current video buffer from the DMA queue and fill its timestamp, 584 * Remove the current video buffer from the DMA queue and fill its timestamp,
586 * field count and state fields before waking up its completion handler. 585 * field count and state fields before waking up its completion handler.
587 * 586 *
588 * The buffer state is set to VIDEOBUF_DONE if no error occurred (@error is 0) 587 * For capture video nodes the buffer state is set to ISP_BUF_STATE_DONE if no
589 * or VIDEOBUF_ERROR otherwise (@error is non-zero). 588 * error has been flagged in the pipeline, or to ISP_BUF_STATE_ERROR otherwise.
589 * For video output nodes the buffer state is always set to ISP_BUF_STATE_DONE.
590 * 590 *
591 * The DMA queue is expected to contain at least one buffer. 591 * The DMA queue is expected to contain at least one buffer.
592 * 592 *
593 * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is 593 * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is
594 * empty. 594 * empty.
595 */ 595 */
596struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video, 596struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
597 unsigned int error)
598{ 597{
599 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity); 598 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
600 struct isp_video_queue *queue = video->queue; 599 struct isp_video_queue *queue = video->queue;
@@ -629,7 +628,13 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
629 else 628 else
630 buf->vbuf.sequence = atomic_read(&pipe->frame_number); 629 buf->vbuf.sequence = atomic_read(&pipe->frame_number);
631 630
632 buf->state = error ? ISP_BUF_STATE_ERROR : ISP_BUF_STATE_DONE; 631 /* Report pipeline errors to userspace on the capture device side. */
632 if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
633 buf->state = ISP_BUF_STATE_ERROR;
634 pipe->error = false;
635 } else {
636 buf->state = ISP_BUF_STATE_DONE;
637 }
633 638
634 wake_up(&buf->wait); 639 wake_up(&buf->wait);
635 640
@@ -1015,6 +1020,8 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
1015 if (ret < 0) 1020 if (ret < 0)
1016 goto error; 1021 goto error;
1017 1022
1023 pipe->error = false;
1024
1018 spin_lock_irqsave(&pipe->lock, flags); 1025 spin_lock_irqsave(&pipe->lock, flags);
1019 pipe->state &= ~ISP_PIPELINE_STREAM; 1026 pipe->state &= ~ISP_PIPELINE_STREAM;
1020 pipe->state |= state; 1027 pipe->state |= state;
diff --git a/drivers/media/video/omap3isp/ispvideo.h b/drivers/media/video/omap3isp/ispvideo.h
index 08cbfa144e6e..d91bdb919be0 100644
--- a/drivers/media/video/omap3isp/ispvideo.h
+++ b/drivers/media/video/omap3isp/ispvideo.h
@@ -85,6 +85,10 @@ enum isp_pipeline_state {
85 ISP_PIPELINE_STREAM = 64, 85 ISP_PIPELINE_STREAM = 64,
86}; 86};
87 87
88/*
89 * struct isp_pipeline - An ISP hardware pipeline
90 * @error: A hardware error occurred during capture
91 */
88struct isp_pipeline { 92struct isp_pipeline {
89 struct media_pipeline pipe; 93 struct media_pipeline pipe;
90 spinlock_t lock; /* Pipeline state and queue flags */ 94 spinlock_t lock; /* Pipeline state and queue flags */
@@ -96,6 +100,7 @@ struct isp_pipeline {
96 unsigned int max_rate; 100 unsigned int max_rate;
97 atomic_t frame_number; 101 atomic_t frame_number;
98 bool do_propagation; /* of frame number */ 102 bool do_propagation; /* of frame number */
103 bool error;
99 struct v4l2_fract max_timeperframe; 104 struct v4l2_fract max_timeperframe;
100}; 105};
101 106
@@ -194,8 +199,7 @@ void omap3isp_video_cleanup(struct isp_video *video);
194int omap3isp_video_register(struct isp_video *video, 199int omap3isp_video_register(struct isp_video *video,
195 struct v4l2_device *vdev); 200 struct v4l2_device *vdev);
196void omap3isp_video_unregister(struct isp_video *video); 201void omap3isp_video_unregister(struct isp_video *video);
197struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video, 202struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video);
198 unsigned int error);
199void omap3isp_video_resume(struct isp_video *video, int continuous); 203void omap3isp_video_resume(struct isp_video *video, int continuous);
200struct media_pad *omap3isp_video_remote_pad(struct isp_video *video); 204struct media_pad *omap3isp_video_remote_pad(struct isp_video *video);
201 205