summaryrefslogtreecommitdiff
path: root/drivers/media/i2c/ccs/ccs-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c/ccs/ccs-core.c')
-rw-r--r--drivers/media/i2c/ccs/ccs-core.c58
1 files changed, 51 insertions, 7 deletions
diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c
index a9403a227c6b..5363f3bcafe3 100644
--- a/drivers/media/i2c/ccs/ccs-core.c
+++ b/drivers/media/i2c/ccs/ccs-core.c
@@ -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)
@@ -2673,8 +2718,7 @@ static int ccs_get_skip_top_lines(struct v4l2_subdev *subdev, u32 *lines)
*/
static ssize_t
-ccs_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
- char *buf)
+nvm_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev));
struct i2c_client *client = v4l2_get_subdevdata(subdev);
@@ -2704,11 +2748,10 @@ ccs_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
*/
return rval;
}
-static DEVICE_ATTR(nvm, S_IRUGO, ccs_sysfs_nvm_read, NULL);
+static DEVICE_ATTR_RO(nvm);
static ssize_t
-ccs_sysfs_ident_read(struct device *dev, struct device_attribute *attr,
- char *buf)
+ident_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev));
struct ccs_sensor *sensor = to_ccs_sensor(subdev);
@@ -2723,8 +2766,7 @@ ccs_sysfs_ident_read(struct device *dev, struct device_attribute *attr,
minfo->smia_manufacturer_id, minfo->model_id,
minfo->revision_number) + 1;
}
-
-static DEVICE_ATTR(ident, S_IRUGO, ccs_sysfs_ident_read, NULL);
+static DEVICE_ATTR_RO(ident);
/* -----------------------------------------------------------------------------
* V4L2 subdev core operations
@@ -3058,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 = {