diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-23 19:33:56 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-23 19:33:56 -0700 |
commit | d0b3cfee333eb7eecb6ce72f06f5a02d249b9bdf (patch) | |
tree | bd884989b8e0d08a64cb40384819a6e670ccf470 | |
parent | 299d14d4c31aff3b37a03894e012edf8421676ee (diff) | |
parent | c0b64faf0fe6ca2574a00faed1ae833130db4e08 (diff) | |
download | linux-d0b3cfee333eb7eecb6ce72f06f5a02d249b9bdf.tar.bz2 |
Merge tag 'backlight-next-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight
Pull backlight updates from Lee Jones:
"Core Frameworks
- Obtain scale type through sysfs
New Functionality:
- Provide Device Tree functionality in rave-sp-backlight
- Calculate if scale type is (non-)linear in pwm_bl
Fix-ups:
- Simplify code in lm3630a_bl
- Trivial rename/whitespace/typo fixes in lms283gf05
- Remove superfluous NULL check in tosa_lcd
- Fix power state initialisation in gpio_backlight
- List supported file in MAINTAINERS
Bug Fixes:
- Kconfig - default to not building unless requested in
{LED,BACKLIGHT}_CLASS_DEVICE"
* tag 'backlight-next-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight:
backlight: pwm_bl: Set scale type for brightness curves specified in the DT
backlight: pwm_bl: Set scale type for CIE 1931 curves
backlight: Expose brightness curve type through sysfs
MAINTAINERS: Add entry for stable backlight sysfs ABI documentation
backlight: gpio-backlight: Correct initial power state handling
video: backlight: tosa_lcd: drop check because i2c_unregister_device() is NULL safe
video: backlight: Drop default m for {LCD,BACKLIGHT_CLASS_DEVICE}
backlight: lms283gf05: Fix a typo in the description passed to 'devm_gpio_request_one()'
backlight: lm3630a: Switch to use fwnode_property_count_uXX()
backlight: rave-sp: Leave initial state and register with correct device
-rw-r--r-- | Documentation/ABI/testing/sysfs-class-backlight | 26 | ||||
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rw-r--r-- | drivers/video/backlight/Kconfig | 2 | ||||
-rw-r--r-- | drivers/video/backlight/backlight.c | 19 | ||||
-rw-r--r-- | drivers/video/backlight/gpio_backlight.c | 24 | ||||
-rw-r--r-- | drivers/video/backlight/lm3630a_bl.c | 3 | ||||
-rw-r--r-- | drivers/video/backlight/lms283gf05.c | 2 | ||||
-rw-r--r-- | drivers/video/backlight/pwm_bl.c | 35 | ||||
-rw-r--r-- | drivers/video/backlight/rave-sp-backlight.c | 10 | ||||
-rw-r--r-- | drivers/video/backlight/tosa_lcd.c | 3 | ||||
-rw-r--r-- | include/linux/backlight.h | 8 |
11 files changed, 120 insertions, 14 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-backlight b/Documentation/ABI/testing/sysfs-class-backlight new file mode 100644 index 000000000000..3ab175a3f5cb --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-backlight @@ -0,0 +1,26 @@ +What: /sys/class/backlight/<backlight>/scale +Date: July 2019 +KernelVersion: 5.4 +Contact: Daniel Thompson <daniel.thompson@linaro.org> +Description: + Description of the scale of the brightness curve. + + The human eye senses brightness approximately logarithmically, + hence linear changes in brightness are perceived as being + non-linear. To achieve a linear perception of brightness changes + controls like sliders need to apply a logarithmic mapping for + backlights with a linear brightness curve. + + Possible values of the attribute are: + + unknown + The scale of the brightness curve is unknown. + + linear + The brightness changes linearly with each step. Brightness + controls should apply a logarithmic mapping for a linear + perception. + + non-linear + The brightness changes non-linearly with each step. Brightness + controls should use a linear mapping for a linear perception. diff --git a/MAINTAINERS b/MAINTAINERS index 6ee4bb5f6d30..1360243a7ff3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2921,6 +2921,8 @@ F: drivers/video/backlight/ F: include/linux/backlight.h F: include/linux/pwm_backlight.h F: Documentation/devicetree/bindings/leds/backlight +F: Documentation/ABI/stable/sysfs-class-backlight +F: Documentation/ABI/testing/sysfs-class-backlight BATMAN ADVANCED M: Marek Lindner <mareklindner@neomailbox.ch> diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 8b081d61773e..40676be2e46a 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -10,7 +10,6 @@ menu "Backlight & LCD device support" # config LCD_CLASS_DEVICE tristate "Lowlevel LCD controls" - default m help This framework adds support for low-level control of LCD. Some framebuffer devices connect to platform-specific LCD modules @@ -143,7 +142,6 @@ endif # LCD_CLASS_DEVICE # config BACKLIGHT_CLASS_DEVICE tristate "Lowlevel Backlight controls" - default m help This framework adds support for low-level control of the LCD backlight. This includes support for brightness and power. diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 5dc07106a59e..cac3e35d7630 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -32,6 +32,12 @@ static const char *const backlight_types[] = { [BACKLIGHT_FIRMWARE] = "firmware", }; +static const char *const backlight_scale_types[] = { + [BACKLIGHT_SCALE_UNKNOWN] = "unknown", + [BACKLIGHT_SCALE_LINEAR] = "linear", + [BACKLIGHT_SCALE_NON_LINEAR] = "non-linear", +}; + #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)) /* This callback gets called when something important happens inside a @@ -246,6 +252,18 @@ static ssize_t actual_brightness_show(struct device *dev, } static DEVICE_ATTR_RO(actual_brightness); +static ssize_t scale_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct backlight_device *bd = to_backlight_device(dev); + + if (WARN_ON(bd->props.scale > BACKLIGHT_SCALE_NON_LINEAR)) + return sprintf(buf, "unknown\n"); + + return sprintf(buf, "%s\n", backlight_scale_types[bd->props.scale]); +} +static DEVICE_ATTR_RO(scale); + static struct class *backlight_class; #ifdef CONFIG_PM_SLEEP @@ -292,6 +310,7 @@ static struct attribute *bl_device_attrs[] = { &dev_attr_brightness.attr, &dev_attr_actual_brightness.attr, &dev_attr_max_brightness.attr, + &dev_attr_scale.attr, &dev_attr_type.attr, NULL, }; diff --git a/drivers/video/backlight/gpio_backlight.c b/drivers/video/backlight/gpio_backlight.c index e84f3087e29f..18e053e4716c 100644 --- a/drivers/video/backlight/gpio_backlight.c +++ b/drivers/video/backlight/gpio_backlight.c @@ -59,13 +59,11 @@ static int gpio_backlight_probe_dt(struct platform_device *pdev, struct gpio_backlight *gbl) { struct device *dev = &pdev->dev; - enum gpiod_flags flags; int ret; gbl->def_value = device_property_read_bool(dev, "default-on"); - flags = gbl->def_value ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; - gbl->gpiod = devm_gpiod_get(dev, NULL, flags); + gbl->gpiod = devm_gpiod_get(dev, NULL, GPIOD_ASIS); if (IS_ERR(gbl->gpiod)) { ret = PTR_ERR(gbl->gpiod); @@ -79,6 +77,22 @@ static int gpio_backlight_probe_dt(struct platform_device *pdev, return 0; } +static int gpio_backlight_initial_power_state(struct gpio_backlight *gbl) +{ + struct device_node *node = gbl->dev->of_node; + + /* Not booted with device tree or no phandle link to the node */ + if (!node || !node->phandle) + return gbl->def_value ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; + + /* if the enable GPIO is disabled, do not enable the backlight */ + if (gpiod_get_value_cansleep(gbl->gpiod) == 0) + return FB_BLANK_POWERDOWN; + + return FB_BLANK_UNBLANK; +} + + static int gpio_backlight_probe(struct platform_device *pdev) { struct gpio_backlight_platform_data *pdata = @@ -136,7 +150,9 @@ static int gpio_backlight_probe(struct platform_device *pdev) return PTR_ERR(bl); } - bl->props.brightness = gbl->def_value; + bl->props.power = gpio_backlight_initial_power_state(gbl); + bl->props.brightness = 1; + backlight_update_status(bl); platform_set_drvdata(pdev, bl); diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c index b04b35d007a2..2d8e8192e4e2 100644 --- a/drivers/video/backlight/lm3630a_bl.c +++ b/drivers/video/backlight/lm3630a_bl.c @@ -377,8 +377,7 @@ static int lm3630a_parse_led_sources(struct fwnode_handle *node, u32 sources[LM3630A_NUM_SINKS]; int ret, num_sources, i; - num_sources = fwnode_property_read_u32_array(node, "led-sources", NULL, - 0); + num_sources = fwnode_property_count_u32(node, "led-sources"); if (num_sources < 0) return default_led_sources; else if (num_sources > ARRAY_SIZE(sources)) diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c index 35bc012b22cc..0e45685bcc1c 100644 --- a/drivers/video/backlight/lms283gf05.c +++ b/drivers/video/backlight/lms283gf05.c @@ -158,7 +158,7 @@ static int lms283gf05_probe(struct spi_device *spi) ret = devm_gpio_request_one(&spi->dev, pdata->reset_gpio, GPIOF_DIR_OUT | (!pdata->reset_inverted ? GPIOF_INIT_HIGH : GPIOF_INIT_LOW), - "LMS285GF05 RESET"); + "LMS283GF05 RESET"); if (ret) return ret; } diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 2201b8c78641..746eebc411df 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -387,6 +387,31 @@ int pwm_backlight_brightness_default(struct device *dev, } #endif +static bool pwm_backlight_is_linear(struct platform_pwm_backlight_data *data) +{ + unsigned int nlevels = data->max_brightness + 1; + unsigned int min_val = data->levels[0]; + unsigned int max_val = data->levels[nlevels - 1]; + /* + * Multiplying by 128 means that even in pathological cases such + * as (max_val - min_val) == nlevels the error at max_val is less + * than 1%. + */ + unsigned int slope = (128 * (max_val - min_val)) / nlevels; + unsigned int margin = (max_val - min_val) / 20; /* 5% */ + int i; + + for (i = 1; i < nlevels; i++) { + unsigned int linear_value = min_val + ((i * slope) / 128); + unsigned int delta = abs(linear_value - data->levels[i]); + + if (delta > margin) + return false; + } + + return true; +} + static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb) { struct device_node *node = pb->dev->of_node; @@ -536,6 +561,8 @@ static int pwm_backlight_probe(struct platform_device *pdev) goto err_alloc; } + memset(&props, 0, sizeof(struct backlight_properties)); + if (data->levels) { /* * For the DT case, only when brightness levels is defined @@ -548,6 +575,11 @@ static int pwm_backlight_probe(struct platform_device *pdev) pb->levels = data->levels; } + + if (pwm_backlight_is_linear(data)) + props.scale = BACKLIGHT_SCALE_LINEAR; + else + props.scale = BACKLIGHT_SCALE_NON_LINEAR; } else if (!data->max_brightness) { /* * If no brightness levels are provided and max_brightness is @@ -574,6 +606,8 @@ static int pwm_backlight_probe(struct platform_device *pdev) pb->levels = data->levels; } + + props.scale = BACKLIGHT_SCALE_NON_LINEAR; } else { /* * That only happens for the non-DT case, where platform data @@ -584,7 +618,6 @@ static int pwm_backlight_probe(struct platform_device *pdev) pb->lth_brightness = data->lth_brightness * (state.period / pb->scale); - memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = data->max_brightness; bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb, diff --git a/drivers/video/backlight/rave-sp-backlight.c b/drivers/video/backlight/rave-sp-backlight.c index 462f14a1b19d..05b5f003a3d1 100644 --- a/drivers/video/backlight/rave-sp-backlight.c +++ b/drivers/video/backlight/rave-sp-backlight.c @@ -48,14 +48,20 @@ static int rave_sp_backlight_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct backlight_device *bd; - bd = devm_backlight_device_register(dev, pdev->name, dev->parent, + bd = devm_backlight_device_register(dev, pdev->name, dev, dev_get_drvdata(dev->parent), &rave_sp_backlight_ops, &rave_sp_backlight_props); if (IS_ERR(bd)) return PTR_ERR(bd); - backlight_update_status(bd); + /* + * If there is a phandle pointing to the device node we can + * assume that another device will manage the status changes. + * If not we make sure the backlight is in a consistent state. + */ + if (!dev->of_node->phandle) + backlight_update_status(bd); return 0; } diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c index 65cb7578776f..29af8e27b6e5 100644 --- a/drivers/video/backlight/tosa_lcd.c +++ b/drivers/video/backlight/tosa_lcd.c @@ -222,8 +222,7 @@ static int tosa_lcd_remove(struct spi_device *spi) { struct tosa_lcd_data *data = spi_get_drvdata(spi); - if (data->i2c) - i2c_unregister_device(data->i2c); + i2c_unregister_device(data->i2c); tosa_lcd_tg_off(data); diff --git a/include/linux/backlight.h b/include/linux/backlight.h index 0b5897446dca..c7d6b2e8c3b5 100644 --- a/include/linux/backlight.h +++ b/include/linux/backlight.h @@ -46,6 +46,12 @@ enum backlight_notification { BACKLIGHT_UNREGISTERED, }; +enum backlight_scale { + BACKLIGHT_SCALE_UNKNOWN = 0, + BACKLIGHT_SCALE_LINEAR, + BACKLIGHT_SCALE_NON_LINEAR, +}; + struct backlight_device; struct fb_info; @@ -80,6 +86,8 @@ struct backlight_properties { enum backlight_type type; /* Flags used to signal drivers of state changes */ unsigned int state; + /* Type of the brightness scale (linear, non-linear, ...) */ + enum backlight_scale scale; #define BL_CORE_SUSPENDED (1 << 0) /* backlight is suspended */ #define BL_CORE_FBBLANK (1 << 1) /* backlight is under an fb blank event */ |