diff options
Diffstat (limited to 'drivers/media/platform/imx8/mxc-isi-cap.c')
-rw-r--r-- | drivers/media/platform/imx8/mxc-isi-cap.c | 152 |
1 files changed, 131 insertions, 21 deletions
diff --git a/drivers/media/platform/imx8/mxc-isi-cap.c b/drivers/media/platform/imx8/mxc-isi-cap.c index 16d43b6a786f..a6756b70ae9d 100644 --- a/drivers/media/platform/imx8/mxc-isi-cap.c +++ b/drivers/media/platform/imx8/mxc-isi-cap.c @@ -161,14 +161,50 @@ struct mxc_isi_fmt *mxc_isi_get_src_fmt(struct v4l2_subdev_format *sd_fmt) { u32 index; - /* two fmt RGB32 and YUV444 from pixellink */ - if (sd_fmt->format.code == MEDIA_BUS_FMT_YUYV8_1X16 || - sd_fmt->format.code == MEDIA_BUS_FMT_YVYU8_2X8 || - sd_fmt->format.code == MEDIA_BUS_FMT_AYUV8_1X32 || - sd_fmt->format.code == MEDIA_BUS_FMT_UYVY8_2X8) + /* Treat all yuv fomats equally */ + switch (sd_fmt->format.code) { + case MEDIA_BUS_FMT_Y8_1X8: + case MEDIA_BUS_FMT_UV8_1X8: + case MEDIA_BUS_FMT_UYVY8_1_5X8: + case MEDIA_BUS_FMT_VYUY8_1_5X8: + case MEDIA_BUS_FMT_YUYV8_1_5X8: + case MEDIA_BUS_FMT_YVYU8_1_5X8: + case MEDIA_BUS_FMT_UYVY8_2X8: + case MEDIA_BUS_FMT_VYUY8_2X8: + case MEDIA_BUS_FMT_YUYV8_2X8: + case MEDIA_BUS_FMT_YVYU8_2X8: + case MEDIA_BUS_FMT_Y10_1X10: + case MEDIA_BUS_FMT_UYVY10_2X10: + case MEDIA_BUS_FMT_VYUY10_2X10: + case MEDIA_BUS_FMT_YUYV10_2X10: + case MEDIA_BUS_FMT_YVYU10_2X10: + case MEDIA_BUS_FMT_Y12_1X12: + case MEDIA_BUS_FMT_UYVY12_2X12: + case MEDIA_BUS_FMT_VYUY12_2X12: + case MEDIA_BUS_FMT_YUYV12_2X12: + case MEDIA_BUS_FMT_YVYU12_2X12: + case MEDIA_BUS_FMT_UYVY8_1X16: + case MEDIA_BUS_FMT_VYUY8_1X16: + case MEDIA_BUS_FMT_YUYV8_1X16: + case MEDIA_BUS_FMT_YVYU8_1X16: + case MEDIA_BUS_FMT_YDYUYDYV8_1X16: + case MEDIA_BUS_FMT_UYVY10_1X20: + case MEDIA_BUS_FMT_VYUY10_1X20: + case MEDIA_BUS_FMT_YUYV10_1X20: + case MEDIA_BUS_FMT_YVYU10_1X20: + case MEDIA_BUS_FMT_VUY8_1X24: + case MEDIA_BUS_FMT_YUV8_1X24: + case MEDIA_BUS_FMT_UYVY12_1X24: + case MEDIA_BUS_FMT_VYUY12_1X24: + case MEDIA_BUS_FMT_YUYV12_1X24: + case MEDIA_BUS_FMT_YVYU12_1X24: + case MEDIA_BUS_FMT_YUV10_1X30: + case MEDIA_BUS_FMT_AYUV8_1X32: index = 1; - else + break; + default: index = 0; + } return &mxc_isi_src_formats[index]; } @@ -849,6 +885,65 @@ static int mxc_isi_cap_try_fmt_mplane(struct file *file, void *fh, return 0; } +static struct media_pad *subdev_get_remote_source_pad(struct v4l2_subdev *subdev) +{ + struct media_pad *sink_pad, *source_pad; + int i; + + while (1) { + source_pad = NULL; + for (i = 0; i < subdev->entity.num_pads; i++) { + sink_pad = &subdev->entity.pads[i]; + + if (sink_pad->flags & MEDIA_PAD_FL_SINK) { + source_pad = media_entity_remote_pad(sink_pad); + if (source_pad) + break; + } + } + /* return first pad point in the loop */ + return source_pad; + } + + return NULL; +} + +static struct v4l2_subdev *mxc_isi_get_sensor_subdev(struct v4l2_subdev *subdev) +{ + struct media_pad *source_pad; + struct v4l2_subdev *sd; + + /* Firstly find mipi interface, so remote source for the isi */ + source_pad = subdev_get_remote_source_pad(subdev); + if (source_pad == NULL) { + v4l2_err(subdev->v4l2_dev, "%s, No remote pad found!\n", __func__); + return NULL; + } + + /* Get remote source pad subdev */ + sd = media_entity_to_v4l2_subdev(source_pad->entity); + if (sd == NULL) { + v4l2_err(subdev->v4l2_dev, "Can't find subdev\n"); + return NULL; + } + + /* Then find the actual sensor which should be on the pad of mipi */ + source_pad = subdev_get_remote_source_pad(sd); + if (source_pad == NULL) { + v4l2_err(subdev->v4l2_dev, "%s, No remote pad found!\n", __func__); + return NULL; + } + + /* Get remote source pad subdev */ + sd = media_entity_to_v4l2_subdev(source_pad->entity); + if (sd == NULL) { + v4l2_err(subdev->v4l2_dev, "Can't find subdev\n"); + return NULL; + } + + return sd; +} + /* Update input frame size and formate */ static int mxc_isi_source_fmt_init(struct mxc_isi_dev *mxc_isi) { @@ -860,7 +955,7 @@ static int mxc_isi_source_fmt_init(struct mxc_isi_dev *mxc_isi) int ret; /* Get remote source pad */ - source_pad = mxc_isi_get_remote_source_pad(mxc_isi); + source_pad = subdev_get_remote_source_pad(&mxc_isi->isi_cap.sd); if (source_pad == NULL) { v4l2_err(mxc_isi->v4l2_dev, "%s, No remote pad found!\n", __func__); return -EINVAL; @@ -873,6 +968,20 @@ static int mxc_isi_source_fmt_init(struct mxc_isi_dev *mxc_isi) return -EINVAL; } +# if 0 + struct mxc_isi_frame *dst_f = &mxc_isi->isi_cap.dst_f; + struct v4l2_subdev_format dst_fmt; + struct v4l2_subdev *sd; + + dst_fmt.pad = source_pad->index; + dst_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + dst_fmt.format.width = dst_f->o_width; + dst_fmt.format.height = dst_f->o_height; + + sd = mxc_isi_get_sensor_subdev(&mxc_isi->isi_cap.sd); + v4l2_subdev_call(sd, pad, set_fmt, NULL, &dst_fmt); +# endif + src_fmt.pad = source_pad->index; src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; src_fmt.format.width = dst_f->width; @@ -1132,6 +1241,7 @@ static int mxc_isi_cap_g_chip_ident(struct file *file, void *fb, struct device_node *local, *remote, *endpoint; struct mxc_isi_dev *mxc_isi = video_drvdata(file); struct video_device *vdev = video_devdata(file); + struct v4l2_dbg_chip_ident ci; struct v4l2_subdev *sd; struct media_pad *source_pad; @@ -1142,7 +1252,7 @@ static int mxc_isi_cap_g_chip_ident(struct file *file, void *fb, } /* Get remote source pad subdev */ - sd = media_entity_to_v4l2_subdev(source_pad->entity); + sd = mxc_isi_get_sensor_subdev(&mxc_isi->isi_cap.sd); if (sd == NULL) { v4l2_err(mxc_isi->v4l2_dev, "%s, No remote subdev found!\n", __func__); return -EINVAL; @@ -1168,9 +1278,14 @@ static int mxc_isi_cap_g_chip_ident(struct file *file, void *fb, return -ENODEV; } - sprintf(chip->match.name, "imx8_%s_%d", remote->name, vdev->num); + sprintf(chip->match.name, "%s-%d\n", sd->name, vdev->num); - return 0; + /* Just check if the callback of the sensor device returns success, + * no need to actually identify the device since we're using the + * pads to find it. + */ + + return v4l2_subdev_call(sd, core, g_chip_ident, &ci); } static int mxc_isi_cap_g_parm(struct file *file, void *fh, @@ -1187,7 +1302,7 @@ static int mxc_isi_cap_g_parm(struct file *file, void *fh, } /* Get remote source pad subdev */ - sd = media_entity_to_v4l2_subdev(source_pad->entity); + sd = mxc_isi_get_sensor_subdev(&mxc_isi->isi_cap.sd); if (sd == NULL) { v4l2_err(mxc_isi->v4l2_dev, "%s, No remote subdev found!\n", __func__); return -EINVAL; @@ -1209,7 +1324,7 @@ static int mxc_isi_cap_s_parm(struct file *file, void *fh, } /* Get remote source pad subdev */ - sd = media_entity_to_v4l2_subdev(source_pad->entity); + sd = mxc_isi_get_sensor_subdev(&mxc_isi->isi_cap.sd); if (sd == NULL) { v4l2_err(mxc_isi->v4l2_dev, "%s, No remote subdev found!\n", __func__); return -EINVAL; @@ -1242,12 +1357,7 @@ static int mxc_isi_cap_enum_framesizes(struct file *file, void *priv, } /* Get remote source pad subdev */ - sd = media_entity_to_v4l2_subdev(source_pad->entity); - if (sd == NULL) { - v4l2_err(mxc_isi->v4l2_dev, "%s, No remote subdev found!\n", __func__); - return -EINVAL; - } - + sd = mxc_isi_get_sensor_subdev(&mxc_isi->isi_cap.sd); if (sd == NULL) { v4l2_err(&mxc_isi->isi_cap.sd, "Can't find subdev\n"); return -ENODEV; @@ -1303,10 +1413,10 @@ static int mxc_isi_cap_enum_frameintervals(struct file *file, void *fh, } /* Get remote source pad subdev */ - sd = media_entity_to_v4l2_subdev(source_pad->entity); + sd = mxc_isi_get_sensor_subdev(&mxc_isi->isi_cap.sd); if (sd == NULL) { - v4l2_err(mxc_isi->v4l2_dev, "%s, No remote subdev found!\n", __func__); - return -EINVAL; + v4l2_err(&mxc_isi->isi_cap.sd, "Can't find sensor subdev\n"); + return -ENODEV; } ret = v4l2_subdev_call(sd, pad, enum_frame_interval, NULL, &fie); |