1 /* 2 * Copyright 2008 3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de> 4 * 5 * This file is subject to the terms and conditions of version 2 of 6 * the GNU General Public License. See the file COPYING in the main 7 * directory of this archive for more details. 8 * 9 * LED driver for the DAC124S085 SPI DAC 10 */ 11 12 #include <linux/leds.h> 13 #include <linux/module.h> 14 #include <linux/mutex.h> 15 #include <linux/slab.h> 16 #include <linux/spi/spi.h> 17 18 struct dac124s085_led { 19 struct led_classdev ldev; 20 struct spi_device *spi; 21 int id; 22 char name[sizeof("dac124s085-3")]; 23 24 struct mutex mutex; 25 }; 26 27 struct dac124s085 { 28 struct dac124s085_led leds[4]; 29 }; 30 31 #define REG_WRITE (0 << 12) 32 #define REG_WRITE_UPDATE (1 << 12) 33 #define ALL_WRITE_UPDATE (2 << 12) 34 #define POWER_DOWN_OUTPUT (3 << 12) 35 36 static int dac124s085_set_brightness(struct led_classdev *ldev, 37 enum led_brightness brightness) 38 { 39 struct dac124s085_led *led = container_of(ldev, struct dac124s085_led, 40 ldev); 41 u16 word; 42 int ret; 43 44 mutex_lock(&led->mutex); 45 word = cpu_to_le16(((led->id) << 14) | REG_WRITE_UPDATE | 46 (brightness & 0xfff)); 47 ret = spi_write(led->spi, (const u8 *)&word, sizeof(word)); 48 mutex_unlock(&led->mutex); 49 50 return ret; 51 } 52 53 static int dac124s085_probe(struct spi_device *spi) 54 { 55 struct dac124s085 *dac; 56 struct dac124s085_led *led; 57 int i, ret; 58 59 dac = devm_kzalloc(&spi->dev, sizeof(*dac), GFP_KERNEL); 60 if (!dac) 61 return -ENOMEM; 62 63 spi->bits_per_word = 16; 64 65 for (i = 0; i < ARRAY_SIZE(dac->leds); i++) { 66 led = dac->leds + i; 67 led->id = i; 68 led->spi = spi; 69 snprintf(led->name, sizeof(led->name), "dac124s085-%d", i); 70 mutex_init(&led->mutex); 71 led->ldev.name = led->name; 72 led->ldev.brightness = LED_OFF; 73 led->ldev.max_brightness = 0xfff; 74 led->ldev.brightness_set_blocking = dac124s085_set_brightness; 75 ret = led_classdev_register(&spi->dev, &led->ldev); 76 if (ret < 0) 77 goto eledcr; 78 } 79 80 spi_set_drvdata(spi, dac); 81 82 return 0; 83 84 eledcr: 85 while (i--) 86 led_classdev_unregister(&dac->leds[i].ldev); 87 88 return ret; 89 } 90 91 static int dac124s085_remove(struct spi_device *spi) 92 { 93 struct dac124s085 *dac = spi_get_drvdata(spi); 94 int i; 95 96 for (i = 0; i < ARRAY_SIZE(dac->leds); i++) 97 led_classdev_unregister(&dac->leds[i].ldev); 98 99 return 0; 100 } 101 102 static struct spi_driver dac124s085_driver = { 103 .probe = dac124s085_probe, 104 .remove = dac124s085_remove, 105 .driver = { 106 .name = "dac124s085", 107 }, 108 }; 109 110 module_spi_driver(dac124s085_driver); 111 112 MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>"); 113 MODULE_DESCRIPTION("DAC124S085 LED driver"); 114 MODULE_LICENSE("GPL v2"); 115 MODULE_ALIAS("spi:dac124s085"); 116