- New Functionality
- Add support for an enable GPIO; lm3630a_bl - Add support for short circuit handling; qcom-wled - Add support for automatic string detection; qcom-wled - Fix-ups - Update Device Tree bindings; lm3630a-backlight, led-backlight, qcom-wled - Constify; ipaq_micro_bl - Optimise for CPU cycles; pwm_bl - Coding style fix-ups; pwm_bl - Trivial fix-ups (white space, comments, renaming); pwm_bl, gpio_backlight, qcom-wled - Kconfig dependency hacking; LCD_HP700 - Rename, refactor and add peripherals; pm8941-wled => qcom-wled - Make use of GPIO look-up tables; tosa_bl, tosa_lcd - Remove superfluous code; gpio_backlight - Adapt GPIO direction handling; gpio_backlight - Remove legacy use of platform data; gpio_backlight - Bug Fixes - Provide modules aliases; lm3630a_bl -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEdrbJNaO+IJqU8IdIUa+KL4f8d2EFAl3f2c8ACgkQUa+KL4f8 d2HFlg//Y7NRP+FdSYC74S94fmG6H73H+/iGp7qfRF9qud41Ux87/ERbCXj180d1 i0TSfynGUfk367kM08GUGdVuABeq/0UObJeOplIXEOJF6P/B7Dc+grbmilzC2CjE ygjLp4iPcbl6HuIBr2zMu7S3RWi9lbM4ClOhjSjP4cACnZCr4p8Z4RTATQaOhx2B vXez5PbYfs43FyLqXDnVsmykHzer8Y5MU7APS7KXxt1elqX87yS8AHOMnjTjoiif xe0r06H9zda1YVkRoQnDyc1OVZmYqKNT4zeATrm2r9La9IO3quelBs9NAD0bl9Rw ES6mmEbUJ8nTnYS+Om0T9aKe6jrsCUMY5+a5Sct33FAiHAXyMpCCtjfZIlkEb2iv Hew9Xp4aFrTEh5tPV4F15jyMgu9JJoTS4k0d7STj/eWigsdh3Ir+fMt+VGqDLW5G epLEPuNMT4fchsETPangnkTKb+3CWkK9YyEjtC5zaM/WmFh2VIcTLyYdmuHbT5Yo +BoyqWMAUgCSS8ytclaLOAEvZ8OxCMUaTSCUqvRGVk661uJm5w1gabIUs2p16bMA nTba3hqHdgSCFFZfgkJa3ZD+Hcbc49BN3qxHJjim6pezTKiLZKmDDcW1JaX9uHrW 75gC3Ka9nfYAjZqocoMywNSDAKRr4pJ1DpPX6z6gc6oP6Vb2Bjs= =8RxV -----END PGP SIGNATURE----- Merge tag 'backlight-next-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight Pull backlight updates from Lee Jones: "New Functionality: - Add support for an enable GPIO; lm3630a_bl - Add support for short circuit handling; qcom-wled - Add support for automatic string detection; qcom-wled Fix-ups: - Update Device Tree bindings; lm3630a-backlight, led-backlight, qcom-wled - Constify; ipaq_micro_bl - Optimise for CPU cycles; pwm_bl - Coding style fix-ups; pwm_bl - Trivial fix-ups (white space, comments, renaming); pwm_bl, gpio_backlight, qcom-wled - Kconfig dependency hacking; LCD_HP700 - Rename, refactor and add peripherals; pm8941-wled => qcom-wled - Make use of GPIO look-up tables; tosa_bl, tosa_lcd - Remove superfluous code; gpio_backlight - Adapt GPIO direction handling; gpio_backlight - Remove legacy use of platform data; gpio_backlight Bug Fixes: - Provide modules aliases; lm3630a_bl" * tag 'backlight-next-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight: (32 commits) backlight: qcom-wled: Fix spelling mistake "trigged" -> "triggered" backlight: gpio: Pull gpio_backlight_initial_power_state() into probe backlight: gpio: Use a helper variable for &pdev->dev backlight: gpio: Remove unused fields from platform data sh: ecovec24: don't set unused fields in platform data backlight: gpio: Simplify the platform data handling sh: ecovec24: add additional properties to the backlight device backlight: gpio: Explicitly set the direction of the GPIO backlight: gpio: Remove stray newline backlight: gpio: Remove unneeded include video: backlight: tosa: Use GPIO lookup table backlight: qcom-wled: Add auto string detection logic backlight: qcom-wled: Add support for short circuit handling backlight: qcom-wled: Add support for WLED4 peripheral backlight: qcom-wled: Restructure the driver for WLED3 backlight: qcom-wled: Rename PM8941* to WLED3 backlight: qcom-wled: Add new properties for PMI8998 backlight: qcom-wled: Restructure the qcom-wled bindings backlight: qcom-wled: Rename pm8941-wled.c to qcom-wled.c dt-bindings: backlight: lm3630a: Fix missing include ...
This commit is contained in:
commit
38edc3dff9
|
@ -0,0 +1,28 @@
|
|||
led-backlight bindings
|
||||
|
||||
This binding is used to describe a basic backlight device made of LEDs.
|
||||
It can also be used to describe a backlight device controlled by the output of
|
||||
a LED driver.
|
||||
|
||||
Required properties:
|
||||
- compatible: "led-backlight"
|
||||
- leds: a list of LEDs
|
||||
|
||||
Optional properties:
|
||||
- brightness-levels: Array of distinct brightness levels. The levels must be
|
||||
in the range accepted by the underlying LED devices.
|
||||
This is used to translate a backlight brightness level
|
||||
into a LED brightness level. If it is not provided, the
|
||||
identity mapping is used.
|
||||
|
||||
- default-brightness-level: The default brightness level.
|
||||
|
||||
Example:
|
||||
|
||||
backlight {
|
||||
compatible = "led-backlight";
|
||||
|
||||
leds = <&led1>, <&led2>;
|
||||
brightness-levels = <0 4 8 16 32 64 128 255>;
|
||||
default-brightness-level = <6>;
|
||||
};
|
|
@ -29,6 +29,10 @@ properties:
|
|||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
enable-gpios:
|
||||
description: GPIO to use to enable/disable the backlight (HWEN pin).
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -89,6 +93,7 @@ additionalProperties: false
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -96,6 +101,7 @@ examples:
|
|||
led-controller@38 {
|
||||
compatible = "ti,lm3630a";
|
||||
reg = <0x38>;
|
||||
enable-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
Binding for Qualcomm PM8941 WLED driver
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "qcom,pm8941-wled"
|
||||
- reg: slave address
|
||||
|
||||
Optional properties:
|
||||
- default-brightness: brightness value on boot, value from: 0-4095
|
||||
default: 2048
|
||||
- label: The name of the backlight device
|
||||
- qcom,cs-out: bool; enable current sink output
|
||||
- qcom,cabc: bool; enable content adaptive backlight control
|
||||
- qcom,ext-gen: bool; use externally generated modulator signal to dim
|
||||
- qcom,current-limit: mA; per-string current limit; value from 0 to 25
|
||||
default: 20mA
|
||||
- qcom,current-boost-limit: mA; boost current limit; one of:
|
||||
105, 385, 525, 805, 980, 1260, 1400, 1680
|
||||
default: 805mA
|
||||
- qcom,switching-freq: kHz; switching frequency; one of:
|
||||
600, 640, 685, 738, 800, 872, 960, 1066, 1200, 1371,
|
||||
1600, 1920, 2400, 3200, 4800, 9600,
|
||||
default: 1600kHz
|
||||
- qcom,ovp: V; Over-voltage protection limit; one of:
|
||||
27, 29, 32, 35
|
||||
default: 29V
|
||||
- qcom,num-strings: #; number of led strings attached; value from 1 to 3
|
||||
default: 2
|
||||
|
||||
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>;
|
||||
};
|
|
@ -0,0 +1,154 @@
|
|||
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>;
|
||||
};
|
|
@ -72,18 +72,6 @@
|
|||
#define TOSA_GPIO_BAT0_TH_ON (TOSA_TC6393XB_GPIO_BASE + 14)
|
||||
#define TOSA_GPIO_BAT1_TH_ON (TOSA_TC6393XB_GPIO_BASE + 15)
|
||||
|
||||
/*
|
||||
* Timing Generator
|
||||
*/
|
||||
#define TG_PNLCTL 0x00
|
||||
#define TG_TPOSCTL 0x01
|
||||
#define TG_DUTYCTL 0x02
|
||||
#define TG_GPOSR 0x03
|
||||
#define TG_GPODR1 0x04
|
||||
#define TG_GPODR2 0x05
|
||||
#define TG_PINICTL 0x06
|
||||
#define TG_HPOSCTL 0x07
|
||||
|
||||
/*
|
||||
* PXA GPIOs
|
||||
*/
|
||||
|
@ -192,7 +180,4 @@
|
|||
#define TOSA_KEY_MAIL KEY_MAIL
|
||||
#endif
|
||||
|
||||
struct spi_device;
|
||||
extern int tosa_bl_enable(struct spi_device *spi, int enable);
|
||||
|
||||
#endif /* _ASM_ARCH_TOSA_H_ */
|
||||
|
|
|
@ -813,6 +813,26 @@ static struct pxa2xx_spi_controller pxa_ssp_master_info = {
|
|||
.num_chipselect = 1,
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table tosa_lcd_gpio_table = {
|
||||
.dev_id = "spi2.0",
|
||||
.table = {
|
||||
GPIO_LOOKUP("tc6393xb",
|
||||
TOSA_GPIO_TG_ON - TOSA_TC6393XB_GPIO_BASE,
|
||||
"tg #pwr", GPIO_ACTIVE_HIGH),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table tosa_lcd_bl_gpio_table = {
|
||||
.dev_id = "i2c-tosa-bl",
|
||||
.table = {
|
||||
GPIO_LOOKUP("tc6393xb",
|
||||
TOSA_GPIO_BL_C20MA - TOSA_TC6393XB_GPIO_BASE,
|
||||
"backlight", GPIO_ACTIVE_HIGH),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct spi_board_info spi_board_info[] __initdata = {
|
||||
{
|
||||
.modalias = "tosa-lcd",
|
||||
|
@ -923,6 +943,8 @@ static void __init tosa_init(void)
|
|||
platform_scoop_config = &tosa_pcmcia_config;
|
||||
|
||||
pxa2xx_set_spi_info(2, &pxa_ssp_master_info);
|
||||
gpiod_add_lookup_table(&tosa_lcd_gpio_table);
|
||||
gpiod_add_lookup_table(&tosa_lcd_bl_gpio_table);
|
||||
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
|
||||
|
||||
clk_add_alias("CLK_CK3P6MI", tc6393xb_device.name, "GPIO11_CLK", NULL);
|
||||
|
|
|
@ -371,20 +371,32 @@ static struct platform_device lcdc_device = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct gpio_backlight_platform_data gpio_backlight_data = {
|
||||
.fbdev = &lcdc_device.dev,
|
||||
.gpio = GPIO_PTR1,
|
||||
.def_value = 1,
|
||||
.name = "backlight",
|
||||
};
|
||||
|
||||
static struct platform_device gpio_backlight_device = {
|
||||
.name = "gpio-backlight",
|
||||
.dev = {
|
||||
.platform_data = &gpio_backlight_data,
|
||||
static struct gpiod_lookup_table gpio_backlight_lookup = {
|
||||
.dev_id = "gpio-backlight.0",
|
||||
.table = {
|
||||
GPIO_LOOKUP("sh7724_pfc", GPIO_PTR1, NULL, GPIO_ACTIVE_HIGH),
|
||||
{ }
|
||||
},
|
||||
};
|
||||
|
||||
static struct property_entry gpio_backlight_props[] = {
|
||||
PROPERTY_ENTRY_BOOL("default-on"),
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct gpio_backlight_platform_data gpio_backlight_data = {
|
||||
.fbdev = &lcdc_device.dev,
|
||||
};
|
||||
|
||||
static const struct platform_device_info gpio_backlight_device_info = {
|
||||
.name = "gpio-backlight",
|
||||
.data = &gpio_backlight_data,
|
||||
.size_data = sizeof(gpio_backlight_data),
|
||||
.properties = gpio_backlight_props,
|
||||
};
|
||||
|
||||
static struct platform_device *gpio_backlight_device;
|
||||
|
||||
/* CEU0 */
|
||||
static struct ceu_platform_data ceu0_pdata = {
|
||||
.num_subdevs = 2,
|
||||
|
@ -1006,7 +1018,6 @@ static struct platform_device *ecovec_devices[] __initdata = {
|
|||
&usb1_common_device,
|
||||
&usbhs_device,
|
||||
&lcdc_device,
|
||||
&gpio_backlight_device,
|
||||
&keysc_device,
|
||||
&cn12_power,
|
||||
#if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
|
||||
|
@ -1462,6 +1473,12 @@ static int __init arch_setup(void)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
gpiod_add_lookup_table(&gpio_backlight_lookup);
|
||||
gpio_backlight_device = platform_device_register_full(
|
||||
&gpio_backlight_device_info);
|
||||
if (IS_ERR(gpio_backlight_device))
|
||||
return PTR_ERR(gpio_backlight_device);
|
||||
|
||||
return platform_add_devices(ecovec_devices,
|
||||
ARRAY_SIZE(ecovec_devices));
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ config LCD_TOSA
|
|||
|
||||
config LCD_HP700
|
||||
tristate "HP Jornada 700 series LCD Driver"
|
||||
depends on SA1100_JORNADA720_SSP && !PREEMPT
|
||||
depends on SA1100_JORNADA720_SSP && !PREEMPTION
|
||||
default y
|
||||
help
|
||||
If you have an HP Jornada 700 series handheld (710/720/728)
|
||||
|
@ -228,7 +228,7 @@ config BACKLIGHT_HP680
|
|||
|
||||
config BACKLIGHT_HP700
|
||||
tristate "HP Jornada 700 series Backlight Driver"
|
||||
depends on SA1100_JORNADA720_SSP && !PREEMPT
|
||||
depends on SA1100_JORNADA720_SSP && !PREEMPTION
|
||||
default y
|
||||
help
|
||||
If you have an HP Jornada 700 series,
|
||||
|
@ -282,12 +282,12 @@ config BACKLIGHT_TOSA
|
|||
If you have an Sharp SL-6000 Zaurus say Y to enable a driver
|
||||
for its backlight
|
||||
|
||||
config BACKLIGHT_PM8941_WLED
|
||||
tristate "Qualcomm PM8941 WLED Driver"
|
||||
config BACKLIGHT_QCOM_WLED
|
||||
tristate "Qualcomm PMIC WLED Driver"
|
||||
select REGMAP
|
||||
help
|
||||
If you have the Qualcomm PM8941, say Y to enable a driver for the
|
||||
WLED block.
|
||||
If you have the Qualcomm PMIC, say Y to enable a driver for the
|
||||
WLED block. Currently it supports PM8941 and PMI8998.
|
||||
|
||||
config BACKLIGHT_SAHARA
|
||||
tristate "Tabletkiosk Sahara Touch-iT Backlight Driver"
|
||||
|
|
|
@ -48,8 +48,8 @@ obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
|
|||
obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o
|
||||
obj-$(CONFIG_BACKLIGHT_PM8941_WLED) += pm8941-wled.o
|
||||
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_QCOM_WLED) += qcom-wled.o
|
||||
obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o
|
||||
obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
|
||||
|
|
|
@ -6,29 +6,23 @@
|
|||
#include <linux/backlight.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/gpio.h> /* Only for legacy support */
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/platform_data/gpio_backlight.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct gpio_backlight {
|
||||
struct device *dev;
|
||||
struct device *fbdev;
|
||||
|
||||
struct gpio_desc *gpiod;
|
||||
int def_value;
|
||||
};
|
||||
|
||||
static int gpio_backlight_update_status(struct backlight_device *bl)
|
||||
static int gpio_backlight_get_next_brightness(struct backlight_device *bl)
|
||||
{
|
||||
struct gpio_backlight *gbl = bl_get_data(bl);
|
||||
int brightness = bl->props.brightness;
|
||||
|
||||
if (bl->props.power != FB_BLANK_UNBLANK ||
|
||||
|
@ -36,6 +30,14 @@ static int gpio_backlight_update_status(struct backlight_device *bl)
|
|||
bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
|
||||
brightness = 0;
|
||||
|
||||
return brightness;
|
||||
}
|
||||
|
||||
static int gpio_backlight_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct gpio_backlight *gbl = bl_get_data(bl);
|
||||
int brightness = gpio_backlight_get_next_brightness(bl);
|
||||
|
||||
gpiod_set_value_cansleep(gbl->gpiod, brightness);
|
||||
|
||||
return 0;
|
||||
|
@ -55,105 +57,63 @@ static const struct backlight_ops gpio_backlight_ops = {
|
|||
.check_fb = gpio_backlight_check_fb,
|
||||
};
|
||||
|
||||
static int gpio_backlight_probe_dt(struct platform_device *pdev,
|
||||
struct gpio_backlight *gbl)
|
||||
static int gpio_backlight_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret;
|
||||
struct gpio_backlight_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct device_node *of_node = dev->of_node;
|
||||
struct backlight_properties props;
|
||||
struct backlight_device *bl;
|
||||
struct gpio_backlight *gbl;
|
||||
int ret, init_brightness, def_value;
|
||||
|
||||
gbl->def_value = device_property_read_bool(dev, "default-on");
|
||||
gbl = devm_kzalloc(dev, sizeof(*gbl), GFP_KERNEL);
|
||||
if (gbl == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (pdata)
|
||||
gbl->fbdev = pdata->fbdev;
|
||||
|
||||
def_value = device_property_read_bool(dev, "default-on");
|
||||
|
||||
gbl->gpiod = devm_gpiod_get(dev, NULL, GPIOD_ASIS);
|
||||
if (IS_ERR(gbl->gpiod)) {
|
||||
ret = PTR_ERR(gbl->gpiod);
|
||||
|
||||
if (ret != -EPROBE_DEFER) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev,
|
||||
"Error: The gpios parameter is missing or invalid.\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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 =
|
||||
dev_get_platdata(&pdev->dev);
|
||||
struct backlight_properties props;
|
||||
struct backlight_device *bl;
|
||||
struct gpio_backlight *gbl;
|
||||
int ret;
|
||||
|
||||
gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL);
|
||||
if (gbl == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
gbl->dev = &pdev->dev;
|
||||
|
||||
if (pdev->dev.fwnode) {
|
||||
ret = gpio_backlight_probe_dt(pdev, gbl);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else if (pdata) {
|
||||
/*
|
||||
* Legacy platform data GPIO retrieveal. Do not expand
|
||||
* the use of this code path, currently only used by one
|
||||
* SH board.
|
||||
*/
|
||||
unsigned long flags = GPIOF_DIR_OUT;
|
||||
|
||||
gbl->fbdev = pdata->fbdev;
|
||||
gbl->def_value = pdata->def_value;
|
||||
flags |= gbl->def_value ? GPIOF_INIT_HIGH : GPIOF_INIT_LOW;
|
||||
|
||||
ret = devm_gpio_request_one(gbl->dev, pdata->gpio, flags,
|
||||
pdata ? pdata->name : "backlight");
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "unable to request GPIO\n");
|
||||
return ret;
|
||||
}
|
||||
gbl->gpiod = gpio_to_desc(pdata->gpio);
|
||||
if (!gbl->gpiod)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to find platform data or device tree node.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
props.type = BACKLIGHT_RAW;
|
||||
props.max_brightness = 1;
|
||||
bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev),
|
||||
&pdev->dev, gbl, &gpio_backlight_ops,
|
||||
&props);
|
||||
bl = devm_backlight_device_register(dev, dev_name(dev), dev, gbl,
|
||||
&gpio_backlight_ops, &props);
|
||||
if (IS_ERR(bl)) {
|
||||
dev_err(&pdev->dev, "failed to register backlight\n");
|
||||
dev_err(dev, "failed to register backlight\n");
|
||||
return PTR_ERR(bl);
|
||||
}
|
||||
|
||||
bl->props.power = gpio_backlight_initial_power_state(gbl);
|
||||
/* Set the initial power state */
|
||||
if (!of_node || !of_node->phandle)
|
||||
/* Not booted with device tree or no phandle link to the node */
|
||||
bl->props.power = def_value ? FB_BLANK_UNBLANK
|
||||
: FB_BLANK_POWERDOWN;
|
||||
else if (gpiod_get_direction(gbl->gpiod) == 0 &&
|
||||
gpiod_get_value_cansleep(gbl->gpiod) == 0)
|
||||
bl->props.power = FB_BLANK_POWERDOWN;
|
||||
else
|
||||
bl->props.power = FB_BLANK_UNBLANK;
|
||||
|
||||
bl->props.brightness = 1;
|
||||
|
||||
backlight_update_status(bl);
|
||||
init_brightness = gpio_backlight_get_next_brightness(bl);
|
||||
ret = gpiod_direction_output(gbl->gpiod, init_brightness);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to set initial brightness\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, bl);
|
||||
return 0;
|
||||
|
|
|
@ -44,7 +44,7 @@ static const struct backlight_ops micro_bl_ops = {
|
|||
.update_status = micro_bl_update_status,
|
||||
};
|
||||
|
||||
static struct backlight_properties micro_bl_props = {
|
||||
static const struct backlight_properties micro_bl_props = {
|
||||
.type = BACKLIGHT_RAW,
|
||||
.max_brightness = 255,
|
||||
.power = FB_BLANK_UNBLANK,
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/uaccess.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/platform_data/lm3630a_bl.h>
|
||||
|
||||
|
@ -48,6 +49,7 @@ struct lm3630a_chip {
|
|||
struct lm3630a_platform_data *pdata;
|
||||
struct backlight_device *bleda;
|
||||
struct backlight_device *bledb;
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct regmap *regmap;
|
||||
struct pwm_device *pwmd;
|
||||
};
|
||||
|
@ -534,6 +536,13 @@ static int lm3630a_probe(struct i2c_client *client,
|
|||
}
|
||||
pchip->pdata = pdata;
|
||||
|
||||
pchip->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(pchip->enable_gpio)) {
|
||||
rval = PTR_ERR(pchip->enable_gpio);
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* chip initialize */
|
||||
rval = lm3630a_chip_init(pchip);
|
||||
if (rval < 0) {
|
||||
|
@ -598,12 +607,14 @@ static const struct i2c_device_id lm3630a_id[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, lm3630a_id);
|
||||
|
||||
static const struct of_device_id lm3630a_match_table[] = {
|
||||
{ .compatible = "ti,lm3630a", },
|
||||
{ },
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, lm3630a_id);
|
||||
MODULE_DEVICE_TABLE(of, lm3630a_match_table);
|
||||
|
||||
static struct i2c_driver lm3630a_i2c_driver = {
|
||||
.driver = {
|
||||
|
|
|
@ -1,424 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2015, Sony Mobile Communications, AB.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* From DT binding */
|
||||
#define PM8941_WLED_DEFAULT_BRIGHTNESS 2048
|
||||
|
||||
#define PM8941_WLED_REG_VAL_BASE 0x40
|
||||
#define PM8941_WLED_REG_VAL_MAX 0xFFF
|
||||
|
||||
#define PM8941_WLED_REG_MOD_EN 0x46
|
||||
#define PM8941_WLED_REG_MOD_EN_BIT BIT(7)
|
||||
#define PM8941_WLED_REG_MOD_EN_MASK BIT(7)
|
||||
|
||||
#define PM8941_WLED_REG_SYNC 0x47
|
||||
#define PM8941_WLED_REG_SYNC_MASK 0x07
|
||||
#define PM8941_WLED_REG_SYNC_LED1 BIT(0)
|
||||
#define PM8941_WLED_REG_SYNC_LED2 BIT(1)
|
||||
#define PM8941_WLED_REG_SYNC_LED3 BIT(2)
|
||||
#define PM8941_WLED_REG_SYNC_ALL 0x07
|
||||
#define PM8941_WLED_REG_SYNC_CLEAR 0x00
|
||||
|
||||
#define PM8941_WLED_REG_FREQ 0x4c
|
||||
#define PM8941_WLED_REG_FREQ_MASK 0x0f
|
||||
|
||||
#define PM8941_WLED_REG_OVP 0x4d
|
||||
#define PM8941_WLED_REG_OVP_MASK 0x03
|
||||
|
||||
#define PM8941_WLED_REG_BOOST 0x4e
|
||||
#define PM8941_WLED_REG_BOOST_MASK 0x07
|
||||
|
||||
#define PM8941_WLED_REG_SINK 0x4f
|
||||
#define PM8941_WLED_REG_SINK_MASK 0xe0
|
||||
#define PM8941_WLED_REG_SINK_SHFT 0x05
|
||||
|
||||
/* Per-'string' registers below */
|
||||
#define PM8941_WLED_REG_STR_OFFSET 0x10
|
||||
|
||||
#define PM8941_WLED_REG_STR_MOD_EN_BASE 0x60
|
||||
#define PM8941_WLED_REG_STR_MOD_MASK BIT(7)
|
||||
#define PM8941_WLED_REG_STR_MOD_EN BIT(7)
|
||||
|
||||
#define PM8941_WLED_REG_STR_SCALE_BASE 0x62
|
||||
#define PM8941_WLED_REG_STR_SCALE_MASK 0x1f
|
||||
|
||||
#define PM8941_WLED_REG_STR_MOD_SRC_BASE 0x63
|
||||
#define PM8941_WLED_REG_STR_MOD_SRC_MASK 0x01
|
||||
#define PM8941_WLED_REG_STR_MOD_SRC_INT 0x00
|
||||
#define PM8941_WLED_REG_STR_MOD_SRC_EXT 0x01
|
||||
|
||||
#define PM8941_WLED_REG_STR_CABC_BASE 0x66
|
||||
#define PM8941_WLED_REG_STR_CABC_MASK BIT(7)
|
||||
#define PM8941_WLED_REG_STR_CABC_EN BIT(7)
|
||||
|
||||
struct pm8941_wled_config {
|
||||
u32 i_boost_limit;
|
||||
u32 ovp;
|
||||
u32 switch_freq;
|
||||
u32 num_strings;
|
||||
u32 i_limit;
|
||||
bool cs_out_en;
|
||||
bool ext_gen;
|
||||
bool cabc_en;
|
||||
};
|
||||
|
||||
struct pm8941_wled {
|
||||
const char *name;
|
||||
struct regmap *regmap;
|
||||
u16 addr;
|
||||
|
||||
struct pm8941_wled_config cfg;
|
||||
};
|
||||
|
||||
static int pm8941_wled_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct pm8941_wled *wled = bl_get_data(bl);
|
||||
u16 val = bl->props.brightness;
|
||||
u8 ctrl = 0;
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
if (bl->props.power != FB_BLANK_UNBLANK ||
|
||||
bl->props.fb_blank != FB_BLANK_UNBLANK ||
|
||||
bl->props.state & BL_CORE_FBBLANK)
|
||||
val = 0;
|
||||
|
||||
if (val != 0)
|
||||
ctrl = PM8941_WLED_REG_MOD_EN_BIT;
|
||||
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
wled->addr + PM8941_WLED_REG_MOD_EN,
|
||||
PM8941_WLED_REG_MOD_EN_MASK, ctrl);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
for (i = 0; i < wled->cfg.num_strings; ++i) {
|
||||
u8 v[2] = { val & 0xff, (val >> 8) & 0xf };
|
||||
|
||||
rc = regmap_bulk_write(wled->regmap,
|
||||
wled->addr + PM8941_WLED_REG_VAL_BASE + 2 * i,
|
||||
v, 2);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
wled->addr + PM8941_WLED_REG_SYNC,
|
||||
PM8941_WLED_REG_SYNC_MASK, PM8941_WLED_REG_SYNC_ALL);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
wled->addr + PM8941_WLED_REG_SYNC,
|
||||
PM8941_WLED_REG_SYNC_MASK, PM8941_WLED_REG_SYNC_CLEAR);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int pm8941_wled_setup(struct pm8941_wled *wled)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
wled->addr + PM8941_WLED_REG_OVP,
|
||||
PM8941_WLED_REG_OVP_MASK, wled->cfg.ovp);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
wled->addr + PM8941_WLED_REG_BOOST,
|
||||
PM8941_WLED_REG_BOOST_MASK, wled->cfg.i_boost_limit);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
wled->addr + PM8941_WLED_REG_FREQ,
|
||||
PM8941_WLED_REG_FREQ_MASK, wled->cfg.switch_freq);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (wled->cfg.cs_out_en) {
|
||||
u8 all = (BIT(wled->cfg.num_strings) - 1)
|
||||
<< PM8941_WLED_REG_SINK_SHFT;
|
||||
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
wled->addr + PM8941_WLED_REG_SINK,
|
||||
PM8941_WLED_REG_SINK_MASK, all);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (i = 0; i < wled->cfg.num_strings; ++i) {
|
||||
u16 addr = wled->addr + PM8941_WLED_REG_STR_OFFSET * i;
|
||||
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
addr + PM8941_WLED_REG_STR_MOD_EN_BASE,
|
||||
PM8941_WLED_REG_STR_MOD_MASK,
|
||||
PM8941_WLED_REG_STR_MOD_EN);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (wled->cfg.ext_gen) {
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
addr + PM8941_WLED_REG_STR_MOD_SRC_BASE,
|
||||
PM8941_WLED_REG_STR_MOD_SRC_MASK,
|
||||
PM8941_WLED_REG_STR_MOD_SRC_EXT);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
addr + PM8941_WLED_REG_STR_SCALE_BASE,
|
||||
PM8941_WLED_REG_STR_SCALE_MASK,
|
||||
wled->cfg.i_limit);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
addr + PM8941_WLED_REG_STR_CABC_BASE,
|
||||
PM8941_WLED_REG_STR_CABC_MASK,
|
||||
wled->cfg.cabc_en ?
|
||||
PM8941_WLED_REG_STR_CABC_EN : 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pm8941_wled_config pm8941_wled_config_defaults = {
|
||||
.i_boost_limit = 3,
|
||||
.i_limit = 20,
|
||||
.ovp = 2,
|
||||
.switch_freq = 5,
|
||||
.num_strings = 0,
|
||||
.cs_out_en = false,
|
||||
.ext_gen = false,
|
||||
.cabc_en = false,
|
||||
};
|
||||
|
||||
struct pm8941_wled_var_cfg {
|
||||
const u32 *values;
|
||||
u32 (*fn)(u32);
|
||||
int size;
|
||||
};
|
||||
|
||||
static const u32 pm8941_wled_i_boost_limit_values[] = {
|
||||
105, 385, 525, 805, 980, 1260, 1400, 1680,
|
||||
};
|
||||
|
||||
static const struct pm8941_wled_var_cfg pm8941_wled_i_boost_limit_cfg = {
|
||||
.values = pm8941_wled_i_boost_limit_values,
|
||||
.size = ARRAY_SIZE(pm8941_wled_i_boost_limit_values),
|
||||
};
|
||||
|
||||
static const u32 pm8941_wled_ovp_values[] = {
|
||||
35, 32, 29, 27,
|
||||
};
|
||||
|
||||
static const struct pm8941_wled_var_cfg pm8941_wled_ovp_cfg = {
|
||||
.values = pm8941_wled_ovp_values,
|
||||
.size = ARRAY_SIZE(pm8941_wled_ovp_values),
|
||||
};
|
||||
|
||||
static u32 pm8941_wled_num_strings_values_fn(u32 idx)
|
||||
{
|
||||
return idx + 1;
|
||||
}
|
||||
|
||||
static const struct pm8941_wled_var_cfg pm8941_wled_num_strings_cfg = {
|
||||
.fn = pm8941_wled_num_strings_values_fn,
|
||||
.size = 3,
|
||||
};
|
||||
|
||||
static u32 pm8941_wled_switch_freq_values_fn(u32 idx)
|
||||
{
|
||||
return 19200 / (2 * (1 + idx));
|
||||
}
|
||||
|
||||
static const struct pm8941_wled_var_cfg pm8941_wled_switch_freq_cfg = {
|
||||
.fn = pm8941_wled_switch_freq_values_fn,
|
||||
.size = 16,
|
||||
};
|
||||
|
||||
static const struct pm8941_wled_var_cfg pm8941_wled_i_limit_cfg = {
|
||||
.size = 26,
|
||||
};
|
||||
|
||||
static u32 pm8941_wled_values(const struct pm8941_wled_var_cfg *cfg, u32 idx)
|
||||
{
|
||||
if (idx >= cfg->size)
|
||||
return UINT_MAX;
|
||||
if (cfg->fn)
|
||||
return cfg->fn(idx);
|
||||
if (cfg->values)
|
||||
return cfg->values[idx];
|
||||
return idx;
|
||||
}
|
||||
|
||||
static int pm8941_wled_configure(struct pm8941_wled *wled, struct device *dev)
|
||||
{
|
||||
struct pm8941_wled_config *cfg = &wled->cfg;
|
||||
u32 val;
|
||||
int rc;
|
||||
u32 c;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
const struct {
|
||||
const char *name;
|
||||
u32 *val_ptr;
|
||||
const struct pm8941_wled_var_cfg *cfg;
|
||||
} u32_opts[] = {
|
||||
{
|
||||
"qcom,current-boost-limit",
|
||||
&cfg->i_boost_limit,
|
||||
.cfg = &pm8941_wled_i_boost_limit_cfg,
|
||||
},
|
||||
{
|
||||
"qcom,current-limit",
|
||||
&cfg->i_limit,
|
||||
.cfg = &pm8941_wled_i_limit_cfg,
|
||||
},
|
||||
{
|
||||
"qcom,ovp",
|
||||
&cfg->ovp,
|
||||
.cfg = &pm8941_wled_ovp_cfg,
|
||||
},
|
||||
{
|
||||
"qcom,switching-freq",
|
||||
&cfg->switch_freq,
|
||||
.cfg = &pm8941_wled_switch_freq_cfg,
|
||||
},
|
||||
{
|
||||
"qcom,num-strings",
|
||||
&cfg->num_strings,
|
||||
.cfg = &pm8941_wled_num_strings_cfg,
|
||||
},
|
||||
};
|
||||
const struct {
|
||||
const char *name;
|
||||
bool *val_ptr;
|
||||
} bool_opts[] = {
|
||||
{ "qcom,cs-out", &cfg->cs_out_en, },
|
||||
{ "qcom,ext-gen", &cfg->ext_gen, },
|
||||
{ "qcom,cabc", &cfg->cabc_en, },
|
||||
};
|
||||
|
||||
rc = of_property_read_u32(dev->of_node, "reg", &val);
|
||||
if (rc || val > 0xffff) {
|
||||
dev_err(dev, "invalid IO resources\n");
|
||||
return rc ? rc : -EINVAL;
|
||||
}
|
||||
wled->addr = val;
|
||||
|
||||
rc = of_property_read_string(dev->of_node, "label", &wled->name);
|
||||
if (rc)
|
||||
wled->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn", dev->of_node);
|
||||
|
||||
*cfg = pm8941_wled_config_defaults;
|
||||
for (i = 0; i < ARRAY_SIZE(u32_opts); ++i) {
|
||||
rc = of_property_read_u32(dev->of_node, u32_opts[i].name, &val);
|
||||
if (rc == -EINVAL) {
|
||||
continue;
|
||||
} else if (rc) {
|
||||
dev_err(dev, "error reading '%s'\n", u32_opts[i].name);
|
||||
return rc;
|
||||
}
|
||||
|
||||
c = UINT_MAX;
|
||||
for (j = 0; c != val; j++) {
|
||||
c = pm8941_wled_values(u32_opts[i].cfg, j);
|
||||
if (c == UINT_MAX) {
|
||||
dev_err(dev, "invalid value for '%s'\n",
|
||||
u32_opts[i].name);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(dev, "'%s' = %u\n", u32_opts[i].name, c);
|
||||
*u32_opts[i].val_ptr = j;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bool_opts); ++i) {
|
||||
if (of_property_read_bool(dev->of_node, bool_opts[i].name))
|
||||
*bool_opts[i].val_ptr = true;
|
||||
}
|
||||
|
||||
cfg->num_strings = cfg->num_strings + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct backlight_ops pm8941_wled_ops = {
|
||||
.update_status = pm8941_wled_update_status,
|
||||
};
|
||||
|
||||
static int pm8941_wled_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct backlight_properties props;
|
||||
struct backlight_device *bl;
|
||||
struct pm8941_wled *wled;
|
||||
struct regmap *regmap;
|
||||
u32 val;
|
||||
int rc;
|
||||
|
||||
regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
if (!regmap) {
|
||||
dev_err(&pdev->dev, "Unable to get regmap\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wled = devm_kzalloc(&pdev->dev, sizeof(*wled), GFP_KERNEL);
|
||||
if (!wled)
|
||||
return -ENOMEM;
|
||||
|
||||
wled->regmap = regmap;
|
||||
|
||||
rc = pm8941_wled_configure(wled, &pdev->dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = pm8941_wled_setup(wled);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
val = PM8941_WLED_DEFAULT_BRIGHTNESS;
|
||||
of_property_read_u32(pdev->dev.of_node, "default-brightness", &val);
|
||||
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.type = BACKLIGHT_RAW;
|
||||
props.brightness = val;
|
||||
props.max_brightness = PM8941_WLED_REG_VAL_MAX;
|
||||
bl = devm_backlight_device_register(&pdev->dev, wled->name,
|
||||
&pdev->dev, wled,
|
||||
&pm8941_wled_ops, &props);
|
||||
return PTR_ERR_OR_ZERO(bl);
|
||||
};
|
||||
|
||||
static const struct of_device_id pm8941_wled_match_table[] = {
|
||||
{ .compatible = "qcom,pm8941-wled" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pm8941_wled_match_table);
|
||||
|
||||
static struct platform_driver pm8941_wled_driver = {
|
||||
.probe = pm8941_wled_probe,
|
||||
.driver = {
|
||||
.name = "pm8941-wled",
|
||||
.of_match_table = pm8941_wled_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(pm8941_wled_driver);
|
||||
|
||||
MODULE_DESCRIPTION("pm8941 wled driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -125,8 +125,9 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
|
|||
state.duty_cycle = compute_duty_cycle(pb, brightness);
|
||||
pwm_apply_state(pb->pwm, &state);
|
||||
pwm_backlight_power_on(pb);
|
||||
} else
|
||||
} else {
|
||||
pwm_backlight_power_off(pb);
|
||||
}
|
||||
|
||||
if (pb->notify_after)
|
||||
pb->notify_after(pb->dev, brightness);
|
||||
|
@ -148,15 +149,16 @@ static const struct backlight_ops pwm_backlight_ops = {
|
|||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
#define PWM_LUMINANCE_SCALE 10000 /* luminance scale */
|
||||
#define PWM_LUMINANCE_SHIFT 16
|
||||
#define PWM_LUMINANCE_SCALE (1 << PWM_LUMINANCE_SHIFT) /* luminance scale */
|
||||
|
||||
/*
|
||||
* CIE lightness to PWM conversion.
|
||||
*
|
||||
* The CIE 1931 lightness formula is what actually describes how we perceive
|
||||
* light:
|
||||
* Y = (L* / 902.3) if L* ≤ 0.08856
|
||||
* Y = ((L* + 16) / 116)^3 if L* > 0.08856
|
||||
* Y = (L* / 903.3) if L* ≤ 8
|
||||
* Y = ((L* + 16) / 116)^3 if L* > 8
|
||||
*
|
||||
* Where Y is the luminance, the amount of light coming out of the screen, and
|
||||
* is a number between 0.0 and 1.0; and L* is the lightness, how bright a human
|
||||
|
@ -165,16 +167,25 @@ static const struct backlight_ops pwm_backlight_ops = {
|
|||
* The following function does the fixed point maths needed to implement the
|
||||
* above formula.
|
||||
*/
|
||||
static u64 cie1931(unsigned int lightness, unsigned int scale)
|
||||
static u64 cie1931(unsigned int lightness)
|
||||
{
|
||||
u64 retval;
|
||||
|
||||
/*
|
||||
* @lightness is given as a number between 0 and 1, expressed
|
||||
* as a fixed-point number in scale
|
||||
* PWM_LUMINANCE_SCALE. Convert to a percentage, still
|
||||
* expressed as a fixed-point number, so the above formulas
|
||||
* can be applied.
|
||||
*/
|
||||
lightness *= 100;
|
||||
if (lightness <= (8 * scale)) {
|
||||
retval = DIV_ROUND_CLOSEST_ULL(lightness * 10, 9023);
|
||||
if (lightness <= (8 * PWM_LUMINANCE_SCALE)) {
|
||||
retval = DIV_ROUND_CLOSEST(lightness * 10, 9033);
|
||||
} else {
|
||||
retval = int_pow((lightness + (16 * scale)) / 116, 3);
|
||||
retval = DIV_ROUND_CLOSEST_ULL(retval, (scale * scale));
|
||||
retval = (lightness + (16 * PWM_LUMINANCE_SCALE)) / 116;
|
||||
retval *= retval * retval;
|
||||
retval += 1ULL << (2*PWM_LUMINANCE_SHIFT - 1);
|
||||
retval >>= 2*PWM_LUMINANCE_SHIFT;
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
@ -208,8 +219,7 @@ int pwm_backlight_brightness_default(struct device *dev,
|
|||
/* Fill the table using the cie1931 algorithm */
|
||||
for (i = 0; i < data->max_brightness; i++) {
|
||||
retval = cie1931((i * PWM_LUMINANCE_SCALE) /
|
||||
data->max_brightness, PWM_LUMINANCE_SCALE) *
|
||||
period;
|
||||
data->max_brightness) * period;
|
||||
retval = DIV_ROUND_CLOSEST_ULL(retval, PWM_LUMINANCE_SCALE);
|
||||
if (retval > UINT_MAX)
|
||||
return -EINVAL;
|
||||
|
@ -564,18 +574,17 @@ static int pwm_backlight_probe(struct platform_device *pdev)
|
|||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
|
||||
if (data->levels) {
|
||||
pb->levels = data->levels;
|
||||
|
||||
/*
|
||||
* For the DT case, only when brightness levels is defined
|
||||
* data->levels is filled. For the non-DT case, data->levels
|
||||
* can come from platform data, however is not usual.
|
||||
*/
|
||||
for (i = 0; i <= data->max_brightness; i++) {
|
||||
for (i = 0; i <= data->max_brightness; i++)
|
||||
if (data->levels[i] > pb->scale)
|
||||
pb->scale = data->levels[i];
|
||||
|
||||
pb->levels = data->levels;
|
||||
}
|
||||
|
||||
if (pwm_backlight_is_linear(data))
|
||||
props.scale = BACKLIGHT_SCALE_LINEAR;
|
||||
else
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include <asm/mach/sharpsl_param.h>
|
||||
|
||||
#include <mach/tosa.h>
|
||||
#include "tosa_bl.h"
|
||||
|
||||
#define COMADJ_DEFAULT 97
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
|||
struct tosa_bl_data {
|
||||
struct i2c_client *i2c;
|
||||
struct backlight_device *bl;
|
||||
struct gpio_desc *gpio;
|
||||
|
||||
int comadj;
|
||||
};
|
||||
|
@ -42,7 +43,7 @@ static void tosa_bl_set_backlight(struct tosa_bl_data *data, int brightness)
|
|||
i2c_smbus_write_byte_data(data->i2c, DAC_CH2, (u8)(brightness & 0xff));
|
||||
|
||||
/* SetBacklightVR */
|
||||
gpio_set_value(TOSA_GPIO_BL_C20MA, brightness & 0x100);
|
||||
gpiod_set_value(data->gpio, brightness & 0x100);
|
||||
|
||||
tosa_bl_enable(spi, brightness);
|
||||
}
|
||||
|
@ -87,9 +88,8 @@ static int tosa_bl_probe(struct i2c_client *client,
|
|||
return -ENOMEM;
|
||||
|
||||
data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj;
|
||||
|
||||
ret = devm_gpio_request_one(&client->dev, TOSA_GPIO_BL_C20MA,
|
||||
GPIOF_OUT_INIT_LOW, "backlight");
|
||||
data->gpio = devm_gpiod_get(&client->dev, "backlight", GPIOD_OUT_LOW);
|
||||
ret = PTR_ERR_OR_ZERO(data->gpio);
|
||||
if (ret) {
|
||||
dev_dbg(&data->bl->dev, "Unable to request gpio!\n");
|
||||
return ret;
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef _TOSA_BL_H
|
||||
#define _TOSA_BL_H
|
||||
|
||||
struct spi_device;
|
||||
extern int tosa_bl_enable(struct spi_device *spi, int enable);
|
||||
|
||||
#endif
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include <asm/mach/sharpsl_param.h>
|
||||
|
||||
#include <mach/tosa.h>
|
||||
#include "tosa_bl.h"
|
||||
|
||||
#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
|
||||
|
||||
|
@ -28,12 +28,26 @@
|
|||
#define TG_REG0_UD 0x0004
|
||||
#define TG_REG0_LR 0x0008
|
||||
|
||||
/*
|
||||
* Timing Generator
|
||||
*/
|
||||
#define TG_PNLCTL 0x00
|
||||
#define TG_TPOSCTL 0x01
|
||||
#define TG_DUTYCTL 0x02
|
||||
#define TG_GPOSR 0x03
|
||||
#define TG_GPODR1 0x04
|
||||
#define TG_GPODR2 0x05
|
||||
#define TG_PINICTL 0x06
|
||||
#define TG_HPOSCTL 0x07
|
||||
|
||||
|
||||
#define DAC_BASE 0x4e
|
||||
|
||||
struct tosa_lcd_data {
|
||||
struct spi_device *spi;
|
||||
struct lcd_device *lcd;
|
||||
struct i2c_client *i2c;
|
||||
struct gpio_desc *gpiod_tg;
|
||||
|
||||
int lcd_power;
|
||||
bool is_vga;
|
||||
|
@ -66,7 +80,7 @@ EXPORT_SYMBOL(tosa_bl_enable);
|
|||
static void tosa_lcd_tg_init(struct tosa_lcd_data *data)
|
||||
{
|
||||
/* TG on */
|
||||
gpio_set_value(TOSA_GPIO_TG_ON, 0);
|
||||
gpiod_set_value(data->gpiod_tg, 0);
|
||||
|
||||
mdelay(60);
|
||||
|
||||
|
@ -100,6 +114,7 @@ static void tosa_lcd_tg_on(struct tosa_lcd_data *data)
|
|||
*/
|
||||
struct i2c_adapter *adap = i2c_get_adapter(0);
|
||||
struct i2c_board_info info = {
|
||||
.dev_name = "tosa-bl",
|
||||
.type = "tosa-bl",
|
||||
.addr = DAC_BASE,
|
||||
.platform_data = data->spi,
|
||||
|
@ -121,7 +136,7 @@ static void tosa_lcd_tg_off(struct tosa_lcd_data *data)
|
|||
mdelay(50);
|
||||
|
||||
/* TG Off */
|
||||
gpio_set_value(TOSA_GPIO_TG_ON, 1);
|
||||
gpiod_set_value(data->gpiod_tg, 1);
|
||||
mdelay(100);
|
||||
}
|
||||
|
||||
|
@ -191,10 +206,9 @@ static int tosa_lcd_probe(struct spi_device *spi)
|
|||
data->spi = spi;
|
||||
spi_set_drvdata(spi, data);
|
||||
|
||||
ret = devm_gpio_request_one(&spi->dev, TOSA_GPIO_TG_ON,
|
||||
GPIOF_OUT_INIT_LOW, "tg #pwr");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
data->gpiod_tg = devm_gpiod_get(&spi->dev, "tg #pwr", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(data->gpiod_tg))
|
||||
return PTR_ERR(data->gpiod_tg);
|
||||
|
||||
mdelay(60);
|
||||
|
||||
|
|
|
@ -9,9 +9,6 @@ struct device;
|
|||
|
||||
struct gpio_backlight_platform_data {
|
||||
struct device *fbdev;
|
||||
int gpio;
|
||||
int def_value;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue