Commit 0a8d6c9c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'backlight-next-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight

Pull backlight updates from Lee Jones:
 "New Functionality:
   - Add lots of Device Tree bindings / support
   - Turn off LED strings when display is blank
   - Switch I2C drivers from .probe_new() to .probe()
   - Remove superfluous NULL checks
   - Only obtain PWM information once and do it in .probe()

  Fix-ups:
   - Ensure locks are obtained and held when required"

* tag 'backlight-next-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight:
  backlight: led_bl: Take led_access lock when required
  video: backlight: lp855x: Get PWM for PWM mode during probe
  dt-bindings: backlight: lp855x: Convert to YAML and modernize
  dt-bindings: backlight: pwm: Make power-supply not required
  backlight: pwm_bl: Remove unneeded checks for valid GPIOs
  backlight: Switch i2c drivers back to use .probe()
  backlight: lm3630a: Turn off both led strings when display is blank
  dt-bindings: leds: backlight: ktz8866: Add reg property and update example
parents c156d4af a33677b9
...@@ -21,6 +21,9 @@ properties: ...@@ -21,6 +21,9 @@ properties:
compatible: compatible:
const: kinetic,ktz8866 const: kinetic,ktz8866
reg:
maxItems: 1
vddpos-supply: vddpos-supply:
description: positive boost supply regulator. description: positive boost supply regulator.
...@@ -54,6 +57,7 @@ properties: ...@@ -54,6 +57,7 @@ properties:
required: required:
- compatible - compatible
- reg
- vddpos-supply - vddpos-supply
- vddneg-supply - vddneg-supply
- enable-gpios - enable-gpios
...@@ -64,14 +68,19 @@ examples: ...@@ -64,14 +68,19 @@ examples:
- | - |
#include <dt-bindings/gpio/gpio.h> #include <dt-bindings/gpio/gpio.h>
backlight { i2c {
compatible = "kinetic,ktz8866"; #address-cells = <1>;
#size-cells = <0>;
vddpos-supply = <&bl_vddpos_5p5>;
vddneg-supply = <&bl_vddneg_5p5>; backlight@11 {
enable-gpios = <&tlmm 139 GPIO_ACTIVE_HIGH>; compatible = "kinetic,ktz8866";
current-num-sinks = <5>; reg = <0x11>;
kinetic,current-ramp-delay-ms = <128>; vddpos-supply = <&bl_vddpos_5p5>;
kinetic,led-enable-ramp-delay-ms = <1>; vddneg-supply = <&bl_vddneg_5p5>;
kinetic,enable-lcd-bias; enable-gpios = <&tlmm 139 GPIO_ACTIVE_HIGH>;
current-num-sinks = <5>;
kinetic,current-ramp-delay-ms = <128>;
kinetic,led-enable-ramp-delay-ms = <1>;
kinetic,enable-lcd-bias;
};
}; };
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/leds/backlight/lp855x-backlight.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments LP855X backlight controllers
maintainers:
- Artur Weber <aweber.kernel@gmail.com>
properties:
compatible:
enum:
- ti,lp8550
- ti,lp8551
- ti,lp8552
- ti,lp8553
- ti,lp8555
- ti,lp8556
- ti,lp8557
reg:
maxItems: 1
dev-ctrl:
$ref: /schemas/types.yaml#/definitions/uint8
description:
Value of device control register. This is a device-specific value.
bl-name:
$ref: /schemas/types.yaml#/definitions/string
description: Backlight device name.
init-brt:
$ref: /schemas/types.yaml#/definitions/uint8
description: Initial value of backlight brightness.
power-supply:
description: Regulator which controls the 3V rail.
enable-supply:
description: Regulator which controls the EN/VDDIO input.
pwms:
maxItems: 1
description: |
PWM channel to use for controlling the backlight; setting this
enables the PWM-based backlight control mode.
pwm-names: true
pwm-period:
$ref: /schemas/types.yaml#/definitions/uint32
description:
PWM period value. Deprecated; set the period value in the pwms
property instead.
deprecated: true
patternProperties:
"^rom-[0-9a-f]{2}h$":
type: object
description: Nodes containing the values of configuration registers.
additionalProperties: false
properties:
rom-addr:
$ref: /schemas/types.yaml#/definitions/uint8
description: Register address of ROM area to be updated.
rom-val:
$ref: /schemas/types.yaml#/definitions/uint8
description: Value to write to the ROM register.
required:
- compatible
- reg
- dev-ctrl
unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
backlight@2c {
compatible = "ti,lp8555";
reg = <0x2c>;
dev-ctrl = /bits/ 8 <0x00>;
pwms = <&pwm 0 10000>;
pwm-names = "lp8555";
/* 4V OV, 4 output LED0 string enabled */
rom-14h {
rom-addr = /bits/ 8 <0x14>;
rom-val = /bits/ 8 <0xcf>;
};
/* Heavy smoothing, 24ms ramp time step */
rom-15h {
rom-addr = /bits/ 8 <0x15>;
rom-val = /bits/ 8 <0xc7>;
};
/* 4 output LED1 string enabled */
rom-19h {
rom-addr = /bits/ 8 <0x19>;
rom-val = /bits/ 8 <0x0f>;
};
};
};
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
backlight@2c {
compatible = "ti,lp8556";
reg = <0x2c>;
bl-name = "lcd-bl";
dev-ctrl = /bits/ 8 <0x85>;
init-brt = /bits/ 8 <0x10>;
};
};
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
backlight@2c {
compatible = "ti,lp8557";
reg = <0x2c>;
enable-supply = <&backlight_vddio>;
power-supply = <&backlight_vdd>;
dev-ctrl = /bits/ 8 <0x41>;
init-brt = /bits/ 8 <0x0a>;
/* 4V OV, 4 output LED string enabled */
rom-14h {
rom-addr = /bits/ 8 <0x14>;
rom-val = /bits/ 8 <0xcf>;
};
};
};
lp855x bindings
Required properties:
- compatible: "ti,lp8550", "ti,lp8551", "ti,lp8552", "ti,lp8553",
"ti,lp8555", "ti,lp8556", "ti,lp8557"
- reg: I2C slave address (u8)
- dev-ctrl: Value of DEVICE CONTROL register (u8). It depends on the device.
Optional properties:
- bl-name: Backlight device name (string)
- init-brt: Initial value of backlight brightness (u8)
- pwm-period: PWM period value. Set only PWM input mode used (u32)
- rom-addr: Register address of ROM area to be updated (u8)
- rom-val: Register value to be updated (u8)
- power-supply: Regulator which controls the 3V rail
- enable-supply: Regulator which controls the EN/VDDIO input
Example:
/* LP8555 */
backlight@2c {
compatible = "ti,lp8555";
reg = <0x2c>;
dev-ctrl = /bits/ 8 <0x00>;
pwm-period = <10000>;
/* 4V OV, 4 output LED0 string enabled */
rom_14h {
rom-addr = /bits/ 8 <0x14>;
rom-val = /bits/ 8 <0xcf>;
};
/* Heavy smoothing, 24ms ramp time step */
rom_15h {
rom-addr = /bits/ 8 <0x15>;
rom-val = /bits/ 8 <0xc7>;
};
/* 4 output LED1 string enabled */
rom_19h {
rom-addr = /bits/ 8 <0x19>;
rom-val = /bits/ 8 <0x0f>;
};
};
/* LP8556 */
backlight@2c {
compatible = "ti,lp8556";
reg = <0x2c>;
bl-name = "lcd-bl";
dev-ctrl = /bits/ 8 <0x85>;
init-brt = /bits/ 8 <0x10>;
};
/* LP8557 */
backlight@2c {
compatible = "ti,lp8557";
reg = <0x2c>;
enable-supply = <&backlight_vddio>;
power-supply = <&backlight_vdd>;
dev-ctrl = /bits/ 8 <0x41>;
init-brt = /bits/ 8 <0x0a>;
/* 4V OV, 4 output LED string enabled */
rom_14h {
rom-addr = /bits/ 8 <0x14>;
rom-val = /bits/ 8 <0xcf>;
};
};
...@@ -68,7 +68,6 @@ dependencies: ...@@ -68,7 +68,6 @@ dependencies:
required: required:
- compatible - compatible
- pwms - pwms
- power-supply
additionalProperties: false additionalProperties: false
......
...@@ -803,8 +803,8 @@ static struct i2c_driver adp8860_driver = { ...@@ -803,8 +803,8 @@ static struct i2c_driver adp8860_driver = {
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
.pm = &adp8860_i2c_pm_ops, .pm = &adp8860_i2c_pm_ops,
}, },
.probe_new = adp8860_probe, .probe = adp8860_probe,
.remove = adp8860_remove, .remove = adp8860_remove,
.id_table = adp8860_id, .id_table = adp8860_id,
}; };
......
...@@ -973,8 +973,8 @@ static struct i2c_driver adp8870_driver = { ...@@ -973,8 +973,8 @@ static struct i2c_driver adp8870_driver = {
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
.pm = &adp8870_i2c_pm_ops, .pm = &adp8870_i2c_pm_ops,
}, },
.probe_new = adp8870_probe, .probe = adp8870_probe,
.remove = adp8870_remove, .remove = adp8870_remove,
.id_table = adp8870_id, .id_table = adp8870_id,
}; };
......
...@@ -392,7 +392,7 @@ static struct i2c_driver arcxcnn_driver = { ...@@ -392,7 +392,7 @@ static struct i2c_driver arcxcnn_driver = {
.name = "arcxcnn_bl", .name = "arcxcnn_bl",
.of_match_table = arcxcnn_dt_ids, .of_match_table = arcxcnn_dt_ids,
}, },
.probe_new = arcxcnn_probe, .probe = arcxcnn_probe,
.remove = arcxcnn_remove, .remove = arcxcnn_remove,
.id_table = arcxcnn_ids, .id_table = arcxcnn_ids,
}; };
......
...@@ -192,7 +192,7 @@ static struct i2c_driver bd6107_driver = { ...@@ -192,7 +192,7 @@ static struct i2c_driver bd6107_driver = {
.driver = { .driver = {
.name = "bd6107", .name = "bd6107",
}, },
.probe_new = bd6107_probe, .probe = bd6107_probe,
.remove = bd6107_remove, .remove = bd6107_remove,
.id_table = bd6107_ids, .id_table = bd6107_ids,
}; };
......
...@@ -196,7 +196,7 @@ static struct i2c_driver ktz8866_driver = { ...@@ -196,7 +196,7 @@ static struct i2c_driver ktz8866_driver = {
.name = "ktz8866", .name = "ktz8866",
.of_match_table = ktz8866_match_table, .of_match_table = ktz8866_match_table,
}, },
.probe_new = ktz8866_probe, .probe = ktz8866_probe,
.remove = ktz8866_remove, .remove = ktz8866_remove,
.id_table = ktz8866_ids, .id_table = ktz8866_ids,
}; };
......
...@@ -209,8 +209,11 @@ static int led_bl_probe(struct platform_device *pdev) ...@@ -209,8 +209,11 @@ static int led_bl_probe(struct platform_device *pdev)
return PTR_ERR(priv->bl_dev); return PTR_ERR(priv->bl_dev);
} }
for (i = 0; i < priv->nb_leds; i++) for (i = 0; i < priv->nb_leds; i++) {
mutex_lock(&priv->leds[i]->led_access);
led_sysfs_disable(priv->leds[i]); led_sysfs_disable(priv->leds[i]);
mutex_unlock(&priv->leds[i]->led_access);
}
backlight_update_status(priv->bl_dev); backlight_update_status(priv->bl_dev);
......
...@@ -202,7 +202,9 @@ static int lm3630a_bank_a_update_status(struct backlight_device *bl) ...@@ -202,7 +202,9 @@ static int lm3630a_bank_a_update_status(struct backlight_device *bl)
usleep_range(1000, 2000); usleep_range(1000, 2000);
/* minimum brightness is 0x04 */ /* minimum brightness is 0x04 */
ret = lm3630a_write(pchip, REG_BRT_A, bl->props.brightness); ret = lm3630a_write(pchip, REG_BRT_A, bl->props.brightness);
if (bl->props.brightness < 0x4)
if (backlight_is_blank(bl) || (backlight_get_brightness(bl) < 0x4))
/* turn the string off */
ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDA_ENABLE, 0); ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDA_ENABLE, 0);
else else
ret |= lm3630a_update(pchip, REG_CTRL, ret |= lm3630a_update(pchip, REG_CTRL,
...@@ -277,7 +279,9 @@ static int lm3630a_bank_b_update_status(struct backlight_device *bl) ...@@ -277,7 +279,9 @@ static int lm3630a_bank_b_update_status(struct backlight_device *bl)
usleep_range(1000, 2000); usleep_range(1000, 2000);
/* minimum brightness is 0x04 */ /* minimum brightness is 0x04 */
ret = lm3630a_write(pchip, REG_BRT_B, bl->props.brightness); ret = lm3630a_write(pchip, REG_BRT_B, bl->props.brightness);
if (bl->props.brightness < 0x4)
if (backlight_is_blank(bl) || (backlight_get_brightness(bl) < 0x4))
/* turn the string off */
ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, 0); ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, 0);
else else
ret |= lm3630a_update(pchip, REG_CTRL, ret |= lm3630a_update(pchip, REG_CTRL,
...@@ -616,7 +620,7 @@ static struct i2c_driver lm3630a_i2c_driver = { ...@@ -616,7 +620,7 @@ static struct i2c_driver lm3630a_i2c_driver = {
.name = LM3630A_NAME, .name = LM3630A_NAME,
.of_match_table = lm3630a_match_table, .of_match_table = lm3630a_match_table,
}, },
.probe_new = lm3630a_probe, .probe = lm3630a_probe,
.remove = lm3630a_remove, .remove = lm3630a_remove,
.id_table = lm3630a_id, .id_table = lm3630a_id,
}; };
......
...@@ -411,7 +411,7 @@ static struct i2c_driver lm3639_i2c_driver = { ...@@ -411,7 +411,7 @@ static struct i2c_driver lm3639_i2c_driver = {
.driver = { .driver = {
.name = LM3639_NAME, .name = LM3639_NAME,
}, },
.probe_new = lm3639_probe, .probe = lm3639_probe,
.remove = lm3639_remove, .remove = lm3639_remove,
.id_table = lm3639_id, .id_table = lm3639_id,
}; };
......
...@@ -218,23 +218,10 @@ static int lp855x_configure(struct lp855x *lp) ...@@ -218,23 +218,10 @@ static int lp855x_configure(struct lp855x *lp)
static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br) static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br)
{ {
struct pwm_device *pwm;
struct pwm_state state; struct pwm_state state;
/* request pwm device with the consumer name */ pwm_get_state(lp->pwm, &state);
if (!lp->pwm) {
pwm = devm_pwm_get(lp->dev, lp->chipname);
if (IS_ERR(pwm))
return;
lp->pwm = pwm;
pwm_init_state(lp->pwm, &state);
} else {
pwm_get_state(lp->pwm, &state);
}
state.period = lp->pdata->period_ns;
state.duty_cycle = div_u64(br * state.period, max_br); state.duty_cycle = div_u64(br * state.period, max_br);
state.enabled = state.duty_cycle; state.enabled = state.duty_cycle;
...@@ -339,6 +326,7 @@ static int lp855x_parse_dt(struct lp855x *lp) ...@@ -339,6 +326,7 @@ static int lp855x_parse_dt(struct lp855x *lp)
of_property_read_string(node, "bl-name", &pdata->name); of_property_read_string(node, "bl-name", &pdata->name);
of_property_read_u8(node, "dev-ctrl", &pdata->device_control); of_property_read_u8(node, "dev-ctrl", &pdata->device_control);
of_property_read_u8(node, "init-brt", &pdata->initial_brightness); of_property_read_u8(node, "init-brt", &pdata->initial_brightness);
/* Deprecated, specify period in pwms property instead */
of_property_read_u32(node, "pwm-period", &pdata->period_ns); of_property_read_u32(node, "pwm-period", &pdata->period_ns);
/* Fill ROM platform data if defined */ /* Fill ROM platform data if defined */
...@@ -399,6 +387,7 @@ static int lp855x_probe(struct i2c_client *cl) ...@@ -399,6 +387,7 @@ static int lp855x_probe(struct i2c_client *cl)
const struct i2c_device_id *id = i2c_client_get_device_id(cl); const struct i2c_device_id *id = i2c_client_get_device_id(cl);
const struct acpi_device_id *acpi_id = NULL; const struct acpi_device_id *acpi_id = NULL;
struct device *dev = &cl->dev; struct device *dev = &cl->dev;
struct pwm_state pwmstate;
struct lp855x *lp; struct lp855x *lp;
int ret; int ret;
...@@ -457,11 +446,6 @@ static int lp855x_probe(struct i2c_client *cl) ...@@ -457,11 +446,6 @@ static int lp855x_probe(struct i2c_client *cl)
} }
} }
if (lp->pdata->period_ns > 0)
lp->mode = PWM_BASED;
else
lp->mode = REGISTER_BASED;
lp->supply = devm_regulator_get(dev, "power"); lp->supply = devm_regulator_get(dev, "power");
if (IS_ERR(lp->supply)) { if (IS_ERR(lp->supply)) {
if (PTR_ERR(lp->supply) == -EPROBE_DEFER) if (PTR_ERR(lp->supply) == -EPROBE_DEFER)
...@@ -472,11 +456,31 @@ static int lp855x_probe(struct i2c_client *cl) ...@@ -472,11 +456,31 @@ static int lp855x_probe(struct i2c_client *cl)
lp->enable = devm_regulator_get_optional(dev, "enable"); lp->enable = devm_regulator_get_optional(dev, "enable");
if (IS_ERR(lp->enable)) { if (IS_ERR(lp->enable)) {
ret = PTR_ERR(lp->enable); ret = PTR_ERR(lp->enable);
if (ret == -ENODEV) { if (ret == -ENODEV)
lp->enable = NULL; lp->enable = NULL;
} else { else
return dev_err_probe(dev, ret, "getting enable regulator\n"); return dev_err_probe(dev, ret, "getting enable regulator\n");
} }
lp->pwm = devm_pwm_get(lp->dev, lp->chipname);
if (IS_ERR(lp->pwm)) {
ret = PTR_ERR(lp->pwm);
if (ret == -ENODEV || ret == -EINVAL)
lp->pwm = NULL;
else
return dev_err_probe(dev, ret, "getting PWM\n");
lp->mode = REGISTER_BASED;
dev_dbg(dev, "mode: register based\n");
} else {
pwm_init_state(lp->pwm, &pwmstate);
/* Legacy platform data compatibility */
if (lp->pdata->period_ns > 0)
pwmstate.period = lp->pdata->period_ns;
pwm_apply_state(lp->pwm, &pwmstate);
lp->mode = PWM_BASED;
dev_dbg(dev, "mode: PWM based\n");
} }
if (lp->supply) { if (lp->supply) {
...@@ -587,7 +591,7 @@ static struct i2c_driver lp855x_driver = { ...@@ -587,7 +591,7 @@ static struct i2c_driver lp855x_driver = {
.of_match_table = of_match_ptr(lp855x_dt_ids), .of_match_table = of_match_ptr(lp855x_dt_ids),
.acpi_match_table = ACPI_PTR(lp855x_acpi_match), .acpi_match_table = ACPI_PTR(lp855x_acpi_match),
}, },
.probe_new = lp855x_probe, .probe = lp855x_probe,
.remove = lp855x_remove, .remove = lp855x_remove,
.id_table = lp855x_ids, .id_table = lp855x_ids,
}; };
......
...@@ -141,7 +141,7 @@ static struct i2c_driver lv5207lp_driver = { ...@@ -141,7 +141,7 @@ static struct i2c_driver lv5207lp_driver = {
.driver = { .driver = {
.name = "lv5207lp", .name = "lv5207lp",
}, },
.probe_new = lv5207lp_probe, .probe = lv5207lp_probe,
.remove = lv5207lp_remove, .remove = lv5207lp_remove,
.id_table = lv5207lp_ids, .id_table = lv5207lp_ids,
}; };
......
...@@ -54,8 +54,7 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb) ...@@ -54,8 +54,7 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb)
if (pb->post_pwm_on_delay) if (pb->post_pwm_on_delay)
msleep(pb->post_pwm_on_delay); msleep(pb->post_pwm_on_delay);
if (pb->enable_gpio) gpiod_set_value_cansleep(pb->enable_gpio, 1);
gpiod_set_value_cansleep(pb->enable_gpio, 1);
pb->enabled = true; pb->enabled = true;
} }
...@@ -65,8 +64,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb) ...@@ -65,8 +64,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb)
if (!pb->enabled) if (!pb->enabled)
return; return;
if (pb->enable_gpio) gpiod_set_value_cansleep(pb->enable_gpio, 0);
gpiod_set_value_cansleep(pb->enable_gpio, 0);
if (pb->pwm_off_delay) if (pb->pwm_off_delay)
msleep(pb->pwm_off_delay); msleep(pb->pwm_off_delay);
...@@ -429,8 +427,7 @@ static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb) ...@@ -429,8 +427,7 @@ static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
* Synchronize the enable_gpio with the observed state of the * Synchronize the enable_gpio with the observed state of the
* hardware. * hardware.
*/ */
if (pb->enable_gpio) gpiod_direction_output(pb->enable_gpio, active);
gpiod_direction_output(pb->enable_gpio, active);
/* /*
* Do not change pb->enabled here! pb->enabled essentially * Do not change pb->enabled here! pb->enabled essentially
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment