Commit 5665eee7 authored by Dave Stevenson's avatar Dave Stevenson Committed by Mark Brown

regulator: rpi-panel: Handle I2C errors/timing to the Atmel

The Atmel is doing some things in the I2C ISR, during which
period it will not respond to further commands. This is
particularly true of the POWERON command.

Increase delays appropriately, and retry should I2C errors be
reported.
Signed-off-by: default avatarDave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: default avatarDetlev Casanova <detlev.casanova@collabora.com>
Link: https://lore.kernel.org/r/20220124220129.158891-3-detlev.casanova@collabora.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 7291e7d6
...@@ -37,11 +37,24 @@ static const struct regmap_config attiny_regmap_config = { ...@@ -37,11 +37,24 @@ static const struct regmap_config attiny_regmap_config = {
static int attiny_lcd_power_enable(struct regulator_dev *rdev) static int attiny_lcd_power_enable(struct regulator_dev *rdev)
{ {
unsigned int data; unsigned int data;
int ret, i;
regmap_write(rdev->regmap, REG_POWERON, 1); regmap_write(rdev->regmap, REG_POWERON, 1);
msleep(80);
/* Wait for nPWRDWN to go low to indicate poweron is done. */ /* Wait for nPWRDWN to go low to indicate poweron is done. */
regmap_read_poll_timeout(rdev->regmap, REG_PORTB, data, for (i = 0; i < 20; i++) {
data & BIT(0), 10, 1000000); ret = regmap_read(rdev->regmap, REG_PORTB, &data);
if (!ret) {
if (data & BIT(0))
break;
}
usleep_range(10000, 12000);
}
usleep_range(10000, 12000);
if (ret)
pr_err("%s: regmap_read_poll_timeout failed %d\n", __func__, ret);
/* Default to the same orientation as the closed source /* Default to the same orientation as the closed source
* firmware used for the panel. Runtime rotation * firmware used for the panel. Runtime rotation
...@@ -57,23 +70,34 @@ static int attiny_lcd_power_disable(struct regulator_dev *rdev) ...@@ -57,23 +70,34 @@ static int attiny_lcd_power_disable(struct regulator_dev *rdev)
{ {
regmap_write(rdev->regmap, REG_PWM, 0); regmap_write(rdev->regmap, REG_PWM, 0);
regmap_write(rdev->regmap, REG_POWERON, 0); regmap_write(rdev->regmap, REG_POWERON, 0);
udelay(1); msleep(30);
return 0; return 0;
} }
static int attiny_lcd_power_is_enabled(struct regulator_dev *rdev) static int attiny_lcd_power_is_enabled(struct regulator_dev *rdev)
{ {
unsigned int data; unsigned int data;
int ret; int ret, i;
ret = regmap_read(rdev->regmap, REG_POWERON, &data); for (i = 0; i < 10; i++) {
ret = regmap_read(rdev->regmap, REG_POWERON, &data);
if (!ret)
break;
usleep_range(10000, 12000);
}
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!(data & BIT(0))) if (!(data & BIT(0)))
return 0; return 0;
ret = regmap_read(rdev->regmap, REG_PORTB, &data); for (i = 0; i < 10; i++) {
ret = regmap_read(rdev->regmap, REG_PORTB, &data);
if (!ret)
break;
usleep_range(10000, 12000);
}
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -103,20 +127,32 @@ static int attiny_update_status(struct backlight_device *bl) ...@@ -103,20 +127,32 @@ static int attiny_update_status(struct backlight_device *bl)
{ {
struct regmap *regmap = bl_get_data(bl); struct regmap *regmap = bl_get_data(bl);
int brightness = bl->props.brightness; int brightness = bl->props.brightness;
int ret, i;
if (bl->props.power != FB_BLANK_UNBLANK || if (bl->props.power != FB_BLANK_UNBLANK ||
bl->props.fb_blank != FB_BLANK_UNBLANK) bl->props.fb_blank != FB_BLANK_UNBLANK)
brightness = 0; brightness = 0;
return regmap_write(regmap, REG_PWM, brightness); for (i = 0; i < 10; i++) {
ret = regmap_write(regmap, REG_PWM, brightness);
if (!ret)
break;
}
return ret;
} }
static int attiny_get_brightness(struct backlight_device *bl) static int attiny_get_brightness(struct backlight_device *bl)
{ {
struct regmap *regmap = bl_get_data(bl); struct regmap *regmap = bl_get_data(bl);
int ret, brightness; int ret, brightness, i;
for (i = 0; i < 10; i++) {
ret = regmap_read(regmap, REG_PWM, &brightness);
if (!ret)
break;
}
ret = regmap_read(regmap, REG_PWM, &brightness);
if (ret) if (ret)
return ret; return ret;
...@@ -166,7 +202,7 @@ static int attiny_i2c_probe(struct i2c_client *i2c, ...@@ -166,7 +202,7 @@ static int attiny_i2c_probe(struct i2c_client *i2c,
} }
regmap_write(regmap, REG_POWERON, 0); regmap_write(regmap, REG_POWERON, 0);
mdelay(1); msleep(30);
config.dev = &i2c->dev; config.dev = &i2c->dev;
config.regmap = regmap; config.regmap = regmap;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment