Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

media: i2c: dw9714: add optional regulator support

Allow the dw9714 to control a regulator and adjust suspend() and resume()
to support both runtime and system pm.

Signed-off-by: Angus Ainslie <angus@akkea.ca>
Signed-off-by: Martin Kepplinger <martin.kepplinger@puri.sm>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>

authored by

Angus Ainslie and committed by
Mauro Carvalho Chehab
932de2cd 54ade663

+41 -1
+41 -1
drivers/media/i2c/dw9714.c
··· 5 5 #include <linux/i2c.h> 6 6 #include <linux/module.h> 7 7 #include <linux/pm_runtime.h> 8 + #include <linux/regulator/consumer.h> 8 9 #include <media/v4l2-ctrls.h> 9 10 #include <media/v4l2-device.h> 10 11 #include <media/v4l2-event.h> ··· 37 36 struct v4l2_ctrl_handler ctrls_vcm; 38 37 struct v4l2_subdev sd; 39 38 u16 current_val; 39 + struct regulator *vcc; 40 40 }; 41 41 42 42 static inline struct dw9714_device *to_dw9714_vcm(struct v4l2_ctrl *ctrl) ··· 147 145 if (dw9714_dev == NULL) 148 146 return -ENOMEM; 149 147 148 + dw9714_dev->vcc = devm_regulator_get(&client->dev, "vcc"); 149 + if (IS_ERR(dw9714_dev->vcc)) 150 + return PTR_ERR(dw9714_dev->vcc); 151 + 152 + rval = regulator_enable(dw9714_dev->vcc); 153 + if (rval < 0) { 154 + dev_err(&client->dev, "failed to enable vcc: %d\n", rval); 155 + return rval; 156 + } 157 + 150 158 v4l2_i2c_subdev_init(&dw9714_dev->sd, client, &dw9714_ops); 151 159 dw9714_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | 152 160 V4L2_SUBDEV_FL_HAS_EVENTS; ··· 193 181 { 194 182 struct v4l2_subdev *sd = i2c_get_clientdata(client); 195 183 struct dw9714_device *dw9714_dev = sd_to_dw9714_vcm(sd); 184 + int ret; 196 185 197 186 pm_runtime_disable(&client->dev); 187 + if (!pm_runtime_status_suspended(&client->dev)) { 188 + ret = regulator_disable(dw9714_dev->vcc); 189 + if (ret) { 190 + dev_err(&client->dev, 191 + "Failed to disable vcc: %d\n", ret); 192 + return ret; 193 + } 194 + } 195 + pm_runtime_set_suspended(&client->dev); 198 196 dw9714_subdev_cleanup(dw9714_dev); 199 197 200 198 return 0; ··· 222 200 struct dw9714_device *dw9714_dev = sd_to_dw9714_vcm(sd); 223 201 int ret, val; 224 202 203 + if (pm_runtime_suspended(&client->dev)) 204 + return 0; 205 + 225 206 for (val = dw9714_dev->current_val & ~(DW9714_CTRL_STEPS - 1); 226 207 val >= 0; val -= DW9714_CTRL_STEPS) { 227 208 ret = dw9714_i2c_write(client, ··· 233 208 dev_err_once(dev, "%s I2C failure: %d", __func__, ret); 234 209 usleep_range(DW9714_CTRL_DELAY_US, DW9714_CTRL_DELAY_US + 10); 235 210 } 236 - return 0; 211 + 212 + ret = regulator_disable(dw9714_dev->vcc); 213 + if (ret) 214 + dev_err(dev, "Failed to disable vcc: %d\n", ret); 215 + 216 + return ret; 237 217 } 238 218 239 219 /* ··· 253 223 struct v4l2_subdev *sd = i2c_get_clientdata(client); 254 224 struct dw9714_device *dw9714_dev = sd_to_dw9714_vcm(sd); 255 225 int ret, val; 226 + 227 + if (pm_runtime_suspended(&client->dev)) 228 + return 0; 229 + 230 + ret = regulator_enable(dw9714_dev->vcc); 231 + if (ret) { 232 + dev_err(dev, "Failed to enable vcc: %d\n", ret); 233 + return ret; 234 + } 235 + usleep_range(1000, 2000); 256 236 257 237 for (val = dw9714_dev->current_val % DW9714_CTRL_STEPS; 258 238 val < dw9714_dev->current_val + DW9714_CTRL_STEPS - 1;