/* * Validate a pipeline by checking both ends of all links for format * discrepancies. * * Compute the minimum time per frame value as the maximum of time per frame * limits reported by every block in the pipeline. * * Return 0 if all formats match, or -EPIPE if at least one link is found with * different formats on its two ends or if the pipeline doesn't start with a * video source (either a subdev with no input pad, or a non-subdev entity). */ 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; pipe->max_rate = pipe->l3_ick; 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 (isp->isp_ccdc.vpcfg.pixelclk > 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. */ pad = media_entity_remote_source(pad); if (pad == NULL) return -EPIPE; if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) 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; }
/* * Validate a pipeline by checking both ends of all links for format * discrepancies. * * Compute the minimum time per frame value as the maximum of time per frame * limits reported by every block in the pipeline. * * Return 0 if all formats match, or -EPIPE if at least one link is found with * different formats on its two ends. */ 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; pipe->max_rate = pipe->l3_ick; subdev = isp_video_remote_subdev(pipe->output, NULL); if (subdev == NULL) return -EPIPE; while (1) { /* 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 (isp->isp_ccdc.vpcfg.pixelclk > rate) return -ENOSPC; } /* Retrieve the source format */ pad = media_entity_remote_source(pad); if (pad == NULL || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) 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.code != fmt_sink.format.code || fmt_source.format.width != fmt_sink.format.width || fmt_source.format.height != fmt_sink.format.height) return -EPIPE; } return 0; }