mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 07:03:03 +02:00
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 <dave.stevenson@raspberrypi.com> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
parent
d240430664
commit
e7696f27f8
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
|
|
@ -81,6 +82,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;
|
||||
|
|
@ -102,6 +112,7 @@ struct ov5647 {
|
|||
struct mutex lock;
|
||||
struct clk *xclk;
|
||||
struct gpio_desc *pwdn;
|
||||
struct regulator_bulk_data supplies[OV5647_NUM_SUPPLIES];
|
||||
bool clock_ncont;
|
||||
struct v4l2_ctrl_handler ctrls;
|
||||
const struct ov5647_mode *mode;
|
||||
|
|
@ -777,11 +788,20 @@ static int ov5647_power_on(struct device *dev)
|
|||
|
||||
dev_dbg(dev, "OV5647 power on\n");
|
||||
|
||||
if (sensor->pwdn) {
|
||||
gpiod_set_value_cansleep(sensor->pwdn, 0);
|
||||
msleep(PWDN_ACTIVE_DELAY_MS);
|
||||
ret = regulator_bulk_enable(OV5647_NUM_SUPPLIES, sensor->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpiod_set_value_cansleep(sensor->pwdn, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "pwdn gpio set value failed: %d\n", ret);
|
||||
goto error_reg_disable;
|
||||
}
|
||||
|
||||
msleep(PWDN_ACTIVE_DELAY_MS);
|
||||
|
||||
ret = clk_prepare_enable(sensor->xclk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "clk prepare enable failed\n");
|
||||
|
|
@ -808,6 +828,8 @@ static int ov5647_power_on(struct device *dev)
|
|||
clk_disable_unprepare(sensor->xclk);
|
||||
error_pwdn:
|
||||
gpiod_set_value_cansleep(sensor->pwdn, 1);
|
||||
error_reg_disable:
|
||||
regulator_bulk_disable(OV5647_NUM_SUPPLIES, sensor->supplies);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -837,6 +859,7 @@ static int ov5647_power_off(struct device *dev)
|
|||
|
||||
clk_disable_unprepare(sensor->xclk);
|
||||
gpiod_set_value_cansleep(sensor->pwdn, 1);
|
||||
regulator_bulk_disable(OV5647_NUM_SUPPLIES, sensor->supplies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1284,6 +1307,16 @@ static const struct v4l2_ctrl_ops ov5647_ctrl_ops = {
|
|||
.s_ctrl = ov5647_s_ctrl,
|
||||
};
|
||||
|
||||
static int ov5647_configure_regulators(struct device *dev,
|
||||
struct ov5647 *sensor)
|
||||
{
|
||||
for (unsigned int i = 0; i < OV5647_NUM_SUPPLIES; i++)
|
||||
sensor->supplies[i].supply = ov5647_supply_names[i];
|
||||
|
||||
return devm_regulator_bulk_get(dev, OV5647_NUM_SUPPLIES,
|
||||
sensor->supplies);
|
||||
}
|
||||
|
||||
static int ov5647_init_controls(struct ov5647 *sensor)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd);
|
||||
|
|
@ -1416,6 +1449,10 @@ static int ov5647_probe(struct i2c_client *client)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = ov5647_configure_regulators(dev, sensor);
|
||||
if (ret)
|
||||
dev_err_probe(dev, ret, "Failed to get power regulators\n");
|
||||
|
||||
mutex_init(&sensor->lock);
|
||||
|
||||
sensor->mode = OV5647_DEFAULT_MODE;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user