From: Dave Stevenson Date: Mon, 22 Nov 2021 12:31:35 +0000 (+0000) Subject: media: i2c: ov5647: Add support for regulator control. X-Git-Tag: submit/tizen/20220208.074352~379 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e331e963c21dd809e4649ecd6dba25f8e1ac93c5;p=platform%2Fkernel%2Flinux-rpi.git media: i2c: ov5647: Add support for regulator control. The driver supported using GPIOs to control the shutdown line, but no regulator control. Add regulator hooks. Signed-off-by: Dave Stevenson --- diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index b92c074..3b7a158 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,15 @@ #define OV5647_EXPOSURE_DEFAULT 1000 #define OV5647_EXPOSURE_MAX 65535 +/* regulator supplies */ +static const char * const ov5647_supply_names[] = { + "avdd", /* Analog power */ + "dovdd", /* Digital I/O power */ + "dvdd", /* Digital core power */ +}; + +#define OV5647_NUM_SUPPLIES ARRAY_SIZE(ov5647_supply_names) + struct regval_list { u16 addr; u8 data; @@ -120,6 +130,7 @@ struct ov5647 { int power_count; struct clk *xclk; struct gpio_desc *pwdn; + struct regulator_bulk_data supplies[OV5647_NUM_SUPPLIES]; unsigned int flags; struct v4l2_ctrl_handler ctrls; struct v4l2_ctrl *pixel_rate; @@ -949,6 +960,13 @@ static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) if (on && !ov5647->power_count) { dev_dbg(&client->dev, "OV5647 power on\n"); + ret = regulator_bulk_enable(OV5647_NUM_SUPPLIES, + ov5647->supplies); + if (ret < 0) { + dev_err(&client->dev, "Failed to enable regulators\n"); + goto out; + } + if (ov5647->pwdn) { gpiod_set_value_cansleep(ov5647->pwdn, 0); msleep(PWDN_ACTIVE_DELAY_MS); @@ -956,6 +974,8 @@ static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) ret = clk_prepare_enable(ov5647->xclk); if (ret < 0) { + regulator_bulk_disable(OV5647_NUM_SUPPLIES, + ov5647->supplies); dev_err(&client->dev, "clk prepare enable failed\n"); goto out; } @@ -964,6 +984,8 @@ static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) ARRAY_SIZE(sensor_oe_enable_regs)); if (ret < 0) { clk_disable_unprepare(ov5647->xclk); + regulator_bulk_disable(OV5647_NUM_SUPPLIES, + ov5647->supplies); dev_err(&client->dev, "write sensor_oe_enable_regs error\n"); goto out; @@ -975,6 +997,8 @@ static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) ret = ov5647_stream_off(sd); if (ret < 0) { clk_disable_unprepare(ov5647->xclk); + regulator_bulk_disable(OV5647_NUM_SUPPLIES, + ov5647->supplies); dev_err(&client->dev, "Camera not available, check Power\n"); goto out; @@ -999,6 +1023,8 @@ static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) clk_disable_unprepare(ov5647->xclk); gpiod_set_value_cansleep(ov5647->pwdn, 1); + + regulator_bulk_disable(OV5647_NUM_SUPPLIES, ov5647->supplies); } /* Update the power count. */ @@ -1557,6 +1583,18 @@ static const struct v4l2_ctrl_ops ov5647_ctrl_ops = { .s_ctrl = ov5647_s_ctrl, }; +static int ov5647_configure_regulators(struct device *dev, + struct ov5647 *ov5647) +{ + unsigned int i; + + for (i = 0; i < OV5647_NUM_SUPPLIES; i++) + ov5647->supplies[i].supply = ov5647_supply_names[i]; + + return devm_regulator_bulk_get(dev, OV5647_NUM_SUPPLIES, + ov5647->supplies); +} + static int ov5647_probe(struct i2c_client *client) { struct device *dev = &client->dev; @@ -1597,6 +1635,12 @@ static int ov5647_probe(struct i2c_client *client) sensor->pwdn = devm_gpiod_get_optional(&client->dev, "pwdn", GPIOD_OUT_HIGH); + ret = ov5647_configure_regulators(dev, sensor); + if (ret) { + dev_err(dev, "Failed to get power regulators\n"); + return ret; + } + mutex_init(&sensor->lock); /* Initialise controls. */ @@ -1701,6 +1745,12 @@ static int ov5647_probe(struct i2c_client *client) if (ret < 0) goto mutex_remove; + ret = regulator_bulk_enable(OV5647_NUM_SUPPLIES, sensor->supplies); + if (ret < 0) { + dev_err(dev, "Failed to enable regulators\n"); + goto error; + } + if (sensor->pwdn) { gpiod_set_value_cansleep(sensor->pwdn, 0); msleep(PWDN_ACTIVE_DELAY_MS); @@ -1711,7 +1761,7 @@ static int ov5647_probe(struct i2c_client *client) gpiod_set_value_cansleep(sensor->pwdn, 1); if (ret < 0) - goto error; + goto power_down; ret = v4l2_async_register_subdev(sd); if (ret < 0) @@ -1719,6 +1769,8 @@ static int ov5647_probe(struct i2c_client *client) dev_dbg(dev, "OmniVision OV5647 camera driver probed\n"); return 0; +power_down: + regulator_bulk_disable(OV5647_NUM_SUPPLIES, sensor->supplies); error: media_entity_cleanup(&sd->entity); mutex_remove: