1 /* Copyright (c) 2010, 2011, 2016 The Linux Foundation. All rights reserved.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 #include <linux/leds.h>
13 #include <linux/module.h>
15 #include <linux/of_device.h>
16 #include <linux/platform_device.h>
18 #include <linux/regmap.h>
20 #define PM8058_LED_TYPE_COMMON 0x00
21 #define PM8058_LED_TYPE_KEYPAD 0x01
22 #define PM8058_LED_TYPE_FLASH 0x02
24 #define PM8058_LED_TYPE_COMMON_MASK 0xf8
25 #define PM8058_LED_TYPE_KEYPAD_MASK 0xf0
26 #define PM8058_LED_TYPE_COMMON_SHIFT 3
27 #define PM8058_LED_TYPE_KEYPAD_SHIFT 4
33 struct led_classdev cdev
;
36 static void pm8058_led_set(struct led_classdev
*cled
,
37 enum led_brightness value
)
39 struct pm8058_led
*led
;
41 unsigned int mask
= 0;
44 led
= container_of(cled
, struct pm8058_led
, cdev
);
45 switch (led
->ledtype
) {
46 case PM8058_LED_TYPE_COMMON
:
47 mask
= PM8058_LED_TYPE_COMMON_MASK
;
48 val
= value
<< PM8058_LED_TYPE_COMMON_SHIFT
;
50 case PM8058_LED_TYPE_KEYPAD
:
51 case PM8058_LED_TYPE_FLASH
:
52 mask
= PM8058_LED_TYPE_KEYPAD_MASK
;
53 val
= value
<< PM8058_LED_TYPE_KEYPAD_SHIFT
;
59 ret
= regmap_update_bits(led
->map
, led
->reg
, mask
, val
);
61 pr_err("Failed to set LED brightness\n");
64 static enum led_brightness
pm8058_led_get(struct led_classdev
*cled
)
66 struct pm8058_led
*led
;
70 led
= container_of(cled
, struct pm8058_led
, cdev
);
72 ret
= regmap_read(led
->map
, led
->reg
, &val
);
74 pr_err("Failed to get LED brightness\n");
78 switch (led
->ledtype
) {
79 case PM8058_LED_TYPE_COMMON
:
80 val
&= PM8058_LED_TYPE_COMMON_MASK
;
81 val
>>= PM8058_LED_TYPE_COMMON_SHIFT
;
83 case PM8058_LED_TYPE_KEYPAD
:
84 case PM8058_LED_TYPE_FLASH
:
85 val
&= PM8058_LED_TYPE_KEYPAD_MASK
;
86 val
>>= PM8058_LED_TYPE_KEYPAD_SHIFT
;
96 static int pm8058_led_probe(struct platform_device
*pdev
)
98 struct pm8058_led
*led
;
99 struct device_node
*np
= pdev
->dev
.of_node
;
103 enum led_brightness maxbright
;
105 led
= devm_kzalloc(&pdev
->dev
, sizeof(*led
), GFP_KERNEL
);
109 led
->ledtype
= (u32
)of_device_get_match_data(&pdev
->dev
);
111 map
= dev_get_regmap(pdev
->dev
.parent
, NULL
);
113 dev_err(&pdev
->dev
, "Parent regmap unavailable.\n");
118 ret
= of_property_read_u32(np
, "reg", &led
->reg
);
120 dev_err(&pdev
->dev
, "no register offset specified\n");
124 /* Use label else node name */
125 led
->cdev
.name
= of_get_property(np
, "label", NULL
) ? : np
->name
;
126 led
->cdev
.default_trigger
=
127 of_get_property(np
, "linux,default-trigger", NULL
);
128 led
->cdev
.brightness_set
= pm8058_led_set
;
129 led
->cdev
.brightness_get
= pm8058_led_get
;
130 if (led
->ledtype
== PM8058_LED_TYPE_COMMON
)
131 maxbright
= 31; /* 5 bits */
133 maxbright
= 15; /* 4 bits */
134 led
->cdev
.max_brightness
= maxbright
;
136 state
= of_get_property(np
, "default-state", NULL
);
138 if (!strcmp(state
, "keep")) {
139 led
->cdev
.brightness
= pm8058_led_get(&led
->cdev
);
140 } else if (!strcmp(state
, "on")) {
141 led
->cdev
.brightness
= maxbright
;
142 pm8058_led_set(&led
->cdev
, maxbright
);
144 led
->cdev
.brightness
= LED_OFF
;
145 pm8058_led_set(&led
->cdev
, LED_OFF
);
149 if (led
->ledtype
== PM8058_LED_TYPE_KEYPAD
||
150 led
->ledtype
== PM8058_LED_TYPE_FLASH
)
151 led
->cdev
.flags
= LED_CORE_SUSPENDRESUME
;
153 ret
= devm_led_classdev_register(&pdev
->dev
, &led
->cdev
);
155 dev_err(&pdev
->dev
, "unable to register led \"%s\"\n",
163 static const struct of_device_id pm8058_leds_id_table
[] = {
165 .compatible
= "qcom,pm8058-led",
166 .data
= (void *)PM8058_LED_TYPE_COMMON
169 .compatible
= "qcom,pm8058-keypad-led",
170 .data
= (void *)PM8058_LED_TYPE_KEYPAD
173 .compatible
= "qcom,pm8058-flash-led",
174 .data
= (void *)PM8058_LED_TYPE_FLASH
178 MODULE_DEVICE_TABLE(of
, pm8058_leds_id_table
);
180 static struct platform_driver pm8058_led_driver
= {
181 .probe
= pm8058_led_probe
,
183 .name
= "pm8058-leds",
184 .of_match_table
= pm8058_leds_id_table
,
187 module_platform_driver(pm8058_led_driver
);
189 MODULE_DESCRIPTION("PM8058 LEDs driver");
190 MODULE_LICENSE("GPL v2");
191 MODULE_ALIAS("platform:pm8058-leds");