summaryrefslogtreecommitdiff
path: root/drivers/media/platform/imx8/mxc-isi-cap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/imx8/mxc-isi-cap.c')
-rw-r--r--drivers/media/platform/imx8/mxc-isi-cap.c152
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);