summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/backlight/qcom-wled.c74
1 files changed, 63 insertions, 11 deletions
diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c
index 3ce3bade3b8d..ca350f320e17 100644
--- a/drivers/video/backlight/qcom-wled.c
+++ b/drivers/video/backlight/qcom-wled.c
@@ -290,6 +290,50 @@ static int wled5_set_brightness(struct wled *wled, u16 brightness)
return rc;
}
+static int wled_read_brightness(struct wled *wled)
+{
+ u16 addr, mask;
+ __le16 v;
+ u32 val;
+ int rc;
+
+ rc = regmap_read(wled->regmap, wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN,
+ &val);
+ if (rc < 0)
+ return rc;
+
+ if (!(val & WLED3_CTRL_REG_MOD_EN_MASK))
+ return 0;
+
+ switch (wled->version) {
+ case 3:
+ addr = wled->sink_addr +
+ WLED3_SINK_REG_BRIGHT(wled->cfg.enabled_strings[0]);
+ mask = WLED3_SINK_REG_BRIGHT_MAX;
+ break;
+ case 4:
+ addr = wled->sink_addr +
+ WLED4_SINK_REG_BRIGHT(wled->cfg.enabled_strings[0]);
+ mask = WLED3_SINK_REG_BRIGHT_MAX;
+ break;
+ case 5:
+ addr = wled->sink_addr + (wled->cfg.mod_sel == MOD_A ?
+ WLED5_SINK_REG_MOD_A_BRIGHTNESS_LSB :
+ WLED5_SINK_REG_MOD_B_BRIGHTNESS_LSB);
+ mask = WLED5_SINK_REG_BRIGHT_MAX_15B;
+ break;
+ default:
+ dev_err(wled->dev, "Invalid WLED version\n");
+ return -EINVAL;
+ }
+
+ rc = regmap_bulk_read(wled->regmap, addr, &v, sizeof(v));
+ if (rc < 0)
+ return rc;
+
+ return min_t(u32, le16_to_cpu(v) & mask, wled->max_brightness);
+}
+
static void wled_ovp_work(struct work_struct *work)
{
struct wled *wled = container_of(work,
@@ -480,6 +524,18 @@ unlock_mutex:
return rc;
}
+static int wled_get_brightness(struct backlight_device *bl)
+{
+ struct wled *wled = bl_get_data(bl);
+ int rc;
+
+ mutex_lock(&wled->lock);
+ rc = wled_read_brightness(wled);
+ mutex_unlock(&wled->lock);
+
+ return rc;
+}
+
static int wled4_cabc_config(struct wled *wled, bool enable)
{
int i, j, rc;
@@ -1651,6 +1707,7 @@ static int wled_configure_ovp_irq(struct wled *wled,
static const struct backlight_ops wled_ops = {
.update_status = wled_update_status,
+ .get_brightness = wled_get_brightness,
};
static int wled_probe(struct platform_device *pdev)
@@ -1659,7 +1716,6 @@ static int wled_probe(struct platform_device *pdev)
struct backlight_device *bl;
struct wled *wled;
struct regmap *regmap;
- u32 mod_en;
u32 val;
int rc;
@@ -1734,19 +1790,15 @@ static int wled_probe(struct platform_device *pdev)
of_property_read_u32(pdev->dev.of_node, "default-brightness", &val);
/*
- * The module may already be enabled, either by a bootloader that left
- * the backlight lit or by the setup above. Record that, so that the
- * first brightness update does not enable an already enabled module,
- * and so that the OVP irq is armed from probe rather than from that
- * first update.
+ * The module may already be lit, either by the bootloader or by the
+ * setup above. Start from what the hardware is driving, so that the
+ * first brightness update does not step the brightness.
*/
- rc = regmap_read(wled->regmap, wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN,
- &mod_en);
+ rc = wled_read_brightness(wled);
if (rc < 0)
return rc;
- if (mod_en & WLED3_CTRL_REG_MOD_EN_MASK)
- wled->brightness = val;
+ wled->brightness = rc;
rc = wled_configure_short_irq(wled, pdev);
if (rc < 0)
@@ -1758,7 +1810,7 @@ static int wled_probe(struct platform_device *pdev)
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_RAW;
- props.brightness = val;
+ props.brightness = wled->brightness ?: val;
props.max_brightness = wled->max_brightness;
bl = devm_backlight_device_register(&pdev->dev, wled->name,
&pdev->dev, wled,