aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/omap3isp
diff options
context:
space:
mode:
authorSakari Ailus <sakari.ailus@iki.fi>2012-02-25 18:42:07 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-14 07:53:28 -0400
commita6d7a62dcd1fccb3140100551b205315491eadc5 (patch)
treefe3fa7a1d902c0177c978e5e1625873a434fa37e /drivers/media/video/omap3isp
parent20d4ab7bea8e79bb330c2d52da9c245911ea29ed (diff)
[media] omap3isp: Move CCDC link validation to ccdc_link_validate()
Perform CCDC link validation in ccdc_link_validate() instead of isp_video_validate_pipeline(). Also perform maximum data rate check in isp_video_check_external_subdevs(). Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/omap3isp')
-rw-r--r--drivers/media/video/omap3isp/ispccdc.c65
-rw-r--r--drivers/media/video/omap3isp/ispvideo.c95
2 files changed, 76 insertions, 84 deletions
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c
index 080fe8b513b1..7e32331b60fb 100644
--- a/drivers/media/video/omap3isp/ispccdc.c
+++ b/drivers/media/video/omap3isp/ispccdc.c
@@ -2155,6 +2155,69 @@ static int ccdc_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
2155} 2155}
2156 2156
2157/* 2157/*
2158 * Decide whether desired output pixel code can be obtained with
2159 * the lane shifter by shifting the input pixel code.
2160 * @in: input pixelcode to shifter
2161 * @out: output pixelcode from shifter
2162 * @additional_shift: # of bits the sensor's LSB is offset from CAMEXT[0]
2163 *
2164 * return true if the combination is possible
2165 * return false otherwise
2166 */
2167static bool ccdc_is_shiftable(enum v4l2_mbus_pixelcode in,
2168 enum v4l2_mbus_pixelcode out,
2169 unsigned int additional_shift)
2170{
2171 const struct isp_format_info *in_info, *out_info;
2172
2173 if (in == out)
2174 return true;
2175
2176 in_info = omap3isp_video_format_info(in);
2177 out_info = omap3isp_video_format_info(out);
2178
2179 if ((in_info->flavor == 0) || (out_info->flavor == 0))
2180 return false;
2181
2182 if (in_info->flavor != out_info->flavor)
2183 return false;
2184
2185 return in_info->bpp - out_info->bpp + additional_shift <= 6;
2186}
2187
2188static int ccdc_link_validate(struct v4l2_subdev *sd,
2189 struct media_link *link,
2190 struct v4l2_subdev_format *source_fmt,
2191 struct v4l2_subdev_format *sink_fmt)
2192{
2193 struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
2194 unsigned long parallel_shift;
2195
2196 /* Check if the two ends match */
2197 if (source_fmt->format.width != sink_fmt->format.width ||
2198 source_fmt->format.height != sink_fmt->format.height)
2199 return -EPIPE;
2200
2201 /* We've got a parallel sensor here. */
2202 if (ccdc->input == CCDC_INPUT_PARALLEL) {
2203 struct isp_parallel_platform_data *pdata =
2204 &((struct isp_v4l2_subdevs_group *)
2205 media_entity_to_v4l2_subdev(link->source->entity)
2206 ->host_priv)->bus.parallel;
2207 parallel_shift = pdata->data_lane_shift * 2;
2208 } else {
2209 parallel_shift = 0;
2210 }
2211
2212 /* Lane shifter may be used to drop bits on CCDC sink pad */
2213 if (!ccdc_is_shiftable(source_fmt->format.code,
2214 sink_fmt->format.code, parallel_shift))
2215 return -EPIPE;
2216
2217 return 0;
2218}
2219
2220/*
2158 * ccdc_init_formats - Initialize formats on all pads 2221 * ccdc_init_formats - Initialize formats on all pads
2159 * @sd: ISP CCDC V4L2 subdevice 2222 * @sd: ISP CCDC V4L2 subdevice
2160 * @fh: V4L2 subdev file handle 2223 * @fh: V4L2 subdev file handle
@@ -2198,6 +2261,7 @@ static const struct v4l2_subdev_pad_ops ccdc_v4l2_pad_ops = {
2198 .set_fmt = ccdc_set_format, 2261 .set_fmt = ccdc_set_format,
2199 .get_selection = ccdc_get_selection, 2262 .get_selection = ccdc_get_selection,
2200 .set_selection = ccdc_set_selection, 2263 .set_selection = ccdc_set_selection,
2264 .link_validate = ccdc_link_validate,
2201}; 2265};
2202 2266
2203/* V4L2 subdev operations */ 2267/* V4L2 subdev operations */
@@ -2307,6 +2371,7 @@ static int ccdc_link_setup(struct media_entity *entity,
2307/* media operations */ 2371/* media operations */
2308static const struct media_entity_operations ccdc_media_ops = { 2372static const struct media_entity_operations ccdc_media_ops = {
2309 .link_setup = ccdc_link_setup, 2373 .link_setup = ccdc_link_setup,
2374 .link_validate = v4l2_subdev_link_validate,
2310}; 2375};
2311 2376
2312void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc) 2377void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc)
diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c
index 66bc6749de66..b37379d39cdd 100644
--- a/drivers/media/video/omap3isp/ispvideo.c
+++ b/drivers/media/video/omap3isp/ispvideo.c
@@ -130,37 +130,6 @@ omap3isp_video_format_info(enum v4l2_mbus_pixelcode code)
130} 130}
131 131
132/* 132/*
133 * Decide whether desired output pixel code can be obtained with
134 * the lane shifter by shifting the input pixel code.
135 * @in: input pixelcode to shifter
136 * @out: output pixelcode from shifter
137 * @additional_shift: # of bits the sensor's LSB is offset from CAMEXT[0]
138 *
139 * return true if the combination is possible
140 * return false otherwise
141 */
142static bool isp_video_is_shiftable(enum v4l2_mbus_pixelcode in,
143 enum v4l2_mbus_pixelcode out,
144 unsigned int additional_shift)
145{
146 const struct isp_format_info *in_info, *out_info;
147
148 if (in == out)
149 return true;
150
151 in_info = omap3isp_video_format_info(in);
152 out_info = omap3isp_video_format_info(out);
153
154 if ((in_info->flavor == 0) || (out_info->flavor == 0))
155 return false;
156
157 if (in_info->flavor != out_info->flavor)
158 return false;
159
160 return in_info->bpp - out_info->bpp + additional_shift <= 6;
161}
162
163/*
164 * isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format 133 * isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
165 * @video: ISP video instance 134 * @video: ISP video instance
166 * @mbus: v4l2_mbus_framefmt format (input) 135 * @mbus: v4l2_mbus_framefmt format (input)
@@ -315,51 +284,24 @@ static int isp_video_get_graph_data(struct isp_video *video,
315static int isp_video_validate_pipeline(struct isp_pipeline *pipe) 284static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
316{ 285{
317 struct isp_device *isp = pipe->output->isp; 286 struct isp_device *isp = pipe->output->isp;
318 struct v4l2_subdev_format fmt_source;
319 struct v4l2_subdev_format fmt_sink;
320 struct media_pad *pad; 287 struct media_pad *pad;
321 struct v4l2_subdev *subdev; 288 struct v4l2_subdev *subdev;
322 int ret;
323 289
324 subdev = isp_video_remote_subdev(pipe->output, NULL); 290 subdev = isp_video_remote_subdev(pipe->output, NULL);
325 if (subdev == NULL) 291 if (subdev == NULL)
326 return -EPIPE; 292 return -EPIPE;
327 293
328 while (1) { 294 while (1) {
329 unsigned int shifter_link;
330
331 /* Retrieve the sink format */ 295 /* Retrieve the sink format */
332 pad = &subdev->entity.pads[0]; 296 pad = &subdev->entity.pads[0];
333 if (!(pad->flags & MEDIA_PAD_FL_SINK)) 297 if (!(pad->flags & MEDIA_PAD_FL_SINK))
334 break; 298 break;
335 299
336 fmt_sink.pad = pad->index;
337 fmt_sink.which = V4L2_SUBDEV_FORMAT_ACTIVE;
338 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_sink);
339 if (ret < 0 && ret != -ENOIOCTLCMD)
340 return -EPIPE;
341
342 /* Update the maximum frame rate */ 300 /* Update the maximum frame rate */
343 if (subdev == &isp->isp_res.subdev) 301 if (subdev == &isp->isp_res.subdev)
344 omap3isp_resizer_max_rate(&isp->isp_res, 302 omap3isp_resizer_max_rate(&isp->isp_res,
345 &pipe->max_rate); 303 &pipe->max_rate);
346 304
347 /* Check ccdc maximum data rate when data comes from sensor
348 * TODO: Include ccdc rate in pipe->max_rate and compare the
349 * total pipe rate with the input data rate from sensor.
350 */
351 if (subdev == &isp->isp_ccdc.subdev && pipe->input == NULL) {
352 unsigned int rate = UINT_MAX;
353
354 omap3isp_ccdc_max_rate(&isp->isp_ccdc, &rate);
355 if (pipe->external_rate > rate)
356 return -ENOSPC;
357 }
358
359 /* If sink pad is on CCDC, the link has the lane shifter
360 * in the middle of it. */
361 shifter_link = subdev == &isp->isp_ccdc.subdev;
362
363 /* Retrieve the source format. Return an error if no source 305 /* Retrieve the source format. Return an error if no source
364 * entity can be found, and stop checking the pipeline if the 306 * entity can be found, and stop checking the pipeline if the
365 * source entity isn't a subdev. 307 * source entity isn't a subdev.
@@ -372,32 +314,6 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
372 break; 314 break;
373 315
374 subdev = media_entity_to_v4l2_subdev(pad->entity); 316 subdev = media_entity_to_v4l2_subdev(pad->entity);
375
376 fmt_source.pad = pad->index;
377 fmt_source.which = V4L2_SUBDEV_FORMAT_ACTIVE;
378 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_source);
379 if (ret < 0 && ret != -ENOIOCTLCMD)
380 return -EPIPE;
381
382 /* Check if the two ends match */
383 if (fmt_source.format.width != fmt_sink.format.width ||
384 fmt_source.format.height != fmt_sink.format.height)
385 return -EPIPE;
386
387 if (shifter_link) {
388 unsigned int parallel_shift = 0;
389 if (isp->isp_ccdc.input == CCDC_INPUT_PARALLEL) {
390 struct isp_parallel_platform_data *pdata =
391 &((struct isp_v4l2_subdevs_group *)
392 subdev->host_priv)->bus.parallel;
393 parallel_shift = pdata->data_lane_shift * 2;
394 }
395 if (!isp_video_is_shiftable(fmt_source.format.code,
396 fmt_sink.format.code,
397 parallel_shift))
398 return -EPIPE;
399 } else if (fmt_source.format.code != fmt_sink.format.code)
400 return -EPIPE;
401 } 317 }
402 318
403 return 0; 319 return 0;
@@ -1024,6 +940,17 @@ static int isp_video_check_external_subdevs(struct isp_video *video,
1024 940
1025 pipe->external_rate = ctrl.value64; 941 pipe->external_rate = ctrl.value64;
1026 942
943 if (pipe->entities & (1 << isp->isp_ccdc.subdev.entity.id)) {
944 unsigned int rate = UINT_MAX;
945 /*
946 * Check that maximum allowed CCDC pixel rate isn't
947 * exceeded by the pixel rate.
948 */
949 omap3isp_ccdc_max_rate(&isp->isp_ccdc, &rate);
950 if (pipe->external_rate > rate)
951 return -ENOSPC;
952 }
953
1027 return 0; 954 return 0;
1028} 955}
1029 956