|
@@ -47,29 +47,59 @@
|
|
|
|
|
|
static struct isp_format_info formats[] = {
|
|
|
{ V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
|
|
|
- V4L2_MBUS_FMT_Y8_1X8, V4L2_PIX_FMT_GREY, 8, },
|
|
|
+ V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
|
|
|
+ V4L2_PIX_FMT_GREY, 8, },
|
|
|
+ { V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10,
|
|
|
+ V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8,
|
|
|
+ V4L2_PIX_FMT_Y10, 10, },
|
|
|
+ { V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10,
|
|
|
+ V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8,
|
|
|
+ V4L2_PIX_FMT_Y12, 12, },
|
|
|
+ { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
|
|
|
+ V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
|
|
|
+ V4L2_PIX_FMT_SBGGR8, 8, },
|
|
|
+ { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
|
|
|
+ V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
|
|
|
+ V4L2_PIX_FMT_SGBRG8, 8, },
|
|
|
+ { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
|
|
|
+ V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
|
|
|
+ V4L2_PIX_FMT_SGRBG8, 8, },
|
|
|
+ { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
|
|
|
+ V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
|
|
|
+ V4L2_PIX_FMT_SRGGB8, 8, },
|
|
|
{ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
|
|
|
- V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
|
|
|
+ V4L2_MBUS_FMT_SGRBG10_1X10, 0,
|
|
|
+ V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
|
|
|
{ V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
|
|
|
- V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10, 10, },
|
|
|
+ V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8,
|
|
|
+ V4L2_PIX_FMT_SBGGR10, 10, },
|
|
|
{ V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
|
|
|
- V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10, 10, },
|
|
|
+ V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8,
|
|
|
+ V4L2_PIX_FMT_SGBRG10, 10, },
|
|
|
{ V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
|
|
|
- V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10, 10, },
|
|
|
+ V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8,
|
|
|
+ V4L2_PIX_FMT_SGRBG10, 10, },
|
|
|
{ V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
|
|
|
- V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10, 10, },
|
|
|
+ V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8,
|
|
|
+ V4L2_PIX_FMT_SRGGB10, 10, },
|
|
|
{ V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
|
|
|
- V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12, 12, },
|
|
|
+ V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8,
|
|
|
+ V4L2_PIX_FMT_SBGGR12, 12, },
|
|
|
{ V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
|
|
|
- V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12, 12, },
|
|
|
+ V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8,
|
|
|
+ V4L2_PIX_FMT_SGBRG12, 12, },
|
|
|
{ V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
|
|
|
- V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12, 12, },
|
|
|
+ V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8,
|
|
|
+ V4L2_PIX_FMT_SGRBG12, 12, },
|
|
|
{ V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
|
|
|
- V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12, 12, },
|
|
|
+ V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8,
|
|
|
+ V4L2_PIX_FMT_SRGGB12, 12, },
|
|
|
{ V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
|
|
|
- V4L2_MBUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_UYVY, 16, },
|
|
|
+ V4L2_MBUS_FMT_UYVY8_1X16, 0,
|
|
|
+ V4L2_PIX_FMT_UYVY, 16, },
|
|
|
{ V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
|
|
|
- V4L2_MBUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_YUYV, 16, },
|
|
|
+ V4L2_MBUS_FMT_YUYV8_1X16, 0,
|
|
|
+ V4L2_PIX_FMT_YUYV, 16, },
|
|
|
};
|
|
|
|
|
|
const struct isp_format_info *
|
|
@@ -85,6 +115,37 @@ omap3isp_video_format_info(enum v4l2_mbus_pixelcode code)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Decide whether desired output pixel code can be obtained with
|
|
|
+ * the lane shifter by shifting the input pixel code.
|
|
|
+ * @in: input pixelcode to shifter
|
|
|
+ * @out: output pixelcode from shifter
|
|
|
+ * @additional_shift: # of bits the sensor's LSB is offset from CAMEXT[0]
|
|
|
+ *
|
|
|
+ * return true if the combination is possible
|
|
|
+ * return false otherwise
|
|
|
+ */
|
|
|
+static bool isp_video_is_shiftable(enum v4l2_mbus_pixelcode in,
|
|
|
+ enum v4l2_mbus_pixelcode out,
|
|
|
+ unsigned int additional_shift)
|
|
|
+{
|
|
|
+ const struct isp_format_info *in_info, *out_info;
|
|
|
+
|
|
|
+ if (in == out)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ in_info = omap3isp_video_format_info(in);
|
|
|
+ out_info = omap3isp_video_format_info(out);
|
|
|
+
|
|
|
+ if ((in_info->flavor == 0) || (out_info->flavor == 0))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (in_info->flavor != out_info->flavor)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return in_info->bpp - out_info->bpp + additional_shift <= 6;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
|
|
|
* @video: ISP video instance
|
|
@@ -235,6 +296,7 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
|
|
|
return -EPIPE;
|
|
|
|
|
|
while (1) {
|
|
|
+ unsigned int shifter_link;
|
|
|
/* Retrieve the sink format */
|
|
|
pad = &subdev->entity.pads[0];
|
|
|
if (!(pad->flags & MEDIA_PAD_FL_SINK))
|
|
@@ -263,6 +325,10 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
|
|
|
return -ENOSPC;
|
|
|
}
|
|
|
|
|
|
+ /* If sink pad is on CCDC, the link has the lane shifter
|
|
|
+ * in the middle of it. */
|
|
|
+ shifter_link = subdev == &isp->isp_ccdc.subdev;
|
|
|
+
|
|
|
/* Retrieve the source format */
|
|
|
pad = media_entity_remote_source(pad);
|
|
|
if (pad == NULL ||
|
|
@@ -278,10 +344,24 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
|
|
|
return -EPIPE;
|
|
|
|
|
|
/* Check if the two ends match */
|
|
|
- if (fmt_source.format.code != fmt_sink.format.code ||
|
|
|
- fmt_source.format.width != fmt_sink.format.width ||
|
|
|
+ if (fmt_source.format.width != fmt_sink.format.width ||
|
|
|
fmt_source.format.height != fmt_sink.format.height)
|
|
|
return -EPIPE;
|
|
|
+
|
|
|
+ if (shifter_link) {
|
|
|
+ unsigned int parallel_shift = 0;
|
|
|
+ if (isp->isp_ccdc.input == CCDC_INPUT_PARALLEL) {
|
|
|
+ struct isp_parallel_platform_data *pdata =
|
|
|
+ &((struct isp_v4l2_subdevs_group *)
|
|
|
+ subdev->host_priv)->bus.parallel;
|
|
|
+ parallel_shift = pdata->data_lane_shift * 2;
|
|
|
+ }
|
|
|
+ if (!isp_video_is_shiftable(fmt_source.format.code,
|
|
|
+ fmt_sink.format.code,
|
|
|
+ parallel_shift))
|
|
|
+ return -EPIPE;
|
|
|
+ } else if (fmt_source.format.code != fmt_sink.format.code)
|
|
|
+ return -EPIPE;
|
|
|
}
|
|
|
|
|
|
return 0;
|