diff options
| author | Val Packett <val@packett.cool> | 2025-09-20 15:03:47 +0300 |
|---|---|---|
| committer | Hans Verkuil <hverkuil+cisco@kernel.org> | 2025-10-29 15:47:16 +0300 |
| commit | a4b325c23e0453cff1bcec260dfd4bc092a11285 (patch) | |
| tree | 3e6e89419a934b8090e6017b980d1a94dbe40701 /drivers | |
| parent | 5e18755738632d3c5aaaddd45b76520f78e6d8d4 (diff) | |
| download | linux-a4b325c23e0453cff1bcec260dfd4bc092a11285.tar.xz | |
media: i2c: dw9719: Fix power on/off sequence
The "jiggle" code was not actually expecting failure, which it should
because that's what actually happens when the device wasn't already woken
up by the regulator power-on (i.e. in the case of a shared regulator).
Also, do actually enter the internal suspend mode on shutdown, to save
power in the case of a shared regulator.
Also, wait a bit longer (2x tOPR) on waking up, 1x is not enough at least
on the DW9718S as found on the motorola-nora smartphone.
Signed-off-by: Val Packett <val@packett.cool>
Signed-off-by: André Apitzsch <git@apitzsch.eu>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/media/i2c/dw9719.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/drivers/media/i2c/dw9719.c b/drivers/media/i2c/dw9719.c index a24594523030..3627e78b8b66 100644 --- a/drivers/media/i2c/dw9719.c +++ b/drivers/media/i2c/dw9719.c @@ -95,12 +95,20 @@ struct dw9719_device { static int dw9719_power_down(struct dw9719_device *dw9719) { + u32 reg_pwr = dw9719->model == DW9718S ? DW9718S_PD : DW9719_CONTROL; + + /* + * Worth engaging the internal SHUTDOWN mode especially due to the + * regulator being potentially shared with other devices. + */ + if (cci_write(dw9719->regmap, reg_pwr, DW9719_SHUTDOWN, NULL)) + dev_err(dw9719->dev, "Error writing to power register\n"); return regulator_disable(dw9719->regulator); } static int dw9719_power_up(struct dw9719_device *dw9719, bool detect) { - u32 reg_pwr; + u32 reg_pwr = dw9719->model == DW9718S ? DW9718S_PD : DW9719_CONTROL; u64 val; int ret; int err; @@ -109,13 +117,17 @@ static int dw9719_power_up(struct dw9719_device *dw9719, bool detect) if (ret) return ret; - /* Jiggle SCL pin to wake up device */ - reg_pwr = dw9719->model == DW9718S ? DW9718S_PD : DW9719_CONTROL; - cci_write(dw9719->regmap, reg_pwr, DW9719_SHUTDOWN, &ret); - fsleep(100); + /* + * Need 100us to transition from SHUTDOWN to STANDBY. + * Jiggle the SCL pin to wake up the device (even when the regulator is + * shared) and wait double the time to be sure, as 100us is not enough + * at least on the DW9718S as found on the motorola-nora smartphone, + * then retry the write. + */ + cci_write(dw9719->regmap, reg_pwr, DW9719_STANDBY, NULL); + /* the jiggle is expected to fail, don't even log that as error */ + fsleep(200); cci_write(dw9719->regmap, reg_pwr, DW9719_STANDBY, &ret); - /* Need 100us to transit from SHUTDOWN to STANDBY */ - fsleep(100); if (detect) { /* This model does not have an INFO register */ |
