1a6d511e5SNeilBrown /* 2a6d511e5SNeilBrown * leds-tca6507 3a6d511e5SNeilBrown * 4a6d511e5SNeilBrown * The TCA6507 is a programmable LED controller that can drive 7 5a6d511e5SNeilBrown * separate lines either by holding them low, or by pulsing them 6a6d511e5SNeilBrown * with modulated width. 7a6d511e5SNeilBrown * The modulation can be varied in a simple pattern to produce a blink or 8a6d511e5SNeilBrown * double-blink. 9a6d511e5SNeilBrown * 10a6d511e5SNeilBrown * This driver can configure each line either as a 'GPIO' which is out-only 11a6d511e5SNeilBrown * (no pull-up) or as an LED with variable brightness and hardware-assisted 12a6d511e5SNeilBrown * blinking. 13a6d511e5SNeilBrown * 14a6d511e5SNeilBrown * Apart from OFF and ON there are three programmable brightness levels which 15a6d511e5SNeilBrown * can be programmed from 0 to 15 and indicate how many 500usec intervals in 16a6d511e5SNeilBrown * each 8msec that the led is 'on'. The levels are named MASTER, BANK0 and 17a6d511e5SNeilBrown * BANK1. 18a6d511e5SNeilBrown * 19a6d511e5SNeilBrown * There are two different blink rates that can be programmed, each with 20a6d511e5SNeilBrown * separate time for rise, on, fall, off and second-off. Thus if 3 or more 21a6d511e5SNeilBrown * different non-trivial rates are required, software must be used for the extra 22a6d511e5SNeilBrown * rates. The two different blink rates must align with the two levels BANK0 and 23a6d511e5SNeilBrown * BANK1. 24a6d511e5SNeilBrown * This driver does not support double-blink so 'second-off' always matches 25a6d511e5SNeilBrown * 'off'. 26a6d511e5SNeilBrown * 27a6d511e5SNeilBrown * Only 16 different times can be programmed in a roughly logarithmic scale from 28a6d511e5SNeilBrown * 64ms to 16320ms. To be precise the possible times are: 29a6d511e5SNeilBrown * 0, 64, 128, 192, 256, 384, 512, 768, 30a6d511e5SNeilBrown * 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320 31a6d511e5SNeilBrown * 32a6d511e5SNeilBrown * Times that cannot be closely matched with these must be 33a6d511e5SNeilBrown * handled in software. This driver allows 12.5% error in matching. 34a6d511e5SNeilBrown * 35a6d511e5SNeilBrown * This driver does not allow rise/fall rates to be set explicitly. When trying 36a6d511e5SNeilBrown * to match a given 'on' or 'off' period, an appropriate pair of 'change' and 37a6d511e5SNeilBrown * 'hold' times are chosen to get a close match. If the target delay is even, 38a6d511e5SNeilBrown * the 'change' number will be the smaller; if odd, the 'hold' number will be 39a6d511e5SNeilBrown * the smaller. 40a6d511e5SNeilBrown 41a6d511e5SNeilBrown * Choosing pairs of delays with 12.5% errors allows us to match delays in the 42a6d511e5SNeilBrown * ranges: 56-72, 112-144, 168-216, 224-27504, 28560-36720. 43a6d511e5SNeilBrown * 26% of the achievable sums can be matched by multiple pairings. For example 44a6d511e5SNeilBrown * 1536 == 1536+0, 1024+512, or 768+768. This driver will always choose the 45a6d511e5SNeilBrown * pairing with the least maximum - 768+768 in this case. Other pairings are 46a6d511e5SNeilBrown * not available. 47a6d511e5SNeilBrown * 48a6d511e5SNeilBrown * Access to the 3 levels and 2 blinks are on a first-come, first-served basis. 49a6d511e5SNeilBrown * Access can be shared by multiple leds if they have the same level and 50a6d511e5SNeilBrown * either same blink rates, or some don't blink. 51a6d511e5SNeilBrown * When a led changes, it relinquishes access and tries again, so it might 52a6d511e5SNeilBrown * lose access to hardware blink. 53a6d511e5SNeilBrown * If a blink engine cannot be allocated, software blink is used. 54a6d511e5SNeilBrown * If the desired brightness cannot be allocated, the closest available non-zero 55a6d511e5SNeilBrown * brightness is used. As 'full' is always available, the worst case would be 56a6d511e5SNeilBrown * to have two different blink rates at '1', with Max at '2', then other leds 57a6d511e5SNeilBrown * will have to choose between '2' and '16'. Hopefully this is not likely. 58a6d511e5SNeilBrown * 59a6d511e5SNeilBrown * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the brightness 60a6d511e5SNeilBrown * and LEDs using the blink. It can only be reprogrammed when the appropriate 61a6d511e5SNeilBrown * counter is zero. The MASTER level has a single usage count. 62a6d511e5SNeilBrown * 63a6d511e5SNeilBrown * Each Led has programmable 'on' and 'off' time as milliseconds. With each 64a6d511e5SNeilBrown * there is a flag saying if it was explicitly requested or defaulted. 65a6d511e5SNeilBrown * Similarly the banks know if each time was explicit or a default. Defaults 66a6d511e5SNeilBrown * are permitted to be changed freely - they are not recognised when matching. 67a6d511e5SNeilBrown * 68a6d511e5SNeilBrown * 69a6d511e5SNeilBrown * An led-tca6507 device must be provided with platform data. This data 70a6d511e5SNeilBrown * lists for each output: the name, default trigger, and whether the signal 71a6d511e5SNeilBrown * is being used as a GPiO rather than an led. 'struct led_plaform_data' 72a6d511e5SNeilBrown * is used for this. If 'name' is NULL, the output isn't used. If 'flags' 73a6d511e5SNeilBrown * is TCA6507_MAKE_CPIO, the output is a GPO. 74a6d511e5SNeilBrown * The "struct led_platform_data" can be embedded in a 75a6d511e5SNeilBrown * "struct tca6507_platform_data" which adds a 'gpio_base' for the GPiOs, 76a6d511e5SNeilBrown * and a 'setup' callback which is called once the GPiOs are available. 77a6d511e5SNeilBrown * 78a6d511e5SNeilBrown */ 79a6d511e5SNeilBrown 80a6d511e5SNeilBrown #include <linux/module.h> 81a6d511e5SNeilBrown #include <linux/slab.h> 82a6d511e5SNeilBrown #include <linux/leds.h> 83a6d511e5SNeilBrown #include <linux/err.h> 84a6d511e5SNeilBrown #include <linux/i2c.h> 85a6d511e5SNeilBrown #include <linux/gpio.h> 86a6d511e5SNeilBrown #include <linux/workqueue.h> 87a6d511e5SNeilBrown #include <linux/leds-tca6507.h> 88a6d511e5SNeilBrown 89a6d511e5SNeilBrown /* LED select registers determine the source that drives LED outputs */ 90a6d511e5SNeilBrown #define TCA6507_LS_LED_OFF 0x0 /* Output HI-Z (off) */ 91a6d511e5SNeilBrown #define TCA6507_LS_LED_OFF1 0x1 /* Output HI-Z (off) - not used */ 92a6d511e5SNeilBrown #define TCA6507_LS_LED_PWM0 0x2 /* Output LOW with Bank0 rate */ 93a6d511e5SNeilBrown #define TCA6507_LS_LED_PWM1 0x3 /* Output LOW with Bank1 rate */ 94a6d511e5SNeilBrown #define TCA6507_LS_LED_ON 0x4 /* Output LOW (on) */ 95a6d511e5SNeilBrown #define TCA6507_LS_LED_MIR 0x5 /* Output LOW with Master Intensity */ 96a6d511e5SNeilBrown #define TCA6507_LS_BLINK0 0x6 /* Blink at Bank0 rate */ 97a6d511e5SNeilBrown #define TCA6507_LS_BLINK1 0x7 /* Blink at Bank1 rate */ 98a6d511e5SNeilBrown 99a6d511e5SNeilBrown enum { 100a6d511e5SNeilBrown BANK0, 101a6d511e5SNeilBrown BANK1, 102a6d511e5SNeilBrown MASTER, 103a6d511e5SNeilBrown }; 104a6d511e5SNeilBrown static int bank_source[3] = { 105a6d511e5SNeilBrown TCA6507_LS_LED_PWM0, 106a6d511e5SNeilBrown TCA6507_LS_LED_PWM1, 107a6d511e5SNeilBrown TCA6507_LS_LED_MIR, 108a6d511e5SNeilBrown }; 109a6d511e5SNeilBrown static int blink_source[2] = { 110a6d511e5SNeilBrown TCA6507_LS_BLINK0, 111a6d511e5SNeilBrown TCA6507_LS_BLINK1, 112a6d511e5SNeilBrown }; 113a6d511e5SNeilBrown 114a6d511e5SNeilBrown /* PWM registers */ 115a6d511e5SNeilBrown #define TCA6507_REG_CNT 11 116a6d511e5SNeilBrown 117a6d511e5SNeilBrown /* 118a6d511e5SNeilBrown * 0x00, 0x01, 0x02 encode the TCA6507_LS_* values, each output 119a6d511e5SNeilBrown * owns one bit in each register 120a6d511e5SNeilBrown */ 121a6d511e5SNeilBrown #define TCA6507_FADE_ON 0x03 122a6d511e5SNeilBrown #define TCA6507_FULL_ON 0x04 123a6d511e5SNeilBrown #define TCA6507_FADE_OFF 0x05 124a6d511e5SNeilBrown #define TCA6507_FIRST_OFF 0x06 125a6d511e5SNeilBrown #define TCA6507_SECOND_OFF 0x07 126a6d511e5SNeilBrown #define TCA6507_MAX_INTENSITY 0x08 127a6d511e5SNeilBrown #define TCA6507_MASTER_INTENSITY 0x09 128a6d511e5SNeilBrown #define TCA6507_INITIALIZE 0x0A 129a6d511e5SNeilBrown 130a6d511e5SNeilBrown #define INIT_CODE 0x8 131a6d511e5SNeilBrown 132a6d511e5SNeilBrown #define TIMECODES 16 133a6d511e5SNeilBrown static int time_codes[TIMECODES] = { 134a6d511e5SNeilBrown 0, 64, 128, 192, 256, 384, 512, 768, 135a6d511e5SNeilBrown 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320 136a6d511e5SNeilBrown }; 137a6d511e5SNeilBrown 138a6d511e5SNeilBrown /* Convert an led.brightness level (0..255) to a TCA6507 level (0..15) */ 139a6d511e5SNeilBrown static inline int TO_LEVEL(int brightness) 140a6d511e5SNeilBrown { 141a6d511e5SNeilBrown return brightness >> 4; 142a6d511e5SNeilBrown } 143a6d511e5SNeilBrown 144a6d511e5SNeilBrown /* ...and convert back */ 145a6d511e5SNeilBrown static inline int TO_BRIGHT(int level) 146a6d511e5SNeilBrown { 147a6d511e5SNeilBrown if (level) 148a6d511e5SNeilBrown return (level << 4) | 0xf; 149a6d511e5SNeilBrown return 0; 150a6d511e5SNeilBrown } 151a6d511e5SNeilBrown 152a6d511e5SNeilBrown #define NUM_LEDS 7 153a6d511e5SNeilBrown struct tca6507_chip { 154a6d511e5SNeilBrown int reg_set; /* One bit per register where 155a6d511e5SNeilBrown * a '1' means the register 156a6d511e5SNeilBrown * should be written */ 157a6d511e5SNeilBrown u8 reg_file[TCA6507_REG_CNT]; 158a6d511e5SNeilBrown /* Bank 2 is Master Intensity and doesn't use times */ 159a6d511e5SNeilBrown struct bank { 160a6d511e5SNeilBrown int level; 161a6d511e5SNeilBrown int ontime, offtime; 162a6d511e5SNeilBrown int on_dflt, off_dflt; 163a6d511e5SNeilBrown int time_use, level_use; 164a6d511e5SNeilBrown } bank[3]; 165a6d511e5SNeilBrown struct i2c_client *client; 166a6d511e5SNeilBrown struct work_struct work; 167a6d511e5SNeilBrown spinlock_t lock; 168a6d511e5SNeilBrown 169a6d511e5SNeilBrown struct tca6507_led { 170a6d511e5SNeilBrown struct tca6507_chip *chip; 171a6d511e5SNeilBrown struct led_classdev led_cdev; 172a6d511e5SNeilBrown int num; 173a6d511e5SNeilBrown int ontime, offtime; 174a6d511e5SNeilBrown int on_dflt, off_dflt; 175a6d511e5SNeilBrown int bank; /* Bank used, or -1 */ 176a6d511e5SNeilBrown int blink; /* Set if hardware-blinking */ 177a6d511e5SNeilBrown } leds[NUM_LEDS]; 178a6d511e5SNeilBrown #ifdef CONFIG_GPIOLIB 179a6d511e5SNeilBrown struct gpio_chip gpio; 180a6d511e5SNeilBrown const char *gpio_name[NUM_LEDS]; 181a6d511e5SNeilBrown int gpio_map[NUM_LEDS]; 182a6d511e5SNeilBrown #endif 183a6d511e5SNeilBrown }; 184a6d511e5SNeilBrown 185a6d511e5SNeilBrown static const struct i2c_device_id tca6507_id[] = { 186a6d511e5SNeilBrown { "tca6507" }, 187a6d511e5SNeilBrown { } 188a6d511e5SNeilBrown }; 189a6d511e5SNeilBrown MODULE_DEVICE_TABLE(i2c, tca6507_id); 190a6d511e5SNeilBrown 191a6d511e5SNeilBrown static int choose_times(int msec, int *c1p, int *c2p) 192a6d511e5SNeilBrown { 193a6d511e5SNeilBrown /* 194a6d511e5SNeilBrown * Choose two timecodes which add to 'msec' as near as possible. 195a6d511e5SNeilBrown * The first returned is the 'on' or 'off' time. The second is to be 196a6d511e5SNeilBrown * used as a 'fade-on' or 'fade-off' time. If 'msec' is even, 197a6d511e5SNeilBrown * the first will not be smaller than the second. If 'msec' is odd, 198a6d511e5SNeilBrown * the first will not be larger than the second. 199a6d511e5SNeilBrown * If we cannot get a sum within 1/8 of 'msec' fail with -EINVAL, 200a6d511e5SNeilBrown * otherwise return the sum that was achieved, plus 1 if the first is 201a6d511e5SNeilBrown * smaller. 202a6d511e5SNeilBrown * If two possibilities are equally good (e.g. 512+0, 256+256), choose 203a6d511e5SNeilBrown * the first pair so there is more change-time visible (i.e. it is 204a6d511e5SNeilBrown * softer). 205a6d511e5SNeilBrown */ 206a6d511e5SNeilBrown int c1, c2; 207a6d511e5SNeilBrown int tmax = msec * 9 / 8; 208a6d511e5SNeilBrown int tmin = msec * 7 / 8; 209a6d511e5SNeilBrown int diff = 65536; 210a6d511e5SNeilBrown 211a6d511e5SNeilBrown /* We start at '1' to ensure we never even think of choosing a 212a6d511e5SNeilBrown * total time of '0'. 213a6d511e5SNeilBrown */ 214a6d511e5SNeilBrown for (c1 = 1; c1 < TIMECODES; c1++) { 215a6d511e5SNeilBrown int t = time_codes[c1]; 216a6d511e5SNeilBrown if (t*2 < tmin) 217a6d511e5SNeilBrown continue; 218a6d511e5SNeilBrown if (t > tmax) 219a6d511e5SNeilBrown break; 220a6d511e5SNeilBrown for (c2 = 0; c2 <= c1; c2++) { 221a6d511e5SNeilBrown int tt = t + time_codes[c2]; 222a6d511e5SNeilBrown int d; 223a6d511e5SNeilBrown if (tt < tmin) 224a6d511e5SNeilBrown continue; 225a6d511e5SNeilBrown if (tt > tmax) 226a6d511e5SNeilBrown break; 227a6d511e5SNeilBrown /* This works! */ 228a6d511e5SNeilBrown d = abs(msec - tt); 229a6d511e5SNeilBrown if (d >= diff) 230a6d511e5SNeilBrown continue; 231a6d511e5SNeilBrown /* Best yet */ 232a6d511e5SNeilBrown *c1p = c1; 233a6d511e5SNeilBrown *c2p = c2; 234a6d511e5SNeilBrown diff = d; 235a6d511e5SNeilBrown if (d == 0) 236a6d511e5SNeilBrown return msec; 237a6d511e5SNeilBrown } 238a6d511e5SNeilBrown } 239a6d511e5SNeilBrown if (diff < 65536) { 240a6d511e5SNeilBrown int actual; 241a6d511e5SNeilBrown if (msec & 1) { 242a6d511e5SNeilBrown c1 = *c2p; 243a6d511e5SNeilBrown *c2p = *c1p; 244a6d511e5SNeilBrown *c1p = c1; 245a6d511e5SNeilBrown } 246a6d511e5SNeilBrown actual = time_codes[*c1p] + time_codes[*c2p]; 247a6d511e5SNeilBrown if (*c1p < *c2p) 248a6d511e5SNeilBrown return actual + 1; 249a6d511e5SNeilBrown else 250a6d511e5SNeilBrown return actual; 251a6d511e5SNeilBrown } 252a6d511e5SNeilBrown /* No close match */ 253a6d511e5SNeilBrown return -EINVAL; 254a6d511e5SNeilBrown } 255a6d511e5SNeilBrown 256a6d511e5SNeilBrown /* 257a6d511e5SNeilBrown * Update the register file with the appropriate 3-bit state for 258a6d511e5SNeilBrown * the given led. 259a6d511e5SNeilBrown */ 260a6d511e5SNeilBrown static void set_select(struct tca6507_chip *tca, int led, int val) 261a6d511e5SNeilBrown { 262a6d511e5SNeilBrown int mask = (1 << led); 263a6d511e5SNeilBrown int bit; 264a6d511e5SNeilBrown 265a6d511e5SNeilBrown for (bit = 0; bit < 3; bit++) { 266a6d511e5SNeilBrown int n = tca->reg_file[bit] & ~mask; 267a6d511e5SNeilBrown if (val & (1 << bit)) 268a6d511e5SNeilBrown n |= mask; 269a6d511e5SNeilBrown if (tca->reg_file[bit] != n) { 270a6d511e5SNeilBrown tca->reg_file[bit] = n; 271a6d511e5SNeilBrown tca->reg_set |= (1 << bit); 272a6d511e5SNeilBrown } 273a6d511e5SNeilBrown } 274a6d511e5SNeilBrown } 275a6d511e5SNeilBrown 276a6d511e5SNeilBrown /* Update the register file with the appropriate 4-bit code for 277a6d511e5SNeilBrown * one bank or other. This can be used for timers, for levels, or 278a6d511e5SNeilBrown * for initialisation. 279a6d511e5SNeilBrown */ 280a6d511e5SNeilBrown static void set_code(struct tca6507_chip *tca, int reg, int bank, int new) 281a6d511e5SNeilBrown { 282a6d511e5SNeilBrown int mask = 0xF; 283a6d511e5SNeilBrown int n; 284a6d511e5SNeilBrown if (bank) { 285a6d511e5SNeilBrown mask <<= 4; 286a6d511e5SNeilBrown new <<= 4; 287a6d511e5SNeilBrown } 288a6d511e5SNeilBrown n = tca->reg_file[reg] & ~mask; 289a6d511e5SNeilBrown n |= new; 290a6d511e5SNeilBrown if (tca->reg_file[reg] != n) { 291a6d511e5SNeilBrown tca->reg_file[reg] = n; 292a6d511e5SNeilBrown tca->reg_set |= 1 << reg; 293a6d511e5SNeilBrown } 294a6d511e5SNeilBrown } 295a6d511e5SNeilBrown 296a6d511e5SNeilBrown /* Update brightness level. */ 297a6d511e5SNeilBrown static void set_level(struct tca6507_chip *tca, int bank, int level) 298a6d511e5SNeilBrown { 299a6d511e5SNeilBrown switch (bank) { 300a6d511e5SNeilBrown case BANK0: 301a6d511e5SNeilBrown case BANK1: 302a6d511e5SNeilBrown set_code(tca, TCA6507_MAX_INTENSITY, bank, level); 303a6d511e5SNeilBrown break; 304a6d511e5SNeilBrown case MASTER: 305a6d511e5SNeilBrown set_code(tca, TCA6507_MASTER_INTENSITY, 0, level); 306a6d511e5SNeilBrown break; 307a6d511e5SNeilBrown } 308a6d511e5SNeilBrown tca->bank[bank].level = level; 309a6d511e5SNeilBrown } 310a6d511e5SNeilBrown 311a6d511e5SNeilBrown /* Record all relevant time code for a given bank */ 312a6d511e5SNeilBrown static void set_times(struct tca6507_chip *tca, int bank) 313a6d511e5SNeilBrown { 314a6d511e5SNeilBrown int c1, c2; 315a6d511e5SNeilBrown int result; 316a6d511e5SNeilBrown 317a6d511e5SNeilBrown result = choose_times(tca->bank[bank].ontime, &c1, &c2); 318a6d511e5SNeilBrown dev_dbg(&tca->client->dev, 319a6d511e5SNeilBrown "Chose on times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1], 320a6d511e5SNeilBrown c2, time_codes[c2], tca->bank[bank].ontime); 321a6d511e5SNeilBrown set_code(tca, TCA6507_FADE_ON, bank, c2); 322a6d511e5SNeilBrown set_code(tca, TCA6507_FULL_ON, bank, c1); 323a6d511e5SNeilBrown tca->bank[bank].ontime = result; 324a6d511e5SNeilBrown 325a6d511e5SNeilBrown result = choose_times(tca->bank[bank].offtime, &c1, &c2); 326a6d511e5SNeilBrown dev_dbg(&tca->client->dev, 327a6d511e5SNeilBrown "Chose off times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1], 328a6d511e5SNeilBrown c2, time_codes[c2], tca->bank[bank].offtime); 329a6d511e5SNeilBrown set_code(tca, TCA6507_FADE_OFF, bank, c2); 330a6d511e5SNeilBrown set_code(tca, TCA6507_FIRST_OFF, bank, c1); 331a6d511e5SNeilBrown set_code(tca, TCA6507_SECOND_OFF, bank, c1); 332a6d511e5SNeilBrown tca->bank[bank].offtime = result; 333a6d511e5SNeilBrown 334a6d511e5SNeilBrown set_code(tca, TCA6507_INITIALIZE, bank, INIT_CODE); 335a6d511e5SNeilBrown } 336a6d511e5SNeilBrown 337a6d511e5SNeilBrown /* Write all needed register of tca6507 */ 338a6d511e5SNeilBrown 339a6d511e5SNeilBrown static void tca6507_work(struct work_struct *work) 340a6d511e5SNeilBrown { 341a6d511e5SNeilBrown struct tca6507_chip *tca = container_of(work, struct tca6507_chip, 342a6d511e5SNeilBrown work); 343a6d511e5SNeilBrown struct i2c_client *cl = tca->client; 344a6d511e5SNeilBrown int set; 345a6d511e5SNeilBrown u8 file[TCA6507_REG_CNT]; 346a6d511e5SNeilBrown int r; 347a6d511e5SNeilBrown 348a6d511e5SNeilBrown spin_lock_irq(&tca->lock); 349a6d511e5SNeilBrown set = tca->reg_set; 350a6d511e5SNeilBrown memcpy(file, tca->reg_file, TCA6507_REG_CNT); 351a6d511e5SNeilBrown tca->reg_set = 0; 352a6d511e5SNeilBrown spin_unlock_irq(&tca->lock); 353a6d511e5SNeilBrown 354a6d511e5SNeilBrown for (r = 0; r < TCA6507_REG_CNT; r++) 355a6d511e5SNeilBrown if (set & (1<<r)) 356a6d511e5SNeilBrown i2c_smbus_write_byte_data(cl, r, file[r]); 357a6d511e5SNeilBrown } 358a6d511e5SNeilBrown 359a6d511e5SNeilBrown static void led_release(struct tca6507_led *led) 360a6d511e5SNeilBrown { 361a6d511e5SNeilBrown /* If led owns any resource, release it. */ 362a6d511e5SNeilBrown struct tca6507_chip *tca = led->chip; 363a6d511e5SNeilBrown if (led->bank >= 0) { 364a6d511e5SNeilBrown struct bank *b = tca->bank + led->bank; 365a6d511e5SNeilBrown if (led->blink) 366a6d511e5SNeilBrown b->time_use--; 367a6d511e5SNeilBrown b->level_use--; 368a6d511e5SNeilBrown } 369a6d511e5SNeilBrown led->blink = 0; 370a6d511e5SNeilBrown led->bank = -1; 371a6d511e5SNeilBrown } 372a6d511e5SNeilBrown 373a6d511e5SNeilBrown static int led_prepare(struct tca6507_led *led) 374a6d511e5SNeilBrown { 375a6d511e5SNeilBrown /* Assign this led to a bank, configuring that bank if necessary. */ 376a6d511e5SNeilBrown int level = TO_LEVEL(led->led_cdev.brightness); 377a6d511e5SNeilBrown struct tca6507_chip *tca = led->chip; 378a6d511e5SNeilBrown int c1, c2; 379a6d511e5SNeilBrown int i; 380a6d511e5SNeilBrown struct bank *b; 381a6d511e5SNeilBrown int need_init = 0; 382a6d511e5SNeilBrown 383a6d511e5SNeilBrown led->led_cdev.brightness = TO_BRIGHT(level); 384a6d511e5SNeilBrown if (level == 0) { 385a6d511e5SNeilBrown set_select(tca, led->num, TCA6507_LS_LED_OFF); 386a6d511e5SNeilBrown return 0; 387a6d511e5SNeilBrown } 388a6d511e5SNeilBrown 389a6d511e5SNeilBrown if (led->ontime == 0 || led->offtime == 0) { 390a6d511e5SNeilBrown /* 391a6d511e5SNeilBrown * Just set the brightness, choosing first usable bank. 392a6d511e5SNeilBrown * If none perfect, choose best. 393a6d511e5SNeilBrown * Count backwards so we check MASTER bank first 394a6d511e5SNeilBrown * to avoid wasting a timer. 395a6d511e5SNeilBrown */ 396a6d511e5SNeilBrown int best = -1;/* full-on */ 397a6d511e5SNeilBrown int diff = 15-level; 398a6d511e5SNeilBrown 399a6d511e5SNeilBrown if (level == 15) { 400a6d511e5SNeilBrown set_select(tca, led->num, TCA6507_LS_LED_ON); 401a6d511e5SNeilBrown return 0; 402a6d511e5SNeilBrown } 403a6d511e5SNeilBrown 404a6d511e5SNeilBrown for (i = MASTER; i >= BANK0; i--) { 405a6d511e5SNeilBrown int d; 406a6d511e5SNeilBrown if (tca->bank[i].level == level || 407a6d511e5SNeilBrown tca->bank[i].level_use == 0) { 408a6d511e5SNeilBrown best = i; 409a6d511e5SNeilBrown break; 410a6d511e5SNeilBrown } 411a6d511e5SNeilBrown d = abs(level - tca->bank[i].level); 412a6d511e5SNeilBrown if (d < diff) { 413a6d511e5SNeilBrown diff = d; 414a6d511e5SNeilBrown best = i; 415a6d511e5SNeilBrown } 416a6d511e5SNeilBrown } 417a6d511e5SNeilBrown if (best == -1) { 418a6d511e5SNeilBrown /* Best brightness is full-on */ 419a6d511e5SNeilBrown set_select(tca, led->num, TCA6507_LS_LED_ON); 420a6d511e5SNeilBrown led->led_cdev.brightness = LED_FULL; 421a6d511e5SNeilBrown return 0; 422a6d511e5SNeilBrown } 423a6d511e5SNeilBrown 424a6d511e5SNeilBrown if (!tca->bank[best].level_use) 425a6d511e5SNeilBrown set_level(tca, best, level); 426a6d511e5SNeilBrown 427a6d511e5SNeilBrown tca->bank[best].level_use++; 428a6d511e5SNeilBrown led->bank = best; 429a6d511e5SNeilBrown set_select(tca, led->num, bank_source[best]); 430a6d511e5SNeilBrown led->led_cdev.brightness = TO_BRIGHT(tca->bank[best].level); 431a6d511e5SNeilBrown return 0; 432a6d511e5SNeilBrown } 433a6d511e5SNeilBrown 434a6d511e5SNeilBrown /* 435a6d511e5SNeilBrown * We have on/off time so we need to try to allocate a timing bank. 436a6d511e5SNeilBrown * First check if times are compatible with hardware and give up if 437a6d511e5SNeilBrown * not. 438a6d511e5SNeilBrown */ 439a6d511e5SNeilBrown if (choose_times(led->ontime, &c1, &c2) < 0) 440a6d511e5SNeilBrown return -EINVAL; 441a6d511e5SNeilBrown if (choose_times(led->offtime, &c1, &c2) < 0) 442a6d511e5SNeilBrown return -EINVAL; 443a6d511e5SNeilBrown 444a6d511e5SNeilBrown for (i = BANK0; i <= BANK1; i++) { 445a6d511e5SNeilBrown if (tca->bank[i].level_use == 0) 446a6d511e5SNeilBrown /* not in use - it is ours! */ 447a6d511e5SNeilBrown break; 448a6d511e5SNeilBrown if (tca->bank[i].level != level) 449a6d511e5SNeilBrown /* Incompatible level - skip */ 450a6d511e5SNeilBrown /* FIX: if timer matches we maybe should consider 451a6d511e5SNeilBrown * this anyway... 452a6d511e5SNeilBrown */ 453a6d511e5SNeilBrown continue; 454a6d511e5SNeilBrown 455a6d511e5SNeilBrown if (tca->bank[i].time_use == 0) 456a6d511e5SNeilBrown /* Timer not in use, and level matches - use it */ 457a6d511e5SNeilBrown break; 458a6d511e5SNeilBrown 459a6d511e5SNeilBrown if (!(tca->bank[i].on_dflt || 460a6d511e5SNeilBrown led->on_dflt || 461a6d511e5SNeilBrown tca->bank[i].ontime == led->ontime)) 462a6d511e5SNeilBrown /* on time is incompatible */ 463a6d511e5SNeilBrown continue; 464a6d511e5SNeilBrown 465a6d511e5SNeilBrown if (!(tca->bank[i].off_dflt || 466a6d511e5SNeilBrown led->off_dflt || 467a6d511e5SNeilBrown tca->bank[i].offtime == led->offtime)) 468a6d511e5SNeilBrown /* off time is incompatible */ 469a6d511e5SNeilBrown continue; 470a6d511e5SNeilBrown 471a6d511e5SNeilBrown /* looks like a suitable match */ 472a6d511e5SNeilBrown break; 473a6d511e5SNeilBrown } 474a6d511e5SNeilBrown 475a6d511e5SNeilBrown if (i > BANK1) 476a6d511e5SNeilBrown /* Nothing matches - how sad */ 477a6d511e5SNeilBrown return -EINVAL; 478a6d511e5SNeilBrown 479a6d511e5SNeilBrown b = &tca->bank[i]; 480a6d511e5SNeilBrown if (b->level_use == 0) 481a6d511e5SNeilBrown set_level(tca, i, level); 482a6d511e5SNeilBrown b->level_use++; 483a6d511e5SNeilBrown led->bank = i; 484a6d511e5SNeilBrown 485a6d511e5SNeilBrown if (b->on_dflt || 486a6d511e5SNeilBrown !led->on_dflt || 487a6d511e5SNeilBrown b->time_use == 0) { 488a6d511e5SNeilBrown b->ontime = led->ontime; 489a6d511e5SNeilBrown b->on_dflt = led->on_dflt; 490a6d511e5SNeilBrown need_init = 1; 491a6d511e5SNeilBrown } 492a6d511e5SNeilBrown 493a6d511e5SNeilBrown if (b->off_dflt || 494a6d511e5SNeilBrown !led->off_dflt || 495a6d511e5SNeilBrown b->time_use == 0) { 496a6d511e5SNeilBrown b->offtime = led->offtime; 497a6d511e5SNeilBrown b->off_dflt = led->off_dflt; 498a6d511e5SNeilBrown need_init = 1; 499a6d511e5SNeilBrown } 500a6d511e5SNeilBrown 501a6d511e5SNeilBrown if (need_init) 502a6d511e5SNeilBrown set_times(tca, i); 503a6d511e5SNeilBrown 504a6d511e5SNeilBrown led->ontime = b->ontime; 505a6d511e5SNeilBrown led->offtime = b->offtime; 506a6d511e5SNeilBrown 507a6d511e5SNeilBrown b->time_use++; 508a6d511e5SNeilBrown led->blink = 1; 509a6d511e5SNeilBrown led->led_cdev.brightness = TO_BRIGHT(b->level); 510a6d511e5SNeilBrown set_select(tca, led->num, blink_source[i]); 511a6d511e5SNeilBrown return 0; 512a6d511e5SNeilBrown } 513a6d511e5SNeilBrown 514a6d511e5SNeilBrown static int led_assign(struct tca6507_led *led) 515a6d511e5SNeilBrown { 516a6d511e5SNeilBrown struct tca6507_chip *tca = led->chip; 517a6d511e5SNeilBrown int err; 518a6d511e5SNeilBrown unsigned long flags; 519a6d511e5SNeilBrown 520a6d511e5SNeilBrown spin_lock_irqsave(&tca->lock, flags); 521a6d511e5SNeilBrown led_release(led); 522a6d511e5SNeilBrown err = led_prepare(led); 523a6d511e5SNeilBrown if (err) { 524a6d511e5SNeilBrown /* 525a6d511e5SNeilBrown * Can only fail on timer setup. In that case we need to 526a6d511e5SNeilBrown * re-establish as steady level. 527a6d511e5SNeilBrown */ 528a6d511e5SNeilBrown led->ontime = 0; 529a6d511e5SNeilBrown led->offtime = 0; 530a6d511e5SNeilBrown led_prepare(led); 531a6d511e5SNeilBrown } 532a6d511e5SNeilBrown spin_unlock_irqrestore(&tca->lock, flags); 533a6d511e5SNeilBrown 534a6d511e5SNeilBrown if (tca->reg_set) 535a6d511e5SNeilBrown schedule_work(&tca->work); 536a6d511e5SNeilBrown return err; 537a6d511e5SNeilBrown } 538a6d511e5SNeilBrown 539a6d511e5SNeilBrown static void tca6507_brightness_set(struct led_classdev *led_cdev, 540a6d511e5SNeilBrown enum led_brightness brightness) 541a6d511e5SNeilBrown { 542a6d511e5SNeilBrown struct tca6507_led *led = container_of(led_cdev, struct tca6507_led, 543a6d511e5SNeilBrown led_cdev); 544a6d511e5SNeilBrown led->led_cdev.brightness = brightness; 545a6d511e5SNeilBrown led->ontime = 0; 546a6d511e5SNeilBrown led->offtime = 0; 547a6d511e5SNeilBrown led_assign(led); 548a6d511e5SNeilBrown } 549a6d511e5SNeilBrown 550a6d511e5SNeilBrown static int tca6507_blink_set(struct led_classdev *led_cdev, 551a6d511e5SNeilBrown unsigned long *delay_on, 552a6d511e5SNeilBrown unsigned long *delay_off) 553a6d511e5SNeilBrown { 554a6d511e5SNeilBrown struct tca6507_led *led = container_of(led_cdev, struct tca6507_led, 555a6d511e5SNeilBrown led_cdev); 556a6d511e5SNeilBrown 557a6d511e5SNeilBrown if (*delay_on == 0) 558a6d511e5SNeilBrown led->on_dflt = 1; 559a6d511e5SNeilBrown else if (delay_on != &led_cdev->blink_delay_on) 560a6d511e5SNeilBrown led->on_dflt = 0; 561a6d511e5SNeilBrown led->ontime = *delay_on; 562a6d511e5SNeilBrown 563a6d511e5SNeilBrown if (*delay_off == 0) 564a6d511e5SNeilBrown led->off_dflt = 1; 565a6d511e5SNeilBrown else if (delay_off != &led_cdev->blink_delay_off) 566a6d511e5SNeilBrown led->off_dflt = 0; 567a6d511e5SNeilBrown led->offtime = *delay_off; 568a6d511e5SNeilBrown 569a6d511e5SNeilBrown if (led->ontime == 0) 570a6d511e5SNeilBrown led->ontime = 512; 571a6d511e5SNeilBrown if (led->offtime == 0) 572a6d511e5SNeilBrown led->offtime = 512; 573a6d511e5SNeilBrown 574a6d511e5SNeilBrown if (led->led_cdev.brightness == LED_OFF) 575a6d511e5SNeilBrown led->led_cdev.brightness = LED_FULL; 576a6d511e5SNeilBrown if (led_assign(led) < 0) { 577a6d511e5SNeilBrown led->ontime = 0; 578a6d511e5SNeilBrown led->offtime = 0; 579a6d511e5SNeilBrown led->led_cdev.brightness = LED_OFF; 580a6d511e5SNeilBrown return -EINVAL; 581a6d511e5SNeilBrown } 582a6d511e5SNeilBrown *delay_on = led->ontime; 583a6d511e5SNeilBrown *delay_off = led->offtime; 584a6d511e5SNeilBrown return 0; 585a6d511e5SNeilBrown } 586a6d511e5SNeilBrown 587a6d511e5SNeilBrown #ifdef CONFIG_GPIOLIB 588a6d511e5SNeilBrown static void tca6507_gpio_set_value(struct gpio_chip *gc, 589a6d511e5SNeilBrown unsigned offset, int val) 590a6d511e5SNeilBrown { 591a6d511e5SNeilBrown struct tca6507_chip *tca = container_of(gc, struct tca6507_chip, gpio); 592a6d511e5SNeilBrown unsigned long flags; 593a6d511e5SNeilBrown 594a6d511e5SNeilBrown spin_lock_irqsave(&tca->lock, flags); 595a6d511e5SNeilBrown /* 596a6d511e5SNeilBrown * 'OFF' is floating high, and 'ON' is pulled down, so it has the 597a6d511e5SNeilBrown * inverse sense of 'val'. 598a6d511e5SNeilBrown */ 599a6d511e5SNeilBrown set_select(tca, tca->gpio_map[offset], 600a6d511e5SNeilBrown val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON); 601a6d511e5SNeilBrown spin_unlock_irqrestore(&tca->lock, flags); 602a6d511e5SNeilBrown if (tca->reg_set) 603a6d511e5SNeilBrown schedule_work(&tca->work); 604a6d511e5SNeilBrown } 605a6d511e5SNeilBrown 606a6d511e5SNeilBrown static int tca6507_gpio_direction_output(struct gpio_chip *gc, 607a6d511e5SNeilBrown unsigned offset, int val) 608a6d511e5SNeilBrown { 609a6d511e5SNeilBrown tca6507_gpio_set_value(gc, offset, val); 610a6d511e5SNeilBrown return 0; 611a6d511e5SNeilBrown } 612a6d511e5SNeilBrown 613a6d511e5SNeilBrown static int tca6507_probe_gpios(struct i2c_client *client, 614a6d511e5SNeilBrown struct tca6507_chip *tca, 615a6d511e5SNeilBrown struct tca6507_platform_data *pdata) 616a6d511e5SNeilBrown { 617a6d511e5SNeilBrown int err; 618a6d511e5SNeilBrown int i = 0; 619a6d511e5SNeilBrown int gpios = 0; 620a6d511e5SNeilBrown 621a6d511e5SNeilBrown for (i = 0; i < NUM_LEDS; i++) 622a6d511e5SNeilBrown if (pdata->leds.leds[i].name && pdata->leds.leds[i].flags) { 623a6d511e5SNeilBrown /* Configure as a gpio */ 624a6d511e5SNeilBrown tca->gpio_name[gpios] = pdata->leds.leds[i].name; 625a6d511e5SNeilBrown tca->gpio_map[gpios] = i; 626a6d511e5SNeilBrown gpios++; 627a6d511e5SNeilBrown } 628a6d511e5SNeilBrown 629a6d511e5SNeilBrown if (!gpios) 630a6d511e5SNeilBrown return 0; 631a6d511e5SNeilBrown 632a6d511e5SNeilBrown tca->gpio.label = "gpio-tca6507"; 633a6d511e5SNeilBrown tca->gpio.names = tca->gpio_name; 634a6d511e5SNeilBrown tca->gpio.ngpio = gpios; 635a6d511e5SNeilBrown tca->gpio.base = pdata->gpio_base; 636a6d511e5SNeilBrown tca->gpio.owner = THIS_MODULE; 637a6d511e5SNeilBrown tca->gpio.direction_output = tca6507_gpio_direction_output; 638a6d511e5SNeilBrown tca->gpio.set = tca6507_gpio_set_value; 639a6d511e5SNeilBrown tca->gpio.dev = &client->dev; 640a6d511e5SNeilBrown err = gpiochip_add(&tca->gpio); 641a6d511e5SNeilBrown if (err) { 642a6d511e5SNeilBrown tca->gpio.ngpio = 0; 643a6d511e5SNeilBrown return err; 644a6d511e5SNeilBrown } 645a6d511e5SNeilBrown if (pdata->setup) 646a6d511e5SNeilBrown pdata->setup(tca->gpio.base, tca->gpio.ngpio); 647a6d511e5SNeilBrown return 0; 648a6d511e5SNeilBrown } 649a6d511e5SNeilBrown 650a6d511e5SNeilBrown static void tca6507_remove_gpio(struct tca6507_chip *tca) 651a6d511e5SNeilBrown { 652a6d511e5SNeilBrown if (tca->gpio.ngpio) { 653a6d511e5SNeilBrown int err = gpiochip_remove(&tca->gpio); 654a6d511e5SNeilBrown dev_err(&tca->client->dev, "%s failed, %d\n", 655a6d511e5SNeilBrown "gpiochip_remove()", err); 656a6d511e5SNeilBrown } 657a6d511e5SNeilBrown } 658a6d511e5SNeilBrown #else /* CONFIG_GPIOLIB */ 659a6d511e5SNeilBrown static int tca6507_probe_gpios(struct i2c_client *client, 660a6d511e5SNeilBrown struct tca6507_chip *tca, 661a6d511e5SNeilBrown struct tca6507_platform_data *pdata) 662a6d511e5SNeilBrown { 663a6d511e5SNeilBrown return 0; 664a6d511e5SNeilBrown } 665a6d511e5SNeilBrown static void tca6507_remove_gpio(struct tca6507_chip *tca) 666a6d511e5SNeilBrown { 667a6d511e5SNeilBrown } 668a6d511e5SNeilBrown #endif /* CONFIG_GPIOLIB */ 669a6d511e5SNeilBrown 670a6d511e5SNeilBrown static int __devinit tca6507_probe(struct i2c_client *client, 671a6d511e5SNeilBrown const struct i2c_device_id *id) 672a6d511e5SNeilBrown { 673a6d511e5SNeilBrown struct tca6507_chip *tca; 674a6d511e5SNeilBrown struct i2c_adapter *adapter; 675a6d511e5SNeilBrown struct tca6507_platform_data *pdata; 676a6d511e5SNeilBrown int err; 677a6d511e5SNeilBrown int i = 0; 678a6d511e5SNeilBrown 679a6d511e5SNeilBrown adapter = to_i2c_adapter(client->dev.parent); 680a6d511e5SNeilBrown pdata = client->dev.platform_data; 681a6d511e5SNeilBrown 682a6d511e5SNeilBrown if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) 683a6d511e5SNeilBrown return -EIO; 684a6d511e5SNeilBrown 685a6d511e5SNeilBrown if (!pdata || pdata->leds.num_leds != NUM_LEDS) { 686a6d511e5SNeilBrown dev_err(&client->dev, "Need %d entries in platform-data list\n", 687a6d511e5SNeilBrown NUM_LEDS); 688a6d511e5SNeilBrown return -ENODEV; 689a6d511e5SNeilBrown } 6906770fc60SBryan Wu tca = devm_kzalloc(&client->dev, sizeof(*tca), GFP_KERNEL); 691a6d511e5SNeilBrown if (!tca) 692920c4f4cSDan Carpenter return -ENOMEM; 693a6d511e5SNeilBrown 694a6d511e5SNeilBrown tca->client = client; 695a6d511e5SNeilBrown INIT_WORK(&tca->work, tca6507_work); 696a6d511e5SNeilBrown spin_lock_init(&tca->lock); 697a6d511e5SNeilBrown i2c_set_clientdata(client, tca); 698a6d511e5SNeilBrown 699a6d511e5SNeilBrown for (i = 0; i < NUM_LEDS; i++) { 700a6d511e5SNeilBrown struct tca6507_led *l = tca->leds + i; 701a6d511e5SNeilBrown 702a6d511e5SNeilBrown l->chip = tca; 703a6d511e5SNeilBrown l->num = i; 704a6d511e5SNeilBrown if (pdata->leds.leds[i].name && !pdata->leds.leds[i].flags) { 705a6d511e5SNeilBrown l->led_cdev.name = pdata->leds.leds[i].name; 706a6d511e5SNeilBrown l->led_cdev.default_trigger 707a6d511e5SNeilBrown = pdata->leds.leds[i].default_trigger; 708a6d511e5SNeilBrown l->led_cdev.brightness_set = tca6507_brightness_set; 709a6d511e5SNeilBrown l->led_cdev.blink_set = tca6507_blink_set; 710a6d511e5SNeilBrown l->bank = -1; 711a6d511e5SNeilBrown err = led_classdev_register(&client->dev, 712a6d511e5SNeilBrown &l->led_cdev); 713a6d511e5SNeilBrown if (err < 0) 714a6d511e5SNeilBrown goto exit; 715a6d511e5SNeilBrown } 716a6d511e5SNeilBrown } 717a6d511e5SNeilBrown err = tca6507_probe_gpios(client, tca, pdata); 718a6d511e5SNeilBrown if (err) 719a6d511e5SNeilBrown goto exit; 720a6d511e5SNeilBrown /* set all registers to known state - zero */ 721a6d511e5SNeilBrown tca->reg_set = 0x7f; 722a6d511e5SNeilBrown schedule_work(&tca->work); 723a6d511e5SNeilBrown 724a6d511e5SNeilBrown return 0; 725a6d511e5SNeilBrown exit: 726920c4f4cSDan Carpenter while (i--) { 727a6d511e5SNeilBrown if (tca->leds[i].led_cdev.name) 728a6d511e5SNeilBrown led_classdev_unregister(&tca->leds[i].led_cdev); 729920c4f4cSDan Carpenter } 730a6d511e5SNeilBrown return err; 731a6d511e5SNeilBrown } 732a6d511e5SNeilBrown 733a6d511e5SNeilBrown static int __devexit tca6507_remove(struct i2c_client *client) 734a6d511e5SNeilBrown { 735a6d511e5SNeilBrown int i; 736a6d511e5SNeilBrown struct tca6507_chip *tca = i2c_get_clientdata(client); 737a6d511e5SNeilBrown struct tca6507_led *tca_leds = tca->leds; 738a6d511e5SNeilBrown 739a6d511e5SNeilBrown for (i = 0; i < NUM_LEDS; i++) { 740a6d511e5SNeilBrown if (tca_leds[i].led_cdev.name) 741a6d511e5SNeilBrown led_classdev_unregister(&tca_leds[i].led_cdev); 742a6d511e5SNeilBrown } 743a6d511e5SNeilBrown tca6507_remove_gpio(tca); 744a6d511e5SNeilBrown cancel_work_sync(&tca->work); 745a6d511e5SNeilBrown 746a6d511e5SNeilBrown return 0; 747a6d511e5SNeilBrown } 748a6d511e5SNeilBrown 749a6d511e5SNeilBrown static struct i2c_driver tca6507_driver = { 750a6d511e5SNeilBrown .driver = { 751a6d511e5SNeilBrown .name = "leds-tca6507", 752a6d511e5SNeilBrown .owner = THIS_MODULE, 753a6d511e5SNeilBrown }, 754a6d511e5SNeilBrown .probe = tca6507_probe, 755*df07cf81SBill Pemberton .remove = tca6507_remove, 756a6d511e5SNeilBrown .id_table = tca6507_id, 757a6d511e5SNeilBrown }; 758a6d511e5SNeilBrown 7592e911767SPeter Meerwald module_i2c_driver(tca6507_driver); 760a6d511e5SNeilBrown 761a6d511e5SNeilBrown MODULE_AUTHOR("NeilBrown <neilb@suse.de>"); 762a6d511e5SNeilBrown MODULE_DESCRIPTION("TCA6507 LED/GPO driver"); 763a6d511e5SNeilBrown MODULE_LICENSE("GPL v2"); 764