12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2401dea7fSJohan Hovold /*
3401dea7fSJohan Hovold * leds-lm3533.c -- LM3533 LED driver
4401dea7fSJohan Hovold *
5401dea7fSJohan Hovold * Copyright (C) 2011-2012 Texas Instruments
6401dea7fSJohan Hovold *
7401dea7fSJohan Hovold * Author: Johan Hovold <jhovold@gmail.com>
8401dea7fSJohan Hovold */
9401dea7fSJohan Hovold
10401dea7fSJohan Hovold #include <linux/module.h>
11401dea7fSJohan Hovold #include <linux/leds.h>
12401dea7fSJohan Hovold #include <linux/mfd/core.h>
13401dea7fSJohan Hovold #include <linux/mutex.h>
14401dea7fSJohan Hovold #include <linux/platform_device.h>
15401dea7fSJohan Hovold #include <linux/slab.h>
16401dea7fSJohan Hovold
17401dea7fSJohan Hovold #include <linux/mfd/lm3533.h>
18401dea7fSJohan Hovold
19401dea7fSJohan Hovold
20401dea7fSJohan Hovold #define LM3533_LVCTRLBANK_MIN 2
21401dea7fSJohan Hovold #define LM3533_LVCTRLBANK_MAX 5
22401dea7fSJohan Hovold #define LM3533_LVCTRLBANK_COUNT 4
23401dea7fSJohan Hovold #define LM3533_RISEFALLTIME_MAX 7
24401dea7fSJohan Hovold #define LM3533_ALS_CHANNEL_LV_MIN 1
25401dea7fSJohan Hovold #define LM3533_ALS_CHANNEL_LV_MAX 2
26401dea7fSJohan Hovold
27401dea7fSJohan Hovold #define LM3533_REG_CTRLBANK_BCONF_BASE 0x1b
28401dea7fSJohan Hovold #define LM3533_REG_PATTERN_ENABLE 0x28
29401dea7fSJohan Hovold #define LM3533_REG_PATTERN_LOW_TIME_BASE 0x71
30401dea7fSJohan Hovold #define LM3533_REG_PATTERN_HIGH_TIME_BASE 0x72
31401dea7fSJohan Hovold #define LM3533_REG_PATTERN_RISETIME_BASE 0x74
32401dea7fSJohan Hovold #define LM3533_REG_PATTERN_FALLTIME_BASE 0x75
33401dea7fSJohan Hovold
34401dea7fSJohan Hovold #define LM3533_REG_PATTERN_STEP 0x10
35401dea7fSJohan Hovold
36401dea7fSJohan Hovold #define LM3533_REG_CTRLBANK_BCONF_MAPPING_MASK 0x04
37401dea7fSJohan Hovold #define LM3533_REG_CTRLBANK_BCONF_ALS_EN_MASK 0x02
38401dea7fSJohan Hovold #define LM3533_REG_CTRLBANK_BCONF_ALS_CHANNEL_MASK 0x01
39401dea7fSJohan Hovold
40401dea7fSJohan Hovold #define LM3533_LED_FLAG_PATTERN_ENABLE 1
41401dea7fSJohan Hovold
42401dea7fSJohan Hovold
43401dea7fSJohan Hovold struct lm3533_led {
44401dea7fSJohan Hovold struct lm3533 *lm3533;
45401dea7fSJohan Hovold struct lm3533_ctrlbank cb;
46401dea7fSJohan Hovold struct led_classdev cdev;
47401dea7fSJohan Hovold int id;
48401dea7fSJohan Hovold
49401dea7fSJohan Hovold struct mutex mutex;
50401dea7fSJohan Hovold unsigned long flags;
51401dea7fSJohan Hovold };
52401dea7fSJohan Hovold
53401dea7fSJohan Hovold
to_lm3533_led(struct led_classdev * cdev)54401dea7fSJohan Hovold static inline struct lm3533_led *to_lm3533_led(struct led_classdev *cdev)
55401dea7fSJohan Hovold {
56401dea7fSJohan Hovold return container_of(cdev, struct lm3533_led, cdev);
57401dea7fSJohan Hovold }
58401dea7fSJohan Hovold
lm3533_led_get_ctrlbank_id(struct lm3533_led * led)59401dea7fSJohan Hovold static inline int lm3533_led_get_ctrlbank_id(struct lm3533_led *led)
60401dea7fSJohan Hovold {
61401dea7fSJohan Hovold return led->id + 2;
62401dea7fSJohan Hovold }
63401dea7fSJohan Hovold
lm3533_led_get_lv_reg(struct lm3533_led * led,u8 base)64401dea7fSJohan Hovold static inline u8 lm3533_led_get_lv_reg(struct lm3533_led *led, u8 base)
65401dea7fSJohan Hovold {
66401dea7fSJohan Hovold return base + led->id;
67401dea7fSJohan Hovold }
68401dea7fSJohan Hovold
lm3533_led_get_pattern(struct lm3533_led * led)69401dea7fSJohan Hovold static inline u8 lm3533_led_get_pattern(struct lm3533_led *led)
70401dea7fSJohan Hovold {
71401dea7fSJohan Hovold return led->id;
72401dea7fSJohan Hovold }
73401dea7fSJohan Hovold
lm3533_led_get_pattern_reg(struct lm3533_led * led,u8 base)74401dea7fSJohan Hovold static inline u8 lm3533_led_get_pattern_reg(struct lm3533_led *led,
75401dea7fSJohan Hovold u8 base)
76401dea7fSJohan Hovold {
77401dea7fSJohan Hovold return base + lm3533_led_get_pattern(led) * LM3533_REG_PATTERN_STEP;
78401dea7fSJohan Hovold }
79401dea7fSJohan Hovold
lm3533_led_pattern_enable(struct lm3533_led * led,int enable)80401dea7fSJohan Hovold static int lm3533_led_pattern_enable(struct lm3533_led *led, int enable)
81401dea7fSJohan Hovold {
82401dea7fSJohan Hovold u8 mask;
83401dea7fSJohan Hovold u8 val;
84401dea7fSJohan Hovold int pattern;
85401dea7fSJohan Hovold int state;
86401dea7fSJohan Hovold int ret = 0;
87401dea7fSJohan Hovold
88401dea7fSJohan Hovold dev_dbg(led->cdev.dev, "%s - %d\n", __func__, enable);
89401dea7fSJohan Hovold
90401dea7fSJohan Hovold mutex_lock(&led->mutex);
91401dea7fSJohan Hovold
92401dea7fSJohan Hovold state = test_bit(LM3533_LED_FLAG_PATTERN_ENABLE, &led->flags);
93401dea7fSJohan Hovold if ((enable && state) || (!enable && !state))
94401dea7fSJohan Hovold goto out;
95401dea7fSJohan Hovold
96401dea7fSJohan Hovold pattern = lm3533_led_get_pattern(led);
97401dea7fSJohan Hovold mask = 1 << (2 * pattern);
98401dea7fSJohan Hovold
99401dea7fSJohan Hovold if (enable)
100401dea7fSJohan Hovold val = mask;
101401dea7fSJohan Hovold else
102401dea7fSJohan Hovold val = 0;
103401dea7fSJohan Hovold
104401dea7fSJohan Hovold ret = lm3533_update(led->lm3533, LM3533_REG_PATTERN_ENABLE, val, mask);
105401dea7fSJohan Hovold if (ret) {
106401dea7fSJohan Hovold dev_err(led->cdev.dev, "failed to enable pattern %d (%d)\n",
107401dea7fSJohan Hovold pattern, enable);
108401dea7fSJohan Hovold goto out;
109401dea7fSJohan Hovold }
110401dea7fSJohan Hovold
111401dea7fSJohan Hovold __change_bit(LM3533_LED_FLAG_PATTERN_ENABLE, &led->flags);
112401dea7fSJohan Hovold out:
113401dea7fSJohan Hovold mutex_unlock(&led->mutex);
114401dea7fSJohan Hovold
115401dea7fSJohan Hovold return ret;
116401dea7fSJohan Hovold }
117401dea7fSJohan Hovold
lm3533_led_set(struct led_classdev * cdev,enum led_brightness value)118a478851cSAndrew Lunn static int lm3533_led_set(struct led_classdev *cdev,
119401dea7fSJohan Hovold enum led_brightness value)
120401dea7fSJohan Hovold {
121401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(cdev);
122401dea7fSJohan Hovold
123401dea7fSJohan Hovold dev_dbg(led->cdev.dev, "%s - %d\n", __func__, value);
124401dea7fSJohan Hovold
125a478851cSAndrew Lunn if (value == 0)
126a478851cSAndrew Lunn lm3533_led_pattern_enable(led, 0); /* disable blink */
127a478851cSAndrew Lunn
128a478851cSAndrew Lunn return lm3533_ctrlbank_set_brightness(&led->cb, value);
129401dea7fSJohan Hovold }
130401dea7fSJohan Hovold
lm3533_led_get(struct led_classdev * cdev)131401dea7fSJohan Hovold static enum led_brightness lm3533_led_get(struct led_classdev *cdev)
132401dea7fSJohan Hovold {
133401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(cdev);
134401dea7fSJohan Hovold u8 val;
135401dea7fSJohan Hovold int ret;
136401dea7fSJohan Hovold
137401dea7fSJohan Hovold ret = lm3533_ctrlbank_get_brightness(&led->cb, &val);
138401dea7fSJohan Hovold if (ret)
139401dea7fSJohan Hovold return ret;
140401dea7fSJohan Hovold
141401dea7fSJohan Hovold dev_dbg(led->cdev.dev, "%s - %u\n", __func__, val);
142401dea7fSJohan Hovold
143401dea7fSJohan Hovold return val;
144401dea7fSJohan Hovold }
145401dea7fSJohan Hovold
146401dea7fSJohan Hovold /* Pattern generator defines (delays in us). */
147401dea7fSJohan Hovold #define LM3533_LED_DELAY1_VMIN 0x00
148401dea7fSJohan Hovold #define LM3533_LED_DELAY2_VMIN 0x3d
149401dea7fSJohan Hovold #define LM3533_LED_DELAY3_VMIN 0x80
150401dea7fSJohan Hovold
151401dea7fSJohan Hovold #define LM3533_LED_DELAY1_VMAX (LM3533_LED_DELAY2_VMIN - 1)
152401dea7fSJohan Hovold #define LM3533_LED_DELAY2_VMAX (LM3533_LED_DELAY3_VMIN - 1)
153401dea7fSJohan Hovold #define LM3533_LED_DELAY3_VMAX 0xff
154401dea7fSJohan Hovold
155401dea7fSJohan Hovold #define LM3533_LED_DELAY1_TMIN 16384U
156401dea7fSJohan Hovold #define LM3533_LED_DELAY2_TMIN 1130496U
157401dea7fSJohan Hovold #define LM3533_LED_DELAY3_TMIN 10305536U
158401dea7fSJohan Hovold
159401dea7fSJohan Hovold #define LM3533_LED_DELAY1_TMAX 999424U
160401dea7fSJohan Hovold #define LM3533_LED_DELAY2_TMAX 9781248U
161401dea7fSJohan Hovold #define LM3533_LED_DELAY3_TMAX 76890112U
162401dea7fSJohan Hovold
163401dea7fSJohan Hovold /* t_step = (t_max - t_min) / (v_max - v_min) */
164401dea7fSJohan Hovold #define LM3533_LED_DELAY1_TSTEP 16384
165401dea7fSJohan Hovold #define LM3533_LED_DELAY2_TSTEP 131072
166401dea7fSJohan Hovold #define LM3533_LED_DELAY3_TSTEP 524288
167401dea7fSJohan Hovold
168401dea7fSJohan Hovold /* Delay limits for hardware accelerated blinking (in ms). */
169401dea7fSJohan Hovold #define LM3533_LED_DELAY_ON_MAX \
170401dea7fSJohan Hovold ((LM3533_LED_DELAY2_TMAX + LM3533_LED_DELAY2_TSTEP / 2) / 1000)
171401dea7fSJohan Hovold #define LM3533_LED_DELAY_OFF_MAX \
172401dea7fSJohan Hovold ((LM3533_LED_DELAY3_TMAX + LM3533_LED_DELAY3_TSTEP / 2) / 1000)
173401dea7fSJohan Hovold
174401dea7fSJohan Hovold /*
175401dea7fSJohan Hovold * Returns linear map of *t from [t_min,t_max] to [v_min,v_max] with a step
176401dea7fSJohan Hovold * size of t_step, where
177401dea7fSJohan Hovold *
178401dea7fSJohan Hovold * t_step = (t_max - t_min) / (v_max - v_min)
179401dea7fSJohan Hovold *
180401dea7fSJohan Hovold * and updates *t to reflect the mapped value.
181401dea7fSJohan Hovold */
time_to_val(unsigned * t,unsigned t_min,unsigned t_step,u8 v_min,u8 v_max)182401dea7fSJohan Hovold static u8 time_to_val(unsigned *t, unsigned t_min, unsigned t_step,
183401dea7fSJohan Hovold u8 v_min, u8 v_max)
184401dea7fSJohan Hovold {
185401dea7fSJohan Hovold unsigned val;
186401dea7fSJohan Hovold
187401dea7fSJohan Hovold val = (*t + t_step / 2 - t_min) / t_step + v_min;
188401dea7fSJohan Hovold
189401dea7fSJohan Hovold *t = t_step * (val - v_min) + t_min;
190401dea7fSJohan Hovold
191401dea7fSJohan Hovold return (u8)val;
192401dea7fSJohan Hovold }
193401dea7fSJohan Hovold
194401dea7fSJohan Hovold /*
195401dea7fSJohan Hovold * Returns time code corresponding to *delay (in ms) and updates *delay to
196401dea7fSJohan Hovold * reflect actual hardware delay.
197401dea7fSJohan Hovold *
198401dea7fSJohan Hovold * Hardware supports 256 discrete delay times, divided into three groups with
199401dea7fSJohan Hovold * the following ranges and step-sizes:
200401dea7fSJohan Hovold *
201401dea7fSJohan Hovold * [ 16, 999] [0x00, 0x3e] step 16 ms
202401dea7fSJohan Hovold * [ 1130, 9781] [0x3d, 0x7f] step 131 ms
203401dea7fSJohan Hovold * [10306, 76890] [0x80, 0xff] step 524 ms
204401dea7fSJohan Hovold *
205401dea7fSJohan Hovold * Note that delay group 3 is only available for delay_off.
206401dea7fSJohan Hovold */
lm3533_led_get_hw_delay(unsigned * delay)207401dea7fSJohan Hovold static u8 lm3533_led_get_hw_delay(unsigned *delay)
208401dea7fSJohan Hovold {
209401dea7fSJohan Hovold unsigned t;
210401dea7fSJohan Hovold u8 val;
211401dea7fSJohan Hovold
212401dea7fSJohan Hovold t = *delay * 1000;
213401dea7fSJohan Hovold
214401dea7fSJohan Hovold if (t >= (LM3533_LED_DELAY2_TMAX + LM3533_LED_DELAY3_TMIN) / 2) {
215401dea7fSJohan Hovold t = clamp(t, LM3533_LED_DELAY3_TMIN, LM3533_LED_DELAY3_TMAX);
216401dea7fSJohan Hovold val = time_to_val(&t, LM3533_LED_DELAY3_TMIN,
217401dea7fSJohan Hovold LM3533_LED_DELAY3_TSTEP,
218401dea7fSJohan Hovold LM3533_LED_DELAY3_VMIN,
219401dea7fSJohan Hovold LM3533_LED_DELAY3_VMAX);
220401dea7fSJohan Hovold } else if (t >= (LM3533_LED_DELAY1_TMAX + LM3533_LED_DELAY2_TMIN) / 2) {
221401dea7fSJohan Hovold t = clamp(t, LM3533_LED_DELAY2_TMIN, LM3533_LED_DELAY2_TMAX);
222401dea7fSJohan Hovold val = time_to_val(&t, LM3533_LED_DELAY2_TMIN,
223401dea7fSJohan Hovold LM3533_LED_DELAY2_TSTEP,
224401dea7fSJohan Hovold LM3533_LED_DELAY2_VMIN,
225401dea7fSJohan Hovold LM3533_LED_DELAY2_VMAX);
226401dea7fSJohan Hovold } else {
227401dea7fSJohan Hovold t = clamp(t, LM3533_LED_DELAY1_TMIN, LM3533_LED_DELAY1_TMAX);
228401dea7fSJohan Hovold val = time_to_val(&t, LM3533_LED_DELAY1_TMIN,
229401dea7fSJohan Hovold LM3533_LED_DELAY1_TSTEP,
230401dea7fSJohan Hovold LM3533_LED_DELAY1_VMIN,
231401dea7fSJohan Hovold LM3533_LED_DELAY1_VMAX);
232401dea7fSJohan Hovold }
233401dea7fSJohan Hovold
234401dea7fSJohan Hovold *delay = (t + 500) / 1000;
235401dea7fSJohan Hovold
236401dea7fSJohan Hovold return val;
237401dea7fSJohan Hovold }
238401dea7fSJohan Hovold
239401dea7fSJohan Hovold /*
240401dea7fSJohan Hovold * Set delay register base to *delay (in ms) and update *delay to reflect
241401dea7fSJohan Hovold * actual hardware delay used.
242401dea7fSJohan Hovold */
lm3533_led_delay_set(struct lm3533_led * led,u8 base,unsigned long * delay)243401dea7fSJohan Hovold static u8 lm3533_led_delay_set(struct lm3533_led *led, u8 base,
244401dea7fSJohan Hovold unsigned long *delay)
245401dea7fSJohan Hovold {
246401dea7fSJohan Hovold unsigned t;
247401dea7fSJohan Hovold u8 val;
248401dea7fSJohan Hovold u8 reg;
249401dea7fSJohan Hovold int ret;
250401dea7fSJohan Hovold
251401dea7fSJohan Hovold t = (unsigned)*delay;
252401dea7fSJohan Hovold
253401dea7fSJohan Hovold /* Delay group 3 is only available for low time (delay off). */
254401dea7fSJohan Hovold if (base != LM3533_REG_PATTERN_LOW_TIME_BASE)
255401dea7fSJohan Hovold t = min(t, LM3533_LED_DELAY2_TMAX / 1000);
256401dea7fSJohan Hovold
257401dea7fSJohan Hovold val = lm3533_led_get_hw_delay(&t);
258401dea7fSJohan Hovold
259401dea7fSJohan Hovold dev_dbg(led->cdev.dev, "%s - %lu: %u (0x%02x)\n", __func__,
260401dea7fSJohan Hovold *delay, t, val);
261401dea7fSJohan Hovold reg = lm3533_led_get_pattern_reg(led, base);
262401dea7fSJohan Hovold ret = lm3533_write(led->lm3533, reg, val);
263401dea7fSJohan Hovold if (ret)
264401dea7fSJohan Hovold dev_err(led->cdev.dev, "failed to set delay (%02x)\n", reg);
265401dea7fSJohan Hovold
266401dea7fSJohan Hovold *delay = t;
267401dea7fSJohan Hovold
268401dea7fSJohan Hovold return ret;
269401dea7fSJohan Hovold }
270401dea7fSJohan Hovold
lm3533_led_delay_on_set(struct lm3533_led * led,unsigned long * t)271401dea7fSJohan Hovold static int lm3533_led_delay_on_set(struct lm3533_led *led, unsigned long *t)
272401dea7fSJohan Hovold {
273401dea7fSJohan Hovold return lm3533_led_delay_set(led, LM3533_REG_PATTERN_HIGH_TIME_BASE, t);
274401dea7fSJohan Hovold }
275401dea7fSJohan Hovold
lm3533_led_delay_off_set(struct lm3533_led * led,unsigned long * t)276401dea7fSJohan Hovold static int lm3533_led_delay_off_set(struct lm3533_led *led, unsigned long *t)
277401dea7fSJohan Hovold {
278401dea7fSJohan Hovold return lm3533_led_delay_set(led, LM3533_REG_PATTERN_LOW_TIME_BASE, t);
279401dea7fSJohan Hovold }
280401dea7fSJohan Hovold
lm3533_led_blink_set(struct led_classdev * cdev,unsigned long * delay_on,unsigned long * delay_off)281401dea7fSJohan Hovold static int lm3533_led_blink_set(struct led_classdev *cdev,
282401dea7fSJohan Hovold unsigned long *delay_on,
283401dea7fSJohan Hovold unsigned long *delay_off)
284401dea7fSJohan Hovold {
285401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(cdev);
286401dea7fSJohan Hovold int ret;
287401dea7fSJohan Hovold
288401dea7fSJohan Hovold dev_dbg(led->cdev.dev, "%s - on = %lu, off = %lu\n", __func__,
289401dea7fSJohan Hovold *delay_on, *delay_off);
290401dea7fSJohan Hovold
291401dea7fSJohan Hovold if (*delay_on > LM3533_LED_DELAY_ON_MAX ||
292401dea7fSJohan Hovold *delay_off > LM3533_LED_DELAY_OFF_MAX)
293401dea7fSJohan Hovold return -EINVAL;
294401dea7fSJohan Hovold
295401dea7fSJohan Hovold if (*delay_on == 0 && *delay_off == 0) {
296401dea7fSJohan Hovold *delay_on = 500;
297401dea7fSJohan Hovold *delay_off = 500;
298401dea7fSJohan Hovold }
299401dea7fSJohan Hovold
300401dea7fSJohan Hovold ret = lm3533_led_delay_on_set(led, delay_on);
301401dea7fSJohan Hovold if (ret)
302401dea7fSJohan Hovold return ret;
303401dea7fSJohan Hovold
304401dea7fSJohan Hovold ret = lm3533_led_delay_off_set(led, delay_off);
305401dea7fSJohan Hovold if (ret)
306401dea7fSJohan Hovold return ret;
307401dea7fSJohan Hovold
308401dea7fSJohan Hovold return lm3533_led_pattern_enable(led, 1);
309401dea7fSJohan Hovold }
310401dea7fSJohan Hovold
show_id(struct device * dev,struct device_attribute * attr,char * buf)311401dea7fSJohan Hovold static ssize_t show_id(struct device *dev,
312401dea7fSJohan Hovold struct device_attribute *attr, char *buf)
313401dea7fSJohan Hovold {
314401dea7fSJohan Hovold struct led_classdev *led_cdev = dev_get_drvdata(dev);
315401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(led_cdev);
316401dea7fSJohan Hovold
317*3f6fb1cfSye xingchen return sysfs_emit(buf, "%d\n", led->id);
318401dea7fSJohan Hovold }
319401dea7fSJohan Hovold
320401dea7fSJohan Hovold /*
321401dea7fSJohan Hovold * Pattern generator rise/fall times:
322401dea7fSJohan Hovold *
323401dea7fSJohan Hovold * 0 - 2048 us (default)
324401dea7fSJohan Hovold * 1 - 262 ms
325401dea7fSJohan Hovold * 2 - 524 ms
326401dea7fSJohan Hovold * 3 - 1.049 s
327401dea7fSJohan Hovold * 4 - 2.097 s
328401dea7fSJohan Hovold * 5 - 4.194 s
329401dea7fSJohan Hovold * 6 - 8.389 s
330401dea7fSJohan Hovold * 7 - 16.78 s
331401dea7fSJohan Hovold */
show_risefalltime(struct device * dev,struct device_attribute * attr,char * buf,u8 base)332401dea7fSJohan Hovold static ssize_t show_risefalltime(struct device *dev,
333401dea7fSJohan Hovold struct device_attribute *attr,
334401dea7fSJohan Hovold char *buf, u8 base)
335401dea7fSJohan Hovold {
336401dea7fSJohan Hovold struct led_classdev *led_cdev = dev_get_drvdata(dev);
337401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(led_cdev);
338401dea7fSJohan Hovold ssize_t ret;
339401dea7fSJohan Hovold u8 reg;
340401dea7fSJohan Hovold u8 val;
341401dea7fSJohan Hovold
342401dea7fSJohan Hovold reg = lm3533_led_get_pattern_reg(led, base);
343401dea7fSJohan Hovold ret = lm3533_read(led->lm3533, reg, &val);
344401dea7fSJohan Hovold if (ret)
345401dea7fSJohan Hovold return ret;
346401dea7fSJohan Hovold
347*3f6fb1cfSye xingchen return sysfs_emit(buf, "%x\n", val);
348401dea7fSJohan Hovold }
349401dea7fSJohan Hovold
show_risetime(struct device * dev,struct device_attribute * attr,char * buf)350401dea7fSJohan Hovold static ssize_t show_risetime(struct device *dev,
351401dea7fSJohan Hovold struct device_attribute *attr, char *buf)
352401dea7fSJohan Hovold {
353401dea7fSJohan Hovold return show_risefalltime(dev, attr, buf,
354401dea7fSJohan Hovold LM3533_REG_PATTERN_RISETIME_BASE);
355401dea7fSJohan Hovold }
356401dea7fSJohan Hovold
show_falltime(struct device * dev,struct device_attribute * attr,char * buf)357401dea7fSJohan Hovold static ssize_t show_falltime(struct device *dev,
358401dea7fSJohan Hovold struct device_attribute *attr, char *buf)
359401dea7fSJohan Hovold {
360401dea7fSJohan Hovold return show_risefalltime(dev, attr, buf,
361401dea7fSJohan Hovold LM3533_REG_PATTERN_FALLTIME_BASE);
362401dea7fSJohan Hovold }
363401dea7fSJohan Hovold
store_risefalltime(struct device * dev,struct device_attribute * attr,const char * buf,size_t len,u8 base)364401dea7fSJohan Hovold static ssize_t store_risefalltime(struct device *dev,
365401dea7fSJohan Hovold struct device_attribute *attr,
366401dea7fSJohan Hovold const char *buf, size_t len, u8 base)
367401dea7fSJohan Hovold {
368401dea7fSJohan Hovold struct led_classdev *led_cdev = dev_get_drvdata(dev);
369401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(led_cdev);
370401dea7fSJohan Hovold u8 val;
371401dea7fSJohan Hovold u8 reg;
372401dea7fSJohan Hovold int ret;
373401dea7fSJohan Hovold
374401dea7fSJohan Hovold if (kstrtou8(buf, 0, &val) || val > LM3533_RISEFALLTIME_MAX)
375401dea7fSJohan Hovold return -EINVAL;
376401dea7fSJohan Hovold
377401dea7fSJohan Hovold reg = lm3533_led_get_pattern_reg(led, base);
378401dea7fSJohan Hovold ret = lm3533_write(led->lm3533, reg, val);
379401dea7fSJohan Hovold if (ret)
380401dea7fSJohan Hovold return ret;
381401dea7fSJohan Hovold
382401dea7fSJohan Hovold return len;
383401dea7fSJohan Hovold }
384401dea7fSJohan Hovold
store_risetime(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)385401dea7fSJohan Hovold static ssize_t store_risetime(struct device *dev,
386401dea7fSJohan Hovold struct device_attribute *attr,
387401dea7fSJohan Hovold const char *buf, size_t len)
388401dea7fSJohan Hovold {
389401dea7fSJohan Hovold return store_risefalltime(dev, attr, buf, len,
390401dea7fSJohan Hovold LM3533_REG_PATTERN_RISETIME_BASE);
391401dea7fSJohan Hovold }
392401dea7fSJohan Hovold
store_falltime(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)393401dea7fSJohan Hovold static ssize_t store_falltime(struct device *dev,
394401dea7fSJohan Hovold struct device_attribute *attr,
395401dea7fSJohan Hovold const char *buf, size_t len)
396401dea7fSJohan Hovold {
397401dea7fSJohan Hovold return store_risefalltime(dev, attr, buf, len,
398401dea7fSJohan Hovold LM3533_REG_PATTERN_FALLTIME_BASE);
399401dea7fSJohan Hovold }
400401dea7fSJohan Hovold
show_als_channel(struct device * dev,struct device_attribute * attr,char * buf)401401dea7fSJohan Hovold static ssize_t show_als_channel(struct device *dev,
402401dea7fSJohan Hovold struct device_attribute *attr, char *buf)
403401dea7fSJohan Hovold {
404401dea7fSJohan Hovold struct led_classdev *led_cdev = dev_get_drvdata(dev);
405401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(led_cdev);
406401dea7fSJohan Hovold unsigned channel;
407401dea7fSJohan Hovold u8 reg;
408401dea7fSJohan Hovold u8 val;
409401dea7fSJohan Hovold int ret;
410401dea7fSJohan Hovold
411401dea7fSJohan Hovold reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
412401dea7fSJohan Hovold ret = lm3533_read(led->lm3533, reg, &val);
413401dea7fSJohan Hovold if (ret)
414401dea7fSJohan Hovold return ret;
415401dea7fSJohan Hovold
416401dea7fSJohan Hovold channel = (val & LM3533_REG_CTRLBANK_BCONF_ALS_CHANNEL_MASK) + 1;
417401dea7fSJohan Hovold
418*3f6fb1cfSye xingchen return sysfs_emit(buf, "%u\n", channel);
419401dea7fSJohan Hovold }
420401dea7fSJohan Hovold
store_als_channel(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)421401dea7fSJohan Hovold static ssize_t store_als_channel(struct device *dev,
422401dea7fSJohan Hovold struct device_attribute *attr,
423401dea7fSJohan Hovold const char *buf, size_t len)
424401dea7fSJohan Hovold {
425401dea7fSJohan Hovold struct led_classdev *led_cdev = dev_get_drvdata(dev);
426401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(led_cdev);
427401dea7fSJohan Hovold unsigned channel;
428401dea7fSJohan Hovold u8 reg;
429401dea7fSJohan Hovold u8 val;
430401dea7fSJohan Hovold u8 mask;
431401dea7fSJohan Hovold int ret;
432401dea7fSJohan Hovold
433401dea7fSJohan Hovold if (kstrtouint(buf, 0, &channel))
434401dea7fSJohan Hovold return -EINVAL;
435401dea7fSJohan Hovold
436401dea7fSJohan Hovold if (channel < LM3533_ALS_CHANNEL_LV_MIN ||
437401dea7fSJohan Hovold channel > LM3533_ALS_CHANNEL_LV_MAX)
438401dea7fSJohan Hovold return -EINVAL;
439401dea7fSJohan Hovold
440401dea7fSJohan Hovold reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
441401dea7fSJohan Hovold mask = LM3533_REG_CTRLBANK_BCONF_ALS_CHANNEL_MASK;
442401dea7fSJohan Hovold val = channel - 1;
443401dea7fSJohan Hovold
444401dea7fSJohan Hovold ret = lm3533_update(led->lm3533, reg, val, mask);
445401dea7fSJohan Hovold if (ret)
446401dea7fSJohan Hovold return ret;
447401dea7fSJohan Hovold
448401dea7fSJohan Hovold return len;
449401dea7fSJohan Hovold }
450401dea7fSJohan Hovold
show_als_en(struct device * dev,struct device_attribute * attr,char * buf)451401dea7fSJohan Hovold static ssize_t show_als_en(struct device *dev,
452401dea7fSJohan Hovold struct device_attribute *attr, char *buf)
453401dea7fSJohan Hovold {
454401dea7fSJohan Hovold struct led_classdev *led_cdev = dev_get_drvdata(dev);
455401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(led_cdev);
456401dea7fSJohan Hovold bool enable;
457401dea7fSJohan Hovold u8 reg;
458401dea7fSJohan Hovold u8 val;
459401dea7fSJohan Hovold int ret;
460401dea7fSJohan Hovold
461401dea7fSJohan Hovold reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
462401dea7fSJohan Hovold ret = lm3533_read(led->lm3533, reg, &val);
463401dea7fSJohan Hovold if (ret)
464401dea7fSJohan Hovold return ret;
465401dea7fSJohan Hovold
466401dea7fSJohan Hovold enable = val & LM3533_REG_CTRLBANK_BCONF_ALS_EN_MASK;
467401dea7fSJohan Hovold
468*3f6fb1cfSye xingchen return sysfs_emit(buf, "%d\n", enable);
469401dea7fSJohan Hovold }
470401dea7fSJohan Hovold
store_als_en(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)471401dea7fSJohan Hovold static ssize_t store_als_en(struct device *dev,
472401dea7fSJohan Hovold struct device_attribute *attr,
473401dea7fSJohan Hovold const char *buf, size_t len)
474401dea7fSJohan Hovold {
475401dea7fSJohan Hovold struct led_classdev *led_cdev = dev_get_drvdata(dev);
476401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(led_cdev);
477401dea7fSJohan Hovold unsigned enable;
478401dea7fSJohan Hovold u8 reg;
479401dea7fSJohan Hovold u8 mask;
480401dea7fSJohan Hovold u8 val;
481401dea7fSJohan Hovold int ret;
482401dea7fSJohan Hovold
483401dea7fSJohan Hovold if (kstrtouint(buf, 0, &enable))
484401dea7fSJohan Hovold return -EINVAL;
485401dea7fSJohan Hovold
486401dea7fSJohan Hovold reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
487401dea7fSJohan Hovold mask = LM3533_REG_CTRLBANK_BCONF_ALS_EN_MASK;
488401dea7fSJohan Hovold
489401dea7fSJohan Hovold if (enable)
490401dea7fSJohan Hovold val = mask;
491401dea7fSJohan Hovold else
492401dea7fSJohan Hovold val = 0;
493401dea7fSJohan Hovold
494401dea7fSJohan Hovold ret = lm3533_update(led->lm3533, reg, val, mask);
495401dea7fSJohan Hovold if (ret)
496401dea7fSJohan Hovold return ret;
497401dea7fSJohan Hovold
498401dea7fSJohan Hovold return len;
499401dea7fSJohan Hovold }
500401dea7fSJohan Hovold
show_linear(struct device * dev,struct device_attribute * attr,char * buf)501401dea7fSJohan Hovold static ssize_t show_linear(struct device *dev,
502401dea7fSJohan Hovold struct device_attribute *attr, char *buf)
503401dea7fSJohan Hovold {
504401dea7fSJohan Hovold struct led_classdev *led_cdev = dev_get_drvdata(dev);
505401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(led_cdev);
506401dea7fSJohan Hovold u8 reg;
507401dea7fSJohan Hovold u8 val;
508401dea7fSJohan Hovold int linear;
509401dea7fSJohan Hovold int ret;
510401dea7fSJohan Hovold
511401dea7fSJohan Hovold reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
512401dea7fSJohan Hovold ret = lm3533_read(led->lm3533, reg, &val);
513401dea7fSJohan Hovold if (ret)
514401dea7fSJohan Hovold return ret;
515401dea7fSJohan Hovold
516401dea7fSJohan Hovold if (val & LM3533_REG_CTRLBANK_BCONF_MAPPING_MASK)
517401dea7fSJohan Hovold linear = 1;
518401dea7fSJohan Hovold else
519401dea7fSJohan Hovold linear = 0;
520401dea7fSJohan Hovold
521*3f6fb1cfSye xingchen return sysfs_emit(buf, "%x\n", linear);
522401dea7fSJohan Hovold }
523401dea7fSJohan Hovold
store_linear(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)524401dea7fSJohan Hovold static ssize_t store_linear(struct device *dev,
525401dea7fSJohan Hovold struct device_attribute *attr,
526401dea7fSJohan Hovold const char *buf, size_t len)
527401dea7fSJohan Hovold {
528401dea7fSJohan Hovold struct led_classdev *led_cdev = dev_get_drvdata(dev);
529401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(led_cdev);
530401dea7fSJohan Hovold unsigned long linear;
531401dea7fSJohan Hovold u8 reg;
532401dea7fSJohan Hovold u8 mask;
533401dea7fSJohan Hovold u8 val;
534401dea7fSJohan Hovold int ret;
535401dea7fSJohan Hovold
536401dea7fSJohan Hovold if (kstrtoul(buf, 0, &linear))
537401dea7fSJohan Hovold return -EINVAL;
538401dea7fSJohan Hovold
539401dea7fSJohan Hovold reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
540401dea7fSJohan Hovold mask = LM3533_REG_CTRLBANK_BCONF_MAPPING_MASK;
541401dea7fSJohan Hovold
542401dea7fSJohan Hovold if (linear)
543401dea7fSJohan Hovold val = mask;
544401dea7fSJohan Hovold else
545401dea7fSJohan Hovold val = 0;
546401dea7fSJohan Hovold
547401dea7fSJohan Hovold ret = lm3533_update(led->lm3533, reg, val, mask);
548401dea7fSJohan Hovold if (ret)
549401dea7fSJohan Hovold return ret;
550401dea7fSJohan Hovold
551401dea7fSJohan Hovold return len;
552401dea7fSJohan Hovold }
553401dea7fSJohan Hovold
show_pwm(struct device * dev,struct device_attribute * attr,char * buf)554401dea7fSJohan Hovold static ssize_t show_pwm(struct device *dev,
555401dea7fSJohan Hovold struct device_attribute *attr,
556401dea7fSJohan Hovold char *buf)
557401dea7fSJohan Hovold {
558401dea7fSJohan Hovold struct led_classdev *led_cdev = dev_get_drvdata(dev);
559401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(led_cdev);
560401dea7fSJohan Hovold u8 val;
561401dea7fSJohan Hovold int ret;
562401dea7fSJohan Hovold
563401dea7fSJohan Hovold ret = lm3533_ctrlbank_get_pwm(&led->cb, &val);
564401dea7fSJohan Hovold if (ret)
565401dea7fSJohan Hovold return ret;
566401dea7fSJohan Hovold
567*3f6fb1cfSye xingchen return sysfs_emit(buf, "%u\n", val);
568401dea7fSJohan Hovold }
569401dea7fSJohan Hovold
store_pwm(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)570401dea7fSJohan Hovold static ssize_t store_pwm(struct device *dev,
571401dea7fSJohan Hovold struct device_attribute *attr,
572401dea7fSJohan Hovold const char *buf, size_t len)
573401dea7fSJohan Hovold {
574401dea7fSJohan Hovold struct led_classdev *led_cdev = dev_get_drvdata(dev);
575401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(led_cdev);
576401dea7fSJohan Hovold u8 val;
577401dea7fSJohan Hovold int ret;
578401dea7fSJohan Hovold
579401dea7fSJohan Hovold if (kstrtou8(buf, 0, &val))
580401dea7fSJohan Hovold return -EINVAL;
581401dea7fSJohan Hovold
582401dea7fSJohan Hovold ret = lm3533_ctrlbank_set_pwm(&led->cb, val);
583401dea7fSJohan Hovold if (ret)
584401dea7fSJohan Hovold return ret;
585401dea7fSJohan Hovold
586401dea7fSJohan Hovold return len;
587401dea7fSJohan Hovold }
588401dea7fSJohan Hovold
589401dea7fSJohan Hovold static LM3533_ATTR_RW(als_channel);
590401dea7fSJohan Hovold static LM3533_ATTR_RW(als_en);
591401dea7fSJohan Hovold static LM3533_ATTR_RW(falltime);
592401dea7fSJohan Hovold static LM3533_ATTR_RO(id);
593401dea7fSJohan Hovold static LM3533_ATTR_RW(linear);
594401dea7fSJohan Hovold static LM3533_ATTR_RW(pwm);
595401dea7fSJohan Hovold static LM3533_ATTR_RW(risetime);
596401dea7fSJohan Hovold
597401dea7fSJohan Hovold static struct attribute *lm3533_led_attributes[] = {
598401dea7fSJohan Hovold &dev_attr_als_channel.attr,
599401dea7fSJohan Hovold &dev_attr_als_en.attr,
600401dea7fSJohan Hovold &dev_attr_falltime.attr,
601401dea7fSJohan Hovold &dev_attr_id.attr,
602401dea7fSJohan Hovold &dev_attr_linear.attr,
603401dea7fSJohan Hovold &dev_attr_pwm.attr,
604401dea7fSJohan Hovold &dev_attr_risetime.attr,
605401dea7fSJohan Hovold NULL,
606401dea7fSJohan Hovold };
607401dea7fSJohan Hovold
lm3533_led_attr_is_visible(struct kobject * kobj,struct attribute * attr,int n)608401dea7fSJohan Hovold static umode_t lm3533_led_attr_is_visible(struct kobject *kobj,
609401dea7fSJohan Hovold struct attribute *attr, int n)
610401dea7fSJohan Hovold {
6116c3384d8STian Tao struct device *dev = kobj_to_dev(kobj);
612401dea7fSJohan Hovold struct led_classdev *led_cdev = dev_get_drvdata(dev);
613401dea7fSJohan Hovold struct lm3533_led *led = to_lm3533_led(led_cdev);
614401dea7fSJohan Hovold umode_t mode = attr->mode;
615401dea7fSJohan Hovold
616401dea7fSJohan Hovold if (attr == &dev_attr_als_channel.attr ||
617401dea7fSJohan Hovold attr == &dev_attr_als_en.attr) {
618401dea7fSJohan Hovold if (!led->lm3533->have_als)
619401dea7fSJohan Hovold mode = 0;
620401dea7fSJohan Hovold }
621401dea7fSJohan Hovold
622401dea7fSJohan Hovold return mode;
623401dea7fSJohan Hovold };
624401dea7fSJohan Hovold
625430e48ecSAmitoj Kaur Chawla static const struct attribute_group lm3533_led_attribute_group = {
626401dea7fSJohan Hovold .is_visible = lm3533_led_attr_is_visible,
627401dea7fSJohan Hovold .attrs = lm3533_led_attributes
628401dea7fSJohan Hovold };
629401dea7fSJohan Hovold
6309db93860SJohan Hovold static const struct attribute_group *lm3533_led_attribute_groups[] = {
6319db93860SJohan Hovold &lm3533_led_attribute_group,
6329db93860SJohan Hovold NULL
6339db93860SJohan Hovold };
6349db93860SJohan Hovold
lm3533_led_setup(struct lm3533_led * led,struct lm3533_led_platform_data * pdata)63598ea1ea2SBill Pemberton static int lm3533_led_setup(struct lm3533_led *led,
636401dea7fSJohan Hovold struct lm3533_led_platform_data *pdata)
637401dea7fSJohan Hovold {
638401dea7fSJohan Hovold int ret;
639401dea7fSJohan Hovold
640401dea7fSJohan Hovold ret = lm3533_ctrlbank_set_max_current(&led->cb, pdata->max_current);
641401dea7fSJohan Hovold if (ret)
642401dea7fSJohan Hovold return ret;
643401dea7fSJohan Hovold
644401dea7fSJohan Hovold return lm3533_ctrlbank_set_pwm(&led->cb, pdata->pwm);
645401dea7fSJohan Hovold }
646401dea7fSJohan Hovold
lm3533_led_probe(struct platform_device * pdev)64798ea1ea2SBill Pemberton static int lm3533_led_probe(struct platform_device *pdev)
648401dea7fSJohan Hovold {
649401dea7fSJohan Hovold struct lm3533 *lm3533;
650401dea7fSJohan Hovold struct lm3533_led_platform_data *pdata;
651401dea7fSJohan Hovold struct lm3533_led *led;
652401dea7fSJohan Hovold int ret;
653401dea7fSJohan Hovold
654401dea7fSJohan Hovold dev_dbg(&pdev->dev, "%s\n", __func__);
655401dea7fSJohan Hovold
656401dea7fSJohan Hovold lm3533 = dev_get_drvdata(pdev->dev.parent);
657401dea7fSJohan Hovold if (!lm3533)
658401dea7fSJohan Hovold return -EINVAL;
659401dea7fSJohan Hovold
66087aae1eaSJingoo Han pdata = dev_get_platdata(&pdev->dev);
661401dea7fSJohan Hovold if (!pdata) {
662401dea7fSJohan Hovold dev_err(&pdev->dev, "no platform data\n");
663401dea7fSJohan Hovold return -EINVAL;
664401dea7fSJohan Hovold }
665401dea7fSJohan Hovold
666401dea7fSJohan Hovold if (pdev->id < 0 || pdev->id >= LM3533_LVCTRLBANK_COUNT) {
667401dea7fSJohan Hovold dev_err(&pdev->dev, "illegal LED id %d\n", pdev->id);
668401dea7fSJohan Hovold return -EINVAL;
669401dea7fSJohan Hovold }
670401dea7fSJohan Hovold
671401dea7fSJohan Hovold led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
672401dea7fSJohan Hovold if (!led)
673401dea7fSJohan Hovold return -ENOMEM;
674401dea7fSJohan Hovold
675401dea7fSJohan Hovold led->lm3533 = lm3533;
676401dea7fSJohan Hovold led->cdev.name = pdata->name;
677401dea7fSJohan Hovold led->cdev.default_trigger = pdata->default_trigger;
678a478851cSAndrew Lunn led->cdev.brightness_set_blocking = lm3533_led_set;
679401dea7fSJohan Hovold led->cdev.brightness_get = lm3533_led_get;
680401dea7fSJohan Hovold led->cdev.blink_set = lm3533_led_blink_set;
681401dea7fSJohan Hovold led->cdev.brightness = LED_OFF;
6824e04b118SZheng Yongjun led->cdev.groups = lm3533_led_attribute_groups;
683401dea7fSJohan Hovold led->id = pdev->id;
684401dea7fSJohan Hovold
685401dea7fSJohan Hovold mutex_init(&led->mutex);
686401dea7fSJohan Hovold
687401dea7fSJohan Hovold /* The class framework makes a callback to get brightness during
688401dea7fSJohan Hovold * registration so use parent device (for error reporting) until
689401dea7fSJohan Hovold * registered.
690401dea7fSJohan Hovold */
691401dea7fSJohan Hovold led->cb.lm3533 = lm3533;
692401dea7fSJohan Hovold led->cb.id = lm3533_led_get_ctrlbank_id(led);
693401dea7fSJohan Hovold led->cb.dev = lm3533->dev;
694401dea7fSJohan Hovold
695401dea7fSJohan Hovold platform_set_drvdata(pdev, led);
696401dea7fSJohan Hovold
697d584221eSJohan Hovold ret = led_classdev_register(pdev->dev.parent, &led->cdev);
698401dea7fSJohan Hovold if (ret) {
699401dea7fSJohan Hovold dev_err(&pdev->dev, "failed to register LED %d\n", pdev->id);
700401dea7fSJohan Hovold return ret;
701401dea7fSJohan Hovold }
702401dea7fSJohan Hovold
703401dea7fSJohan Hovold led->cb.dev = led->cdev.dev;
704401dea7fSJohan Hovold
705401dea7fSJohan Hovold ret = lm3533_led_setup(led, pdata);
706401dea7fSJohan Hovold if (ret)
707d584221eSJohan Hovold goto err_deregister;
708401dea7fSJohan Hovold
709401dea7fSJohan Hovold ret = lm3533_ctrlbank_enable(&led->cb);
710401dea7fSJohan Hovold if (ret)
711d584221eSJohan Hovold goto err_deregister;
712401dea7fSJohan Hovold
713401dea7fSJohan Hovold return 0;
714d584221eSJohan Hovold
715d584221eSJohan Hovold err_deregister:
716d584221eSJohan Hovold led_classdev_unregister(&led->cdev);
717d584221eSJohan Hovold
718d584221eSJohan Hovold return ret;
719401dea7fSJohan Hovold }
720401dea7fSJohan Hovold
lm3533_led_remove(struct platform_device * pdev)721678e8a6bSBill Pemberton static int lm3533_led_remove(struct platform_device *pdev)
722401dea7fSJohan Hovold {
723401dea7fSJohan Hovold struct lm3533_led *led = platform_get_drvdata(pdev);
724401dea7fSJohan Hovold
725401dea7fSJohan Hovold dev_dbg(&pdev->dev, "%s\n", __func__);
726401dea7fSJohan Hovold
727401dea7fSJohan Hovold lm3533_ctrlbank_disable(&led->cb);
728d584221eSJohan Hovold led_classdev_unregister(&led->cdev);
729401dea7fSJohan Hovold
730401dea7fSJohan Hovold return 0;
731401dea7fSJohan Hovold }
732401dea7fSJohan Hovold
lm3533_led_shutdown(struct platform_device * pdev)733401dea7fSJohan Hovold static void lm3533_led_shutdown(struct platform_device *pdev)
734401dea7fSJohan Hovold {
735401dea7fSJohan Hovold
736401dea7fSJohan Hovold struct lm3533_led *led = platform_get_drvdata(pdev);
737401dea7fSJohan Hovold
738401dea7fSJohan Hovold dev_dbg(&pdev->dev, "%s\n", __func__);
739401dea7fSJohan Hovold
740401dea7fSJohan Hovold lm3533_ctrlbank_disable(&led->cb);
741401dea7fSJohan Hovold lm3533_led_set(&led->cdev, LED_OFF); /* disable blink */
742401dea7fSJohan Hovold }
743401dea7fSJohan Hovold
744401dea7fSJohan Hovold static struct platform_driver lm3533_led_driver = {
745401dea7fSJohan Hovold .driver = {
746401dea7fSJohan Hovold .name = "lm3533-leds",
747401dea7fSJohan Hovold },
748401dea7fSJohan Hovold .probe = lm3533_led_probe,
749df07cf81SBill Pemberton .remove = lm3533_led_remove,
750401dea7fSJohan Hovold .shutdown = lm3533_led_shutdown,
751401dea7fSJohan Hovold };
752401dea7fSJohan Hovold module_platform_driver(lm3533_led_driver);
753401dea7fSJohan Hovold
754401dea7fSJohan Hovold MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
755401dea7fSJohan Hovold MODULE_DESCRIPTION("LM3533 LED driver");
756401dea7fSJohan Hovold MODULE_LICENSE("GPL");
757401dea7fSJohan Hovold MODULE_ALIAS("platform:lm3533-leds");
758