]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: ccs: Implement support for manual LP control
authorSakari Ailus <sakari.ailus@linux.intel.com>
Wed, 23 Jun 2021 14:20:50 +0000 (16:20 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Wed, 4 Aug 2021 12:43:51 +0000 (14:43 +0200)
Use the pre_streamon callback to transition the transmitter to either
LP-11 or LP-111 mode if supported by the sensor.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/i2c/ccs/ccs-core.c

index 121cbe406fe4b560ffd2e4bb09ffe80f5cd498e6..5363f3bcafe3df14a8b2b2bd86cdcec138bd3ab5 100644 (file)
@@ -1943,6 +1943,51 @@ static int ccs_set_stream(struct v4l2_subdev *subdev, int enable)
        return rval;
 }
 
+static int ccs_pre_streamon(struct v4l2_subdev *subdev, u32 flags)
+{
+       struct ccs_sensor *sensor = to_ccs_sensor(subdev);
+       struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+       int rval;
+
+       if (flags & V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP) {
+               switch (sensor->hwcfg.csi_signalling_mode) {
+               case CCS_CSI_SIGNALING_MODE_CSI_2_DPHY:
+                       if (!(CCS_LIM(sensor, PHY_CTRL_CAPABILITY_2) &
+                             CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_DPHY))
+                               return -EACCES;
+                       break;
+               case CCS_CSI_SIGNALING_MODE_CSI_2_CPHY:
+                       if (!(CCS_LIM(sensor, PHY_CTRL_CAPABILITY_2) &
+                             CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_CPHY))
+                               return -EACCES;
+                       break;
+               default:
+                       return -EACCES;
+               }
+       }
+
+       rval = ccs_pm_get_init(sensor);
+       if (rval)
+               return rval;
+
+       if (flags & V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP) {
+               rval = ccs_write(sensor, MANUAL_LP_CTRL,
+                                CCS_MANUAL_LP_CTRL_ENABLE);
+               if (rval)
+                       pm_runtime_put(&client->dev);
+       }
+
+       return rval;
+}
+
+static int ccs_post_streamoff(struct v4l2_subdev *subdev)
+{
+       struct ccs_sensor *sensor = to_ccs_sensor(subdev);
+       struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+
+       return pm_runtime_put(&client->dev);
+}
+
 static int ccs_enum_mbus_code(struct v4l2_subdev *subdev,
                              struct v4l2_subdev_state *sd_state,
                              struct v4l2_subdev_mbus_code_enum *code)
@@ -3055,6 +3100,8 @@ static int ccs_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 
 static const struct v4l2_subdev_video_ops ccs_video_ops = {
        .s_stream = ccs_set_stream,
+       .pre_streamon = ccs_pre_streamon,
+       .post_streamoff = ccs_post_streamoff,
 };
 
 static const struct v4l2_subdev_pad_ops ccs_pad_ops = {