diff options
author | Sakari Ailus <sakari.ailus@iki.fi> | 2012-02-25 18:42:07 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-14 07:53:28 -0400 |
commit | a6d7a62dcd1fccb3140100551b205315491eadc5 (patch) | |
tree | fe3fa7a1d902c0177c978e5e1625873a434fa37e /drivers/media/video/omap3isp | |
parent | 20d4ab7bea8e79bb330c2d52da9c245911ea29ed (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.c | 65 | ||||
-rw-r--r-- | drivers/media/video/omap3isp/ispvideo.c | 95 |
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 | */ | ||
2167 | static 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 | |||
2188 | static 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 */ |
2308 | static const struct media_entity_operations ccdc_media_ops = { | 2372 | static 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 | ||
2312 | void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc) | 2377 | void 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 | */ | ||
142 | static 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, | |||
315 | static int isp_video_validate_pipeline(struct isp_pipeline *pipe) | 284 | static 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 | ||