summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/platform/imx8/mxc-isi-cap.c90
1 files changed, 75 insertions, 15 deletions
diff --git a/drivers/media/platform/imx8/mxc-isi-cap.c b/drivers/media/platform/imx8/mxc-isi-cap.c
index f5bde4e88605..eab0864b7a03 100644
--- a/drivers/media/platform/imx8/mxc-isi-cap.c
+++ b/drivers/media/platform/imx8/mxc-isi-cap.c
@@ -860,6 +860,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)
{
@@ -871,7 +930,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;
@@ -1143,6 +1202,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;
@@ -1153,7 +1213,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;
@@ -1179,9 +1239,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,
@@ -1198,7 +1263,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;
@@ -1220,7 +1285,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;
@@ -1254,12 +1319,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;
@@ -1321,10 +1381,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);