Commit 302d5b33 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull backlight updates from Lee Jones:
 "Core Framework:
   - Add backlight_device_get_by_name() to the API

  New Device Support:
   - Add support for WLED5 to Qualcomm WLED

  Fix-ups:
   - Convert to GPIO descriptors in l4f00242t03
   - Device Tree fix-ups for qcom-wled

  Bug Fixes:
   - Properly disable regulators on .probe() failure"

* tag 'backlight-next-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight:
  backlight: Add backlight_device_get_by_name()
  backlight: qcom-wled: Add support for WLED5 peripheral that is present on PM8150L PMICs
  dt-bindings: backlight: qcom-wled: Add WLED5 bindings
  backlight: qcom-wled: Add callback functions
  dt-bindings: backlight: qcom-wled: Convert the wled bindings to .yaml format
  backlight: l4f00242t03: Convert to GPIO descriptors
  backlight: lp855x: Ensure regulators are disabled on probe failure
parents 512b7d37 479da1f5
Binding for Qualcomm Technologies, Inc. WLED driver
WLED (White Light Emitting Diode) driver is used for controlling display
backlight that is part of PMIC on Qualcomm Technologies, Inc. reference
platforms. The PMIC is connected to the host processor via SPMI bus.
- compatible
Usage: required
Value type: <string>
Definition: should be one of:
"qcom,pm8941-wled"
"qcom,pmi8998-wled"
"qcom,pm660l-wled"
- reg
Usage: required
Value type: <prop encoded array>
Definition: Base address of the WLED modules.
- default-brightness
Usage: optional
Value type: <u32>
Definition: brightness value on boot, value from: 0-4095.
Default: 2048
- label
Usage: required
Value type: <string>
Definition: The name of the backlight device
- qcom,cs-out
Usage: optional
Value type: <bool>
Definition: enable current sink output.
This property is supported only for PM8941.
- qcom,cabc
Usage: optional
Value type: <bool>
Definition: enable content adaptive backlight control.
- qcom,ext-gen
Usage: optional
Value type: <bool>
Definition: use externally generated modulator signal to dim.
This property is supported only for PM8941.
- qcom,current-limit
Usage: optional
Value type: <u32>
Definition: mA; per-string current limit; value from 0 to 25 with
1 mA step. Default 20 mA.
This property is supported only for pm8941.
- qcom,current-limit-microamp
Usage: optional
Value type: <u32>
Definition: uA; per-string current limit; value from 0 to 30000 with
2500 uA step. Default 25 mA.
- qcom,current-boost-limit
Usage: optional
Value type: <u32>
Definition: mA; boost current limit.
For pm8941: one of: 105, 385, 525, 805, 980, 1260, 1400,
1680. Default: 805 mA.
For pmi8998: one of: 105, 280, 450, 620, 970, 1150, 1300,
1500. Default: 970 mA.
- qcom,switching-freq
Usage: optional
Value type: <u32>
Definition: kHz; switching frequency; one of: 600, 640, 685, 738,
800, 872, 960, 1066, 1200, 1371, 1600, 1920, 2400, 3200,
4800, 9600.
Default: for pm8941: 1600 kHz
for pmi8998: 800 kHz
- qcom,ovp
Usage: optional
Value type: <u32>
Definition: V; Over-voltage protection limit; one of:
27, 29, 32, 35. Default: 29V
This property is supported only for PM8941.
- qcom,ovp-millivolt
Usage: optional
Value type: <u32>
Definition: mV; Over-voltage protection limit;
For pmi8998: one of 18100, 19600, 29600, 31100.
Default 29600 mV.
If this property is not specified for PM8941, it
falls back to "qcom,ovp" property.
- qcom,num-strings
Usage: optional
Value type: <u32>
Definition: #; number of led strings attached;
value: For PM8941 from 1 to 3. Default: 2
For PMI8998 from 1 to 4.
- interrupts
Usage: optional
Value type: <prop encoded array>
Definition: Interrupts associated with WLED. This should be
"short" and "ovp" interrupts. Interrupts can be
specified as per the encoding listed under
Documentation/devicetree/bindings/spmi/
qcom,spmi-pmic-arb.txt.
- interrupt-names
Usage: optional
Value type: <string>
Definition: Interrupt names associated with the interrupts.
Must be "short" and "ovp". The short circuit detection
is not supported for PM8941.
- qcom,enabled-strings
Usage: optional
Value tyoe: <u32 array>
Definition: Array of the WLED strings numbered from 0 to 3. Each
string of leds are operated individually. Specify the
list of strings used by the device. Any combination of
led strings can be used.
- qcom,external-pfet
Usage: optional
Value type: <bool>
Definition: Specify if external PFET control for short circuit
protection is used. This property is supported only
for PMI8998.
- qcom,auto-string-detection
Usage: optional
Value type: <bool>
Definition: Enables auto-detection of the WLED string configuration.
This feature is not supported for PM8941.
Example:
pm8941-wled@d800 {
compatible = "qcom,pm8941-wled";
reg = <0xd800>;
label = "backlight";
qcom,cs-out;
qcom,current-limit = <20>;
qcom,current-boost-limit = <805>;
qcom,switching-freq = <1600>;
qcom,ovp = <29>;
qcom,num-strings = <2>;
qcom,enabled-strings = <0 1>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/leds/backlight/qcom-wled.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Binding for Qualcomm Technologies, Inc. WLED driver
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
- Kiran Gunda <kgunda@codeaurora.org>
description: |
WLED (White Light Emitting Diode) driver is used for controlling display
backlight that is part of PMIC on Qualcomm Technologies, Inc. reference
platforms. The PMIC is connected to the host processor via SPMI bus.
properties:
compatible:
enum:
- qcom,pm8941-wled
- qcom,pmi8998-wled
- qcom,pm660l-wled
- qcom,pm8150l-wled
reg:
maxItems: 1
default-brightness:
description: |
brightness value on boot.
label: true
max-brightness:
description: |
Maximum brightness level.
qcom,cs-out:
description: |
enable current sink output.
This property is supported only for WLED3.
type: boolean
qcom,cabc:
description: |
enable content adaptive backlight control.
type: boolean
qcom,ext-gen:
description: |
use externally generated modulator signal to dim.
This property is supported only for WLED3.
type: boolean
qcom,current-limit:
description: |
mA; per-string current limit.
This property is supported only for WLED3.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
default: 20
minimum: 0
maximum: 25
qcom,current-limit-microamp:
description: |
uA; per-string current limit.
default: 25
minimum: 0
maximum: 30000
multipleOf: 25
qcom,current-boost-limit:
description: |
mA; boost current limit.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
qcom,switching-freq:
description: |
kHz; switching frequency.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [ 600, 640, 685, 738, 800, 872, 960, 1066, 1200, 1371, 1600, 1920, 2400, 3200, 4800, 9600 ]
qcom,ovp:
description: |
V; Over-voltage protection limit.
This property is supported only for WLED3.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [ 27, 29, 32, 35 ]
- default: 29
qcom,ovp-millivolt:
description: |
Over-voltage protection limit. This property is for WLED4 only.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [ 18100, 19600, 29600, 31100 ]
- default: 29600
qcom,num-strings:
description: |
number of led strings attached.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
qcom,enabled-strings:
description: |
Array of the WLED strings numbered from 0 to 3. Each
string of leds are operated individually. Specify the
list of strings used by the device. Any combination of
led strings can be used.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 4
qcom,external-pfet:
description: |
Specify if external PFET control for short circuit
protection is used. This property is supported only
for WLED4.
type: boolean
qcom,auto-string-detection:
description: |
Enables auto-detection of the WLED string configuration.
This feature is not supported for WLED3.
type: boolean
interrupts:
minItems: 1
items:
- description: over voltage protection interrupt.
- description: short circuit interrupt.
interrupt-names:
minItems: 1
items:
- const: ovp
- const: short
qcom,modulator-sel:
description: |
Selects the modulator used for brightness modulation.
Allowed values are,
0 - Modulator A
1 - Modulator B
This property is applicable only to WLED5 peripheral.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [ 0, 1 ]
- default: 0
qcom,cabc-sel:
description: |
Selects the CABC pin signal used for brightness modulation.
Allowed values are,
0 - CABC disabled
1 - CABC 1
2 - CABC 2
3 - External signal (e.g. LPG) is used for dimming
This property is applicable only to WLED5 peripheral.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [ 0, 1, 2, 3 ]
allOf:
- if:
properties:
compatible:
contains:
const: qcom,pm8941-wled
then:
properties:
qcom,current-boost-limit:
enum: [ 105, 385, 525, 805, 980, 1260, 1400, 1680 ]
default: 805
qcom,switching-freq:
default: 1600
qcom,num-strings:
enum: [ 1, 2, 3 ]
interrupts:
maxItems: 1
interrupt-names:
maxItems: 1
else:
properties:
qcom,current-boost-limit:
enum: [ 105, 280, 450, 620, 970, 1150, 1300, 1500 ]
default: 970
qcom,switching-freq:
default: 800
qcom,num-strings:
enum: [ 1, 2, 3, 4 ]
interrupts:
minItems: 2
interrupt-names:
minItems: 2
- if:
properties:
compatible:
contains:
enum:
- qcom,pm8150l-wled
then:
properties:
default-brightness:
minimum: 0
maximum: 32767
max-brightness:
minimum: 0
maximum: 32767
else:
properties:
default-brightness:
minimum: 0
maximum: 4095
max-brightness:
minimum: 0
maximum: 4095
required:
- compatible
- reg
- label
additionalProperties: false
examples:
- |
backlight@d800 {
compatible = "qcom,pm8941-wled";
reg = <0xd800 0x100>;
label = "backlight";
qcom,cs-out;
qcom,current-limit = <20>;
qcom,current-boost-limit = <805>;
qcom,switching-freq = <1600>;
qcom,ovp = <29>;
qcom,num-strings = <2>;
qcom,enabled-strings = <0 1>;
};
......@@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/irq.h>
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
......@@ -20,8 +21,6 @@
#include <linux/mfd/mc13783.h>
#include <linux/spi/spi.h>
#include <linux/regulator/machine.h>
#include <linux/spi/l4f00242t03.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
......@@ -351,9 +350,19 @@ static const struct imx_fb_platform_data mx27_3ds_fb_data __initconst = {
};
/* LCD */
static struct l4f00242t03_pdata mx27_3ds_lcd_pdata = {
.reset_gpio = LCD_RESET,
.data_enable_gpio = LCD_ENABLE,
static struct gpiod_lookup_table mx27_3ds_lcd_gpiod_table = {
.dev_id = "spi0.0", /* Bus 0 chipselect 0 */
.table = {
/*
* The i.MX27 has the i.MX21 GPIO controller, the GPIOs
* numbered IMX_GPIO_NR(1, 3) and IMX_GPIO_NR(1, 31)
* are in "bank 1" which is subtracted by one in the macro
* so these are actually bank 0 on "imx21-gpio.0".
*/
GPIO_LOOKUP("imx21-gpio.0", 3, "reset", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("imx21-gpio.0", 31, "enable", GPIO_ACTIVE_HIGH),
{ },
},
};
static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
......@@ -370,7 +379,6 @@ static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
.max_speed_hz = 5000000,
.bus_num = 0,
.chip_select = 0, /* SS0 */
.platform_data = &mx27_3ds_lcd_pdata,
},
};
......@@ -416,6 +424,7 @@ static void __init mx27pdk_late_init(void)
if (!otg_mode_host)
imx27_add_fsl_usb2_udc(&otg_device_pdata);
gpiod_add_lookup_table(&mx27_3ds_lcd_gpiod_table);
mx27_3ds_spi_devs[0].irq = gpio_to_irq(PMIC_INT);
spi_register_board_info(mx27_3ds_spi_devs,
ARRAY_SIZE(mx27_3ds_spi_devs));
......
......@@ -10,10 +10,10 @@
#include <linux/clk.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/platform_device.h>
#include <linux/mfd/mc13783.h>
#include <linux/spi/spi.h>
#include <linux/spi/l4f00242t03.h>
#include <linux/regulator/machine.h>
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
......@@ -160,9 +160,23 @@ static struct mx3fb_platform_data mx3fb_pdata __initdata = {
};
/* LCD */
static struct l4f00242t03_pdata mx31_3ds_l4f00242t03_pdata = {
.reset_gpio = IOMUX_TO_GPIO(MX31_PIN_LCS1),
.data_enable_gpio = IOMUX_TO_GPIO(MX31_PIN_SER_RS),
static struct gpiod_lookup_table mx31_3ds_lcd_gpiod_table = {
.dev_id = "spi0.2", /* Bus 0 chipselect 2 */
.table = {
/*
* "reset" has IOMUX_TO_GPIO(IOMUX_PIN(88, 28)).
* The macro only shifts 88 to bits 9..16 and then
* mask it and shift it back. The GPIO number is 88.
* 88 is 2*32+24
*/
GPIO_LOOKUP("imx31-gpio.2", 24, "reset", GPIO_ACTIVE_HIGH),
/*
* Same reasoning as above for
* IOMUX_TO_GPIO(IOMUX_PIN(89, 27), pin 89 is 2*32+25.
*/
GPIO_LOOKUP("imx31-gpio.2", 25, "enable", GPIO_ACTIVE_HIGH),
{ },
},
};
/*
......@@ -387,7 +401,6 @@ static struct spi_board_info mx31_3ds_spi_devs[] __initdata = {
.max_speed_hz = 5000000,
.bus_num = 0,
.chip_select = 2, /* SS2 */
.platform_data = &mx31_3ds_l4f00242t03_pdata,
},
};
......@@ -566,6 +579,7 @@ static void __init mx31_3ds_init(void)
static void __init mx31_3ds_late(void)
{
gpiod_add_lookup_table(&mx31_3ds_lcd_gpiod_table);
mx31_3ds_spi_devs[0].irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
spi_register_board_info(mx31_3ds_spi_devs,
ARRAY_SIZE(mx31_3ds_spi_devs));
......
......@@ -432,6 +432,27 @@ struct backlight_device *backlight_device_get_by_type(enum backlight_type type)
}
EXPORT_SYMBOL(backlight_device_get_by_type);
/**
* backlight_device_get_by_name - Get backlight device by name
* @name: Device name
*
* This function looks up a backlight device by its name. It obtains a reference
* on the backlight device and it is the caller's responsibility to drop the
* reference by calling backlight_put().
*
* Returns:
* A pointer to the backlight device if found, otherwise NULL.
*/
struct backlight_device *backlight_device_get_by_name(const char *name)
{
struct device *dev;
dev = class_find_device_by_name(backlight_class, name);
return dev ? to_backlight_device(dev) : NULL;
}
EXPORT_SYMBOL(backlight_device_get_by_name);
/**
* backlight_device_unregister - unregisters a backlight device object.
* @bd: the backlight device object to be unregistered and freed.
......
......@@ -14,13 +14,11 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/lcd.h>
#include <linux/slab.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/spi/l4f00242t03.h>
struct l4f00242t03_priv {
struct spi_device *spi;
......@@ -28,16 +26,18 @@ struct l4f00242t03_priv {
int lcd_state;
struct regulator *io_reg;
struct regulator *core_reg;
struct gpio_desc *reset;
struct gpio_desc *enable;
};
static void l4f00242t03_reset(unsigned int gpio)
static void l4f00242t03_reset(struct gpio_desc *gpiod)
{
pr_debug("l4f00242t03_reset.\n");
gpio_set_value(gpio, 1);
gpiod_set_value(gpiod, 1);
mdelay(100);
gpio_set_value(gpio, 0);
gpiod_set_value(gpiod, 0);
mdelay(10); /* tRES >= 100us */
gpio_set_value(gpio, 1);
gpiod_set_value(gpiod, 1);
mdelay(20);
}
......@@ -45,7 +45,6 @@ static void l4f00242t03_reset(unsigned int gpio)
static void l4f00242t03_lcd_init(struct spi_device *spi)
{
struct l4f00242t03_pdata *pdata = dev_get_platdata(&spi->dev);
struct l4f00242t03_priv *priv = spi_get_drvdata(spi);
const u16 cmd[] = { 0x36, param(0), 0x3A, param(0x60) };
int ret;
......@@ -76,21 +75,20 @@ static void l4f00242t03_lcd_init(struct spi_device *spi)
return;
}
l4f00242t03_reset(pdata->reset_gpio);
l4f00242t03_reset(priv->reset);
gpio_set_value(pdata->data_enable_gpio, 1);
gpiod_set_value(priv->enable, 1);
msleep(60);
spi_write(spi, (const u8 *)cmd, ARRAY_SIZE(cmd) * sizeof(u16));
}
static void l4f00242t03_lcd_powerdown(struct spi_device *spi)
{
struct l4f00242t03_pdata *pdata = dev_get_platdata(&spi->dev);
struct l4f00242t03_priv *priv = spi_get_drvdata(spi);
dev_dbg(&spi->dev, "Powering down LCD\n");
gpio_set_value(pdata->data_enable_gpio, 0);
gpiod_set_value(priv->enable, 0);
regulator_disable(priv->io_reg);
regulator_disable(priv->core_reg);
......@@ -168,13 +166,6 @@ static struct lcd_ops l4f_ops = {
static int l4f00242t03_probe(struct spi_device *spi)
{
struct l4f00242t03_priv *priv;
struct l4f00242t03_pdata *pdata = dev_get_platdata(&spi->dev);
int ret;
if (pdata == NULL) {
dev_err(&spi->dev, "Uninitialized platform data.\n");
return -EINVAL;
}
priv = devm_kzalloc(&spi->dev, sizeof(struct l4f00242t03_priv),
GFP_KERNEL);
......@@ -187,21 +178,21 @@ static int l4f00242t03_probe(struct spi_device *spi)
priv->spi = spi;
ret = devm_gpio_request_one(&spi->dev, pdata->reset_gpio,
GPIOF_OUT_INIT_HIGH, "lcd l4f00242t03 reset");
if (ret) {
priv->reset = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(priv->reset)) {
dev_err(&spi->dev,
"Unable to get the lcd l4f00242t03 reset gpio.\n");
return ret;
return PTR_ERR(priv->reset);
}
gpiod_set_consumer_name(priv->reset, "lcd l4f00242t03 reset");
ret = devm_gpio_request_one(&spi->dev, pdata->data_enable_gpio,
GPIOF_OUT_INIT_LOW, "lcd l4f00242t03 data enable");
if (ret) {
priv->enable = devm_gpiod_get(&spi->dev, "enable", GPIOD_OUT_LOW);
if (IS_ERR(priv->enable)) {
dev_err(&spi->dev,
"Unable to get the lcd l4f00242t03 data en gpio.\n");
return ret;
return PTR_ERR(priv->enable);
}
gpiod_set_consumer_name(priv->enable, "lcd l4f00242t03 data enable");
priv->io_reg = devm_regulator_get(&spi->dev, "vdd");
if (IS_ERR(priv->io_reg)) {
......
......@@ -456,7 +456,7 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
ret = regulator_enable(lp->enable);
if (ret < 0) {
dev_err(lp->dev, "failed to enable vddio: %d\n", ret);
return ret;
goto disable_supply;
}
/*
......@@ -471,24 +471,34 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
ret = lp855x_configure(lp);
if (ret) {
dev_err(lp->dev, "device config err: %d", ret);
return ret;
goto disable_vddio;
}
ret = lp855x_backlight_register(lp);
if (ret) {
dev_err(lp->dev,
"failed to register backlight. err: %d\n", ret);
return ret;
goto disable_vddio;
}
ret = sysfs_create_group(&lp->dev->kobj, &lp855x_attr_group);
if (ret) {
dev_err(lp->dev, "failed to register sysfs. err: %d\n", ret);
return ret;
goto disable_vddio;
}
backlight_update_status(lp->bl);
return 0;
disable_vddio:
if (lp->enable)
regulator_disable(lp->enable);
disable_supply:
if (lp->supply)
regulator_disable(lp->supply);
return ret;
}
static int lp855x_remove(struct i2c_client *cl)
......@@ -497,6 +507,8 @@ static int lp855x_remove(struct i2c_client *cl)
lp->bl->props.brightness = 0;
backlight_update_status(lp->bl);
if (lp->enable)
regulator_disable(lp->enable);
if (lp->supply)
regulator_disable(lp->supply);
sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group);
......
This diff is collapsed.
......@@ -190,6 +190,7 @@ extern void backlight_force_update(struct backlight_device *bd,
extern int backlight_register_notifier(struct notifier_block *nb);
extern int backlight_unregister_notifier(struct notifier_block *nb);
extern struct backlight_device *backlight_device_get_by_type(enum backlight_type type);
struct backlight_device *backlight_device_get_by_name(const char *name);
extern int backlight_device_set_brightness(struct backlight_device *bd, unsigned long brightness);
#define to_backlight_device(obj) container_of(obj, struct backlight_device, dev)
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* l4f00242t03.h -- Platform glue for Epson L4F00242T03 LCD
*
* Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
* Based on Marek Vasut work in lms283gf05.h
*/
#ifndef _INCLUDE_LINUX_SPI_L4F00242T03_H_
#define _INCLUDE_LINUX_SPI_L4F00242T03_H_
struct l4f00242t03_pdata {
unsigned int reset_gpio;
unsigned int data_enable_gpio;
};
#endif /* _INCLUDE_LINUX_SPI_L4F00242T03_H_ */
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