1 // SPDX-License-Identifier: GPL-2.0+
3 #include <linux/leds.h>
4 #include <linux/module.h>
5 #include <linux/platform_device.h>
6 #include <linux/regmap.h>
8 #define A500_EC_LED_DELAY_USEC (100 * 1000)
11 REG_RESET_LEDS
= 0x40,
12 REG_POWER_LED_ON
= 0x42,
13 REG_CHARGE_LED_ON
= 0x43,
14 REG_ANDROID_LEDS_OFF
= 0x5a,
18 struct led_classdev cdev
;
19 const struct reg_sequence
*enable_seq
;
20 struct a500_led
*other
;
24 static const struct reg_sequence a500_ec_leds_reset_seq
[] = {
25 REG_SEQ(REG_RESET_LEDS
, 0x0, A500_EC_LED_DELAY_USEC
),
26 REG_SEQ(REG_ANDROID_LEDS_OFF
, 0x0, A500_EC_LED_DELAY_USEC
),
29 static const struct reg_sequence a500_ec_white_led_enable_seq
[] = {
30 REG_SEQ(REG_POWER_LED_ON
, 0x0, A500_EC_LED_DELAY_USEC
),
33 static const struct reg_sequence a500_ec_orange_led_enable_seq
[] = {
34 REG_SEQ(REG_CHARGE_LED_ON
, 0x0, A500_EC_LED_DELAY_USEC
),
37 static int a500_ec_led_brightness_set(struct led_classdev
*led_cdev
,
38 enum led_brightness value
)
40 struct a500_led
*led
= container_of(led_cdev
, struct a500_led
, cdev
);
41 struct reg_sequence control_seq
[2];
42 unsigned int num_regs
= 1;
45 control_seq
[0] = led
->enable_seq
[0];
48 * There is no separate controls which can disable LEDs
49 * individually, there is only RESET_LEDS command that turns
52 * RESET_LEDS turns off both LEDs, thus restore other LED if
55 if (led
->other
->cdev
.brightness
)
58 control_seq
[0] = a500_ec_leds_reset_seq
[0];
59 control_seq
[1] = led
->other
->enable_seq
[0];
62 return regmap_multi_reg_write(led
->rmap
, control_seq
, num_regs
);
65 static int a500_ec_leds_probe(struct platform_device
*pdev
)
67 struct a500_led
*white_led
, *orange_led
;
71 rmap
= dev_get_regmap(pdev
->dev
.parent
, "KB930");
75 /* reset and turn off LEDs */
76 regmap_multi_reg_write(rmap
, a500_ec_leds_reset_seq
, 2);
78 white_led
= devm_kzalloc(&pdev
->dev
, sizeof(*white_led
), GFP_KERNEL
);
82 white_led
->cdev
.name
= "power:white";
83 white_led
->cdev
.brightness_set_blocking
= a500_ec_led_brightness_set
;
84 white_led
->cdev
.flags
= LED_CORE_SUSPENDRESUME
;
85 white_led
->cdev
.max_brightness
= 1;
86 white_led
->enable_seq
= a500_ec_white_led_enable_seq
;
87 white_led
->rmap
= rmap
;
89 orange_led
= devm_kzalloc(&pdev
->dev
, sizeof(*orange_led
), GFP_KERNEL
);
93 orange_led
->cdev
.name
= "power:orange";
94 orange_led
->cdev
.brightness_set_blocking
= a500_ec_led_brightness_set
;
95 orange_led
->cdev
.flags
= LED_CORE_SUSPENDRESUME
;
96 orange_led
->cdev
.max_brightness
= 1;
97 orange_led
->enable_seq
= a500_ec_orange_led_enable_seq
;
98 orange_led
->rmap
= rmap
;
100 white_led
->other
= orange_led
;
101 orange_led
->other
= white_led
;
103 err
= devm_led_classdev_register(&pdev
->dev
, &white_led
->cdev
);
105 dev_err(&pdev
->dev
, "failed to register white LED\n");
109 err
= devm_led_classdev_register(&pdev
->dev
, &orange_led
->cdev
);
111 dev_err(&pdev
->dev
, "failed to register orange LED\n");
118 static struct platform_driver a500_ec_leds_driver
= {
120 .name
= "acer-a500-iconia-leds",
122 .probe
= a500_ec_leds_probe
,
124 module_platform_driver(a500_ec_leds_driver
);
126 MODULE_DESCRIPTION("LED driver for Acer Iconia Tab A500 Power Button");
127 MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>");
128 MODULE_ALIAS("platform:acer-a500-iconia-leds");
129 MODULE_LICENSE("GPL");