media: i2c: gc2145/gc0312 pwdn inactive during out of work

when multiple camera using same dvp data, pwdn shuld
be off during out of work.

Change-Id: I9a12c3e9f5d7b82922b0b5a797288da7ac486448
Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
Cai YiWei
2018-09-07 15:19:04 +08:00
committed by Tao Huang
parent 01beb00127
commit 8ec459b808
2 changed files with 101 additions and 57 deletions

View File

@@ -534,7 +534,7 @@ static int gc0312_read(struct i2c_client *client, u8 reg, u8 *val)
}
dev_err(&client->dev,
"gc0312 read reg(0x%x val:0x%x) failed !\n", reg, *val);
"gc0312 read reg:0x%x failed !\n", reg);
return ret;
}
@@ -668,7 +668,7 @@ static void __gc0312_try_frame_size(struct v4l2_mbus_framefmt *mf,
unsigned int min_err = UINT_MAX;
while (i--) {
int err = abs(fsize->width - mf->width)
unsigned int err = abs(fsize->width - mf->width)
+ abs(fsize->height - mf->height);
if (err < min_err && fsize->regs[0].addr) {
min_err = err;
@@ -755,9 +755,18 @@ static int gc0312_s_stream(struct v4l2_subdev *sd, int on)
/* Stop Streaming Sequence */
gc0312_set_streaming(gc0312, 0x00);
gc0312->streaming = on;
if (!IS_ERR(gc0312->pwdn_gpio)) {
gpiod_set_value_cansleep(gc0312->pwdn_gpio, 1);
usleep_range(2000, 5000);
}
goto unlock;
}
if (!IS_ERR(gc0312->pwdn_gpio)) {
gpiod_set_value_cansleep(gc0312->pwdn_gpio, 0);
usleep_range(2000, 5000);
}
ret = gc0312_write_array(client, gc0312->frame_size->regs);
if (ret)
goto unlock;
@@ -857,9 +866,9 @@ static const struct v4l2_subdev_internal_ops gc0312_subdev_internal_ops = {
};
#endif
static int gc0312_detect(struct v4l2_subdev *sd)
static int gc0312_detect(struct gc0312 *gc0312)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct i2c_client *client = gc0312->client;
u8 pid, ver;
int ret;
@@ -881,6 +890,8 @@ static int gc0312_detect(struct v4l2_subdev *sd)
id, ret);
} else {
dev_info(&client->dev, "Found GC%04X sensor\n", id);
if (!IS_ERR(gc0312->pwdn_gpio))
gpiod_set_value_cansleep(gc0312->pwdn_gpio, 1);
}
}
@@ -892,36 +903,50 @@ static int __gc0312_power_on(struct gc0312 *gc0312)
int ret;
struct device *dev = &gc0312->client->dev;
ret = clk_set_rate(gc0312->xvclk, 24000000);
if (ret < 0)
dev_info(dev, "Failed to set xvclk rate (24MHz)\n");
if (!IS_ERR(gc0312->xvclk)) {
ret = clk_set_rate(gc0312->xvclk, 24000000);
if (ret < 0)
dev_info(dev, "Failed to set xvclk rate (24MHz)\n");
}
gpiod_set_value_cansleep(gc0312->pwdn_gpio, 1);
usleep_range(2000, 5000);
if (!IS_ERR(gc0312->pwdn_gpio)) {
gpiod_set_value_cansleep(gc0312->pwdn_gpio, 1);
usleep_range(2000, 5000);
}
ret = regulator_bulk_enable(GC0312_NUM_SUPPLIES, gc0312->supplies);
if (ret < 0)
dev_info(dev, "Failed to enable regulators\n");
if (!IS_ERR(gc0312->supplies)) {
ret = regulator_bulk_enable(GC0312_NUM_SUPPLIES,
gc0312->supplies);
if (ret < 0)
dev_info(dev, "Failed to enable regulators\n");
usleep_range(20000, 50000);
usleep_range(2000, 5000);
}
gpiod_set_value_cansleep(gc0312->pwdn_gpio, 0);
usleep_range(2000, 5000);
if (!IS_ERR(gc0312->pwdn_gpio)) {
gpiod_set_value_cansleep(gc0312->pwdn_gpio, 0);
usleep_range(2000, 5000);
}
ret = clk_prepare_enable(gc0312->xvclk);
if (ret < 0)
dev_info(dev, "Failed to enable xvclk\n");
if (!IS_ERR(gc0312->xvclk)) {
ret = clk_prepare_enable(gc0312->xvclk);
if (ret < 0)
dev_info(dev, "Failed to enable xvclk\n");
}
usleep_range(70000, 100000);
usleep_range(7000, 10000);
return 0;
}
static void __gc0312_power_off(struct gc0312 *gc0312)
{
clk_disable_unprepare(gc0312->xvclk);
regulator_bulk_disable(GC0312_NUM_SUPPLIES, gc0312->supplies);
gpiod_set_value_cansleep(gc0312->pwdn_gpio, 1);
if (!IS_ERR(gc0312->xvclk))
clk_disable_unprepare(gc0312->xvclk);
if (!IS_ERR(gc0312->supplies))
regulator_bulk_disable(GC0312_NUM_SUPPLIES, gc0312->supplies);
if (!IS_ERR(gc0312->pwdn_gpio))
gpiod_set_value_cansleep(gc0312->pwdn_gpio, 1);
}
static int gc0312_configure_regulators(struct gc0312 *gc0312)
@@ -942,10 +967,8 @@ static int gc0312_parse_of(struct gc0312 *gc0312)
int ret;
gc0312->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
if (IS_ERR(gc0312->pwdn_gpio)) {
dev_info(dev, "Failed to get pwdn-gpios\n");
return 0;
}
if (IS_ERR(gc0312->pwdn_gpio))
dev_info(dev, "Failed to get pwdn-gpios, maybe no used\n");
ret = gc0312_configure_regulators(gc0312);
if (ret)
@@ -1023,7 +1046,7 @@ static int gc0312_probe(struct i2c_client *client,
gc0312_get_default_format(&gc0312->format);
gc0312->frame_size = &gc0312_framesizes[0];
ret = gc0312_detect(sd);
ret = gc0312_detect(gc0312);
if (ret < 0)
goto error;

View File

@@ -1091,7 +1091,7 @@ static int gc2145_read(struct i2c_client *client, u8 reg, u8 *val)
}
dev_err(&client->dev,
"gc2145 read reg(0x%x val:0x%x) failed !\n", reg, *val);
"gc2145 read reg:0x%x failed !\n", reg);
return ret;
}
@@ -1222,11 +1222,11 @@ static void __gc2145_try_frame_size_fps(struct v4l2_mbus_framefmt *mf,
{
const struct gc2145_framesize *fsize = &gc2145_framesizes[0];
const struct gc2145_framesize *match = NULL;
int i = ARRAY_SIZE(gc2145_framesizes);
unsigned int i = ARRAY_SIZE(gc2145_framesizes);
unsigned int min_err = UINT_MAX;
while (i--) {
int err = abs(fsize->width - mf->width)
unsigned int err = abs(fsize->width - mf->width)
+ abs(fsize->height - mf->height);
if (err < min_err && fsize->regs[0].addr) {
min_err = err;
@@ -1325,8 +1325,16 @@ static int gc2145_s_stream(struct v4l2_subdev *sd, int on)
/* Stop Streaming Sequence */
gc2145_set_streaming(gc2145, 0x00);
gc2145->streaming = on;
if (!IS_ERR(gc2145->pwdn_gpio)) {
gpiod_set_value_cansleep(gc2145->pwdn_gpio, 1);
usleep_range(2000, 5000);
}
goto unlock;
}
if (!IS_ERR(gc2145->pwdn_gpio)) {
gpiod_set_value_cansleep(gc2145->pwdn_gpio, 0);
usleep_range(2000, 5000);
}
ret = gc2145_write_array(client, gc2145_init_regs);
if (ret)
@@ -1479,9 +1487,9 @@ static const struct v4l2_subdev_internal_ops gc2145_subdev_internal_ops = {
};
#endif
static int gc2145_detect(struct v4l2_subdev *sd)
static int gc2145_detect(struct gc2145 *gc2145)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct i2c_client *client = gc2145->client;
u8 pid, ver;
int ret;
@@ -1503,6 +1511,8 @@ static int gc2145_detect(struct v4l2_subdev *sd)
id, ret);
} else {
dev_info(&client->dev, "Found GC%04X sensor\n", id);
if (!IS_ERR(gc2145->pwdn_gpio))
gpiod_set_value_cansleep(gc2145->pwdn_gpio, 1);
}
}
@@ -1514,36 +1524,49 @@ static int __gc2145_power_on(struct gc2145 *gc2145)
int ret;
struct device *dev = &gc2145->client->dev;
ret = clk_set_rate(gc2145->xvclk, 24000000);
if (ret < 0)
dev_info(dev, "Failed to set xvclk rate (24MHz)\n");
if (!IS_ERR(gc2145->xvclk)) {
ret = clk_set_rate(gc2145->xvclk, 24000000);
if (ret < 0)
dev_info(dev, "Failed to set xvclk rate (24MHz)\n");
}
gpiod_set_value_cansleep(gc2145->pwdn_gpio, 1);
usleep_range(2000, 5000);
if (!IS_ERR(gc2145->pwdn_gpio)) {
gpiod_set_value_cansleep(gc2145->pwdn_gpio, 1);
usleep_range(2000, 5000);
}
ret = regulator_bulk_enable(GC2145_NUM_SUPPLIES, gc2145->supplies);
if (ret < 0)
dev_info(dev, "Failed to enable regulators\n");
if (!IS_ERR(gc2145->supplies)) {
ret = regulator_bulk_enable(GC2145_NUM_SUPPLIES,
gc2145->supplies);
if (ret < 0)
dev_info(dev, "Failed to enable regulators\n");
usleep_range(20000, 50000);
usleep_range(20000, 50000);
}
gpiod_set_value_cansleep(gc2145->pwdn_gpio, 0);
usleep_range(2000, 5000);
if (!IS_ERR(gc2145->pwdn_gpio)) {
gpiod_set_value_cansleep(gc2145->pwdn_gpio, 0);
usleep_range(2000, 5000);
}
ret = clk_prepare_enable(gc2145->xvclk);
if (ret < 0)
dev_info(dev, "Failed to enable xvclk\n");
usleep_range(70000, 100000);
if (!IS_ERR(gc2145->xvclk)) {
ret = clk_prepare_enable(gc2145->xvclk);
if (ret < 0)
dev_info(dev, "Failed to enable xvclk\n");
}
usleep_range(7000, 10000);
return 0;
}
static void __gc2145_power_off(struct gc2145 *gc2145)
{
clk_disable_unprepare(gc2145->xvclk);
regulator_bulk_disable(GC2145_NUM_SUPPLIES, gc2145->supplies);
gpiod_set_value_cansleep(gc2145->pwdn_gpio, 1);
if (!IS_ERR(gc2145->xvclk))
clk_disable_unprepare(gc2145->xvclk);
if (!IS_ERR(gc2145->supplies))
regulator_bulk_disable(GC2145_NUM_SUPPLIES, gc2145->supplies);
if (!IS_ERR(gc2145->pwdn_gpio))
gpiod_set_value_cansleep(gc2145->pwdn_gpio, 1);
}
static int gc2145_configure_regulators(struct gc2145 *gc2145)
@@ -1564,10 +1587,8 @@ static int gc2145_parse_of(struct gc2145 *gc2145)
int ret;
gc2145->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
if (IS_ERR(gc2145->pwdn_gpio)) {
dev_info(dev, "Failed to get pwdn-gpios\n");
return 0;
}
if (IS_ERR(gc2145->pwdn_gpio))
dev_info(dev, "Failed to get pwdn-gpios, maybe no use\n");
ret = gc2145_configure_regulators(gc2145);
if (ret)
@@ -1646,9 +1667,9 @@ static int gc2145_probe(struct i2c_client *client,
gc2145->frame_size = &gc2145_framesizes[0];
gc2145->format.width = gc2145_framesizes[0].width;
gc2145->format.height = gc2145_framesizes[0].height;
gc2145->fps = 0;
gc2145->fps = gc2145_framesizes[0].fps;
ret = gc2145_detect(sd);
ret = gc2145_detect(gc2145);
if (ret < 0)
goto error;