[media] omap3isp: ccdc: Disable the video port when unused

The video port doesn't support YUV formats. Disable it when the CCDC
sink pad format is set to YUV instead of leaving it enabled and relying
on downstream modules not to process data they receive from the video
port.

Experiments showed that this fixes some of the CCDC failures to stop,
especially in BT.656 mode.

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>
This commit is contained in:
Laurent Pinchart 2014-06-10 11:51:34 -03:00 committed by Mauro Carvalho Chehab
parent 9de7af4d5b
commit aec2de0e93
1 changed files with 29 additions and 41 deletions

View File

@ -808,29 +808,48 @@ static void ccdc_config_vp(struct isp_ccdc_device *ccdc)
struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
struct isp_device *isp = to_isp_device(ccdc);
const struct isp_format_info *info;
struct v4l2_mbus_framefmt *format;
unsigned long l3_ick = pipe->l3_ick;
unsigned int max_div = isp->revision == ISP_REVISION_15_0 ? 64 : 8;
unsigned int div = 0;
u32 fmtcfg_vp;
u32 fmtcfg = ISPCCDC_FMTCFG_VPEN;
fmtcfg_vp = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG)
& ~(ISPCCDC_FMTCFG_VPIN_MASK | ISPCCDC_FMTCFG_VPIF_FRQ_MASK);
format = &ccdc->formats[CCDC_PAD_SOURCE_VP];
if (!format->code) {
/* Disable the video port when the input format isn't supported.
* This is indicated by a pixel code set to 0.
*/
isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
return;
}
isp_reg_writel(isp, (0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
(format->width << ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ);
isp_reg_writel(isp, (0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
((format->height + 1) << ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT);
isp_reg_writel(isp, (format->width << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
(format->height << ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
info = omap3isp_video_format_info(ccdc->formats[CCDC_PAD_SINK].code);
switch (info->width) {
case 8:
case 10:
fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
fmtcfg |= ISPCCDC_FMTCFG_VPIN_9_0;
break;
case 11:
fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
fmtcfg |= ISPCCDC_FMTCFG_VPIN_10_1;
break;
case 12:
fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
fmtcfg |= ISPCCDC_FMTCFG_VPIN_11_2;
break;
case 13:
fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
fmtcfg |= ISPCCDC_FMTCFG_VPIN_12_3;
break;
}
@ -840,24 +859,9 @@ static void ccdc_config_vp(struct isp_ccdc_device *ccdc)
div = l3_ick / pipe->external_rate;
div = clamp(div, 2U, max_div);
fmtcfg_vp |= (div - 2) << ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT;
fmtcfg |= (div - 2) << ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT;
isp_reg_writel(isp, fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
}
/*
* ccdc_enable_vp - Enable Video Port.
* @ccdc: Pointer to ISP CCDC device.
* @enable: 0 Disables VP, 1 Enables VP
*
* This is needed for outputting image to Preview, H3A and HIST ISP submodules.
*/
static void ccdc_enable_vp(struct isp_ccdc_device *ccdc, u8 enable)
{
struct isp_device *isp = to_isp_device(ccdc);
isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
ISPCCDC_FMTCFG_VPEN, enable ? ISPCCDC_FMTCFG_VPEN : 0);
isp_reg_writel(isp, fmtcfg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
}
/*
@ -1282,18 +1286,7 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
/* CCDC_PAD_SOURCE_VP */
format = &ccdc->formats[CCDC_PAD_SOURCE_VP];
isp_reg_writel(isp, (0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
(format->width << ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ);
isp_reg_writel(isp, (0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
((format->height + 1) << ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT);
isp_reg_writel(isp, (format->width << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
(format->height << ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
ccdc_config_vp(ccdc);
/* Lens shading correction. */
spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
@ -1837,11 +1830,6 @@ static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
ccdc_configure(ccdc);
/* TODO: Don't configure the video port if all of its output
* links are inactive.
*/
ccdc_config_vp(ccdc);
ccdc_enable_vp(ccdc, 1);
ccdc_print_status(ccdc);
}