Commit a4b325c2 authored by Val Packett's avatar Val Packett Committed by Hans Verkuil
Browse files

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: default avatarVal Packett <val@packett.cool>
Signed-off-by: default avatarAndré Apitzsch <git@apitzsch.eu>
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarHans Verkuil <hverkuil+cisco@kernel.org>
parent 5e187557
Loading
Loading
Loading
Loading
+19 −7
Original line number Diff line number Diff line
@@ -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 */