mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-06 07:34:03 -04:00
media: atomisp_gmin_platform: Add enable-count to gmin_[v1p8|v2p8]_ctrl()
On devices with 2 sensors the 2 sensors may get probed simultaneously and the v1p8 and v2p8 regulators are ususally shared between the 2 sensors. This means that the probe() function of sensor 1 may end up calling gmin_v1p8_ctrl(..., false) turning the regulator off while sensor 2's probe() function still needs it to be on, causing the probe() of sensor 2 to sometimes fail. Fix this by adding an enable-count for both regulators and only disabling them again when that goes to 0. Note all this really should be converted to use the standard kernel regulator framework, I have doing this on my long term TODO list, this fix is only meant as a temporary workaround for the issue. Link: https://lore.kernel.org/linux-media/20220116215204.307649-6-hdegoede@redhat.com Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
9bad7640dc
commit
74bfe151d0
@@ -118,6 +118,10 @@ static const char *pmic_name[] = {
|
||||
[PMIC_CRYSTALCOVE] = "Crystal Cove PMIC",
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(gmin_regulator_mutex);
|
||||
static int gmin_v1p8_enable_count;
|
||||
static int gmin_v2p8_enable_count;
|
||||
|
||||
/* The atomisp uses type==0 for the end-of-list marker, so leave space. */
|
||||
static struct intel_v4l2_subdev_table pdata_subdevs[MAX_SUBDEVS + 1];
|
||||
|
||||
@@ -851,38 +855,58 @@ static int gmin_v1p8_ctrl(struct v4l2_subdev *subdev, int on)
|
||||
|
||||
gs->v1p8_on = on;
|
||||
|
||||
ret = 0;
|
||||
mutex_lock(&gmin_regulator_mutex);
|
||||
if (on) {
|
||||
gmin_v1p8_enable_count++;
|
||||
if (gmin_v1p8_enable_count > 1)
|
||||
goto out; /* Already on */
|
||||
} else {
|
||||
gmin_v1p8_enable_count--;
|
||||
if (gmin_v1p8_enable_count > 0)
|
||||
goto out; /* Still needed */
|
||||
}
|
||||
|
||||
if (gs->v1p8_gpio >= 0)
|
||||
gpio_set_value(gs->v1p8_gpio, on);
|
||||
|
||||
if (gs->v1p8_reg) {
|
||||
regulator_set_voltage(gs->v1p8_reg, 1800000, 1800000);
|
||||
if (on)
|
||||
return regulator_enable(gs->v1p8_reg);
|
||||
ret = regulator_enable(gs->v1p8_reg);
|
||||
else
|
||||
return regulator_disable(gs->v1p8_reg);
|
||||
ret = regulator_disable(gs->v1p8_reg);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (pmic_id) {
|
||||
case PMIC_AXP:
|
||||
if (on)
|
||||
return axp_v1p8_on(subdev->dev, gs);
|
||||
ret = axp_v1p8_on(subdev->dev, gs);
|
||||
else
|
||||
return axp_v1p8_off(subdev->dev, gs);
|
||||
ret = axp_v1p8_off(subdev->dev, gs);
|
||||
break;
|
||||
case PMIC_TI:
|
||||
value = on ? LDO_1P8V_ON : LDO_1P8V_OFF;
|
||||
|
||||
return gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
|
||||
LDO10_REG, value, 0xff);
|
||||
ret = gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
|
||||
LDO10_REG, value, 0xff);
|
||||
break;
|
||||
case PMIC_CRYSTALCOVE:
|
||||
value = on ? CRYSTAL_ON : CRYSTAL_OFF;
|
||||
|
||||
return gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
|
||||
CRYSTAL_1P8V_REG, value, 0xff);
|
||||
ret = gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
|
||||
CRYSTAL_1P8V_REG, value, 0xff);
|
||||
break;
|
||||
default:
|
||||
dev_err(subdev->dev, "Couldn't set power mode for v1p2\n");
|
||||
dev_err(subdev->dev, "Couldn't set power mode for v1p8\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
out:
|
||||
mutex_unlock(&gmin_regulator_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gmin_v2p8_ctrl(struct v4l2_subdev *subdev, int on)
|
||||
@@ -908,37 +932,57 @@ static int gmin_v2p8_ctrl(struct v4l2_subdev *subdev, int on)
|
||||
return 0;
|
||||
gs->v2p8_on = on;
|
||||
|
||||
ret = 0;
|
||||
mutex_lock(&gmin_regulator_mutex);
|
||||
if (on) {
|
||||
gmin_v2p8_enable_count++;
|
||||
if (gmin_v2p8_enable_count > 1)
|
||||
goto out; /* Already on */
|
||||
} else {
|
||||
gmin_v2p8_enable_count--;
|
||||
if (gmin_v2p8_enable_count > 0)
|
||||
goto out; /* Still needed */
|
||||
}
|
||||
|
||||
if (gs->v2p8_gpio >= 0)
|
||||
gpio_set_value(gs->v2p8_gpio, on);
|
||||
|
||||
if (gs->v2p8_reg) {
|
||||
regulator_set_voltage(gs->v2p8_reg, 2900000, 2900000);
|
||||
if (on)
|
||||
return regulator_enable(gs->v2p8_reg);
|
||||
ret = regulator_enable(gs->v2p8_reg);
|
||||
else
|
||||
return regulator_disable(gs->v2p8_reg);
|
||||
ret = regulator_disable(gs->v2p8_reg);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (pmic_id) {
|
||||
case PMIC_AXP:
|
||||
return axp_regulator_set(subdev->dev, gs, ALDO1_SEL_REG,
|
||||
ALDO1_2P8V, ALDO1_CTRL3_REG,
|
||||
ALDO1_CTRL3_SHIFT, on);
|
||||
ret = axp_regulator_set(subdev->dev, gs, ALDO1_SEL_REG,
|
||||
ALDO1_2P8V, ALDO1_CTRL3_REG,
|
||||
ALDO1_CTRL3_SHIFT, on);
|
||||
break;
|
||||
case PMIC_TI:
|
||||
value = on ? LDO_2P8V_ON : LDO_2P8V_OFF;
|
||||
|
||||
return gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
|
||||
LDO9_REG, value, 0xff);
|
||||
ret = gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
|
||||
LDO9_REG, value, 0xff);
|
||||
break;
|
||||
case PMIC_CRYSTALCOVE:
|
||||
value = on ? CRYSTAL_ON : CRYSTAL_OFF;
|
||||
|
||||
return gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
|
||||
CRYSTAL_2P8V_REG, value, 0xff);
|
||||
ret = gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
|
||||
CRYSTAL_2P8V_REG, value, 0xff);
|
||||
break;
|
||||
default:
|
||||
dev_err(subdev->dev, "Couldn't set power mode for v1p2\n");
|
||||
dev_err(subdev->dev, "Couldn't set power mode for v2p8\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
out:
|
||||
mutex_unlock(&gmin_regulator_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gmin_acpi_pm_ctrl(struct v4l2_subdev *subdev, int on)
|
||||
|
||||
Reference in New Issue
Block a user