summaryrefslogtreecommitdiff
path: root/drivers/media/i2c/dw9714.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-03-24 00:51:35 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2022-03-24 00:51:35 +0300
commit182966e1cd74ec0e326cd376de241803ee79741b (patch)
tree70a09aa4a7b4923446f3f2ba29d87600bbdc4d55 /drivers/media/i2c/dw9714.c
parent9c4b86ebf5bfdaceba4bedbaf76e4ff745db17ef (diff)
parentba2c670ae84bad705ec023bfa7a48f7f8eab5e16 (diff)
downloadlinux-182966e1cd74ec0e326cd376de241803ee79741b.tar.xz
Merge tag 'media/v5.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - a major reorg at platform Kconfig/Makefile files, organizing them per vendor. The other media Kconfig/Makefile files also sorted - New sensor drivers: hi847, isl7998x, ov08d10 - New Amphion vpu decoder stateful driver - New Atmel microchip csi2dc driver - tegra-vde driver promoted from staging - atomisp: some fixes for it to work on BYT - imx7-mipi-csis driver promoted from staging and renamed - camss driver got initial support for VFE hardware version Titan 480 - mtk-vcodec has gained support for MT8192 - lots of driver changes, fixes and improvements * tag 'media/v5.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (417 commits) media: nxp: Restrict VIDEO_IMX_MIPI_CSIS to ARCH_MXC or COMPILE_TEST media: amphion: cleanup media device if register it fail media: amphion: fix some issues to improve robust media: amphion: fix some error related with undefined reference to __divdi3 media: amphion: fix an issue that using pm_runtime_get_sync incorrectly media: vidtv: use vfree() for memory allocated with vzalloc() media: m5mols/m5mols.h: document new reset field media: pixfmt-yuv-planar.rst: fix PIX_FMT labels media: platform: Remove unnecessary print function dev_err() media: amphion: Add missing of_node_put() in vpu_core_parse_dt() media: mtk-vcodec: Add missing of_node_put() in mtk_vdec_hw_prob_done() media: platform: amphion: Fix build error without MAILBOX media: spi: Kconfig: Place SPI drivers on a single menu media: i2c: Kconfig: move camera drivers to the top media: atomisp: fix bad usage at error handling logic media: platform: rename mediatek/mtk-jpeg/ to mediatek/jpeg/ media: media/*/Kconfig: sort entries media: Kconfig: cleanup VIDEO_DEV dependencies media: platform/*/Kconfig: make manufacturer menus more uniform media: platform: Create vendor/{Makefile,Kconfig} files ...
Diffstat (limited to 'drivers/media/i2c/dw9714.c')
-rw-r--r--drivers/media/i2c/dw9714.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/drivers/media/i2c/dw9714.c b/drivers/media/i2c/dw9714.c
index 3863dfeb8293..cd7008ad8f2f 100644
--- a/drivers/media/i2c/dw9714.c
+++ b/drivers/media/i2c/dw9714.c
@@ -5,6 +5,7 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
@@ -36,6 +37,7 @@ struct dw9714_device {
struct v4l2_ctrl_handler ctrls_vcm;
struct v4l2_subdev sd;
u16 current_val;
+ struct regulator *vcc;
};
static inline struct dw9714_device *to_dw9714_vcm(struct v4l2_ctrl *ctrl)
@@ -145,6 +147,16 @@ static int dw9714_probe(struct i2c_client *client)
if (dw9714_dev == NULL)
return -ENOMEM;
+ dw9714_dev->vcc = devm_regulator_get(&client->dev, "vcc");
+ if (IS_ERR(dw9714_dev->vcc))
+ return PTR_ERR(dw9714_dev->vcc);
+
+ rval = regulator_enable(dw9714_dev->vcc);
+ if (rval < 0) {
+ dev_err(&client->dev, "failed to enable vcc: %d\n", rval);
+ return rval;
+ }
+
v4l2_i2c_subdev_init(&dw9714_dev->sd, client, &dw9714_ops);
dw9714_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
@@ -181,8 +193,18 @@ static int dw9714_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct dw9714_device *dw9714_dev = sd_to_dw9714_vcm(sd);
+ int ret;
pm_runtime_disable(&client->dev);
+ if (!pm_runtime_status_suspended(&client->dev)) {
+ ret = regulator_disable(dw9714_dev->vcc);
+ if (ret) {
+ dev_err(&client->dev,
+ "Failed to disable vcc: %d\n", ret);
+ return ret;
+ }
+ }
+ pm_runtime_set_suspended(&client->dev);
dw9714_subdev_cleanup(dw9714_dev);
return 0;
@@ -200,6 +222,9 @@ static int __maybe_unused dw9714_vcm_suspend(struct device *dev)
struct dw9714_device *dw9714_dev = sd_to_dw9714_vcm(sd);
int ret, val;
+ if (pm_runtime_suspended(&client->dev))
+ return 0;
+
for (val = dw9714_dev->current_val & ~(DW9714_CTRL_STEPS - 1);
val >= 0; val -= DW9714_CTRL_STEPS) {
ret = dw9714_i2c_write(client,
@@ -208,7 +233,12 @@ static int __maybe_unused dw9714_vcm_suspend(struct device *dev)
dev_err_once(dev, "%s I2C failure: %d", __func__, ret);
usleep_range(DW9714_CTRL_DELAY_US, DW9714_CTRL_DELAY_US + 10);
}
- return 0;
+
+ ret = regulator_disable(dw9714_dev->vcc);
+ if (ret)
+ dev_err(dev, "Failed to disable vcc: %d\n", ret);
+
+ return ret;
}
/*
@@ -224,6 +254,16 @@ static int __maybe_unused dw9714_vcm_resume(struct device *dev)
struct dw9714_device *dw9714_dev = sd_to_dw9714_vcm(sd);
int ret, val;
+ if (pm_runtime_suspended(&client->dev))
+ return 0;
+
+ ret = regulator_enable(dw9714_dev->vcc);
+ if (ret) {
+ dev_err(dev, "Failed to enable vcc: %d\n", ret);
+ return ret;
+ }
+ usleep_range(1000, 2000);
+
for (val = dw9714_dev->current_val % DW9714_CTRL_STEPS;
val < dw9714_dev->current_val + DW9714_CTRL_STEPS - 1;
val += DW9714_CTRL_STEPS) {