mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	- 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
					
				
					 19 changed files with 1658 additions and 617 deletions
				
			
		|  | @ -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': |   '#size-cells': | ||||||
|     const: 0 |     const: 0 | ||||||
| 
 | 
 | ||||||
|  |   enable-gpios: | ||||||
|  |     description: GPIO to use to enable/disable the backlight (HWEN pin). | ||||||
|  |     maxItems: 1 | ||||||
|  | 
 | ||||||
| required: | required: | ||||||
|   - compatible |   - compatible | ||||||
|   - reg |   - reg | ||||||
|  | @ -89,6 +93,7 @@ additionalProperties: false | ||||||
| 
 | 
 | ||||||
| examples: | examples: | ||||||
|   - | |   - | | ||||||
|  |     #include <dt-bindings/gpio/gpio.h> | ||||||
|     i2c { |     i2c { | ||||||
|         #address-cells = <1>; |         #address-cells = <1>; | ||||||
|         #size-cells = <0>; |         #size-cells = <0>; | ||||||
|  | @ -96,6 +101,7 @@ examples: | ||||||
|         led-controller@38 { |         led-controller@38 { | ||||||
|                 compatible = "ti,lm3630a"; |                 compatible = "ti,lm3630a"; | ||||||
|                 reg = <0x38>; |                 reg = <0x38>; | ||||||
|  |                 enable-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>; | ||||||
| 
 | 
 | ||||||
|                 #address-cells = <1>; |                 #address-cells = <1>; | ||||||
|                 #size-cells = <0>; |                 #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>; |  | ||||||
| }; |  | ||||||
							
								
								
									
										154
									
								
								Documentation/devicetree/bindings/leds/backlight/qcom-wled.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								Documentation/devicetree/bindings/leds/backlight/qcom-wled.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -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_BAT0_TH_ON		(TOSA_TC6393XB_GPIO_BASE + 14) | ||||||
| #define TOSA_GPIO_BAT1_TH_ON		(TOSA_TC6393XB_GPIO_BASE + 15) | #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 |  * PXA GPIOs | ||||||
|  */ |  */ | ||||||
|  | @ -192,7 +180,4 @@ | ||||||
| #define TOSA_KEY_MAIL		KEY_MAIL | #define TOSA_KEY_MAIL		KEY_MAIL | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| struct spi_device; |  | ||||||
| extern int tosa_bl_enable(struct spi_device *spi, int enable); |  | ||||||
| 
 |  | ||||||
| #endif /* _ASM_ARCH_TOSA_H_ */ | #endif /* _ASM_ARCH_TOSA_H_ */ | ||||||
|  |  | ||||||
|  | @ -813,6 +813,26 @@ static struct pxa2xx_spi_controller pxa_ssp_master_info = { | ||||||
| 	.num_chipselect	= 1, | 	.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 = { | static struct spi_board_info spi_board_info[] __initdata = { | ||||||
| 	{ | 	{ | ||||||
| 		.modalias	= "tosa-lcd", | 		.modalias	= "tosa-lcd", | ||||||
|  | @ -923,6 +943,8 @@ static void __init tosa_init(void) | ||||||
| 	platform_scoop_config = &tosa_pcmcia_config; | 	platform_scoop_config = &tosa_pcmcia_config; | ||||||
| 
 | 
 | ||||||
| 	pxa2xx_set_spi_info(2, &pxa_ssp_master_info); | 	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)); | 	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); | ||||||
| 
 | 
 | ||||||
| 	clk_add_alias("CLK_CK3P6MI", tc6393xb_device.name, "GPIO11_CLK", NULL); | 	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 = { | static struct gpiod_lookup_table gpio_backlight_lookup = { | ||||||
| 	.fbdev = &lcdc_device.dev, | 	.dev_id		= "gpio-backlight.0", | ||||||
| 	.gpio = GPIO_PTR1, | 	.table = { | ||||||
| 	.def_value = 1, | 		GPIO_LOOKUP("sh7724_pfc", GPIO_PTR1, NULL, GPIO_ACTIVE_HIGH), | ||||||
| 	.name = "backlight", | 		{ } | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static struct platform_device gpio_backlight_device = { |  | ||||||
| 	.name = "gpio-backlight", |  | ||||||
| 	.dev = { |  | ||||||
| 		.platform_data = &gpio_backlight_data, |  | ||||||
| 	}, | 	}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | 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 */ | /* CEU0 */ | ||||||
| static struct ceu_platform_data ceu0_pdata = { | static struct ceu_platform_data ceu0_pdata = { | ||||||
| 	.num_subdevs			= 2, | 	.num_subdevs			= 2, | ||||||
|  | @ -1006,7 +1018,6 @@ static struct platform_device *ecovec_devices[] __initdata = { | ||||||
| 	&usb1_common_device, | 	&usb1_common_device, | ||||||
| 	&usbhs_device, | 	&usbhs_device, | ||||||
| 	&lcdc_device, | 	&lcdc_device, | ||||||
| 	&gpio_backlight_device, |  | ||||||
| 	&keysc_device, | 	&keysc_device, | ||||||
| 	&cn12_power, | 	&cn12_power, | ||||||
| #if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE) | #if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE) | ||||||
|  | @ -1462,6 +1473,12 @@ static int __init arch_setup(void) | ||||||
| #endif | #endif | ||||||
| #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, | 	return platform_add_devices(ecovec_devices, | ||||||
| 				    ARRAY_SIZE(ecovec_devices)); | 				    ARRAY_SIZE(ecovec_devices)); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -99,7 +99,7 @@ config LCD_TOSA | ||||||
| 
 | 
 | ||||||
| config LCD_HP700 | config LCD_HP700 | ||||||
| 	tristate "HP Jornada 700 series LCD Driver" | 	tristate "HP Jornada 700 series LCD Driver" | ||||||
| 	depends on SA1100_JORNADA720_SSP && !PREEMPT | 	depends on SA1100_JORNADA720_SSP && !PREEMPTION | ||||||
| 	default y | 	default y | ||||||
| 	help | 	help | ||||||
| 	  If you have an HP Jornada 700 series handheld (710/720/728) | 	  If you have an HP Jornada 700 series handheld (710/720/728) | ||||||
|  | @ -228,7 +228,7 @@ config BACKLIGHT_HP680 | ||||||
| 
 | 
 | ||||||
| config BACKLIGHT_HP700 | config BACKLIGHT_HP700 | ||||||
| 	tristate "HP Jornada 700 series Backlight Driver" | 	tristate "HP Jornada 700 series Backlight Driver" | ||||||
| 	depends on SA1100_JORNADA720_SSP && !PREEMPT | 	depends on SA1100_JORNADA720_SSP && !PREEMPTION | ||||||
| 	default y | 	default y | ||||||
| 	help | 	help | ||||||
| 	  If you have an HP Jornada 700 series, | 	  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 | 	  If you have an Sharp SL-6000 Zaurus say Y to enable a driver | ||||||
| 	  for its backlight | 	  for its backlight | ||||||
| 
 | 
 | ||||||
| config BACKLIGHT_PM8941_WLED | config BACKLIGHT_QCOM_WLED | ||||||
| 	tristate "Qualcomm PM8941 WLED Driver" | 	tristate "Qualcomm PMIC WLED Driver" | ||||||
| 	select REGMAP | 	select REGMAP | ||||||
| 	help | 	help | ||||||
| 	  If you have the Qualcomm PM8941, say Y to enable a driver for the | 	  If you have the Qualcomm PMIC, say Y to enable a driver for the | ||||||
| 	  WLED block. | 	  WLED block. Currently it supports PM8941 and PMI8998. | ||||||
| 
 | 
 | ||||||
| config BACKLIGHT_SAHARA | config BACKLIGHT_SAHARA | ||||||
| 	tristate "Tabletkiosk Sahara Touch-iT Backlight Driver" | 	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_OT200)		+= ot200_bl.o | ||||||
| obj-$(CONFIG_BACKLIGHT_PANDORA)		+= pandora_bl.o | obj-$(CONFIG_BACKLIGHT_PANDORA)		+= pandora_bl.o | ||||||
| obj-$(CONFIG_BACKLIGHT_PCF50633)	+= pcf50633-backlight.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_PWM)		+= pwm_bl.o | ||||||
|  | obj-$(CONFIG_BACKLIGHT_QCOM_WLED)	+= qcom-wled.o | ||||||
| obj-$(CONFIG_BACKLIGHT_SAHARA)		+= kb3886_bl.o | obj-$(CONFIG_BACKLIGHT_SAHARA)		+= kb3886_bl.o | ||||||
| obj-$(CONFIG_BACKLIGHT_SKY81452)	+= sky81452-backlight.o | obj-$(CONFIG_BACKLIGHT_SKY81452)	+= sky81452-backlight.o | ||||||
| obj-$(CONFIG_BACKLIGHT_TOSA)		+= tosa_bl.o | obj-$(CONFIG_BACKLIGHT_TOSA)		+= tosa_bl.o | ||||||
|  |  | ||||||
|  | @ -6,29 +6,23 @@ | ||||||
| #include <linux/backlight.h> | #include <linux/backlight.h> | ||||||
| #include <linux/err.h> | #include <linux/err.h> | ||||||
| #include <linux/fb.h> | #include <linux/fb.h> | ||||||
| #include <linux/gpio.h> /* Only for legacy support */ |  | ||||||
| #include <linux/gpio/consumer.h> | #include <linux/gpio/consumer.h> | ||||||
| #include <linux/init.h> | #include <linux/init.h> | ||||||
| #include <linux/kernel.h> | #include <linux/kernel.h> | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/of.h> | #include <linux/of.h> | ||||||
| #include <linux/of_gpio.h> |  | ||||||
| #include <linux/platform_data/gpio_backlight.h> | #include <linux/platform_data/gpio_backlight.h> | ||||||
| #include <linux/platform_device.h> | #include <linux/platform_device.h> | ||||||
| #include <linux/property.h> | #include <linux/property.h> | ||||||
| #include <linux/slab.h> | #include <linux/slab.h> | ||||||
| 
 | 
 | ||||||
| struct gpio_backlight { | struct gpio_backlight { | ||||||
| 	struct device *dev; |  | ||||||
| 	struct device *fbdev; | 	struct device *fbdev; | ||||||
| 
 |  | ||||||
| 	struct gpio_desc *gpiod; | 	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; | 	int brightness = bl->props.brightness; | ||||||
| 
 | 
 | ||||||
| 	if (bl->props.power != FB_BLANK_UNBLANK || | 	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)) | 	    bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) | ||||||
| 		brightness = 0; | 		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); | 	gpiod_set_value_cansleep(gbl->gpiod, brightness); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -55,105 +57,63 @@ static const struct backlight_ops gpio_backlight_ops = { | ||||||
| 	.check_fb	= gpio_backlight_check_fb, | 	.check_fb	= gpio_backlight_check_fb, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static int gpio_backlight_probe_dt(struct platform_device *pdev, | static int gpio_backlight_probe(struct platform_device *pdev) | ||||||
| 				   struct gpio_backlight *gbl) |  | ||||||
| { | { | ||||||
| 	struct device *dev = &pdev->dev; | 	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); | 	gbl->gpiod = devm_gpiod_get(dev, NULL, GPIOD_ASIS); | ||||||
| 	if (IS_ERR(gbl->gpiod)) { | 	if (IS_ERR(gbl->gpiod)) { | ||||||
| 		ret = PTR_ERR(gbl->gpiod); | 		ret = PTR_ERR(gbl->gpiod); | ||||||
| 
 | 		if (ret != -EPROBE_DEFER) | ||||||
| 		if (ret != -EPROBE_DEFER) { |  | ||||||
| 			dev_err(dev, | 			dev_err(dev, | ||||||
| 				"Error: The gpios parameter is missing or invalid.\n"); | 				"Error: The gpios parameter is missing or invalid.\n"); | ||||||
| 		} |  | ||||||
| 		return ret; | 		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)); | 	memset(&props, 0, sizeof(props)); | ||||||
| 	props.type = BACKLIGHT_RAW; | 	props.type = BACKLIGHT_RAW; | ||||||
| 	props.max_brightness = 1; | 	props.max_brightness = 1; | ||||||
| 	bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), | 	bl = devm_backlight_device_register(dev, dev_name(dev), dev, gbl, | ||||||
| 					&pdev->dev, gbl, &gpio_backlight_ops, | 					    &gpio_backlight_ops, &props); | ||||||
| 					&props); |  | ||||||
| 	if (IS_ERR(bl)) { | 	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); | 		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; | 	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); | 	platform_set_drvdata(pdev, bl); | ||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
|  | @ -44,7 +44,7 @@ static const struct backlight_ops micro_bl_ops = { | ||||||
| 	.update_status  = micro_bl_update_status, | 	.update_status  = micro_bl_update_status, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static struct backlight_properties micro_bl_props = { | static const struct backlight_properties micro_bl_props = { | ||||||
| 	.type = BACKLIGHT_RAW, | 	.type = BACKLIGHT_RAW, | ||||||
| 	.max_brightness = 255, | 	.max_brightness = 255, | ||||||
| 	.power = FB_BLANK_UNBLANK, | 	.power = FB_BLANK_UNBLANK, | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ | ||||||
| #include <linux/uaccess.h> | #include <linux/uaccess.h> | ||||||
| #include <linux/interrupt.h> | #include <linux/interrupt.h> | ||||||
| #include <linux/regmap.h> | #include <linux/regmap.h> | ||||||
|  | #include <linux/gpio/consumer.h> | ||||||
| #include <linux/pwm.h> | #include <linux/pwm.h> | ||||||
| #include <linux/platform_data/lm3630a_bl.h> | #include <linux/platform_data/lm3630a_bl.h> | ||||||
| 
 | 
 | ||||||
|  | @ -48,6 +49,7 @@ struct lm3630a_chip { | ||||||
| 	struct lm3630a_platform_data *pdata; | 	struct lm3630a_platform_data *pdata; | ||||||
| 	struct backlight_device *bleda; | 	struct backlight_device *bleda; | ||||||
| 	struct backlight_device *bledb; | 	struct backlight_device *bledb; | ||||||
|  | 	struct gpio_desc *enable_gpio; | ||||||
| 	struct regmap *regmap; | 	struct regmap *regmap; | ||||||
| 	struct pwm_device *pwmd; | 	struct pwm_device *pwmd; | ||||||
| }; | }; | ||||||
|  | @ -534,6 +536,13 @@ static int lm3630a_probe(struct i2c_client *client, | ||||||
| 	} | 	} | ||||||
| 	pchip->pdata = pdata; | 	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 */ | 	/* chip initialize */ | ||||||
| 	rval = lm3630a_chip_init(pchip); | 	rval = lm3630a_chip_init(pchip); | ||||||
| 	if (rval < 0) { | 	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[] = { | static const struct of_device_id lm3630a_match_table[] = { | ||||||
| 	{ .compatible = "ti,lm3630a", }, | 	{ .compatible = "ti,lm3630a", }, | ||||||
| 	{ }, | 	{ }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| MODULE_DEVICE_TABLE(i2c, lm3630a_id); | MODULE_DEVICE_TABLE(of, lm3630a_match_table); | ||||||
| 
 | 
 | ||||||
| static struct i2c_driver lm3630a_i2c_driver = { | static struct i2c_driver lm3630a_i2c_driver = { | ||||||
| 	.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); | 		state.duty_cycle = compute_duty_cycle(pb, brightness); | ||||||
| 		pwm_apply_state(pb->pwm, &state); | 		pwm_apply_state(pb->pwm, &state); | ||||||
| 		pwm_backlight_power_on(pb); | 		pwm_backlight_power_on(pb); | ||||||
| 	} else | 	} else { | ||||||
| 		pwm_backlight_power_off(pb); | 		pwm_backlight_power_off(pb); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if (pb->notify_after) | 	if (pb->notify_after) | ||||||
| 		pb->notify_after(pb->dev, brightness); | 		pb->notify_after(pb->dev, brightness); | ||||||
|  | @ -148,15 +149,16 @@ static const struct backlight_ops pwm_backlight_ops = { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_OF | #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. |  * CIE lightness to PWM conversion. | ||||||
|  * |  * | ||||||
|  * The CIE 1931 lightness formula is what actually describes how we perceive |  * The CIE 1931 lightness formula is what actually describes how we perceive | ||||||
|  * light: |  * light: | ||||||
|  *          Y = (L* / 902.3)           if L* ≤ 0.08856 |  *          Y = (L* / 903.3)           if L* ≤ 8 | ||||||
|  *          Y = ((L* + 16) / 116)^3    if L* > 0.08856 |  *          Y = ((L* + 16) / 116)^3    if L* > 8 | ||||||
|  * |  * | ||||||
|  * Where Y is the luminance, the amount of light coming out of the screen, and |  * 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 |  * 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 |  * The following function does the fixed point maths needed to implement the | ||||||
|  * above formula. |  * above formula. | ||||||
|  */ |  */ | ||||||
| static u64 cie1931(unsigned int lightness, unsigned int scale) | static u64 cie1931(unsigned int lightness) | ||||||
| { | { | ||||||
| 	u64 retval; | 	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; | 	lightness *= 100; | ||||||
| 	if (lightness <= (8 * scale)) { | 	if (lightness <= (8 * PWM_LUMINANCE_SCALE)) { | ||||||
| 		retval = DIV_ROUND_CLOSEST_ULL(lightness * 10, 9023); | 		retval = DIV_ROUND_CLOSEST(lightness * 10, 9033); | ||||||
| 	} else { | 	} else { | ||||||
| 		retval = int_pow((lightness + (16 * scale)) / 116, 3); | 		retval = (lightness + (16 * PWM_LUMINANCE_SCALE)) / 116; | ||||||
| 		retval = DIV_ROUND_CLOSEST_ULL(retval, (scale * scale)); | 		retval *= retval * retval; | ||||||
|  | 		retval += 1ULL << (2*PWM_LUMINANCE_SHIFT - 1); | ||||||
|  | 		retval >>= 2*PWM_LUMINANCE_SHIFT; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return retval; | 	return retval; | ||||||
|  | @ -208,8 +219,7 @@ int pwm_backlight_brightness_default(struct device *dev, | ||||||
| 	/* Fill the table using the cie1931 algorithm */ | 	/* Fill the table using the cie1931 algorithm */ | ||||||
| 	for (i = 0; i < data->max_brightness; i++) { | 	for (i = 0; i < data->max_brightness; i++) { | ||||||
| 		retval = cie1931((i * PWM_LUMINANCE_SCALE) / | 		retval = cie1931((i * PWM_LUMINANCE_SCALE) / | ||||||
| 				 data->max_brightness, PWM_LUMINANCE_SCALE) * | 				 data->max_brightness) * period; | ||||||
| 				 period; |  | ||||||
| 		retval = DIV_ROUND_CLOSEST_ULL(retval, PWM_LUMINANCE_SCALE); | 		retval = DIV_ROUND_CLOSEST_ULL(retval, PWM_LUMINANCE_SCALE); | ||||||
| 		if (retval > UINT_MAX) | 		if (retval > UINT_MAX) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
|  | @ -564,18 +574,17 @@ static int pwm_backlight_probe(struct platform_device *pdev) | ||||||
| 	memset(&props, 0, sizeof(struct backlight_properties)); | 	memset(&props, 0, sizeof(struct backlight_properties)); | ||||||
| 
 | 
 | ||||||
| 	if (data->levels) { | 	if (data->levels) { | ||||||
|  | 		pb->levels = data->levels; | ||||||
|  | 
 | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * For the DT case, only when brightness levels is defined | 		 * For the DT case, only when brightness levels is defined | ||||||
| 		 * data->levels is filled. For the non-DT case, data->levels | 		 * data->levels is filled. For the non-DT case, data->levels | ||||||
| 		 * can come from platform data, however is not usual. | 		 * 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) | 			if (data->levels[i] > pb->scale) | ||||||
| 				pb->scale = data->levels[i]; | 				pb->scale = data->levels[i]; | ||||||
| 
 | 
 | ||||||
| 			pb->levels = data->levels; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (pwm_backlight_is_linear(data)) | 		if (pwm_backlight_is_linear(data)) | ||||||
| 			props.scale = BACKLIGHT_SCALE_LINEAR; | 			props.scale = BACKLIGHT_SCALE_LINEAR; | ||||||
| 		else | 		else | ||||||
|  |  | ||||||
							
								
								
									
										1296
									
								
								drivers/video/backlight/qcom-wled.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1296
									
								
								drivers/video/backlight/qcom-wled.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -18,7 +18,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <asm/mach/sharpsl_param.h> | #include <asm/mach/sharpsl_param.h> | ||||||
| 
 | 
 | ||||||
| #include <mach/tosa.h> | #include "tosa_bl.h" | ||||||
| 
 | 
 | ||||||
| #define COMADJ_DEFAULT	97 | #define COMADJ_DEFAULT	97 | ||||||
| 
 | 
 | ||||||
|  | @ -28,6 +28,7 @@ | ||||||
| struct tosa_bl_data { | struct tosa_bl_data { | ||||||
| 	struct i2c_client *i2c; | 	struct i2c_client *i2c; | ||||||
| 	struct backlight_device *bl; | 	struct backlight_device *bl; | ||||||
|  | 	struct gpio_desc *gpio; | ||||||
| 
 | 
 | ||||||
| 	int comadj; | 	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)); | 	i2c_smbus_write_byte_data(data->i2c, DAC_CH2, (u8)(brightness & 0xff)); | ||||||
| 
 | 
 | ||||||
| 	/* SetBacklightVR */ | 	/* SetBacklightVR */ | ||||||
| 	gpio_set_value(TOSA_GPIO_BL_C20MA, brightness & 0x100); | 	gpiod_set_value(data->gpio, brightness & 0x100); | ||||||
| 
 | 
 | ||||||
| 	tosa_bl_enable(spi, brightness); | 	tosa_bl_enable(spi, brightness); | ||||||
| } | } | ||||||
|  | @ -87,9 +88,8 @@ static int tosa_bl_probe(struct i2c_client *client, | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
| 	data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj; | 	data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj; | ||||||
| 
 | 	data->gpio = devm_gpiod_get(&client->dev, "backlight", GPIOD_OUT_LOW); | ||||||
| 	ret = devm_gpio_request_one(&client->dev, TOSA_GPIO_BL_C20MA, | 	ret = PTR_ERR_OR_ZERO(data->gpio); | ||||||
| 				GPIOF_OUT_INIT_LOW, "backlight"); |  | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		dev_dbg(&data->bl->dev, "Unable to request gpio!\n"); | 		dev_dbg(&data->bl->dev, "Unable to request gpio!\n"); | ||||||
| 		return ret; | 		return ret; | ||||||
|  |  | ||||||
							
								
								
									
										8
									
								
								drivers/video/backlight/tosa_bl.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								drivers/video/backlight/tosa_bl.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 <asm/mach/sharpsl_param.h> | ||||||
| 
 | 
 | ||||||
| #include <mach/tosa.h> | #include "tosa_bl.h" | ||||||
| 
 | 
 | ||||||
| #define POWER_IS_ON(pwr)	((pwr) <= FB_BLANK_NORMAL) | #define POWER_IS_ON(pwr)	((pwr) <= FB_BLANK_NORMAL) | ||||||
| 
 | 
 | ||||||
|  | @ -28,12 +28,26 @@ | ||||||
| #define TG_REG0_UD	0x0004 | #define TG_REG0_UD	0x0004 | ||||||
| #define TG_REG0_LR	0x0008 | #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 | #define	DAC_BASE	0x4e | ||||||
| 
 | 
 | ||||||
| struct tosa_lcd_data { | struct tosa_lcd_data { | ||||||
| 	struct spi_device *spi; | 	struct spi_device *spi; | ||||||
| 	struct lcd_device *lcd; | 	struct lcd_device *lcd; | ||||||
| 	struct i2c_client *i2c; | 	struct i2c_client *i2c; | ||||||
|  | 	struct gpio_desc *gpiod_tg; | ||||||
| 
 | 
 | ||||||
| 	int lcd_power; | 	int lcd_power; | ||||||
| 	bool is_vga; | 	bool is_vga; | ||||||
|  | @ -66,7 +80,7 @@ EXPORT_SYMBOL(tosa_bl_enable); | ||||||
| static void tosa_lcd_tg_init(struct tosa_lcd_data *data) | static void tosa_lcd_tg_init(struct tosa_lcd_data *data) | ||||||
| { | { | ||||||
| 	/* TG on */ | 	/* TG on */ | ||||||
| 	gpio_set_value(TOSA_GPIO_TG_ON, 0); | 	gpiod_set_value(data->gpiod_tg, 0); | ||||||
| 
 | 
 | ||||||
| 	mdelay(60); | 	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_adapter *adap = i2c_get_adapter(0); | ||||||
| 		struct i2c_board_info info = { | 		struct i2c_board_info info = { | ||||||
|  | 			.dev_name = "tosa-bl", | ||||||
| 			.type	= "tosa-bl", | 			.type	= "tosa-bl", | ||||||
| 			.addr	= DAC_BASE, | 			.addr	= DAC_BASE, | ||||||
| 			.platform_data = data->spi, | 			.platform_data = data->spi, | ||||||
|  | @ -121,7 +136,7 @@ static void tosa_lcd_tg_off(struct tosa_lcd_data *data) | ||||||
| 	mdelay(50); | 	mdelay(50); | ||||||
| 
 | 
 | ||||||
| 	/* TG Off */ | 	/* TG Off */ | ||||||
| 	gpio_set_value(TOSA_GPIO_TG_ON, 1); | 	gpiod_set_value(data->gpiod_tg, 1); | ||||||
| 	mdelay(100); | 	mdelay(100); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -191,10 +206,9 @@ static int tosa_lcd_probe(struct spi_device *spi) | ||||||
| 	data->spi = spi; | 	data->spi = spi; | ||||||
| 	spi_set_drvdata(spi, data); | 	spi_set_drvdata(spi, data); | ||||||
| 
 | 
 | ||||||
| 	ret = devm_gpio_request_one(&spi->dev, TOSA_GPIO_TG_ON, | 	data->gpiod_tg = devm_gpiod_get(&spi->dev, "tg #pwr", GPIOD_OUT_LOW); | ||||||
| 				GPIOF_OUT_INIT_LOW, "tg #pwr"); | 	if (IS_ERR(data->gpiod_tg)) | ||||||
| 	if (ret < 0) | 		return PTR_ERR(data->gpiod_tg); | ||||||
| 		return ret; |  | ||||||
| 
 | 
 | ||||||
| 	mdelay(60); | 	mdelay(60); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,9 +9,6 @@ struct device; | ||||||
| 
 | 
 | ||||||
| struct gpio_backlight_platform_data { | struct gpio_backlight_platform_data { | ||||||
| 	struct device *fbdev; | 	struct device *fbdev; | ||||||
| 	int gpio; |  | ||||||
| 	int def_value; |  | ||||||
| 	const char *name; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Linus Torvalds
						Linus Torvalds