@@ -366,6 +366,12 @@ static const struct ov02c10_mode supported_modes[] = {
},
};
+static const char * const ov02c10_supply_names[] = {
+ "dovdd", /* Digital I/O power */
+ "avdd", /* Analog power */
+ "dvdd", /* Digital core power */
+};
+
struct ov02c10 {
struct v4l2_subdev sd;
struct media_pad pad;
@@ -380,8 +386,8 @@ struct ov02c10 {
struct v4l2_ctrl *exposure;
struct clk *img_clk;
- struct regulator *avdd;
struct gpio_desc *reset;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(ov02c10_supply_names)];
/* Current mode */
const struct ov02c10_mode *cur_mode;
@@ -632,6 +638,7 @@ static int ov02c10_get_pm_resources(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct ov02c10 *ov02c10 = to_ov02c10(sd);
+ int i;
ov02c10->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ov02c10->reset))
@@ -645,28 +652,26 @@ static int ov02c10_get_pm_resources(struct device *dev)
return dev_err_probe(dev, PTR_ERR(ov02c10->img_clk),
"failed to get imaging clock\n");
- ov02c10->avdd = devm_regulator_get(dev, "avdd");
- if (IS_ERR(ov02c10->avdd))
- return dev_err_probe(dev, PTR_ERR(ov02c10->avdd),
- "failed to get avdd regulator\n");
+ for (i = 0; i < ARRAY_SIZE(ov02c10_supply_names); i++)
+ ov02c10->supplies[i].supply = ov02c10_supply_names[i];
- return 0;
+ return devm_regulator_bulk_get(dev, ARRAY_SIZE(ov02c10_supply_names),
+ ov02c10->supplies);
}
static int ov02c10_power_off(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct ov02c10 *ov02c10 = to_ov02c10(sd);
- int ret = 0;
gpiod_set_value_cansleep(ov02c10->reset, 1);
- if (ov02c10->avdd)
- ret = regulator_disable(ov02c10->avdd);
+ regulator_bulk_disable(ARRAY_SIZE(ov02c10_supply_names),
+ ov02c10->supplies);
clk_disable_unprepare(ov02c10->img_clk);
- return ret;
+ return 0;
}
static int ov02c10_power_on(struct device *dev)
@@ -681,13 +686,12 @@ static int ov02c10_power_on(struct device *dev)
return ret;
}
- if (ov02c10->avdd) {
- ret = regulator_enable(ov02c10->avdd);
- if (ret < 0) {
- dev_err(dev, "failed to enable avdd: %d", ret);
- clk_disable_unprepare(ov02c10->img_clk);
- return ret;
- }
+ ret = regulator_bulk_enable(ARRAY_SIZE(ov02c10_supply_names),
+ ov02c10->supplies);
+ if (ret < 0) {
+ dev_err(dev, "failed to enable regulators: %d", ret);
+ clk_disable_unprepare(ov02c10->img_clk);
+ return ret;
}
gpiod_set_value_cansleep(ov02c10->reset, 0);
Use regulator_bulk_* to get the array of potential power rails for the ov02c10. The original IPU6 sensor from Intel only has code for avdd but on other systems such as Qualcomm Co-Pilot laptops we need to manage avdd, dvdd and dovdd with regulator_bulk_enable/disable. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> --- drivers/media/i2c/ov02c10.c | 38 ++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-)