Blame view
drivers/leds/leds-pca963x.c
10.6 KB
36edc9395 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
75cb2e1d1 drivers/leds: add... |
2 3 |
/* * Copyright 2011 bct electronic GmbH |
af67384f0 leds-pca9633: Add... |
4 |
* Copyright 2013 Qtechnology/AS |
75cb2e1d1 drivers/leds: add... |
5 6 |
* * Author: Peter Meerwald <p.meerwald@bct-electronic.com> |
cea0fad0f mailmap: change e... |
7 |
* Author: Ricardo Ribalda <ribalda@kernel.org> |
75cb2e1d1 drivers/leds: add... |
8 9 10 |
* * Based on leds-pca955x.c * |
75cb2e1d1 drivers/leds: add... |
11 |
* LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62) |
3dfedb9d5 leds:pca963x: Add... |
12 |
* LED driver for the PCA9634/5 I2C LED driver (7-bit slave address set by hw.) |
75cb2e1d1 drivers/leds: add... |
13 |
* |
8465b0182 leds: pca9633: Ad... |
14 15 16 17 18 19 20 |
* Note that hardware blinking violates the leds infrastructure driver * interface since the hardware only supports blinking all LEDs with the * same delay_on/delay_off rates. That is, only the LEDs that are set to * blink will actually blink but all LEDs that are set to blink will blink * in identical fashion. The delay_on/delay_off values of the last LED * that is set to blink will be used for all of the blinking LEDs. * Hardware blinking is disabled by default but can be enabled by setting |
56a1740c2 leds-pca9633: Ren... |
21 |
* the 'blink_type' member in the platform_data struct to 'PCA963X_HW_BLINK' |
8465b0182 leds: pca9633: Ad... |
22 |
* or by adding the 'nxp,hw-blink' property to the DTS. |
75cb2e1d1 drivers/leds: add... |
23 24 25 26 27 28 29 30 31 |
*/ #include <linux/module.h> #include <linux/delay.h> #include <linux/string.h> #include <linux/ctype.h> #include <linux/leds.h> #include <linux/err.h> #include <linux/i2c.h> |
0b6034d84 leds: pca963x: Ma... |
32 |
#include <linux/property.h> |
75cb2e1d1 drivers/leds: add... |
33 |
#include <linux/slab.h> |
81d228780 leds: Add device ... |
34 |
#include <linux/of.h> |
75cb2e1d1 drivers/leds: add... |
35 36 |
/* LED select registers determine the source that drives LED outputs */ |
56a1740c2 leds-pca9633: Ren... |
37 38 39 40 |
#define PCA963X_LED_OFF 0x0 /* LED driver off */ #define PCA963X_LED_ON 0x1 /* LED driver on */ #define PCA963X_LED_PWM 0x2 /* Controlled through PWM */ #define PCA963X_LED_GRP_PWM 0x3 /* Controlled through PWM/GRPPWM */ |
75cb2e1d1 drivers/leds: add... |
41 |
|
697529091 leds: pca963x: Fi... |
42 43 |
#define PCA963X_MODE2_OUTDRV 0x04 /* Open-drain or totem pole */ #define PCA963X_MODE2_INVRT 0x10 /* Normal or inverted direction */ |
56a1740c2 leds-pca9633: Ren... |
44 |
#define PCA963X_MODE2_DMBLNK 0x20 /* Enable blinking */ |
8465b0182 leds: pca9633: Ad... |
45 |
|
56a1740c2 leds-pca9633: Ren... |
46 47 48 |
#define PCA963X_MODE1 0x00 #define PCA963X_MODE2 0x01 #define PCA963X_PWM_BASE 0x02 |
af67384f0 leds-pca9633: Add... |
49 |
|
56a1740c2 leds-pca9633: Ren... |
50 |
enum pca963x_type { |
af67384f0 leds-pca9633: Add... |
51 52 |
pca9633, pca9634, |
3dfedb9d5 leds:pca963x: Add... |
53 |
pca9635, |
af67384f0 leds-pca9633: Add... |
54 |
}; |
56a1740c2 leds-pca9633: Ren... |
55 |
struct pca963x_chipdef { |
af67384f0 leds-pca9633: Add... |
56 57 58 59 |
u8 grppwm; u8 grpfreq; u8 ledout_base; int n_leds; |
35c7d3017 leds: pca963x: wo... |
60 |
unsigned int scaling; |
af67384f0 leds-pca9633: Add... |
61 |
}; |
56a1740c2 leds-pca9633: Ren... |
62 |
static struct pca963x_chipdef pca963x_chipdefs[] = { |
af67384f0 leds-pca9633: Add... |
63 64 65 66 67 68 69 70 71 72 73 74 |
[pca9633] = { .grppwm = 0x6, .grpfreq = 0x7, .ledout_base = 0x8, .n_leds = 4, }, [pca9634] = { .grppwm = 0xa, .grpfreq = 0xb, .ledout_base = 0xc, .n_leds = 8, }, |
3dfedb9d5 leds:pca963x: Add... |
75 76 77 78 79 80 |
[pca9635] = { .grppwm = 0x12, .grpfreq = 0x13, .ledout_base = 0x14, .n_leds = 16, }, |
af67384f0 leds-pca9633: Add... |
81 |
}; |
75cb2e1d1 drivers/leds: add... |
82 |
|
8465b0182 leds: pca9633: Ad... |
83 |
/* Total blink period in milliseconds */ |
56a1740c2 leds-pca9633: Ren... |
84 85 |
#define PCA963X_BLINK_PERIOD_MIN 42 #define PCA963X_BLINK_PERIOD_MAX 10667 |
8465b0182 leds: pca9633: Ad... |
86 |
|
56a1740c2 leds-pca9633: Ren... |
87 |
static const struct i2c_device_id pca963x_id[] = { |
af67384f0 leds-pca9633: Add... |
88 89 90 |
{ "pca9632", pca9633 }, { "pca9633", pca9633 }, { "pca9634", pca9634 }, |
3dfedb9d5 leds:pca963x: Add... |
91 |
{ "pca9635", pca9635 }, |
75cb2e1d1 drivers/leds: add... |
92 93 |
{ } }; |
56a1740c2 leds-pca9633: Ren... |
94 |
MODULE_DEVICE_TABLE(i2c, pca963x_id); |
75cb2e1d1 drivers/leds: add... |
95 |
|
b5a3b44f2 leds: pca963x: us... |
96 |
struct pca963x; |
a7d0e9884 leds-pca9633: Add... |
97 |
|
56a1740c2 leds-pca9633: Ren... |
98 99 |
struct pca963x_led { struct pca963x *chip; |
75cb2e1d1 drivers/leds: add... |
100 |
struct led_classdev led_cdev; |
3dfedb9d5 leds:pca963x: Add... |
101 |
int led_num; /* 0 .. 15 potentially */ |
8465b0182 leds: pca9633: Ad... |
102 103 |
u8 gdc; u8 gfrq; |
75cb2e1d1 drivers/leds: add... |
104 |
}; |
b5a3b44f2 leds: pca963x: us... |
105 106 107 108 109 110 111 |
struct pca963x { struct pca963x_chipdef *chipdef; struct mutex mutex; struct i2c_client *client; unsigned long leds_on; struct pca963x_led leds[]; }; |
5db850934 leds: pca963x: co... |
112 |
static int pca963x_brightness(struct pca963x_led *led, |
39118499a leds: pca963x: co... |
113 |
enum led_brightness brightness) |
75cb2e1d1 drivers/leds: add... |
114 |
{ |
5db850934 leds: pca963x: co... |
115 116 |
struct i2c_client *client = led->chip->client; struct pca963x_chipdef *chipdef = led->chip->chipdef; |
39118499a leds: pca963x: co... |
117 118 |
u8 ledout_addr, ledout, mask, val; int shift; |
5029a2e33 leds: pca963x: Re... |
119 |
int ret; |
75cb2e1d1 drivers/leds: add... |
120 |
|
5db850934 leds: pca963x: co... |
121 122 |
ledout_addr = chipdef->ledout_base + (led->led_num / 4); shift = 2 * (led->led_num % 4); |
39118499a leds: pca963x: co... |
123 124 |
mask = 0x3 << shift; ledout = i2c_smbus_read_byte_data(client, ledout_addr); |
5029a2e33 leds: pca963x: Re... |
125 |
switch (brightness) { |
75cb2e1d1 drivers/leds: add... |
126 |
case LED_FULL: |
39118499a leds: pca963x: co... |
127 128 |
val = (ledout & ~mask) | (PCA963X_LED_ON << shift); ret = i2c_smbus_write_byte_data(client, ledout_addr, val); |
75cb2e1d1 drivers/leds: add... |
129 130 |
break; case LED_OFF: |
39118499a leds: pca963x: co... |
131 132 |
val = ledout & ~mask; ret = i2c_smbus_write_byte_data(client, ledout_addr, val); |
75cb2e1d1 drivers/leds: add... |
133 134 |
break; default: |
39118499a leds: pca963x: co... |
135 136 |
ret = i2c_smbus_write_byte_data(client, PCA963X_PWM_BASE + |
5db850934 leds: pca963x: co... |
137 |
led->led_num, |
39118499a leds: pca963x: co... |
138 |
brightness); |
5029a2e33 leds: pca963x: Re... |
139 |
if (ret < 0) |
a8c170b01 leds: pca963x: en... |
140 |
return ret; |
39118499a leds: pca963x: co... |
141 142 143 |
val = (ledout & ~mask) | (PCA963X_LED_PWM << shift); ret = i2c_smbus_write_byte_data(client, ledout_addr, val); |
75cb2e1d1 drivers/leds: add... |
144 145 |
break; } |
a8c170b01 leds: pca963x: en... |
146 |
|
5029a2e33 leds: pca963x: Re... |
147 |
return ret; |
75cb2e1d1 drivers/leds: add... |
148 |
} |
5db850934 leds: pca963x: co... |
149 |
static void pca963x_blink(struct pca963x_led *led) |
8465b0182 leds: pca9633: Ad... |
150 |
{ |
5db850934 leds: pca963x: co... |
151 152 |
struct i2c_client *client = led->chip->client; struct pca963x_chipdef *chipdef = led->chip->chipdef; |
39118499a leds: pca963x: co... |
153 154 |
u8 ledout_addr, ledout, mask, val, mode2; int shift; |
5db850934 leds: pca963x: co... |
155 156 |
ledout_addr = chipdef->ledout_base + (led->led_num / 4); shift = 2 * (led->led_num % 4); |
39118499a leds: pca963x: co... |
157 158 |
mask = 0x3 << shift; mode2 = i2c_smbus_read_byte_data(client, PCA963X_MODE2); |
8465b0182 leds: pca9633: Ad... |
159 |
|
5db850934 leds: pca963x: co... |
160 |
i2c_smbus_write_byte_data(client, chipdef->grppwm, led->gdc); |
8465b0182 leds: pca9633: Ad... |
161 |
|
5db850934 leds: pca963x: co... |
162 |
i2c_smbus_write_byte_data(client, chipdef->grpfreq, led->gfrq); |
8465b0182 leds: pca9633: Ad... |
163 |
|
56a1740c2 leds-pca9633: Ren... |
164 |
if (!(mode2 & PCA963X_MODE2_DMBLNK)) |
39118499a leds: pca963x: co... |
165 166 |
i2c_smbus_write_byte_data(client, PCA963X_MODE2, mode2 | PCA963X_MODE2_DMBLNK); |
8465b0182 leds: pca9633: Ad... |
167 |
|
5db850934 leds: pca963x: co... |
168 |
mutex_lock(&led->chip->mutex); |
39118499a leds: pca963x: co... |
169 170 171 172 173 174 |
ledout = i2c_smbus_read_byte_data(client, ledout_addr); if ((ledout & mask) != (PCA963X_LED_GRP_PWM << shift)) { val = (ledout & ~mask) | (PCA963X_LED_GRP_PWM << shift); i2c_smbus_write_byte_data(client, ledout_addr, val); } |
5db850934 leds: pca963x: co... |
175 |
mutex_unlock(&led->chip->mutex); |
8465b0182 leds: pca9633: Ad... |
176 |
} |
5db850934 leds: pca963x: co... |
177 |
static int pca963x_power_state(struct pca963x_led *led) |
a8c170b01 leds: pca963x: en... |
178 |
{ |
5db850934 leds: pca963x: co... |
179 180 |
struct i2c_client *client = led->chip->client; unsigned long *leds_on = &led->chip->leds_on; |
39118499a leds: pca963x: co... |
181 |
unsigned long cached_leds = *leds_on; |
a8c170b01 leds: pca963x: en... |
182 |
|
5db850934 leds: pca963x: co... |
183 184 |
if (led->led_cdev.brightness) set_bit(led->led_num, leds_on); |
a8c170b01 leds: pca963x: en... |
185 |
else |
5db850934 leds: pca963x: co... |
186 |
clear_bit(led->led_num, leds_on); |
a8c170b01 leds: pca963x: en... |
187 188 |
if (!(*leds_on) != !cached_leds) |
39118499a leds: pca963x: co... |
189 190 |
return i2c_smbus_write_byte_data(client, PCA963X_MODE1, *leds_on ? 0 : BIT(4)); |
a8c170b01 leds: pca963x: en... |
191 192 193 |
return 0; } |
5029a2e33 leds: pca963x: Re... |
194 |
static int pca963x_led_set(struct led_classdev *led_cdev, |
39118499a leds: pca963x: co... |
195 |
enum led_brightness value) |
75cb2e1d1 drivers/leds: add... |
196 |
{ |
5db850934 leds: pca963x: co... |
197 |
struct pca963x_led *led; |
a8c170b01 leds: pca963x: en... |
198 |
int ret; |
75cb2e1d1 drivers/leds: add... |
199 |
|
5db850934 leds: pca963x: co... |
200 |
led = container_of(led_cdev, struct pca963x_led, led_cdev); |
75cb2e1d1 drivers/leds: add... |
201 |
|
5db850934 leds: pca963x: co... |
202 |
mutex_lock(&led->chip->mutex); |
a8c170b01 leds: pca963x: en... |
203 |
|
5db850934 leds: pca963x: co... |
204 |
ret = pca963x_brightness(led, value); |
a8c170b01 leds: pca963x: en... |
205 206 |
if (ret < 0) goto unlock; |
5db850934 leds: pca963x: co... |
207 |
ret = pca963x_power_state(led); |
a8c170b01 leds: pca963x: en... |
208 209 |
unlock: |
5db850934 leds: pca963x: co... |
210 |
mutex_unlock(&led->chip->mutex); |
a8c170b01 leds: pca963x: en... |
211 |
return ret; |
75cb2e1d1 drivers/leds: add... |
212 |
} |
5db850934 leds: pca963x: co... |
213 |
static unsigned int pca963x_period_scale(struct pca963x_led *led, |
39118499a leds: pca963x: co... |
214 |
unsigned int val) |
35c7d3017 leds: pca963x: wo... |
215 |
{ |
5db850934 leds: pca963x: co... |
216 |
unsigned int scaling = led->chip->chipdef->scaling; |
35c7d3017 leds: pca963x: wo... |
217 218 219 |
return scaling ? DIV_ROUND_CLOSEST(val * scaling, 1000) : val; } |
56a1740c2 leds-pca9633: Ren... |
220 |
static int pca963x_blink_set(struct led_classdev *led_cdev, |
39118499a leds: pca963x: co... |
221 |
unsigned long *delay_on, unsigned long *delay_off) |
8465b0182 leds: pca9633: Ad... |
222 |
{ |
8465b0182 leds: pca9633: Ad... |
223 |
unsigned long time_on, time_off, period; |
5db850934 leds: pca963x: co... |
224 |
struct pca963x_led *led; |
8465b0182 leds: pca9633: Ad... |
225 |
u8 gdc, gfrq; |
5db850934 leds: pca963x: co... |
226 |
led = container_of(led_cdev, struct pca963x_led, led_cdev); |
8465b0182 leds: pca9633: Ad... |
227 228 229 230 231 232 233 234 235 |
time_on = *delay_on; time_off = *delay_off; /* If both zero, pick reasonable defaults of 500ms each */ if (!time_on && !time_off) { time_on = 500; time_off = 500; } |
5db850934 leds: pca963x: co... |
236 |
period = pca963x_period_scale(led, time_on + time_off); |
8465b0182 leds: pca9633: Ad... |
237 238 |
/* If period not supported by hardware, default to someting sane. */ |
56a1740c2 leds-pca9633: Ren... |
239 240 |
if ((period < PCA963X_BLINK_PERIOD_MIN) || (period > PCA963X_BLINK_PERIOD_MAX)) { |
8465b0182 leds: pca9633: Ad... |
241 242 |
time_on = 500; time_off = 500; |
5db850934 leds: pca963x: co... |
243 |
period = pca963x_period_scale(led, 1000); |
8465b0182 leds: pca9633: Ad... |
244 245 246 247 248 249 250 |
} /* * From manual: duty cycle = (GDC / 256) -> * (time_on / period) = (GDC / 256) -> * GDC = ((time_on * 256) / period) */ |
5db850934 leds: pca963x: co... |
251 |
gdc = (pca963x_period_scale(led, time_on) * 256) / period; |
8465b0182 leds: pca9633: Ad... |
252 253 254 255 256 257 258 |
/* * From manual: period = ((GFRQ + 1) / 24) in seconds. * So, period (in ms) = (((GFRQ + 1) / 24) * 1000) -> * GFRQ = ((period * 24 / 1000) - 1) */ gfrq = (period * 24 / 1000) - 1; |
5db850934 leds: pca963x: co... |
259 260 |
led->gdc = gdc; led->gfrq = gfrq; |
8465b0182 leds: pca9633: Ad... |
261 |
|
5db850934 leds: pca963x: co... |
262 |
pca963x_blink(led); |
8465b0182 leds: pca9633: Ad... |
263 264 265 266 267 268 |
*delay_on = time_on; *delay_off = time_off; return 0; } |
85fc8efe8 leds: pca963x: re... |
269 270 |
static int pca963x_register_leds(struct i2c_client *client, struct pca963x *chip) |
81d228780 leds: Add device ... |
271 |
{ |
85fc8efe8 leds: pca963x: re... |
272 273 274 |
struct pca963x_chipdef *chipdef = chip->chipdef; struct pca963x_led *led = chip->leds; struct device *dev = &client->dev; |
0b6034d84 leds: pca963x: Ma... |
275 |
struct fwnode_handle *child; |
85fc8efe8 leds: pca963x: re... |
276 277 278 279 |
bool hw_blink; s32 mode2; u32 reg; int ret; |
81d228780 leds: Add device ... |
280 |
|
85fc8efe8 leds: pca963x: re... |
281 282 283 |
if (device_property_read_u32(dev, "nxp,period-scale", &chipdef->scaling)) chipdef->scaling = 1000; |
81d228780 leds: Add device ... |
284 |
|
85fc8efe8 leds: pca963x: re... |
285 |
hw_blink = device_property_read_bool(dev, "nxp,hw-blink"); |
81d228780 leds: Add device ... |
286 |
|
85fc8efe8 leds: pca963x: re... |
287 288 289 |
mode2 = i2c_smbus_read_byte_data(client, PCA963X_MODE2); if (mode2 < 0) return mode2; |
81d228780 leds: Add device ... |
290 |
|
85fc8efe8 leds: pca963x: re... |
291 292 293 294 295 |
/* default to open-drain unless totem pole (push-pull) is specified */ if (device_property_read_bool(dev, "nxp,totem-pole")) mode2 |= PCA963X_MODE2_OUTDRV; else mode2 &= ~PCA963X_MODE2_OUTDRV; |
0b6034d84 leds: pca963x: Ma... |
296 |
|
85fc8efe8 leds: pca963x: re... |
297 298 299 300 301 |
/* default to non-inverted output, unless inverted is specified */ if (device_property_read_bool(dev, "nxp,inverted-out")) mode2 |= PCA963X_MODE2_INVRT; else mode2 &= ~PCA963X_MODE2_INVRT; |
0b6034d84 leds: pca963x: Ma... |
302 |
|
85fc8efe8 leds: pca963x: re... |
303 304 305 |
ret = i2c_smbus_write_byte_data(client, PCA963X_MODE2, mode2); if (ret < 0) return ret; |
0b6034d84 leds: pca963x: Ma... |
306 |
|
85fc8efe8 leds: pca963x: re... |
307 |
device_for_each_child_node(dev, child) { |
564ead128 leds: pca963x: us... |
308 309 |
struct led_init_data init_data = {}; char default_label[32]; |
85fc8efe8 leds: pca963x: re... |
310 311 312 313 314 315 316 317 |
ret = fwnode_property_read_u32(child, "reg", ®); if (ret || reg >= chipdef->n_leds) { dev_err(dev, "Invalid 'reg' property for node %pfw ", child); ret = -EINVAL; goto err; } |
81d228780 leds: Add device ... |
318 |
|
85fc8efe8 leds: pca963x: re... |
319 320 |
led->led_num = reg; led->chip = chip; |
85fc8efe8 leds: pca963x: re... |
321 322 323 |
led->led_cdev.brightness_set_blocking = pca963x_led_set; if (hw_blink) led->led_cdev.blink_set = pca963x_blink_set; |
8465b0182 leds: pca9633: Ad... |
324 |
|
564ead128 leds: pca963x: us... |
325 326 327 328 329 330 331 332 333 |
init_data.fwnode = child; /* for backwards compatibility */ init_data.devicename = "pca963x"; snprintf(default_label, sizeof(default_label), "%d:%.2x:%u", client->adapter->nr, client->addr, reg); init_data.default_label = default_label; ret = devm_led_classdev_register_ext(dev, &led->led_cdev, &init_data); |
85fc8efe8 leds: pca963x: re... |
334 335 336 337 338 339 |
if (ret) { dev_err(dev, "Failed to register LED for node %pfw ", child); goto err; } |
35c7d3017 leds: pca963x: wo... |
340 |
|
85fc8efe8 leds: pca963x: re... |
341 342 |
++led; } |
bb29b9ccc leds: pca963x: Ad... |
343 |
|
85fc8efe8 leds: pca963x: re... |
344 345 346 347 |
return 0; err: fwnode_handle_put(child); return ret; |
81d228780 leds: Add device ... |
348 |
} |
56a1740c2 leds-pca9633: Ren... |
349 |
static const struct of_device_id of_pca963x_match[] = { |
af67384f0 leds-pca9633: Add... |
350 351 352 |
{ .compatible = "nxp,pca9632", }, { .compatible = "nxp,pca9633", }, { .compatible = "nxp,pca9634", }, |
3dfedb9d5 leds:pca963x: Add... |
353 |
{ .compatible = "nxp,pca9635", }, |
81d228780 leds: Add device ... |
354 355 |
{}, }; |
4d59ed854 leds: Export OF m... |
356 |
MODULE_DEVICE_TABLE(of, of_pca963x_match); |
81d228780 leds: Add device ... |
357 |
|
56a1740c2 leds-pca9633: Ren... |
358 |
static int pca963x_probe(struct i2c_client *client, |
39118499a leds: pca963x: co... |
359 |
const struct i2c_device_id *id) |
75cb2e1d1 drivers/leds: add... |
360 |
{ |
39118499a leds: pca963x: co... |
361 |
struct device *dev = &client->dev; |
fc0b1eca2 leds: pca963x: co... |
362 |
struct pca963x_chipdef *chipdef; |
fc0b1eca2 leds: pca963x: co... |
363 |
struct pca963x *chip; |
85fc8efe8 leds: pca963x: re... |
364 |
int i, count; |
75cb2e1d1 drivers/leds: add... |
365 |
|
fc0b1eca2 leds: pca963x: co... |
366 |
chipdef = &pca963x_chipdefs[id->driver_data]; |
75cb2e1d1 drivers/leds: add... |
367 |
|
85fc8efe8 leds: pca963x: re... |
368 369 370 371 372 |
count = device_get_child_node_count(dev); if (!count || count > chipdef->n_leds) { dev_err(dev, "Node %pfw must define between 1 and %d LEDs ", dev_fwnode(dev), chipdef->n_leds); |
af67384f0 leds-pca9633: Add... |
373 |
return -EINVAL; |
75cb2e1d1 drivers/leds: add... |
374 |
} |
85fc8efe8 leds: pca963x: re... |
375 |
chip = devm_kzalloc(dev, struct_size(chip, leds, count), GFP_KERNEL); |
fc0b1eca2 leds: pca963x: co... |
376 |
if (!chip) |
a7d0e9884 leds-pca9633: Add... |
377 |
return -ENOMEM; |
75cb2e1d1 drivers/leds: add... |
378 |
|
fc0b1eca2 leds: pca963x: co... |
379 |
i2c_set_clientdata(client, chip); |
a7d0e9884 leds-pca9633: Add... |
380 |
|
fc0b1eca2 leds: pca963x: co... |
381 382 383 |
mutex_init(&chip->mutex); chip->chipdef = chipdef; chip->client = client; |
a7d0e9884 leds-pca9633: Add... |
384 385 |
/* Turn off LEDs by default*/ |
fc0b1eca2 leds: pca963x: co... |
386 387 |
for (i = 0; i < chipdef->n_leds / 4; i++) i2c_smbus_write_byte_data(client, chipdef->ledout_base + i, 0x00); |
75cb2e1d1 drivers/leds: add... |
388 |
|
a8c170b01 leds: pca963x: en... |
389 390 |
/* Disable LED all-call address, and power down initially */ i2c_smbus_write_byte_data(client, PCA963X_MODE1, BIT(4)); |
75cb2e1d1 drivers/leds: add... |
391 |
|
85fc8efe8 leds: pca963x: re... |
392 |
return pca963x_register_leds(client, chip); |
75cb2e1d1 drivers/leds: add... |
393 |
} |
56a1740c2 leds-pca9633: Ren... |
394 |
static struct i2c_driver pca963x_driver = { |
75cb2e1d1 drivers/leds: add... |
395 |
.driver = { |
56a1740c2 leds-pca9633: Ren... |
396 |
.name = "leds-pca963x", |
0b6034d84 leds: pca963x: Ma... |
397 |
.of_match_table = of_pca963x_match, |
75cb2e1d1 drivers/leds: add... |
398 |
}, |
56a1740c2 leds-pca9633: Ren... |
399 |
.probe = pca963x_probe, |
56a1740c2 leds-pca9633: Ren... |
400 |
.id_table = pca963x_id, |
75cb2e1d1 drivers/leds: add... |
401 |
}; |
56a1740c2 leds-pca9633: Ren... |
402 |
module_i2c_driver(pca963x_driver); |
75cb2e1d1 drivers/leds: add... |
403 404 |
MODULE_AUTHOR("Peter Meerwald <p.meerwald@bct-electronic.com>"); |
56a1740c2 leds-pca9633: Ren... |
405 |
MODULE_DESCRIPTION("PCA963X LED driver"); |
75cb2e1d1 drivers/leds: add... |
406 |
MODULE_LICENSE("GPL v2"); |