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@xxxxxxxxxx> --- drivers/media/i2c/ov02c10.c | 38 ++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/media/i2c/ov02c10.c b/drivers/media/i2c/ov02c10.c index 5626aa2fe62c..f6542cdf7472 100644 --- a/drivers/media/i2c/ov02c10.c +++ b/drivers/media/i2c/ov02c10.c @@ -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); -- 2.48.1