# HG changeset patch
# User Matt Mackall <mpm@selenic.com>
# Date 1249942085 18000
# Node ID 632717a42c32cf9dc0357d5f6c88c8e3f6e5882d
# Parent  09ddc16e60459f93193c2355e9ca405bef495895
imported patch ooma-led-hack

diff -r 4ba2397d39a8 drivers/i2c/busses/i2c-comcerto.c
--- a/drivers/i2c/busses/i2c-comcerto.c	Mon Aug 10 17:08:05 2009 -0500
+++ b/drivers/i2c/busses/i2c-comcerto.c	Fri Aug 14 14:47:53 2009 -0500
@@ -662,6 +662,112 @@
 	.remove	= comcerto_i2c_remove,
 };
 
+//
+// led init hack - init the LEDs as early as possible during system init
+// putting this code here is very tacky for which I appologise - but the spec
+// requires me to do this asap once we're in the kernel - so no modules and as 
+// soon as possible after the i2c hardware has been initialised - Paul
+//
+static int tlc_attach_adapter(struct i2c_adapter *adapter);
+static int tlc_detach_client(struct i2c_client *client);
+static struct i2c_driver tlc_driver =
+{
+        .driver = { .name="tmp_led_driver" },
+	.id     = 102,          // ??? made up - we don't need to share
+	.attach_adapter = tlc_attach_adapter,
+	.detach_client  = tlc_detach_client,
+};
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+static unsigned short probe[]      = { I2C_CLIENT_END };
+static unsigned short ignore[]     = { I2C_CLIENT_END };
+static unsigned short tlc_flist[] = { -1, 0x60, I2C_CLIENT_END };
+static const unsigned short * tlc_forces_list[] = { tlc_flist, NULL };
+static struct i2c_client_address_data tlc_addr_data =
+{
+        .normal_i2c     = normal_i2c,
+	.probe          = probe,
+	.ignore         = ignore,
+	.forces         = tlc_forces_list
+};
+static  struct i2c_client *tlc_client;
+static int tlc_probe(struct i2c_adapter *adap, int address, int kind)
+{
+        int     rc;
+
+	tlc_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	if (!tlc_client)
+		return -ENOMEM;
+	strncpy(tlc_client->name, "tlcDriver", I2C_NAME_SIZE);
+	tlc_client->addr = address;
+	tlc_client->adapter = adap;
+	tlc_client->driver = &tlc_driver;
+	if ((rc = i2c_attach_client(tlc_client)) != 0) {
+		kfree(tlc_client);
+	}
+	printk(KERN_DEBUG "%s() exit. rc=%d\n", __FUNCTION__, rc);
+	return rc;
+}
+static int tlc_attach_adapter(struct i2c_adapter *adapter) { return i2c_probe(adapter, &tlc_addr_data, tlc_probe); }
+static int tlc_detach_client(struct i2c_client *client)
+{
+        int rc;
+
+	if ((rc = i2c_detach_client(client)) == 0) 
+		kfree(client);
+	return rc;
+}
+static int tlc_write_register(int address, int value)
+{
+        unsigned char   wbuf[2];
+	int ret = 0;
+
+	wbuf[0] = (unsigned char)address;
+	wbuf[1] = (unsigned char)value;
+	
+	if (i2c_master_send(tlc_client, wbuf, 2) != 2) {
+		dev_err(&tlc_client->dev, "tlc_write_register: Write error\n");
+		ret = -1;
+	}
+	return ret;
+}
+#define TLC_MODE1       0x00
+#define TLC_MODE2       0x01
+#define TLC_PWM(n)      (0x02+(n))
+#define TLC_GRPPWM      0x12
+#define TLC_GRPFREQ     0x13
+#define TLC_LEDOUT0     0x14
+#define TLC_LEDOUT1     0x15
+#define TLC_LEDOUT2     0x16
+#define TLC_LEDOUT3     0x17
+#define TLC_SUBADR1     0x18
+#define TLC_SUBADR2     0x19
+#define TLC_SUBADR3     0x1a
+#define TLC_ALLCALLADR  0x1b
+#define TLC_IREF        0x1c
+#define TLC_EFLAG1      0x1d
+#define TLC_EFLAG2      0x1e
+static void tlc_init(void)
+{
+	int i;
+	i2c_add_driver(&tlc_driver);	// temp driver to init fp at boot
+	tlc_write_register(TLC_MODE1, 0);   // no auto inc, no call addresses
+	tlc_write_register(TLC_MODE2, 0);   // error ignored dimming change on stop
+	tlc_write_register(TLC_IREF, 0x40);     // hc = 1, d = 0, cm = 0
+	tlc_write_register(TLC_LEDOUT0, 0x00);  // off
+	tlc_write_register(TLC_LEDOUT1, 0x00);  // off
+	tlc_write_register(TLC_LEDOUT2, 0x0f);  // trash/vm on`
+	tlc_write_register(TLC_LEDOUT3, 0x00);  // off
+	for (i = 0; i < 16; i++)
+		tlc_write_register(TLC_PWM(i), 0xff);   // error ignored dimming change on stop
+	tlc_write_register(TLC_GRPPWM, 0xff);
+	i2c_del_driver(&tlc_driver);
+}
+//
+// end led init hack
+//
+
+
+
 static int __init comcerto_i2c_init(void)
 {
 	printk(KERN_DEBUG "%s: module loaded\n", __FUNCTION__);
@@ -671,6 +777,7 @@
 		return -1;
 	}
 
+	tlc_init();
 	return 0;
 }
 
