aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/omap3isp/ispvideo.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/omap3isp/ispvideo.c')
-rw-r--r--drivers/media/video/omap3isp/ispvideo.c108
1 files changed, 94 insertions, 14 deletions
diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c
index 208a7ec739d7..9cd8f1aa567b 100644
--- a/drivers/media/video/omap3isp/ispvideo.c
+++ b/drivers/media/video/omap3isp/ispvideo.c
@@ -47,29 +47,59 @@
47 47
48static struct isp_format_info formats[] = { 48static struct isp_format_info formats[] = {
49 { V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8, 49 { V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
50 V4L2_MBUS_FMT_Y8_1X8, V4L2_PIX_FMT_GREY, 8, }, 50 V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
51 V4L2_PIX_FMT_GREY, 8, },
52 { V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10,
53 V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8,
54 V4L2_PIX_FMT_Y10, 10, },
55 { V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10,
56 V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8,
57 V4L2_PIX_FMT_Y12, 12, },
58 { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
59 V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
60 V4L2_PIX_FMT_SBGGR8, 8, },
61 { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
62 V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
63 V4L2_PIX_FMT_SGBRG8, 8, },
64 { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
65 V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
66 V4L2_PIX_FMT_SGRBG8, 8, },
67 { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
68 V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
69 V4L2_PIX_FMT_SRGGB8, 8, },
51 { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, 70 { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
52 V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10DPCM8, 8, }, 71 V4L2_MBUS_FMT_SGRBG10_1X10, 0,
72 V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
53 { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10, 73 { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
54 V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10, 10, }, 74 V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8,
75 V4L2_PIX_FMT_SBGGR10, 10, },
55 { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10, 76 { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
56 V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10, 10, }, 77 V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8,
78 V4L2_PIX_FMT_SGBRG10, 10, },
57 { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10, 79 { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
58 V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10, 10, }, 80 V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8,
81 V4L2_PIX_FMT_SGRBG10, 10, },
59 { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10, 82 { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
60 V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10, 10, }, 83 V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8,
84 V4L2_PIX_FMT_SRGGB10, 10, },
61 { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10, 85 { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
62 V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12, 12, }, 86 V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8,
87 V4L2_PIX_FMT_SBGGR12, 12, },
63 { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10, 88 { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
64 V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12, 12, }, 89 V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8,
90 V4L2_PIX_FMT_SGBRG12, 12, },
65 { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10, 91 { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
66 V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12, 12, }, 92 V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8,
93 V4L2_PIX_FMT_SGRBG12, 12, },
67 { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10, 94 { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
68 V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12, 12, }, 95 V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8,
96 V4L2_PIX_FMT_SRGGB12, 12, },
69 { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16, 97 { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
70 V4L2_MBUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_UYVY, 16, }, 98 V4L2_MBUS_FMT_UYVY8_1X16, 0,
99 V4L2_PIX_FMT_UYVY, 16, },
71 { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16, 100 { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
72 V4L2_MBUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_YUYV, 16, }, 101 V4L2_MBUS_FMT_YUYV8_1X16, 0,
102 V4L2_PIX_FMT_YUYV, 16, },
73}; 103};
74 104
75const struct isp_format_info * 105const struct isp_format_info *
@@ -86,6 +116,37 @@ omap3isp_video_format_info(enum v4l2_mbus_pixelcode code)
86} 116}
87 117
88/* 118/*
119 * Decide whether desired output pixel code can be obtained with
120 * the lane shifter by shifting the input pixel code.
121 * @in: input pixelcode to shifter
122 * @out: output pixelcode from shifter
123 * @additional_shift: # of bits the sensor's LSB is offset from CAMEXT[0]
124 *
125 * return true if the combination is possible
126 * return false otherwise
127 */
128static bool isp_video_is_shiftable(enum v4l2_mbus_pixelcode in,
129 enum v4l2_mbus_pixelcode out,
130 unsigned int additional_shift)
131{
132 const struct isp_format_info *in_info, *out_info;
133
134 if (in == out)
135 return true;
136
137 in_info = omap3isp_video_format_info(in);
138 out_info = omap3isp_video_format_info(out);
139
140 if ((in_info->flavor == 0) || (out_info->flavor == 0))
141 return false;
142
143 if (in_info->flavor != out_info->flavor)
144 return false;
145
146 return in_info->bpp - out_info->bpp + additional_shift <= 6;
147}
148
149/*
89 * isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format 150 * isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
90 * @video: ISP video instance 151 * @video: ISP video instance
91 * @mbus: v4l2_mbus_framefmt format (input) 152 * @mbus: v4l2_mbus_framefmt format (input)
@@ -235,6 +296,7 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
235 return -EPIPE; 296 return -EPIPE;
236 297
237 while (1) { 298 while (1) {
299 unsigned int shifter_link;
238 /* Retrieve the sink format */ 300 /* Retrieve the sink format */
239 pad = &subdev->entity.pads[0]; 301 pad = &subdev->entity.pads[0];
240 if (!(pad->flags & MEDIA_PAD_FL_SINK)) 302 if (!(pad->flags & MEDIA_PAD_FL_SINK))
@@ -263,6 +325,10 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
263 return -ENOSPC; 325 return -ENOSPC;
264 } 326 }
265 327
328 /* If sink pad is on CCDC, the link has the lane shifter
329 * in the middle of it. */
330 shifter_link = subdev == &isp->isp_ccdc.subdev;
331
266 /* Retrieve the source format */ 332 /* Retrieve the source format */
267 pad = media_entity_remote_source(pad); 333 pad = media_entity_remote_source(pad);
268 if (pad == NULL || 334 if (pad == NULL ||
@@ -278,10 +344,24 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
278 return -EPIPE; 344 return -EPIPE;
279 345
280 /* Check if the two ends match */ 346 /* Check if the two ends match */
281 if (fmt_source.format.code != fmt_sink.format.code || 347 if (fmt_source.format.width != fmt_sink.format.width ||
282 fmt_source.format.width != fmt_sink.format.width ||
283 fmt_source.format.height != fmt_sink.format.height) 348 fmt_source.format.height != fmt_sink.format.height)
284 return -EPIPE; 349 return -EPIPE;
350
351 if (shifter_link) {
352 unsigned int parallel_shift = 0;
353 if (isp->isp_ccdc.input == CCDC_INPUT_PARALLEL) {
354 struct isp_parallel_platform_data *pdata =
355 &((struct isp_v4l2_subdevs_group *)
356 subdev->host_priv)->bus.parallel;
357 parallel_shift = pdata->data_lane_shift * 2;
358 }
359 if (!isp_video_is_shiftable(fmt_source.format.code,
360 fmt_sink.format.code,
361 parallel_shift))
362 return -EPIPE;
363 } else if (fmt_source.format.code != fmt_sink.format.code)
364 return -EPIPE;
285 } 365 }
286 366
287 return 0; 367 return 0;