summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-09-23 19:33:56 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2019-09-23 19:33:56 -0700
commitd0b3cfee333eb7eecb6ce72f06f5a02d249b9bdf (patch)
treebd884989b8e0d08a64cb40384819a6e670ccf470
parent299d14d4c31aff3b37a03894e012edf8421676ee (diff)
parentc0b64faf0fe6ca2574a00faed1ae833130db4e08 (diff)
downloadlinux-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-backlight26
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/video/backlight/Kconfig2
-rw-r--r--drivers/video/backlight/backlight.c19
-rw-r--r--drivers/video/backlight/gpio_backlight.c24
-rw-r--r--drivers/video/backlight/lm3630a_bl.c3
-rw-r--r--drivers/video/backlight/lms283gf05.c2
-rw-r--r--drivers/video/backlight/pwm_bl.c35
-rw-r--r--drivers/video/backlight/rave-sp-backlight.c10
-rw-r--r--drivers/video/backlight/tosa_lcd.c3
-rw-r--r--include/linux/backlight.h8
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 */