diff options
| -rw-r--r-- | drivers/video/backlight/qcom-wled.c | 74 |
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, |
