From a785a4ac69a638aba6059bdd547a4ca42c1528ce Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Tue, 11 Jan 2022 09:32:50 +0100 Subject: [PATCH 1/7] media: s5k3l6xx: implement start streaming command sequence Application note REV0.20 cap.3.1 documents the Streaming On command sequence. Implement it. --- drivers/media/i2c/s5k3l6xx.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/s5k3l6xx.c b/drivers/media/i2c/s5k3l6xx.c index 1652ddaf438d..a932b9d61aa4 100644 --- a/drivers/media/i2c/s5k3l6xx.c +++ b/drivers/media/i2c/s5k3l6xx.c @@ -68,6 +68,8 @@ module_param(debug, int, 0644); #define S5K3L6XX_REG_AF 0x3403 #define S5K3L6XX_REG_AF_BIT_FILTER 0b100 +#define S5K3L6XX_REG_PLL_PD 0x3c1e + #define S5K3L6XX_REG_MODE_SELECT 0x100 #define S5K3L6XX_MODE_STREAMING 0x1 #define S5K3L6XX_MODE_STANDBY 0x0 @@ -665,8 +667,29 @@ static int s5k3l6xx_set_power(struct v4l2_subdev *sd, int on) static int s5k3l6xx_hw_set_stream(struct s5k3l6xx *state, int enable) { + int ret; + v4l2_dbg(3, debug, &state->sd, "set_stream %d", enable); - return s5k3l6xx_i2c_write(state, S5K3L6XX_REG_MODE_SELECT, enable ? S5K3L6XX_MODE_STREAMING : S5K3L6XX_MODE_STANDBY); + + if (!enable) { + ret = s5k3l6xx_i2c_write(state, S5K3L6XX_REG_MODE_SELECT, + S5K3L6XX_MODE_STANDBY); + if (ret) + return ret; + + return 0; + } + + ret = s5k3l6xx_i2c_write(state, S5K3L6XX_REG_PLL_PD, 0x01); + if (ret) + return ret; + + ret = s5k3l6xx_i2c_write(state, S5K3L6XX_REG_MODE_SELECT, + S5K3L6XX_MODE_STREAMING); + if (ret) + return ret; + + return s5k3l6xx_i2c_write(state, S5K3L6XX_REG_PLL_PD, 0x00); } static int s5k3l6xx_s_stream(struct v4l2_subdev *sd, int on) -- GitLab From 7fe488ea5c6733fd5eb94955f7ef1c831f7c393c Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Tue, 11 Jan 2022 10:48:14 +0100 Subject: [PATCH 2/7] media: s5k3l6xx: add more delays to power on / off sequence --- drivers/media/i2c/s5k3l6xx.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/s5k3l6xx.c b/drivers/media/i2c/s5k3l6xx.c index a932b9d61aa4..06e5dbcb223f 100644 --- a/drivers/media/i2c/s5k3l6xx.c +++ b/drivers/media/i2c/s5k3l6xx.c @@ -587,8 +587,9 @@ static void s5k3l6xx_gpio_deassert(struct s5k3l6xx *state, int id) static int s5k3l6xx_power_on(struct s5k3l6xx *state) { int ret; + v4l2_dbg(1, debug, &state->sd, "power_ON\n"); - // Will this fail if any regulator is already enabled? + ret = regulator_bulk_enable(S5K3L6XX_NUM_SUPPLIES, state->supplies); if (ret < 0) goto err; @@ -604,8 +605,10 @@ static int s5k3l6xx_power_on(struct s5k3l6xx *state) v4l2_dbg(1, debug, &state->sd, "ON. clock frequency: %ld\n", clk_get_rate(state->clock)); - usleep_range(50, 100); + usleep_range(500, 1000); s5k3l6xx_gpio_deassert(state, RST); + usleep_range(500, 1000); + return 0; err_reg_dis: @@ -618,11 +621,15 @@ static int s5k3l6xx_power_on(struct s5k3l6xx *state) static int s5k3l6xx_power_off(struct s5k3l6xx *state) { int ret; + v4l2_dbg(1, debug, &state->sd, "power_OFF\n"); + state->streaming = 0; state->apply_cfg = 0; state->apply_crop = 0; + usleep_range(500, 1000); + s5k3l6xx_gpio_assert(state, RST); if (!IS_ERR(state->clock)) -- GitLab From b19c8e0b2a4e4cb0c2dc06fe7a58a15492957695 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Tue, 11 Jan 2022 11:23:21 +0100 Subject: [PATCH 3/7] media: s5k3l6xx: remove v4l2_info when sd not initialized yet --- drivers/media/i2c/s5k3l6xx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/i2c/s5k3l6xx.c b/drivers/media/i2c/s5k3l6xx.c index 06e5dbcb223f..47f6b0d21a84 100644 --- a/drivers/media/i2c/s5k3l6xx.c +++ b/drivers/media/i2c/s5k3l6xx.c @@ -1387,7 +1387,6 @@ static int s5k3l6xx_configure_subdevs(struct s5k3l6xx *state, ret = media_entity_pads_init(&sd->entity, NUM_CIS_PADS, &state->cis_pad); if (ret < 0) goto err;*/ - v4l2_info(&state->sd, "probe sd %px", (void*)&state->sd); sd = &state->sd; v4l2_i2c_subdev_init(sd, c, &s5k3l6xx_subdev_ops); v4l2_info(sd, "probe i2c %px", (void*)c); -- GitLab From 042826be1635ce021e6bdde6dd127f690ad3fbfc Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Tue, 11 Jan 2022 12:17:35 +0100 Subject: [PATCH 4/7] media: s5k3l6xx: use gpio_set_value_cansleep we're not in any atomic context, so use the cansleep variant. --- drivers/media/i2c/s5k3l6xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/s5k3l6xx.c b/drivers/media/i2c/s5k3l6xx.c index 47f6b0d21a84..1a0c00b08708 100644 --- a/drivers/media/i2c/s5k3l6xx.c +++ b/drivers/media/i2c/s5k3l6xx.c @@ -571,7 +571,7 @@ static void s5k3l6xx_gpio_assert(struct s5k3l6xx *state, int id) if (gpio == 0) return; - gpio_set_value(gpio->gpio, gpio->level); + gpio_set_value_cansleep(gpio->gpio, gpio->level); } static void s5k3l6xx_gpio_deassert(struct s5k3l6xx *state, int id) @@ -581,7 +581,7 @@ static void s5k3l6xx_gpio_deassert(struct s5k3l6xx *state, int id) if (gpio == 0) return; - gpio_set_value(gpio->gpio, !gpio->level); + gpio_set_value_cansleep(gpio->gpio, !gpio->level); } static int s5k3l6xx_power_on(struct s5k3l6xx *state) -- GitLab From 53a6b1158edce071b4dc4ef2649e4cca22b70e03 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Tue, 11 Jan 2022 12:18:01 +0100 Subject: [PATCH 5/7] media: s5k3l6xx: fix s5k3l6xx_configure_gpios() --- drivers/media/i2c/s5k3l6xx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/i2c/s5k3l6xx.c b/drivers/media/i2c/s5k3l6xx.c index 1a0c00b08708..ef6371f09e21 100644 --- a/drivers/media/i2c/s5k3l6xx.c +++ b/drivers/media/i2c/s5k3l6xx.c @@ -1269,10 +1269,9 @@ static int __maybe_unused s5k3l6xx_resume(struct device *dev) return ret; } -// FIXME: are we even using this? static int s5k3l6xx_configure_gpios(struct s5k3l6xx *state) { - static const char * const name[] = { "S5K5BAF_RST" }; + static const char * const name[] = { "S5K3L6XX_RST" }; struct i2c_client *c = v4l2_get_subdevdata(&state->sd); struct s5k3l6xx_gpio *g = state->gpios; int ret, i; -- GitLab From 182d5f0cb53842970910e2ed74149e201d6002b2 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Tue, 11 Jan 2022 12:37:23 +0100 Subject: [PATCH 6/7] media: s5k3l6xx: remove s_power callback legacy api that's not needed to be implemented. --- drivers/media/i2c/s5k3l6xx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/i2c/s5k3l6xx.c b/drivers/media/i2c/s5k3l6xx.c index ef6371f09e21..ea2643fc5c9e 100644 --- a/drivers/media/i2c/s5k3l6xx.c +++ b/drivers/media/i2c/s5k3l6xx.c @@ -1227,7 +1227,6 @@ static int s5k3l6xx_initialize_ctrls(struct s5k3l6xx *state) * V4L2 subdev internal operations */ static const struct v4l2_subdev_core_ops s5k3l6xx_core_ops = { - .s_power = s5k3l6xx_set_power, .log_status = v4l2_ctrl_subdev_log_status, }; -- GitLab From 902a76b4168ecdb3e852a90eb862a03ce85e07fb Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Tue, 11 Jan 2022 12:37:42 +0100 Subject: [PATCH 7/7] media: s5k3l6xx: remove sleep in resume handle all delays inside of set_power() as part of the power sequencing --- drivers/media/i2c/s5k3l6xx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/i2c/s5k3l6xx.c b/drivers/media/i2c/s5k3l6xx.c index ea2643fc5c9e..83e35cd681e4 100644 --- a/drivers/media/i2c/s5k3l6xx.c +++ b/drivers/media/i2c/s5k3l6xx.c @@ -1260,7 +1260,6 @@ static int __maybe_unused s5k3l6xx_resume(struct device *dev) dev_dbg(dev, "%s\n", __func__); ret = s5k3l6xx_set_power(sd, TRUE); - msleep(500); if (ret == 0 && state->streaming) s5k3l6xx_hw_set_stream(state, 1); -- GitLab