Skip to content

Commit 4a1b669

Browse files
Vladimir ZapolskiyHans Verkuil
authored andcommitted
media: i2c: og01a1b: Add management of optional sensor supply lines
Omnivision OG01A1B camera sensor is supplied by three power rails, if supplies are present as device properties, include them into sensor power up sequence. Signed-off-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
1 parent 1cb7b39 commit 4a1b669

1 file changed

Lines changed: 80 additions & 1 deletion

File tree

drivers/media/i2c/og01a1b.c

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/i2c.h>
1010
#include <linux/module.h>
1111
#include <linux/pm_runtime.h>
12+
#include <linux/regulator/consumer.h>
1213
#include <media/v4l2-ctrls.h>
1314
#include <media/v4l2-device.h>
1415
#include <media/v4l2-fwnode.h>
@@ -422,6 +423,9 @@ static const struct og01a1b_mode supported_modes[] = {
422423
struct og01a1b {
423424
struct clk *xvclk;
424425
struct gpio_desc *reset_gpio;
426+
struct regulator *avdd;
427+
struct regulator *dovdd;
428+
struct regulator *dvdd;
425429

426430
struct v4l2_subdev sd;
427431
struct media_pad pad;
@@ -985,9 +989,27 @@ static int og01a1b_power_on(struct device *dev)
985989
struct og01a1b *og01a1b = to_og01a1b(sd);
986990
int ret;
987991

992+
if (og01a1b->avdd) {
993+
ret = regulator_enable(og01a1b->avdd);
994+
if (ret)
995+
return ret;
996+
}
997+
998+
if (og01a1b->dovdd) {
999+
ret = regulator_enable(og01a1b->dovdd);
1000+
if (ret)
1001+
goto avdd_disable;
1002+
}
1003+
1004+
if (og01a1b->dvdd) {
1005+
ret = regulator_enable(og01a1b->dvdd);
1006+
if (ret)
1007+
goto dovdd_disable;
1008+
}
1009+
9881010
ret = clk_prepare_enable(og01a1b->xvclk);
9891011
if (ret)
990-
return ret;
1012+
goto dvdd_disable;
9911013

9921014
gpiod_set_value_cansleep(og01a1b->reset_gpio, 0);
9931015

@@ -997,6 +1019,18 @@ static int og01a1b_power_on(struct device *dev)
9971019
usleep_range(delay, 2 * delay);
9981020

9991021
return 0;
1022+
1023+
dvdd_disable:
1024+
if (og01a1b->dvdd)
1025+
regulator_disable(og01a1b->dvdd);
1026+
dovdd_disable:
1027+
if (og01a1b->dovdd)
1028+
regulator_disable(og01a1b->dovdd);
1029+
avdd_disable:
1030+
if (og01a1b->avdd)
1031+
regulator_disable(og01a1b->avdd);
1032+
1033+
return ret;
10001034
}
10011035

10021036
static int og01a1b_power_off(struct device *dev)
@@ -1012,6 +1046,15 @@ static int og01a1b_power_off(struct device *dev)
10121046

10131047
gpiod_set_value_cansleep(og01a1b->reset_gpio, 1);
10141048

1049+
if (og01a1b->dvdd)
1050+
regulator_disable(og01a1b->dvdd);
1051+
1052+
if (og01a1b->dovdd)
1053+
regulator_disable(og01a1b->dovdd);
1054+
1055+
if (og01a1b->avdd)
1056+
regulator_disable(og01a1b->avdd);
1057+
10151058
return 0;
10161059
}
10171060

@@ -1059,6 +1102,42 @@ static int og01a1b_probe(struct i2c_client *client)
10591102
return PTR_ERR(og01a1b->reset_gpio);
10601103
}
10611104

1105+
og01a1b->avdd = devm_regulator_get_optional(&client->dev, "avdd");
1106+
if (IS_ERR(og01a1b->avdd)) {
1107+
ret = PTR_ERR(og01a1b->avdd);
1108+
if (ret != -ENODEV) {
1109+
dev_err_probe(&client->dev, ret,
1110+
"Failed to get 'avdd' regulator\n");
1111+
return ret;
1112+
}
1113+
1114+
og01a1b->avdd = NULL;
1115+
}
1116+
1117+
og01a1b->dovdd = devm_regulator_get_optional(&client->dev, "dovdd");
1118+
if (IS_ERR(og01a1b->dovdd)) {
1119+
ret = PTR_ERR(og01a1b->dovdd);
1120+
if (ret != -ENODEV) {
1121+
dev_err_probe(&client->dev, ret,
1122+
"Failed to get 'dovdd' regulator\n");
1123+
return ret;
1124+
}
1125+
1126+
og01a1b->dovdd = NULL;
1127+
}
1128+
1129+
og01a1b->dvdd = devm_regulator_get_optional(&client->dev, "dvdd");
1130+
if (IS_ERR(og01a1b->dvdd)) {
1131+
ret = PTR_ERR(og01a1b->dvdd);
1132+
if (ret != -ENODEV) {
1133+
dev_err_probe(&client->dev, ret,
1134+
"Failed to get 'dvdd' regulator\n");
1135+
return ret;
1136+
}
1137+
1138+
og01a1b->dvdd = NULL;
1139+
}
1140+
10621141
/* The sensor must be powered on to read the CHIP_ID register */
10631142
ret = og01a1b_power_on(&client->dev);
10641143
if (ret)

0 commit comments

Comments
 (0)