15 #include <linux/module.h>
16 #include <linux/i2c.h>
17 #include <linux/slab.h>
19 #include <linux/input.h>
26 #define PCA9532_REG_INPUT(i) ((i) >> 3)
27 #define PCA9532_REG_OFFSET(m) ((m) >> 4)
28 #define PCA9532_REG_PSC(m, i) (PCA9532_REG_OFFSET(m) + 0x1 + (i) * 2)
29 #define PCA9532_REG_PWM(m, i) (PCA9532_REG_OFFSET(m) + 0x2 + (i) * 2)
30 #define LED_REG(m, led) (PCA9532_REG_OFFSET(m) + 0x5 + (led >> 2))
31 #define LED_NUM(led) (led & 0x3)
33 #define ldev_to_led(c) container_of(c, struct pca9532_led, ldev)
45 #ifdef CONFIG_LEDS_PCA9532_GPIO
46 struct gpio_chip
gpio;
91 .name =
"leds-pca953x",
93 .probe = pca9532_probe,
94 .remove = pca9532_remove,
95 .id_table = pca9532_id,
106 int a = 0,
b = 0,
i = 0;
112 b += data->
leds[
i].ldev.brightness;
117 "fear of division by zero %d/%d, wanted %d\n",
129 static int pca9532_setpwm(
struct i2c_client *client,
int pwm)
161 static void pca9532_set_brightness(
struct led_classdev *led_cdev,
173 err = pca9532_calcpwm(led->
client, 0, 0, value);
180 static int pca9532_set_blink(
struct led_classdev *led_cdev,
181 unsigned long *delay_on,
unsigned long *delay_off)
188 if (*delay_on == 0 && *delay_off == 0) {
193 if (*delay_on != *delay_off || *delay_on > 1690 || *delay_on < 6)
197 psc = (*delay_on * 152-1)/1000;
198 err = pca9532_calcpwm(client, 0, psc, led_cdev->
brightness);
205 static int pca9532_event(
struct input_dev *
dev,
unsigned int type,
206 unsigned int code,
int value)
214 if (value > 1 && value < 32767)
236 static void pca9532_led_work(
struct work_struct *work)
241 pca9532_setpwm(led->
client, 0);
245 #ifdef CONFIG_LEDS_PCA9532_GPIO
246 static int pca9532_gpio_request_pin(
struct gpio_chip *
gc,
unsigned offset)
257 static void pca9532_gpio_set_value(
struct gpio_chip *gc,
unsigned offset,
int val)
270 static int pca9532_gpio_get_value(
struct gpio_chip *gc,
unsigned offset)
277 return !!(reg & (1 << (offset % 8)));
280 static int pca9532_gpio_direction_input(
struct gpio_chip *gc,
unsigned offset)
283 pca9532_gpio_set_value(gc, offset, 0);
288 static int pca9532_gpio_direction_output(
struct gpio_chip *gc,
unsigned offset,
int val)
290 pca9532_gpio_set_value(gc, offset, val);
296 static int pca9532_destroy_devices(
struct pca9532_data *data,
int n_devs)
304 switch (data->
leds[i].type) {
314 input_unregister_device(data->
idev);
322 #ifdef CONFIG_LEDS_PCA9532_GPIO
323 if (data->gpio.dev) {
327 "gpiochip_remove()", err);
336 static int pca9532_configure(
struct i2c_client *client,
343 for (i = 0; i < 2; i++) {
352 for (i = 0; i < data->
chip_info->num_leds; i++) {
369 led->
ldev.brightness_set = pca9532_set_brightness;
370 led->
ldev.blink_set = pca9532_set_blink;
375 "couldn't register LED %s\n",
385 data->
idev = input_allocate_device();
391 data->
idev->phys =
"i2c/pca9532";
393 data->
idev->id.vendor = 0x001f;
394 data->
idev->id.product = 0x0001;
395 data->
idev->id.version = 0x0100;
399 data->
idev->event = pca9532_event;
400 input_set_drvdata(data->
idev, data);
402 err = input_register_device(data->
idev);
404 input_free_device(data->
idev);
413 #ifdef CONFIG_LEDS_PCA9532_GPIO
415 data->gpio.label =
"gpio-pca9532";
416 data->gpio.direction_input = pca9532_gpio_direction_input;
417 data->gpio.direction_output = pca9532_gpio_direction_output;
418 data->gpio.set = pca9532_gpio_set_value;
419 data->gpio.get = pca9532_gpio_get_value;
420 data->gpio.request = pca9532_gpio_request_pin;
421 data->gpio.can_sleep = 1;
423 data->gpio.ngpio = data->
chip_info->num_leds;
424 data->gpio.dev = &client->
dev;
430 data->gpio.dev =
NULL;
431 dev_warn(&client->
dev,
"could not add gpiochip\n");
434 data->gpio.base, data->gpio.base +
435 data->gpio.ngpio - 1);
443 pca9532_destroy_devices(data, i);
447 static int pca9532_probe(
struct i2c_client *client,
456 if (!i2c_check_functionality(client->
adapter,
464 data->
chip_info = &pca9532_chip_info_tbl[
id->driver_data];
467 i2c_set_clientdata(client, data);
471 return pca9532_configure(client, data, pca9532_pdata);
474 static int pca9532_remove(
struct i2c_client *client)
479 err = pca9532_destroy_devices(data, data->
chip_info->num_leds);