--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -487,6 +487,15 @@ config LEDS_BLINKM
 	  This option enables support for the BlinkM RGB LED connected
 	  through I2C. Say Y to enable support for the BlinkM LED.
 
+config LEDS_TLC59116
+	tristate "LED driver for TLC59116F dimmer"
+	depends on LEDS_CLASS
+	depends on I2C
+	help
+	  This option enables support for Texas Instruments TLC59116F
+	  LED controller. It is generally only useful
+	  as a platform driver
+
 comment "LED Triggers"
 source "drivers/leds/trigger/Kconfig"
 
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_LEDS_ASIC3)		+= leds-asic3.
 obj-$(CONFIG_LEDS_MAX8997)		+= leds-max8997.o
 obj-$(CONFIG_LEDS_LM355x)		+= leds-lm355x.o
 obj-$(CONFIG_LEDS_BLINKM)		+= leds-blinkm.o
+obj-$(CONFIG_LEDS_TLC59116)		+= leds-tlc59116.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
--- /dev/null
+++ b/drivers/leds/leds-tlc59116.c
@@ -0,0 +1,498 @@
+/*
+ * Copyright 2014 Belkin Inc.
+ *
+ * Author: Belkin Inc.
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * LED driver for various TLC59116 I2C LED drivers
+  */
+
+#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>
+#include <linux/workqueue.h>
+
+/* LED select registers determine the source that drives LED outputs */
+#define TLC59116_LED_OFF	0x0	/* Output LOW */
+#define TLC59116_LED_ON	0x1	/* Output HI-Z */
+#define TLC59116_DIM	0x2	/* Dimming */
+#define TLC59116_BLINK	0x3	/* Blinking */
+
+#define TLC59116_PINS		16
+#define TLC59116_REG_MODE1	0x00	/* Mode register 0 */
+#define MODE1_RESPON_ADDR_MASK	0xF0
+#define MODE1_NORMAL_MODE	(0 << 4)
+#define MODE1_SPEED_MODE	(1 << 4)
+
+#define TLC59116_REG_MODE2	0x01	/* Mode register 1 */
+#define MODE2_DIM		(0 << 5)
+#define MODE2_BLINK		(1 << 5)
+#define MODE2_OCH_STOP                  (0 << 3)
+#define MODE2_OCH_ACK                   (1 << 3)
+
+#define TLC59116_REG_PWM0	0x02
+#define TLC59116_REG_PWM1	0x03
+#define TLC59116_REG_PWM2	0x04
+#define TLC59116_REG_PWM3	0x05
+#define TLC59116_REG_PWM4	0x06
+#define TLC59116_REG_PWM5	0x07
+#define TLC59116_REG_PWM6	0x08
+#define TLC59116_REG_PWM7	0x09
+#define TLC59116_REG_PWM8	0x0a
+#define TLC59116_REG_PWM9	0x0b
+#define TLC59116_REG_PWM10	0x0c
+#define TLC59116_REG_PWM11	0x0d
+#define TLC59116_REG_PWM12	0x0e
+#define TLC59116_REG_PWM13	0x0f
+#define TLC59116_REG_PWM14	0x10
+#define TLC59116_REG_PWM15	0x01
+
+#define TLC59116_REG_GRPPWM	0x12
+#define TLC59116_REG_GRPFREQ	0x13
+
+#define TLC59116_PERIOD_MIN	41	/* 41ms */
+#define TLC59116_PERIOD_MAX	10730	/* 10.73s */
+
+#define TLC59116_REG_LEDOUT0         0x14    /* LED [3:0] driver output state registers */              
+#define TLC59116_REG_LEDOUT1         0x15    /* LED [7:4] driver output state registers */
+#define TLC59116_REG_LEDOUT2         0x16    /* LED [11:8] driver output state registers */
+#define TLC59116_REG_LEDOUT3         0x17    /* LED [15:12] driver output state registers */
+
+#define GPIO0_MASK        0x3
+
+#define DEBUG 0
+
+#if DEBUG > 1
+#define led_dbg(fmt, arg...) printk(KERN_DEBUG "tlc59116:%s " fmt "\n", __func__ , ## arg)
+#else
+#define led_dbg(fmt, arg...)
+#endif
+
+
+#if DEBUG > 0
+#define led_info(fmt, arg...) printk("tlc59116:%s " fmt "\n", __func__ , ## arg)
+#else
+#define led_info(fmt, arg...)
+#endif
+
+enum tlc59116_type {
+	tlc59116,
+};
+
+struct tlc59116_chipdef {
+	int			bits;
+	u8			slv_addr;	/* 7-bit slave address mask */
+	int			slv_addr_shift;	/* Number of bits to ignore */
+};
+
+static struct tlc59116_chipdef tlc59116_chipdefs[] = {
+	[tlc59116] = {
+		.bits		= 16,
+		.slv_addr	= /* 1100xxx */ 0x68,
+		.slv_addr_shift	= 3,
+	},
+};
+
+static const struct i2c_device_id tlc59116_id[] = {
+	{ "tlc59116", tlc59116 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tlc59116_id);
+
+struct tlc59116_led {
+	struct tlc59116_chipdef	*chipdef;
+	struct i2c_client	*client;
+	struct work_struct	work;
+	spinlock_t		lock;
+	enum led_brightness	brightness;
+	struct led_classdev	led_cdev;
+	int			led_num;	/* 0 .. 8 potentially */
+	char			name[32];
+};
+
+//#define DUMP_REGS
+
+#ifdef DUMP_REGS
+void dump_regs(struct i2c_client *client)
+{
+        int i, j = 0;
+        u8 data;
+        printk ("\n-------------------------------------\n");
+        for (i = 0; i< 0x20; i++)
+        {
+                data = i2c_smbus_read_byte_data(client, i);
+		printk ("[0x%x] = 0x%x ",i, data);
+                j++;
+                if (j == 5)
+                {
+                        printk ("\n");
+                        j = 0;
+                }
+        }
+        printk ("\n");
+}
+#endif
+
+static int tlc59116_set_mode(struct i2c_client *client, uint8_t mode)
+{
+	uint8_t val = 0;
+	
+	if ((mode != MODE2_DIM) && (mode != MODE2_BLINK))
+		mode = MODE2_DIM;
+
+	/* Configure MODE1 register */
+	val &= 0x0;
+	val &= MODE1_RESPON_ADDR_MASK;
+	val |= MODE1_NORMAL_MODE;
+        i2c_smbus_write_byte_data(client, TLC59116_REG_MODE1, val);
+
+        /* Configure MODE2 Reg */
+        val &= 0x00;
+        val |= MODE2_OCH_STOP;
+
+        val |= mode;
+
+        i2c_smbus_write_byte_data(client, TLC59116_REG_MODE2, val);
+        mdelay(100);
+	
+	return 0;
+}
+
+static int tlc59116_set_gpio_act(struct i2c_client *client, u8 gpio_no, u8 act_mode)
+{
+        char data, addr = 0, i;
+
+        if ((gpio_no >= 0) && (gpio_no < 4))
+                addr = TLC59116_REG_LEDOUT0;
+        else if ((gpio_no >= 4) && (gpio_no < 8))
+                addr = TLC59116_REG_LEDOUT1;
+        else if ((gpio_no >= 8) && (gpio_no < 12))
+                addr = TLC59116_REG_LEDOUT2;
+        else if ((gpio_no >=12 ) && (gpio_no < 16))
+                addr = TLC59116_REG_LEDOUT3;
+
+        data = i2c_smbus_read_byte_data(client, addr);
+
+        i = (gpio_no % 4) * 2;
+
+        data &= ~(GPIO0_MASK << i);
+        act_mode = act_mode << i;
+        data |= act_mode;
+
+        if(i2c_smbus_write_byte_data(client, addr, data) != 0) {
+                return -1;
+        }
+        return 0;
+}
+
+static int tlc59116_set_gpio(struct i2c_client *client, uint8_t gpio_no, uint8_t val)
+{
+	val &= 0x03;
+        tlc59116_set_gpio_act(client, gpio_no, val);
+#ifdef DUMP_REGS
+	dump_regs(client);
+#endif
+        return 0;
+}
+
+static int tlc59116_get_gpio(struct i2c_client *client, uint8_t gpio_no)
+{
+	uint8_t val, reg, data;
+	
+	led_dbg("gpio = %d\n", gpio_no);
+	reg = TLC59116_REG_LEDOUT0;
+
+        if ((gpio_no >= 0) && (gpio_no < 4))
+                reg = TLC59116_REG_LEDOUT0;
+        else if ((gpio_no >= 4) && (gpio_no < 8)) {
+                reg = TLC59116_REG_LEDOUT1;
+		gpio_no = gpio_no - 4;
+	}
+        else if ((gpio_no >= 8) && (gpio_no < 12)) {
+                reg = TLC59116_REG_LEDOUT2;
+		gpio_no = gpio_no - 8;
+	}
+        else if ((gpio_no >=12 ) && (gpio_no < 16)) {
+                reg = TLC59116_REG_LEDOUT3;
+		gpio_no = gpio_no - 12;
+	}
+	
+	val = i2c_smbus_read_byte_data(client, reg);
+
+	data = (val >> (gpio_no * 2)) & 0x03;
+	return data;
+}
+
+/*
+ * gpio_no [0..7]
+ * duty_cycle [0..99]%
+ * 
+ * */
+static int tlc59116_individual_brighness_control(struct i2c_client *client, uint8_t gpio_no, uint8_t brightness)
+{
+	uint8_t pwm;
+
+	pwm = gpio_no + TLC59116_REG_PWM0;
+        i2c_smbus_write_byte_data(client, pwm, brightness);
+
+        return 0;
+}
+
+static void tlc59116_led_work(struct work_struct *work)
+{
+	struct tlc59116_led *tlc59116;
+
+	tlc59116 = container_of(work, struct tlc59116_led, work);
+
+	led_dbg("\nbrighness = %d \n", tlc59116->brightness);
+	switch (tlc59116->brightness) {
+	case LED_OFF:
+		led_info("\nLed off\n");
+		tlc59116_set_gpio(tlc59116->client, tlc59116->led_num, TLC59116_LED_OFF);
+		break;
+
+	case LED_FULL:
+		led_info("\nLed on\n");
+		tlc59116_set_gpio(tlc59116->client, tlc59116->led_num, TLC59116_LED_ON);
+		break;
+	default:
+		led_info("\nBrightness is %d\n", tlc59116->brightness);
+		if (TLC59116_BLINK != tlc59116_get_gpio(tlc59116->client, tlc59116->led_num))
+			tlc59116_set_gpio(tlc59116->client, tlc59116->led_num, TLC59116_DIM);
+
+		tlc59116_individual_brighness_control(tlc59116->client, tlc59116->led_num, tlc59116->brightness);
+		break;
+	}
+
+}
+
+static void tlc59116_led_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+	struct tlc59116_led *tlc59116;
+
+	tlc59116 = container_of(led_cdev, struct tlc59116_led, led_cdev);
+
+	spin_lock(&tlc59116->lock);
+	tlc59116->brightness = value;
+
+	/*
+	 * Must use workqueue for the actual I/O since I2C operations
+	 * can sleep.
+	 */
+	schedule_work(&tlc59116->work);
+
+	spin_unlock(&tlc59116->lock);
+}
+
+/*
+ * delay_on, delay_off: units are in ms
+ *
+ */
+
+static int tlc59116_set_blink(struct led_classdev *led_cdev,
+				unsigned long *delay_on,
+				unsigned long *delay_off)
+{
+	struct tlc59116_led *tlc59116;
+	uint16_t	period;
+	uint16_t	duty_cycle;
+	uint8_t		gdc;
+	uint8_t		gfrq;
+	
+	tlc59116 = container_of(led_cdev, struct tlc59116_led, led_cdev);
+	led_info ("Blinking: delay_on = %ldms, delay_off = %ldms, brightness = %d\n", 
+				*delay_on, *delay_off, tlc59116->brightness);
+
+	// Hardware blinking only for tricolor leds . The rest will have software blinking
+	if (tlc59116->led_num > 2) 
+		return 1;
+
+	if ((*delay_on == 0) && (*delay_off ==0)) {
+		spin_lock(&tlc59116->lock);
+
+		/* MODE2[DMBLNK] = 1 */
+		tlc59116_set_mode(tlc59116->client, MODE2_BLINK);
+
+		/* Set LDRx = 11 */
+		tlc59116_set_gpio(tlc59116->client, tlc59116->led_num, TLC59116_BLINK);
+
+		tlc59116_individual_brighness_control(tlc59116->client, tlc59116->led_num, tlc59116->brightness);
+		spin_unlock(&tlc59116->lock);
+		return 0;
+	}
+
+
+	if ((*delay_on + *delay_off) > TLC59116_PERIOD_MAX)
+	{
+		led_dbg ("Max period is %dms\n", TLC59116_PERIOD_MAX);
+		return -EINVAL;
+	}
+
+	if ((*delay_on + *delay_off) < TLC59116_PERIOD_MIN)
+	{
+		*delay_on = TLC59116_PERIOD_MIN/2 + 1;
+		*delay_off = TLC59116_PERIOD_MIN/2 + 1;
+	}
+	period = (*delay_on) + (*delay_off);
+
+	duty_cycle = (100 * (*delay_on)) / period;
+
+	spin_lock(&tlc59116->lock);
+	
+	/* MODE2[DMBLNK] = 1 */
+	tlc59116_set_mode(tlc59116->client, MODE2_BLINK);
+
+	/* Set LDRx = 11 */
+	tlc59116_set_gpio(tlc59116->client, tlc59116->led_num, TLC59116_BLINK);
+
+	tlc59116_individual_brighness_control(tlc59116->client, tlc59116->led_num, tlc59116->brightness);
+
+	gdc = (duty_cycle * 256)/100;
+	i2c_smbus_write_byte_data(tlc59116->client, TLC59116_REG_GRPPWM, gdc);	
+
+	gfrq = (24 * period)/1000 - 1; /* unit is in second (convert from ms to second) */
+	i2c_smbus_write_byte_data(tlc59116->client, TLC59116_REG_GRPFREQ, gfrq);		
+	
+
+#ifdef DUMP_REGS
+	dump_regs(tlc59116->client);
+#endif
+
+	spin_unlock(&tlc59116->lock);
+	return 0;
+}
+
+static int tlc59116_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	struct tlc59116_led *tlc59116;
+	struct tlc59116_chipdef *chip;
+	struct i2c_adapter *adapter;
+	struct led_platform_data *pdata;
+	int i, err;
+
+	chip = &tlc59116_chipdefs[id->driver_data];
+	adapter = to_i2c_adapter(client->dev.parent);
+	pdata = client->dev.platform_data;
+
+	/* Make sure the slave address / chip type combo given is possible */
+	if ((client->addr & ~((1 << chip->slv_addr_shift) - 1)) !=
+	    chip->slv_addr) {
+		dev_err(&client->dev, "invalid slave address %02x\n",
+				client->addr);
+		return -ENODEV;
+	}
+
+	printk(KERN_INFO "leds-tlc59116: Using %s %d-bit LED driver at "
+			"slave address 0x%02x\n",
+			id->name, chip->bits, client->addr);
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
+		return -EIO;
+
+	if (pdata) {
+		if (pdata->num_leds != chip->bits) {
+			dev_err(&client->dev, "board info claims %d LEDs"
+					" on a %d-bit chip\n",
+					pdata->num_leds, chip->bits);
+			return -ENODEV;
+		}
+	}
+
+	tlc59116 = devm_kzalloc(&client->dev, sizeof(*tlc59116) * chip->bits, GFP_KERNEL);
+	if (!tlc59116)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, tlc59116);
+
+	for (i = 0; i < chip->bits; i++) {
+		tlc59116[i].chipdef = chip;
+		tlc59116[i].client = client;
+		tlc59116[i].led_num = i;
+
+		/* Platform data can specify LED names and default triggers */
+		if (pdata) {
+			if (pdata->leds[i].name)
+				snprintf(tlc59116[i].name,
+					 sizeof(tlc59116[i].name), "tlc59116:%s",
+					 pdata->leds[i].name);
+			if (pdata->leds[i].default_trigger)
+				tlc59116[i].led_cdev.default_trigger =
+					pdata->leds[i].default_trigger;
+		} else {
+			snprintf(tlc59116[i].name, sizeof(tlc59116[i].name),
+				 "tlc59116:%d", i);
+		}
+
+		spin_lock_init(&tlc59116[i].lock);
+
+		tlc59116[i].led_cdev.name = tlc59116[i].name;
+		tlc59116[i].led_cdev.brightness_set = tlc59116_led_set;
+	        tlc59116[i].led_cdev.blink_set = tlc59116_set_blink;	
+		tlc59116[i].led_cdev.brightness = 0;
+
+		INIT_WORK(&tlc59116[i].work, tlc59116_led_work);
+
+		err = led_classdev_register(&client->dev, &tlc59116[i].led_cdev);
+		if (err < 0)
+			goto exit;
+	}
+		
+        tlc59116_set_mode(client, MODE2_DIM);
+
+	/* Turn off LEDs */
+	for (i = 0; i < chip->bits; i++)
+		tlc59116_set_gpio(client, i, TLC59116_LED_OFF);
+
+	return 0;
+
+exit:
+	while (i--) {
+		led_classdev_unregister(&tlc59116[i].led_cdev);
+		cancel_work_sync(&tlc59116[i].work);
+	}
+
+	devm_kfree(&client->dev, tlc59116);
+	i2c_set_clientdata(client, NULL);
+
+	return err;
+}
+
+static int tlc59116_remove(struct i2c_client *client)
+{
+	struct tlc59116_led *tlc59116 = i2c_get_clientdata(client);
+	int i;
+
+	for (i = 0; i < tlc59116->chipdef->bits; i++) {
+		led_classdev_unregister(&tlc59116[i].led_cdev);
+		cancel_work_sync(&tlc59116[i].work);
+	}
+
+	devm_kfree(&client->dev, tlc59116);
+	i2c_set_clientdata(client, NULL);
+
+	return 0;
+}
+
+static struct i2c_driver tlc59116_driver = {
+	.driver = {
+		.name	= "leds-tlc59116",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= tlc59116_probe,
+	.remove	= tlc59116_remove,
+	.id_table = tlc59116_id,
+};
+
+module_i2c_driver(tlc59116_driver);
+
+MODULE_AUTHOR("Belkin Inc.");
+MODULE_DESCRIPTION("TLC59116 LED driver");
+MODULE_LICENSE("GPL v2");
