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