aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/omap3isp
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2014-06-10 08:41:57 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-08-21 16:25:16 -0400
commit93456527b4488510d87a523028b3bb73dfdd7669 (patch)
tree88554f4c19fdc522bcf91c651e05027af273a721 /drivers/media/platform/omap3isp
parentfd93c10afe383d7c28b5edffa29f92b6dae55191 (diff)
[media] omap3isp: ccdc: Fix freeze when a short frame is received
In BT.656 mode the synchronization signals are generated by the CCDC from the embedded sync codes. The VD0 and VD1 interrupts are thus only triggered when the CCDC is enabled, unlike external sync mode where the line counter runs even when the CCDC is stopped. We can't disable the CCDC at VD1 time, as no VD0 interrupt would be generated for a short frame, which would result in the CCDC being stopped and no VD interrupt generated anymore. The CCDC is stopped from the VD0 interrupt handler instead for BT.656. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Tested-by: Enrico Butera <ebutera@users.sourceforge.net> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/platform/omap3isp')
-rw-r--r--drivers/media/platform/omap3isp/ispccdc.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c
index 112bced5af99..ff2ea2bf31e4 100644
--- a/drivers/media/platform/omap3isp/ispccdc.c
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -1647,10 +1647,27 @@ static void ccdc_vd0_isr(struct isp_ccdc_device *ccdc)
1647 atomic_inc(&pipe->frame_number); 1647 atomic_inc(&pipe->frame_number);
1648 } 1648 }
1649 1649
1650 /* Emulate a VD1 interrupt for BT.656 mode, as we can't stop the CCDC in
1651 * the VD1 interrupt handler in that mode without risking a CCDC stall
1652 * if a short frame is received.
1653 */
1654 if (ccdc->bt656) {
1655 spin_lock_irqsave(&ccdc->lock, flags);
1656 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS &&
1657 ccdc->output & CCDC_OUTPUT_MEMORY) {
1658 if (ccdc->lsc.state != LSC_STATE_STOPPED)
1659 __ccdc_lsc_enable(ccdc, 0);
1660 __ccdc_enable(ccdc, 0);
1661 }
1662 ccdc_handle_stopping(ccdc, CCDC_EVENT_VD1);
1663 spin_unlock_irqrestore(&ccdc->lock, flags);
1664 }
1665
1650 if (ccdc->output & CCDC_OUTPUT_MEMORY) 1666 if (ccdc->output & CCDC_OUTPUT_MEMORY)
1651 restart = ccdc_isr_buffer(ccdc); 1667 restart = ccdc_isr_buffer(ccdc);
1652 1668
1653 spin_lock_irqsave(&ccdc->lock, flags); 1669 spin_lock_irqsave(&ccdc->lock, flags);
1670
1654 if (ccdc_handle_stopping(ccdc, CCDC_EVENT_VD0)) { 1671 if (ccdc_handle_stopping(ccdc, CCDC_EVENT_VD0)) {
1655 spin_unlock_irqrestore(&ccdc->lock, flags); 1672 spin_unlock_irqrestore(&ccdc->lock, flags);
1656 return; 1673 return;
@@ -1672,6 +1689,18 @@ static void ccdc_vd1_isr(struct isp_ccdc_device *ccdc)
1672{ 1689{
1673 unsigned long flags; 1690 unsigned long flags;
1674 1691
1692 /* In BT.656 mode the synchronization signals are generated by the CCDC
1693 * from the embedded sync codes. The VD0 and VD1 interrupts are thus
1694 * only triggered when the CCDC is enabled, unlike external sync mode
1695 * where the line counter runs even when the CCDC is stopped. We can't
1696 * disable the CCDC at VD1 time, as no VD0 interrupt would be generated
1697 * for a short frame, which would result in the CCDC being stopped and
1698 * no VD interrupt generated anymore. The CCDC is stopped from the VD0
1699 * interrupt handler instead for BT.656.
1700 */
1701 if (ccdc->bt656)
1702 return;
1703
1675 spin_lock_irqsave(&ccdc->lsc.req_lock, flags); 1704 spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
1676 1705
1677 /* 1706 /*