summaryrefslogtreecommitdiff
path: root/drivers/staging/media/imx/imx-media-csi.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2017-06-07 15:34:09 -0300
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2017-06-20 08:02:24 -0300
commit949ffdbfdb505708f4c308f79312d9d3ea6c3c28 (patch)
tree25edd7f7364afd3d48f168c5fcc194c8f5334b85 /drivers/staging/media/imx/imx-media-csi.c
parent69e78611ffc84be13cf96781e10521103dfe50dd (diff)
[media] media: imx: csi: add frame size/interval enumeration
Add frame size and frame interval enumeration to CSI. CSI can downscale the image independently horizontally and vertically by a factor of two, which enumerates to four different frame sizes at the output pads. The input pad supports a range of frame sizes. CSI can also drop frames, resulting in frame rate reduction, so enumerate the resulting possible output frame rates. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/staging/media/imx/imx-media-csi.c')
-rw-r--r--drivers/staging/media/imx/imx-media-csi.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index 6fdcaa580ead..b19052fe60bc 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1139,6 +1139,74 @@ out:
return ret;
}
+static int csi_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ struct csi_priv *priv = v4l2_get_subdevdata(sd);
+ struct v4l2_rect *crop;
+ int ret = 0;
+
+ if (fse->pad >= CSI_NUM_PADS ||
+ fse->index > (fse->pad == CSI_SINK_PAD ? 0 : 3))
+ return -EINVAL;
+
+ mutex_lock(&priv->lock);
+
+ if (fse->pad == CSI_SINK_PAD) {
+ fse->min_width = MIN_W;
+ fse->max_width = MAX_W;
+ fse->min_height = MIN_H;
+ fse->max_height = MAX_H;
+ } else {
+ crop = __csi_get_crop(priv, cfg, fse->which);
+
+ fse->min_width = fse->max_width = fse->index & 1 ?
+ crop->width / 2 : crop->width;
+ fse->min_height = fse->max_height = fse->index & 2 ?
+ crop->height / 2 : crop->height;
+ }
+
+ mutex_unlock(&priv->lock);
+ return ret;
+}
+
+static int csi_enum_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_interval_enum *fie)
+{
+ struct csi_priv *priv = v4l2_get_subdevdata(sd);
+ struct v4l2_fract *input_fi;
+ struct v4l2_rect *crop;
+ int ret = 0;
+
+ if (fie->pad >= CSI_NUM_PADS ||
+ fie->index >= (fie->pad != CSI_SRC_PAD_IDMAC ?
+ 1 : ARRAY_SIZE(csi_skip)))
+ return -EINVAL;
+
+ mutex_lock(&priv->lock);
+
+ input_fi = &priv->frame_interval[CSI_SINK_PAD];
+ crop = __csi_get_crop(priv, cfg, fie->which);
+
+ if ((fie->width != crop->width && fie->width != crop->width / 2) ||
+ (fie->height != crop->height && fie->height != crop->height / 2)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ fie->interval = *input_fi;
+
+ if (fie->pad == CSI_SRC_PAD_IDMAC)
+ csi_apply_skip_interval(&csi_skip[fie->index],
+ &fie->interval);
+
+out:
+ mutex_unlock(&priv->lock);
+ return ret;
+}
+
static int csi_get_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *sdformat)
@@ -1606,6 +1674,8 @@ static const struct v4l2_subdev_video_ops csi_video_ops = {
static const struct v4l2_subdev_pad_ops csi_pad_ops = {
.enum_mbus_code = csi_enum_mbus_code,
+ .enum_frame_size = csi_enum_frame_size,
+ .enum_frame_interval = csi_enum_frame_interval,
.get_fmt = csi_get_fmt,
.set_fmt = csi_set_fmt,
.get_selection = csi_get_selection,