static int __isp_video_get_format(struct isp_video *video, struct v4l2_format *format) { struct v4l2_subdev_format fmt; struct v4l2_subdev *subdev; u32 pad; int ret; subdev = isp_video_remote_subdev(video, &pad); if (subdev == NULL) return -EINVAL; mutex_lock(&video->mutex); fmt.pad = pad; fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); if (ret == -ENOIOCTLCMD) ret = -EINVAL; mutex_unlock(&video->mutex); if (ret) return ret; format->type = video->type; return isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix); }
static int isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop) { struct isp_video *video = video_drvdata(file); struct v4l2_subdev *subdev; struct v4l2_mbus_framefmt format; u32 pad; int ret; subdev = isp_video_remote_subdev(video, &pad); if (subdev == NULL) return -EINVAL; /* Try the get crop operation first and fallback to get format if not * implemented. */ ret = v4l2_subdev_call(subdev, video, g_crop, crop); if (ret != -ENOIOCTLCMD) return ret; ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, pad, &format, V4L2_SUBDEV_FORMAT_ACTIVE); if (ret < 0) return ret == -ENOIOCTLCMD ? -EINVAL : ret; crop->c.left = 0; crop->c.top = 0; crop->c.width = format.width; crop->c.height = format.height; return 0; }
static int isp_video_try_format(struct file *file, void *fh, struct v4l2_format *format) { struct isp_video *video = video_drvdata(file); struct v4l2_mbus_framefmt fmt; struct v4l2_subdev *subdev; u32 pad; int ret; if (format->type != video->type) return -EINVAL; subdev = isp_video_remote_subdev(video, &pad); if (subdev == NULL) return -EINVAL; isp_video_pix_to_mbus(&format->fmt.pix, &fmt); ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, pad, &fmt, V4L2_SUBDEV_FORMAT_ACTIVE); if (ret) return ret == -ENOIOCTLCMD ? -EINVAL : ret; isp_video_mbus_to_pix(video, &fmt, &format->fmt.pix); return 0; }
/* * Validate a pipeline by checking both ends of all links for format * discrepancies. * * 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 v4l2_mbus_framefmt fmt_source; struct v4l2_mbus_framefmt fmt_sink; struct media_entity_pad *pad; struct v4l2_subdev *subdev; int ret; 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->type != MEDIA_PAD_TYPE_INPUT) break; ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, pad->index, &fmt_sink, V4L2_SUBDEV_FORMAT_ACTIVE); if (ret < 0 && ret != -ENOIOCTLCMD) return -EPIPE; /* Retrieve the source format */ pad = media_entity_remote_pad(pad); if (pad == NULL || pad->entity->type != MEDIA_ENTITY_TYPE_SUBDEV) break; subdev = media_entity_to_v4l2_subdev(pad->entity); ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, pad->index, &fmt_source, V4L2_SUBDEV_FORMAT_ACTIVE); if (ret < 0 && ret != -ENOIOCTLCMD) return -EPIPE; /* Check if the two ends match */ if (fmt_source.code != fmt_sink.code || fmt_source.width != fmt_sink.width || fmt_source.height != fmt_sink.height) { printk(KERN_ERR "%s format mismatch\n", __func__); printk(KERN_ERR " code source=%d sink=%d\n", fmt_source.code, fmt_sink.code); printk(KERN_ERR " width source=%d sink=%d\n", fmt_source.width, fmt_sink.width); printk(KERN_ERR " height source=%d sink=%d\n", fmt_source.height, fmt_sink.height); return -EPIPE; } } return 0; }
static int isp_video_set_crop(struct file *file, void *fh, struct v4l2_crop *crop) { struct isp_video *video = video_drvdata(file); struct v4l2_subdev *subdev; int ret; subdev = isp_video_remote_subdev(video, NULL); if (subdev == NULL) return -EINVAL; mutex_lock(&video->mutex); ret = v4l2_subdev_call(subdev, video, s_crop, crop); mutex_unlock(&video->mutex); return ret == -ENOIOCTLCMD ? -EINVAL : ret; }
/* * 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 media_pad *pad; struct v4l2_subdev *subdev; 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; /* Update the maximum frame rate */ if (subdev == &isp->isp_res.subdev) omap3isp_resizer_max_rate(&isp->isp_res, &pipe->max_rate); /* 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); } 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 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_FLAG_INPUT)) 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) ispresizer_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; ispccdc_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_ENTITY_TYPE_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; }