|
@@ -970,10 +970,16 @@ static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
|
|
|
|
|
|
if (format->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
|
|
|
format->code == V4L2_MBUS_FMT_UYVY8_2X8) {
|
|
|
- /* The bridge is enabled for YUV8 formats. Configure the input
|
|
|
- * mode accordingly.
|
|
|
+ /* According to the OMAP3 TRM the input mode only affects SYNC
|
|
|
+ * mode, enabling BT.656 mode should take precedence. However,
|
|
|
+ * in practice setting the input mode to YCbCr data on 8 bits
|
|
|
+ * seems to be required in BT.656 mode. In SYNC mode set it to
|
|
|
+ * YCbCr on 16 bits as the bridge is enabled in that case.
|
|
|
*/
|
|
|
- syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
|
|
|
+ if (ccdc->bt656)
|
|
|
+ syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR8;
|
|
|
+ else
|
|
|
+ syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
|
|
|
}
|
|
|
|
|
|
switch (data_size) {
|
|
@@ -997,7 +1003,10 @@ static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
|
|
|
if (pdata && pdata->hs_pol)
|
|
|
syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
|
|
|
|
|
|
- if (pdata && pdata->vs_pol)
|
|
|
+ /* The polarity of the vertical sync signal output by the BT.656
|
|
|
+ * decoder is not documented and seems to be active low.
|
|
|
+ */
|
|
|
+ if ((pdata && pdata->vs_pol) || ccdc->bt656)
|
|
|
syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
|
|
|
|
|
|
if (pdata && pdata->fld_pol)
|
|
@@ -1015,8 +1024,16 @@ static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
|
|
|
isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
|
|
|
ISPCCDC_CFG_Y8POS);
|
|
|
|
|
|
- isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
|
|
|
- ISPCCDC_REC656IF_R656ON);
|
|
|
+ /* Enable or disable BT.656 mode, including error correction for the
|
|
|
+ * synchronization codes.
|
|
|
+ */
|
|
|
+ if (ccdc->bt656)
|
|
|
+ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
|
|
|
+ ISPCCDC_REC656IF_R656ON | ISPCCDC_REC656IF_ECCFVH);
|
|
|
+ else
|
|
|
+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
|
|
|
+ ISPCCDC_REC656IF_R656ON | ISPCCDC_REC656IF_ECCFVH);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/* CCDC formats descriptions */
|
|
@@ -1107,20 +1124,32 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
|
|
|
unsigned long flags;
|
|
|
unsigned int bridge;
|
|
|
unsigned int shift;
|
|
|
+ unsigned int nph;
|
|
|
+ unsigned int sph;
|
|
|
u32 syn_mode;
|
|
|
u32 ccdc_pattern;
|
|
|
|
|
|
+ ccdc->bt656 = false;
|
|
|
+
|
|
|
pad = media_entity_remote_pad(&ccdc->pads[CCDC_PAD_SINK]);
|
|
|
sensor = media_entity_to_v4l2_subdev(pad->entity);
|
|
|
- if (ccdc->input == CCDC_INPUT_PARALLEL)
|
|
|
+ if (ccdc->input == CCDC_INPUT_PARALLEL) {
|
|
|
+ struct v4l2_mbus_config cfg;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = v4l2_subdev_call(sensor, video, g_mbus_config, &cfg);
|
|
|
+ if (!ret)
|
|
|
+ ccdc->bt656 = cfg.type == V4L2_MBUS_BT656;
|
|
|
+
|
|
|
pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
|
|
|
->bus.parallel;
|
|
|
+ }
|
|
|
|
|
|
/* CCDC_PAD_SINK */
|
|
|
format = &ccdc->formats[CCDC_PAD_SINK];
|
|
|
|
|
|
/* Compute the lane shifter shift value and enable the bridge when the
|
|
|
- * input format is YUV.
|
|
|
+ * input format is a non-BT.656 YUV variant.
|
|
|
*/
|
|
|
fmt_src.pad = pad->index;
|
|
|
fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
|
@@ -1133,7 +1162,9 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
|
|
|
depth_out = fmt_info->width;
|
|
|
shift = depth_in - depth_out;
|
|
|
|
|
|
- if (fmt_info->code == V4L2_MBUS_FMT_YUYV8_2X8)
|
|
|
+ if (ccdc->bt656)
|
|
|
+ bridge = ISPCTRL_PAR_BRIDGE_DISABLE;
|
|
|
+ else if (fmt_info->code == V4L2_MBUS_FMT_YUYV8_2X8)
|
|
|
bridge = ISPCTRL_PAR_BRIDGE_LENDIAN;
|
|
|
else if (fmt_info->code == V4L2_MBUS_FMT_UYVY8_2X8)
|
|
|
bridge = ISPCTRL_PAR_BRIDGE_BENDIAN;
|
|
@@ -1194,10 +1225,24 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
|
|
|
format = &ccdc->formats[CCDC_PAD_SOURCE_OF];
|
|
|
crop = &ccdc->crop;
|
|
|
|
|
|
- isp_reg_writel(isp, (crop->left << ISPCCDC_HORZ_INFO_SPH_SHIFT) |
|
|
|
- ((crop->width - 1) << ISPCCDC_HORZ_INFO_NPH_SHIFT),
|
|
|
+ /* The horizontal coordinates are expressed in pixel clock cycles. We
|
|
|
+ * need two cycles per pixel in BT.656 mode, and one cycle per pixel in
|
|
|
+ * SYNC mode regardless of the format as the bridge is enabled for YUV
|
|
|
+ * formats in that case.
|
|
|
+ */
|
|
|
+ if (ccdc->bt656) {
|
|
|
+ sph = crop->left * 2;
|
|
|
+ nph = crop->width * 2 - 1;
|
|
|
+ } else {
|
|
|
+ sph = crop->left;
|
|
|
+ nph = crop->width - 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ isp_reg_writel(isp, (sph << ISPCCDC_HORZ_INFO_SPH_SHIFT) |
|
|
|
+ (nph << ISPCCDC_HORZ_INFO_NPH_SHIFT),
|
|
|
OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO);
|
|
|
- isp_reg_writel(isp, crop->top << ISPCCDC_VERT_START_SLV0_SHIFT,
|
|
|
+ isp_reg_writel(isp, (crop->top << ISPCCDC_VERT_START_SLV0_SHIFT) |
|
|
|
+ (crop->top << ISPCCDC_VERT_START_SLV1_SHIFT),
|
|
|
OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START);
|
|
|
isp_reg_writel(isp, (crop->height - 1)
|
|
|
<< ISPCCDC_VERT_LINES_NLV_SHIFT,
|
|
@@ -1225,8 +1270,11 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
|
|
|
isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
|
|
|
ISPCCDC_CFG_BSWD);
|
|
|
|
|
|
- /* Use PACK8 mode for 1byte per pixel formats. */
|
|
|
- if (omap3isp_video_format_info(format->code)->width <= 8)
|
|
|
+ /* Use PACK8 mode for 1byte per pixel formats. Check for BT.656 mode
|
|
|
+ * explicitly as the driver reports 1X16 instead of 2X8 at the OF pad
|
|
|
+ * for simplicity.
|
|
|
+ */
|
|
|
+ if (omap3isp_video_format_info(format->code)->width <= 8 || ccdc->bt656)
|
|
|
syn_mode |= ISPCCDC_SYN_MODE_PACK8;
|
|
|
else
|
|
|
syn_mode &= ~ISPCCDC_SYN_MODE_PACK8;
|
|
@@ -1598,6 +1646,16 @@ static void ccdc_vd1_isr(struct isp_ccdc_device *ccdc)
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
|
|
|
+ /* In BT.656 mode the CCDC doesn't generate an HS/VS interrupt. We thus
|
|
|
+ * need to increment the frame counter here.
|
|
|
+ */
|
|
|
+ if (ccdc->bt656) {
|
|
|
+ struct isp_pipeline *pipe =
|
|
|
+ to_isp_pipeline(&ccdc->subdev.entity);
|
|
|
+
|
|
|
+ atomic_inc(&pipe->frame_number);
|
|
|
+ }
|
|
|
+
|
|
|
spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
|
|
|
|
|
|
/*
|
|
@@ -1885,8 +1943,12 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
|
|
|
field = fmt->field;
|
|
|
*fmt = *__ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
|
|
|
|
|
|
- /* YUV formats are converted from 2X8 to 1X16 by the bridge and
|
|
|
- * can be byte-swapped.
|
|
|
+ /* In SYNC mode the bridge converts YUV formats from 2X8 to
|
|
|
+ * 1X16. In BT.656 no such conversion occurs. As we don't know
|
|
|
+ * at this point whether the source will use SYNC or BT.656 mode
|
|
|
+ * let's pretend the conversion always occurs. The CCDC will be
|
|
|
+ * configured to pack bytes in BT.656, hiding the inaccuracy.
|
|
|
+ * In all cases bytes can be swapped.
|
|
|
*/
|
|
|
if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
|
|
|
fmt->code == V4L2_MBUS_FMT_UYVY8_2X8) {
|