[media] omap3isp: Move CCDC link validation to ccdc_link_validate()
authorSakari Ailus <sakari.ailus@iki.fi>
Sat, 25 Feb 2012 23:42:07 +0000 (20:42 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 14 May 2012 11:53:28 +0000 (08:53 -0300)
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>
drivers/media/video/omap3isp/ispccdc.c
drivers/media/video/omap3isp/ispvideo.c

index 080fe8b513b1d97f2c8966ef49f1fe08eb40d283..7e32331b60fb0e8362b7cd50ea38680a59638336 100644 (file)
@@ -2154,6 +2154,69 @@ static int ccdc_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return 0;
 }
 
+/*
+ * 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 ccdc_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;
+}
+
+static int ccdc_link_validate(struct v4l2_subdev *sd,
+                             struct media_link *link,
+                             struct v4l2_subdev_format *source_fmt,
+                             struct v4l2_subdev_format *sink_fmt)
+{
+       struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
+       unsigned long parallel_shift;
+
+       /* Check if the two ends match */
+       if (source_fmt->format.width != sink_fmt->format.width ||
+           source_fmt->format.height != sink_fmt->format.height)
+               return -EPIPE;
+
+       /* We've got a parallel sensor here. */
+       if (ccdc->input == CCDC_INPUT_PARALLEL) {
+               struct isp_parallel_platform_data *pdata =
+                       &((struct isp_v4l2_subdevs_group *)
+                         media_entity_to_v4l2_subdev(link->source->entity)
+                         ->host_priv)->bus.parallel;
+               parallel_shift = pdata->data_lane_shift * 2;
+       } else {
+               parallel_shift = 0;
+       }
+
+       /* Lane shifter may be used to drop bits on CCDC sink pad */
+       if (!ccdc_is_shiftable(source_fmt->format.code,
+                              sink_fmt->format.code, parallel_shift))
+               return -EPIPE;
+
+       return 0;
+}
+
 /*
  * ccdc_init_formats - Initialize formats on all pads
  * @sd: ISP CCDC V4L2 subdevice
@@ -2198,6 +2261,7 @@ static const struct v4l2_subdev_pad_ops ccdc_v4l2_pad_ops = {
        .set_fmt = ccdc_set_format,
        .get_selection = ccdc_get_selection,
        .set_selection = ccdc_set_selection,
+       .link_validate = ccdc_link_validate,
 };
 
 /* V4L2 subdev operations */
@@ -2307,6 +2371,7 @@ static int ccdc_link_setup(struct media_entity *entity,
 /* media operations */
 static const struct media_entity_operations ccdc_media_ops = {
        .link_setup = ccdc_link_setup,
+       .link_validate = v4l2_subdev_link_validate,
 };
 
 void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc)
index 66bc6749de66872cc54882ab91d44d5591623b08..b37379d39cdd888c72731377bb49886361b285e8 100644 (file)
@@ -129,37 +129,6 @@ 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
@@ -315,51 +284,24 @@ static int isp_video_get_graph_data(struct isp_video *video,
 static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
 {
        struct isp_device *isp = pipe->output->isp;
-       struct v4l2_subdev_format fmt_source;
-       struct v4l2_subdev_format fmt_sink;
        struct media_pad *pad;
        struct v4l2_subdev *subdev;
-       int ret;
 
        subdev = isp_video_remote_subdev(pipe->output, NULL);
        if (subdev == NULL)
                return -EPIPE;
 
        while (1) {
-               unsigned int shifter_link;
-
                /* Retrieve the sink format */
                pad = &subdev->entity.pads[0];
                if (!(pad->flags & MEDIA_PAD_FL_SINK))
                        break;
 
-               fmt_sink.pad = pad->index;
-               fmt_sink.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-               ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_sink);
-               if (ret < 0 && ret != -ENOIOCTLCMD)
-                       return -EPIPE;
-
                /* Update the maximum frame rate */
                if (subdev == &isp->isp_res.subdev)
                        omap3isp_resizer_max_rate(&isp->isp_res,
                                                  &pipe->max_rate);
 
-               /* Check ccdc maximum data rate when data comes from sensor
-                * TODO: Include ccdc rate in pipe->max_rate and compare the
-                *       total pipe rate with the input data rate from sensor.
-                */
-               if (subdev == &isp->isp_ccdc.subdev && pipe->input == NULL) {
-                       unsigned int rate = UINT_MAX;
-
-                       omap3isp_ccdc_max_rate(&isp->isp_ccdc, &rate);
-                       if (pipe->external_rate > rate)
-                               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. Return an error if no source
                 * entity can be found, and stop checking the pipeline if the
                 * source entity isn't a subdev.
@@ -372,32 +314,6 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
                        break;
 
                subdev = media_entity_to_v4l2_subdev(pad->entity);
-
-               fmt_source.pad = pad->index;
-               fmt_source.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-               ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_source);
-               if (ret < 0 && ret != -ENOIOCTLCMD)
-                       return -EPIPE;
-
-               /* Check if the two ends match */
-               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;
@@ -1024,6 +940,17 @@ static int isp_video_check_external_subdevs(struct isp_video *video,
 
        pipe->external_rate = ctrl.value64;
 
+       if (pipe->entities & (1 << isp->isp_ccdc.subdev.entity.id)) {
+               unsigned int rate = UINT_MAX;
+               /*
+                * Check that maximum allowed CCDC pixel rate isn't
+                * exceeded by the pixel rate.
+                */
+               omap3isp_ccdc_max_rate(&isp->isp_ccdc, &rate);
+               if (pipe->external_rate > rate)
+                       return -ENOSPC;
+       }
+
        return 0;
 }