Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+120 -14
+26
Documentation/ABI/testing/sysfs-class-backlight
··· 1 + What: /sys/class/backlight/<backlight>/scale 2 + Date: July 2019 3 + KernelVersion: 5.4 4 + Contact: Daniel Thompson <daniel.thompson@linaro.org> 5 + Description: 6 + Description of the scale of the brightness curve. 7 + 8 + The human eye senses brightness approximately logarithmically, 9 + hence linear changes in brightness are perceived as being 10 + non-linear. To achieve a linear perception of brightness changes 11 + controls like sliders need to apply a logarithmic mapping for 12 + backlights with a linear brightness curve. 13 + 14 + Possible values of the attribute are: 15 + 16 + unknown 17 + The scale of the brightness curve is unknown. 18 + 19 + linear 20 + The brightness changes linearly with each step. Brightness 21 + controls should apply a logarithmic mapping for a linear 22 + perception. 23 + 24 + non-linear 25 + The brightness changes non-linearly with each step. Brightness 26 + controls should use a linear mapping for a linear perception.
+2
MAINTAINERS
··· 2921 2921 F: include/linux/backlight.h 2922 2922 F: include/linux/pwm_backlight.h 2923 2923 F: Documentation/devicetree/bindings/leds/backlight 2924 + F: Documentation/ABI/stable/sysfs-class-backlight 2925 + F: Documentation/ABI/testing/sysfs-class-backlight 2924 2926 2925 2927 BATMAN ADVANCED 2926 2928 M: Marek Lindner <mareklindner@neomailbox.ch>
-2
drivers/video/backlight/Kconfig
··· 10 10 # 11 11 config LCD_CLASS_DEVICE 12 12 tristate "Lowlevel LCD controls" 13 - default m 14 13 help 15 14 This framework adds support for low-level control of LCD. 16 15 Some framebuffer devices connect to platform-specific LCD modules ··· 142 143 # 143 144 config BACKLIGHT_CLASS_DEVICE 144 145 tristate "Lowlevel Backlight controls" 145 - default m 146 146 help 147 147 This framework adds support for low-level control of the LCD 148 148 backlight. This includes support for brightness and power.
+19
drivers/video/backlight/backlight.c
··· 32 32 [BACKLIGHT_FIRMWARE] = "firmware", 33 33 }; 34 34 35 + static const char *const backlight_scale_types[] = { 36 + [BACKLIGHT_SCALE_UNKNOWN] = "unknown", 37 + [BACKLIGHT_SCALE_LINEAR] = "linear", 38 + [BACKLIGHT_SCALE_NON_LINEAR] = "non-linear", 39 + }; 40 + 35 41 #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ 36 42 defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)) 37 43 /* This callback gets called when something important happens inside a ··· 252 246 } 253 247 static DEVICE_ATTR_RO(actual_brightness); 254 248 249 + static ssize_t scale_show(struct device *dev, 250 + struct device_attribute *attr, char *buf) 251 + { 252 + struct backlight_device *bd = to_backlight_device(dev); 253 + 254 + if (WARN_ON(bd->props.scale > BACKLIGHT_SCALE_NON_LINEAR)) 255 + return sprintf(buf, "unknown\n"); 256 + 257 + return sprintf(buf, "%s\n", backlight_scale_types[bd->props.scale]); 258 + } 259 + static DEVICE_ATTR_RO(scale); 260 + 255 261 static struct class *backlight_class; 256 262 257 263 #ifdef CONFIG_PM_SLEEP ··· 310 292 &dev_attr_brightness.attr, 311 293 &dev_attr_actual_brightness.attr, 312 294 &dev_attr_max_brightness.attr, 295 + &dev_attr_scale.attr, 313 296 &dev_attr_type.attr, 314 297 NULL, 315 298 };
+20 -4
drivers/video/backlight/gpio_backlight.c
··· 59 59 struct gpio_backlight *gbl) 60 60 { 61 61 struct device *dev = &pdev->dev; 62 - enum gpiod_flags flags; 63 62 int ret; 64 63 65 64 gbl->def_value = device_property_read_bool(dev, "default-on"); 66 - flags = gbl->def_value ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; 67 65 68 - gbl->gpiod = devm_gpiod_get(dev, NULL, flags); 66 + gbl->gpiod = devm_gpiod_get(dev, NULL, GPIOD_ASIS); 69 67 if (IS_ERR(gbl->gpiod)) { 70 68 ret = PTR_ERR(gbl->gpiod); 71 69 ··· 76 78 77 79 return 0; 78 80 } 81 + 82 + static int gpio_backlight_initial_power_state(struct gpio_backlight *gbl) 83 + { 84 + struct device_node *node = gbl->dev->of_node; 85 + 86 + /* Not booted with device tree or no phandle link to the node */ 87 + if (!node || !node->phandle) 88 + return gbl->def_value ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; 89 + 90 + /* if the enable GPIO is disabled, do not enable the backlight */ 91 + if (gpiod_get_value_cansleep(gbl->gpiod) == 0) 92 + return FB_BLANK_POWERDOWN; 93 + 94 + return FB_BLANK_UNBLANK; 95 + } 96 + 79 97 80 98 static int gpio_backlight_probe(struct platform_device *pdev) 81 99 { ··· 150 136 return PTR_ERR(bl); 151 137 } 152 138 153 - bl->props.brightness = gbl->def_value; 139 + bl->props.power = gpio_backlight_initial_power_state(gbl); 140 + bl->props.brightness = 1; 141 + 154 142 backlight_update_status(bl); 155 143 156 144 platform_set_drvdata(pdev, bl);
+1 -2
drivers/video/backlight/lm3630a_bl.c
··· 377 377 u32 sources[LM3630A_NUM_SINKS]; 378 378 int ret, num_sources, i; 379 379 380 - num_sources = fwnode_property_read_u32_array(node, "led-sources", NULL, 381 - 0); 380 + num_sources = fwnode_property_count_u32(node, "led-sources"); 382 381 if (num_sources < 0) 383 382 return default_led_sources; 384 383 else if (num_sources > ARRAY_SIZE(sources))
+1 -1
drivers/video/backlight/lms283gf05.c
··· 158 158 ret = devm_gpio_request_one(&spi->dev, pdata->reset_gpio, 159 159 GPIOF_DIR_OUT | (!pdata->reset_inverted ? 160 160 GPIOF_INIT_HIGH : GPIOF_INIT_LOW), 161 - "LMS285GF05 RESET"); 161 + "LMS283GF05 RESET"); 162 162 if (ret) 163 163 return ret; 164 164 }
+34 -1
drivers/video/backlight/pwm_bl.c
··· 387 387 } 388 388 #endif 389 389 390 + static bool pwm_backlight_is_linear(struct platform_pwm_backlight_data *data) 391 + { 392 + unsigned int nlevels = data->max_brightness + 1; 393 + unsigned int min_val = data->levels[0]; 394 + unsigned int max_val = data->levels[nlevels - 1]; 395 + /* 396 + * Multiplying by 128 means that even in pathological cases such 397 + * as (max_val - min_val) == nlevels the error at max_val is less 398 + * than 1%. 399 + */ 400 + unsigned int slope = (128 * (max_val - min_val)) / nlevels; 401 + unsigned int margin = (max_val - min_val) / 20; /* 5% */ 402 + int i; 403 + 404 + for (i = 1; i < nlevels; i++) { 405 + unsigned int linear_value = min_val + ((i * slope) / 128); 406 + unsigned int delta = abs(linear_value - data->levels[i]); 407 + 408 + if (delta > margin) 409 + return false; 410 + } 411 + 412 + return true; 413 + } 414 + 390 415 static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb) 391 416 { 392 417 struct device_node *node = pb->dev->of_node; ··· 561 536 goto err_alloc; 562 537 } 563 538 539 + memset(&props, 0, sizeof(struct backlight_properties)); 540 + 564 541 if (data->levels) { 565 542 /* 566 543 * For the DT case, only when brightness levels is defined ··· 575 548 576 549 pb->levels = data->levels; 577 550 } 551 + 552 + if (pwm_backlight_is_linear(data)) 553 + props.scale = BACKLIGHT_SCALE_LINEAR; 554 + else 555 + props.scale = BACKLIGHT_SCALE_NON_LINEAR; 578 556 } else if (!data->max_brightness) { 579 557 /* 580 558 * If no brightness levels are provided and max_brightness is ··· 606 574 607 575 pb->levels = data->levels; 608 576 } 577 + 578 + props.scale = BACKLIGHT_SCALE_NON_LINEAR; 609 579 } else { 610 580 /* 611 581 * That only happens for the non-DT case, where platform data ··· 618 584 619 585 pb->lth_brightness = data->lth_brightness * (state.period / pb->scale); 620 586 621 - memset(&props, 0, sizeof(struct backlight_properties)); 622 587 props.type = BACKLIGHT_RAW; 623 588 props.max_brightness = data->max_brightness; 624 589 bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
+8 -2
drivers/video/backlight/rave-sp-backlight.c
··· 48 48 struct device *dev = &pdev->dev; 49 49 struct backlight_device *bd; 50 50 51 - bd = devm_backlight_device_register(dev, pdev->name, dev->parent, 51 + bd = devm_backlight_device_register(dev, pdev->name, dev, 52 52 dev_get_drvdata(dev->parent), 53 53 &rave_sp_backlight_ops, 54 54 &rave_sp_backlight_props); 55 55 if (IS_ERR(bd)) 56 56 return PTR_ERR(bd); 57 57 58 - backlight_update_status(bd); 58 + /* 59 + * If there is a phandle pointing to the device node we can 60 + * assume that another device will manage the status changes. 61 + * If not we make sure the backlight is in a consistent state. 62 + */ 63 + if (!dev->of_node->phandle) 64 + backlight_update_status(bd); 59 65 60 66 return 0; 61 67 }
+1 -2
drivers/video/backlight/tosa_lcd.c
··· 222 222 { 223 223 struct tosa_lcd_data *data = spi_get_drvdata(spi); 224 224 225 - if (data->i2c) 226 - i2c_unregister_device(data->i2c); 225 + i2c_unregister_device(data->i2c); 227 226 228 227 tosa_lcd_tg_off(data); 229 228
+8
include/linux/backlight.h
··· 46 46 BACKLIGHT_UNREGISTERED, 47 47 }; 48 48 49 + enum backlight_scale { 50 + BACKLIGHT_SCALE_UNKNOWN = 0, 51 + BACKLIGHT_SCALE_LINEAR, 52 + BACKLIGHT_SCALE_NON_LINEAR, 53 + }; 54 + 49 55 struct backlight_device; 50 56 struct fb_info; 51 57 ··· 86 80 enum backlight_type type; 87 81 /* Flags used to signal drivers of state changes */ 88 82 unsigned int state; 83 + /* Type of the brightness scale (linear, non-linear, ...) */ 84 + enum backlight_scale scale; 89 85 90 86 #define BL_CORE_SUSPENDED (1 << 0) /* backlight is suspended */ 91 87 #define BL_CORE_FBBLANK (1 << 1) /* backlight is under an fb blank event */