Add 'struct media_pad pad' member and suitable glue code, so that
soc_camera/rcar_vin can become agnostic to whether an old or new-
style driver (wrt pad API use) can sit underneath

This version has been reworked to include appropriate constant and
datatype names for kernel v3.18

---

** this version for kernel 3.18.x+ (v4l2 constant names) **
** now including: **
| WmT: assume max resolution at init
|
| Make rcar_vin agnostic to the driver beneath having a smaller
| resolution as its default size. Previously, the logic for calculating
| cropping region size -which depends on going from larger to smaller
| values- would have been confused by this.
---
 drivers/media/platform/soc_camera/rcar_vin.c |  112 +++++++++++++++++++++++---
 1 file changed, 101 insertions(+), 11 deletions(-)

diff --git a/drivers/media/platform/soc_camera/rcar_vin.c 
b/drivers/media/platform/soc_camera/rcar_vin.c
index e4f60d3..046fcc1 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -932,9 +932,27 @@ static int rcar_vin_get_formats(struct soc_camera_device 
*icd, unsigned int idx,
        u32 code;
        const struct soc_mbus_pixelfmt *fmt;
 
-       ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
-       if (ret < 0)
-               return 0;
+       // subdev_has_op -> enum_mbus_code vs enum_mbus_fmt
+       if (v4l2_subdev_has_op(sd, pad, enum_mbus_code)) {
+               struct v4l2_subdev_mbus_code_enum c;
+
+               c.index = idx;
+
+               ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &c);
+               if (ret < 0)
+                       return 0;
+
+#if 1  /*  ideal  */
+               code = c.code;
+#else  /*  Ian HACK - required with full(er) formats table  */
+               code = MEDIA_BUS_FMT_RGB888_1X24; //HACK
+#endif
+       }
+       else {
+               ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+               if (ret < 0)
+                       return 0;
+       }
 
        fmt = soc_mbus_get_fmtdesc(code);
        if (!fmt) {
@@ -948,11 +966,28 @@ static int rcar_vin_get_formats(struct soc_camera_device 
*icd, unsigned int idx,
 
        if (!icd->host_priv) {
                struct v4l2_mbus_framefmt mf;
+               struct v4l2_subdev_format sd_format;
                struct v4l2_rect rect;
                struct device *dev = icd->parent;
                int shift;
 
-               ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
+               // subdev_has_op -> get_fmt vs g_mbus_fmt
+               if (v4l2_subdev_has_op(sd, pad, get_fmt)) {
+                       struct media_pad *remote_pad;
+
+                       remote_pad= 
media_entity_remote_pad(&icd->vdev->entity.pads[0]);
+                       sd_format.pad= remote_pad->index;
+                       sd_format.which=V4L2_SUBDEV_FORMAT_ACTIVE;
+
+                       ret = v4l2_subdev_call(sd, pad, get_fmt, NULL,
+                                               &sd_format);
+                       mf= sd_format.format;
+                       mf.width= VIN_MAX_WIDTH;
+                       mf.height= VIN_MAX_HEIGHT;
+               }
+               else {
+                       ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
+               }
                if (ret < 0)
                        return ret;
 
@@ -979,10 +1014,18 @@ static int rcar_vin_get_formats(struct soc_camera_device 
*icd, unsigned int idx,
 
                        mf.width = 1280 >> shift;
                        mf.height = 960 >> shift;
-                       ret = v4l2_device_call_until_err(sd->v4l2_dev,
-                                                        soc_camera_grp_id(icd),
-                                                        video, s_mbus_fmt,
-                                                        &mf);
+                       // subdev_has_op -> set_fmt vs s_mbus_fmt
+                       if (v4l2_subdev_has_op(sd, pad, set_fmt)) {
+                               ret = v4l2_device_call_until_err(sd->v4l2_dev,
+                                                soc_camera_grp_id(icd),
+                                                pad, set_fmt, NULL,
+                                                &sd_format);
+                       } else {
+                               ret = v4l2_device_call_until_err(sd->v4l2_dev,
+                                                soc_camera_grp_id(icd),
+                                                video, s_mbus_fmt,
+                                                &mf);
+                       }
                        if (ret < 0)
                                return ret;
                }
@@ -1099,7 +1142,22 @@ static int rcar_vin_set_crop(struct soc_camera_device 
*icd,
        /* On success cam_crop contains current camera crop */
 
        /* Retrieve camera output window */
-       ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
+       // subdev_has_op -> get_fmt vs g_mbus_fmt
+       if (v4l2_subdev_has_op(sd, pad, get_fmt))
+       {
+               struct v4l2_subdev_format sd_format;
+               struct media_pad *remote_pad;
+
+               remote_pad= media_entity_remote_pad(&icd->vdev->entity.pads[0]);
+               sd_format.pad= remote_pad->index;
+               sd_format.which= V4L2_SUBDEV_FORMAT_ACTIVE;
+               ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sd_format);
+
+               mf.width= sd_format.format.width;
+               mf.height= sd_format.format.height;
+       } else {
+               ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
+       }
        if (ret < 0)
                return ret;
 
@@ -1314,8 +1372,22 @@ static int rcar_vin_try_fmt(struct soc_camera_device 
*icd,
        mf.code = xlate->code;
        mf.colorspace = pix->colorspace;
 
-       ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd),
+       // subdev_has_op -> get_fmt vs try_mbus_fmt
+       if (v4l2_subdev_has_op(sd, pad, get_fmt)) {
+               struct v4l2_subdev_format sd_format;
+               struct media_pad *remote_pad;
+
+               remote_pad= media_entity_remote_pad(
+                                       &icd->vdev->entity.pads[0]);
+               sd_format.pad= remote_pad->index;
+               sd_format.format= mf;
+               ret= v4l2_device_call_until_err(sd->v4l2_dev, 
soc_camera_grp_id(icd),
+                                        pad, get_fmt, NULL, &sd_format);
+               mf= sd_format.format;
+       } else {
+               ret = v4l2_device_call_until_err(sd->v4l2_dev, 
soc_camera_grp_id(icd),
                                         video, try_mbus_fmt, &mf);
+       }
        if (ret < 0)
                return ret;
 
@@ -1335,10 +1407,28 @@ static int rcar_vin_try_fmt(struct soc_camera_device 
*icd,
                         */
                        mf.width = VIN_MAX_WIDTH;
                        mf.height = VIN_MAX_HEIGHT;
-                       ret = v4l2_device_call_until_err(sd->v4l2_dev,
+                       // subdev_has_op -> get_fmt vs try_mbus_fmt
+                       if (v4l2_subdev_has_op(sd, pad, get_fmt)) {
+                               struct v4l2_subdev_format sd_format;
+                               struct media_pad *remote_pad;
+
+                               remote_pad= media_entity_remote_pad(
+                                       &icd->vdev->entity.pads[0]);
+                               sd_format.pad = remote_pad->index;
+                               sd_format.which= V4L2_SUBDEV_FORMAT_TRY;
+                               sd_format.format= mf;
+                               ret = v4l2_device_call_until_err(sd->v4l2_dev,
+                                                        soc_camera_grp_id(icd),
+                                                        pad, get_fmt,
+                                                        NULL, &sd_format);
+                               mf= sd_format.format;
+                       } else {
+                               ret = v4l2_device_call_until_err(sd->v4l2_dev,
                                                         soc_camera_grp_id(icd),
                                                         video, try_mbus_fmt,
                                                         &mf);
+                       }
+
                        if (ret < 0) {
                                dev_err(icd->parent,
                                        "client try_fmt() = %d\n", ret);
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to