diff -purN linux-omap/drivers/i2c/chips/Kconfig lin_for_twl/drivers/i2c/chips/Kconfig
--- linux-omap/drivers/i2c/chips/Kconfig	2007-01-08 18:56:31.000000000 -0600
+++ lin_for_twl/drivers/i2c/chips/Kconfig	2007-02-26 21:31:32.000000000 -0600
@@ -127,6 +127,10 @@ config TWL4030_CORE
 	help
 	  Say yes here if you have TWL4030 chip on your board
 
+config TWL4030_GPIO
+        bool "TWL4030 GPIO Driver"
+        depends on TWL4030_CORE
+
 config SENSORS_M41T00
 	tristate "ST M41T00 RTC chip"
 	depends on I2C && PPC32
diff -purN linux-omap/drivers/i2c/chips/Makefile lin_for_twl/drivers/i2c/chips/Makefile
--- linux-omap/drivers/i2c/chips/Makefile	2007-01-08 18:56:31.000000000 -0600
+++ lin_for_twl/drivers/i2c/chips/Makefile	2007-02-26 21:32:56.000000000 -0600
@@ -16,6 +16,7 @@ obj-$(CONFIG_SENSORS_TLV320AIC23) += tlv
 obj-$(CONFIG_GPIOEXPANDER_OMAP)	+= gpio_expander_omap.o
 obj-$(CONFIG_MENELAUS)		+= menelaus.o
 obj-$(CONFIG_TWL4030_CORE)      += twl4030_core.o
+obj-$(CONFIG_TWL4030_GPIO)      += twl4030_gpio.o
 obj-$(CONFIG_RTC_X1205_I2C)	+= x1205.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
diff -purN linux-omap/drivers/i2c/chips/twl4030_core.c lin_for_twl/drivers/i2c/chips/twl4030_core.c
--- linux-omap/drivers/i2c/chips/twl4030_core.c	2007-02-16 09:43:31.000000000 -0600
+++ lin_for_twl/drivers/i2c/chips/twl4030_core.c	2007-02-27 18:17:51.000000000 -0600
@@ -1,5 +1,5 @@
 /*
- * twl4030_core.c - driver for TWL4030 PM and audio CODEC device
+ * linux/drivers/i2c/chips/twl4030_core.c
  *
  * Copyright (C) 2005-2006 Texas Instruments, Inc.
  *
@@ -9,9 +9,6 @@
  * Based on tlv320aic23.c:
  * Copyright (c) by Kai Svahn <kai.svahn@nokia.com>
  *
- * Code cleanup and modifications to IRQ handler.
- * by syed khasim <x0khasim@ti.com>
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -28,6 +25,7 @@
  *
  */
 
+/*** Includes */
 #include <linux/module.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>
@@ -36,100 +34,443 @@
 #include <linux/random.h>
 #include <linux/syscalls.h>
 #include <linux/kthread.h>
-
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
-#include <linux/device.h>
-
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
 
 #include <asm/arch/twl4030.h>
+#include <asm/mach/irq.h>
 #include <asm/arch/gpio.h>
+//#include <asm/arch/platform.h>
 #include <asm/arch/mux.h>
 
+#include <linux/device.h>
+
+#define CONFIG_TWL4030_IRQ_PRIO 26
+
+/* Triton Core internal information (END) */
+
+/* Few power values */
+#define R_CFG_BOOT                      0x05
+#define R_PROTECT_KEY                   0x0E
+
+/* access control */
+#define KEY_UNLOCK1                     0xce
+#define KEY_UNLOCK2                     0xec
+#define KEY_LOCK                        0x00
+
+#define HFCLK_FREQ_19p2_MHZ             (1 << 0)
+#define HFCLK_FREQ_26_MHZ               (2 << 0)
+#define HFCLK_FREQ_38p4_MHZ             (3 << 0)
+#define HIGH_PERF_SQ                    (1 << 3)
+
 /**** Macro Definitions */
-#define TWL_CLIENT_STRING		"TWL4030-ID"
-#define TWL_CLIENT_USED			1
-#define TWL_CLIENT_FREE			0
+#define TWL_CLIENT_STRING                        "TWL4030-ID"
+#define TWL_CLIENT_USED                          1
+#define TWL_CLIENT_FREE                          0
 
 /* IRQ Flags */
-#define FREE				0
-#define USED				1
+#define FREE                                     0
+#define USED                                     1
 
 /** Primary Interrupt Handler on TWL4030 Registers */
 
 /**** Register Definitions */
 
-#define REG_PIH_ISR_P1			(0x1)
-#define REG_PIH_ISR_P2			(0x2)
-#define REG_PIH_SIR			(0x3)
+#define REG_PIH_ISR_P1                           (0x1)
+#define REG_PIH_ISR_P2                           (0x2)
+#define REG_PIH_SIR                              (0x3)
+
+/**** BitField Definitions */
+
+/* PIH_ISR_P1 Fields */
+#define BIT_PIH_ISR_P1_PIH_ISR0                  (0x000)
+#define BIT_PIH_ISR_P1_PIH_ISR0_M                (0x00000001)
+#define BIT_PIH_ISR_P1_PIH_ISR1                  (0x001)
+#define BIT_PIH_ISR_P1_PIH_ISR1_M                (0x00000002)
+#define BIT_PIH_ISR_P1_PIH_ISR2                  (0x002)
+#define BIT_PIH_ISR_P1_PIH_ISR2_M                (0x00000004)
+#define BIT_PIH_ISR_P1_PIH_ISR3                  (0x003)
+#define BIT_PIH_ISR_P1_PIH_ISR3_M                (0x00000008)
+#define BIT_PIH_ISR_P1_PIH_ISR4                  (0x004)
+#define BIT_PIH_ISR_P1_PIH_ISR4_M                (0x00000010)
+#define BIT_PIH_ISR_P1_PIH_ISR5                  (0x005)
+#define BIT_PIH_ISR_P1_PIH_ISR5_M                (0x00000020)
+#define BIT_PIH_ISR_P1_PIH_ISR6                  (0x006)
+#define BIT_PIH_ISR_P1_PIH_ISR6_M                (0x00000040)
+#define BIT_PIH_ISR_P1_PIH_ISR7                  (0x007)
+#define BIT_PIH_ISR_P1_PIH_ISR7_M                (0x00000080)
+/* PIH_ISR_P2 Fields */
+#define BIT_PIH_ISR_P2_PIH_ISR0                  (0x000)
+#define BIT_PIH_ISR_P2_PIH_ISR0_M                (0x00000001)
+#define BIT_PIH_ISR_P2_PIH_ISR1                  (0x001)
+#define BIT_PIH_ISR_P2_PIH_ISR1_M                (0x00000002)
+#define BIT_PIH_ISR_P2_PIH_ISR2                  (0x002)
+#define BIT_PIH_ISR_P2_PIH_ISR2_M                (0x00000004)
+#define BIT_PIH_ISR_P2_PIH_ISR3                  (0x003)
+#define BIT_PIH_ISR_P2_PIH_ISR3_M                (0x00000008)
+#define BIT_PIH_ISR_P2_PIH_ISR4                  (0x004)
+#define BIT_PIH_ISR_P2_PIH_ISR4_M                (0x00000010)
+#define BIT_PIH_ISR_P2_PIH_ISR5                  (0x005)
+#define BIT_PIH_ISR_P2_PIH_ISR5_M                (0x00000020)
+#define BIT_PIH_ISR_P2_PIH_ISR6                  (0x006)
+#define BIT_PIH_ISR_P2_PIH_ISR6_M                (0x00000040)
+#define BIT_PIH_ISR_P2_PIH_ISR7                  (0x007)
+#define BIT_PIH_ISR_P2_PIH_ISR7_M                (0x00000080)
+/* PIH_SIR Fields */
+#define BIT_PIH_SIR_PIH1SIR                      (0x000)
+#define BIT_PIH_SIR_PIH1SIR_M                    (0x00000001)
+#define BIT_PIH_SIR_PIH2SIR                      (0x001)
+#define BIT_PIH_SIR_PIH2SIR_M                    (0x00000002)
+#define BIT_PIH_SIR_PIH3SIR                      (0x002)
+#define BIT_PIH_SIR_PIH3SIR_M                    (0x00000004)
+#define BIT_PIH_SIR_PIH4SIR                      (0x003)
+#define BIT_PIH_SIR_PIH4SIR_M                    (0x00000008)
+#define BIT_PIH_SIR_PIH5SIR                      (0x004)
+#define BIT_PIH_SIR_PIH5SIR_M                    (0x00000010)
+#define BIT_PIH_SIR_PIH6SIR                      (0x005)
+#define BIT_PIH_SIR_PIH6SIR_M                    (0x00000020)
 
 /* Triton Core internal information (BEGIN) */
 
 /* Last - for index max*/
-#define TWL4030_MODULE_LAST		TWL4030_MODULE_SECURED_REG
+#define TWL4030_MODULE_LAST         TWL4030_MODULE_SECURED_REG
 
 /* Slave address */
-#define TWL4030_NUM_SLAVES		0x04
-#define TWL4030_SLAVENUM_NUM0		0x00
-#define TWL4030_SLAVENUM_NUM1		0x01
-#define TWL4030_SLAVENUM_NUM2		0x02
-#define TWL4030_SLAVENUM_NUM3		0x03
-#define TWL4030_SLAVEID_ID0		0x48
-#define TWL4030_SLAVEID_ID1		0x49
-#define TWL4030_SLAVEID_ID2		0x4A
-#define TWL4030_SLAVEID_ID3		0x4B
+#define TWL4030_NUM_SLAVES          0x04
+#define TWL4030_SLAVENUM_NUM0       0x00
+#define TWL4030_SLAVENUM_NUM1       0x01
+#define TWL4030_SLAVENUM_NUM2       0x02
+#define TWL4030_SLAVENUM_NUM3       0x03
+#define TWL4030_SLAVEID_ID0         0x48
+#define TWL4030_SLAVEID_ID1         0x49
+#define TWL4030_SLAVEID_ID2         0x4A
+#define TWL4030_SLAVEID_ID3         0x4B
 
 /* Base Address defns */
 /* USB ID */
-#define TWL4030_BASEADD_USB		0x0000
+#define TWL4030_BASEADD_USB         0x0000
 /* AUD ID */
-#define TWL4030_BASEADD_AUDIO_VOICE	0x0000
-#define TWL4030_BASEADD_GPIO		0x0098
+#define TWL4030_BASEADD_AUDIO_VOICE 0x0000
+
+/* M1 companion board GPIO base address */
+#define TWL4030_BASEADD_GPIO        0x0098
 
-#define TWL4030_BASEADD_INTBR		0x0085
-#define TWL4030_BASEADD_PIH		0x0080
-#define TWL4030_BASEADD_TEST		0x004C
+#define TWL4030_BASEADD_INTBR       0x0085
+#define TWL4030_BASEADD_PIH         0x0080
+#define TWL4030_BASEADD_TEST        0x004C
 /* AUX ID */
-#define TWL4030_BASEADD_INTERRUPTS	0x00B9
-#define TWL4030_BASEADD_LED		0x00EE
-#define TWL4030_BASEADD_MADC		0x0000
-#define TWL4030_BASEADD_MAIN_CHARGE	0x0074
-#define TWL4030_BASEADD_PRECHARGE	0x00AA
-#define TWL4030_BASEADD_PWM0		0x00F8
-#define TWL4030_BASEADD_PWM1		0x00FB
-#define TWL4030_BASEADD_PWMA		0x00EF
-#define TWL4030_BASEADD_PWMB		0x00F1
-#define TWL4030_BASEADD_KEYPAD		0x00D2
+#define TWL4030_BASEADD_INTERRUPTS  0x00B9
+#define TWL4030_BASEADD_LED         0x00EE
+#define TWL4030_BASEADD_MADC        0x0000
+#define TWL4030_BASEADD_MAIN_CHARGE 0x0074
+#define TWL4030_BASEADD_PRECHARGE   0x00AA
+#define TWL4030_BASEADD_PWM0        0x00F8
+#define TWL4030_BASEADD_PWM1        0x00FB
+#define TWL4030_BASEADD_PWMA        0x00EF
+#define TWL4030_BASEADD_PWMB        0x00F1
+#define TWL4030_BASEADD_KEYPAD      0x00D2
 /* POWER ID */
-#define TWL4030_BASEADD_BACKUP		0x0014
-#define TWL4030_BASEADD_INT		0x002E
-#define TWL4030_BASEADD_PM_MASTER	0x0036
-#define TWL4030_BASEADD_PM_RECIEVER	0x005B
-#define TWL4030_BASEADD_RTC		0x001C
-#define TWL4030_BASEADD_SECURED_REG	0x0000
+#define TWL4030_BASEADD_BACKUP      0x0014
+#define TWL4030_BASEADD_INT         0x002E
+#define TWL4030_BASEADD_PM_MASTER   0x0036
+#define TWL4030_BASEADD_PM_RECIEVER 0x005B
+#define TWL4030_BASEADD_RTC         0x001C
+#define TWL4030_BASEADD_SECURED_REG 0x0000
 
 /* Triton Core internal information (END) */
 
-/* Few power values */
-#define R_CFG_BOOT			0x05
-#define R_PROTECT_KEY			0x0E
+/* Pull out the board specific config's defines */
+#define CONFIG_I2C_TWL4030_ID0 1
+#define CONFIG_I2C_TWL4030_ID1 1
+#define CONFIG_I2C_TWL4030_ID2 1
+#define CONFIG_I2C_TWL4030_ID3 1
 
-/* access control */
-#define KEY_UNLOCK1			0xce
-#define KEY_UNLOCK2			0xec
-#define KEY_LOCK			0x00
-
-#define HFCLK_FREQ_19p2_MHZ		(1 << 0)
-#define HFCLK_FREQ_26_MHZ		(2 << 0)
-#define HFCLK_FREQ_38p4_MHZ		(3 << 0)
-#define HIGH_PERF_SQ			(1 << 3)
 
-/* on I2C-1 for 2430SDP */
-#define CONFIG_I2C_TWL4030_ID		1
+/* ----- debug defines ----------------------------------------------- */
+/* Debug - four macros:
+ * FN_IN, FN_OUT(value),D1,D2,D3 enabled based on log level
+ */
+
+/* Log level standard used here:
+ * Log level 3 all messages
+ * Log level 2 all entry-exit points
+ * Log level 1 major messages
+ * Log level 0 no messages
+ */
+#define TWL4030_LOG_LEVEL 0
+/* detail - 0 - no detail
+ *          1 - function name
+ *          2 - function name, line number
+ * prefix is added to every log message
+ */
+#define TWL4030_DETAIL    0
+
+/* kernel log level*/
+//#define TWL4030_K_LOG_LEVEL KERN_DEBUG
+#define TWL4030_K_LOG_LEVEL
+
+#if ( TWL4030_DETAIL > 0 )
+#define DL1 "%s "
+#define DR1 ,__FUNCTION__
+#else
+#define DL1
+#define DR1
+#endif
+#if ( TWL4030_DETAIL > 1 )
+#define DL2 "[%d] "
+#define DR2 ,__LINE__
+#else
+#define DL2
+#define DR2
+#endif
+
+#define D(format,...)\
+	printk(TWL4030_K_LOG_LEVEL DL1 DL2 format "\n" DR1 DR2, ## __VA_ARGS__)
+
+#if (TWL4030_LOG_LEVEL >= 1)
+#define D1(ARGS...) D(ARGS)
+#else
+#define D1(ARGS...)
+#endif
+#if (TWL4030_LOG_LEVEL >= 2)
+#define D2(ARGS...) D(ARGS)
+#else
+#define D2(ARGS...)
+#endif
+#if (TWL4030_LOG_LEVEL >= 3)
+#define D3(ARGS...) D(ARGS)
+#else
+#define D3(ARGS...)
+#endif
+
+#if (TWL4030_LOG_LEVEL >= 2)
+#define FN_IN printk("%s Entry\n",__FUNCTION__);
+#define FN_OUT(ARG) printk("%s[%d]:Exit(%d)\n",__FUNCTION__,__LINE__,ARG);
+#else
+#define FN_IN
+#define FN_OUT(ARG)
+#endif
+
+/* Sys FS Helper functions and macros */
+#ifdef CONFIG_I2C_TWL4030_DBG_SYSFS
+/* Device Information- dummy */
+static struct platform_device twl4030_debug_dev = {
+	.name = TWL_CLIENT_STRING,
+	.id = 0,
+};
+
+/* 255 Max bytes in a field register */
+#define READ_REG_SIZE 255
+/* Sys FS support */
+static ssize_t show_mod(int mod, struct device *dev, char *buf)
+{
+	int j;
+	unsigned char temp_buffer[READ_REG_SIZE + 1];
+	struct timeval stv, stv1, stv2;
+	int timespent1, timespent2;
+	char *sval = buf;
+	/* Read from I2c first 255 bytes (the max we can write in the reg) */
+	do_gettimeofday(&stv);
+	if ((j = twl4030_i2c_read(mod, temp_buffer, 0x0, READ_REG_SIZE)) < 0) {
+		printk(KERN_ERR
+		       "unable to read %d bytes returned %d in module %d\n",
+		       READ_REG_SIZE, j, mod);
+		return j;
+	}
+	do_gettimeofday(&stv1);
+	/* do a read of the last 256th byte */
+	if ((j =
+	     twl4030_i2c_read_u8(mod, temp_buffer + READ_REG_SIZE,
+				 READ_REG_SIZE)) < 0) {
+		printk(KERN_ERR
+		       "unable to read %d reg returned %d in module %d\n",
+		       READ_REG_SIZE, j, mod);
+		return j;
+	}
+	do_gettimeofday(&stv2);
+	sval += sprintf(sval, "  | ");
+	for (j = 0; j < 0x10; j++) {
+		sval += sprintf(sval, "%02X ", j);
+	}
+	sval += sprintf(sval, "\n--+");
+
+	for (j = 0; j < 0x10; j++) {
+		sval += sprintf(sval, " --");
+	}
+
+	sval += sprintf(sval, "\n00| ");
+
+	for (j = 0; j <= READ_REG_SIZE; j++) {
+		sval += sprintf(sval, "%02X", temp_buffer[j]);
+		if (j < READ_REG_SIZE) {
+			sval +=
+			    ((j + 1) % 0x10) ? sprintf(sval,
+						       " ") : sprintf(sval,
+								      "\n%02X| ",
+								      j + 1);
+		}
+	}
+	timespent1 =
+	    (stv1.tv_sec - stv.tv_sec) * 1000000 + (stv1.tv_usec - stv.tv_usec);
+	timespent2 =
+	    (stv2.tv_sec - stv1.tv_sec) * 1000000 + (stv2.tv_usec -
+						     stv1.tv_usec);
+	sval +=
+	    sprintf(sval, "\nTime Taken(uSec): 255bytes=%d 1byte=%d\n", timespent1,
+		    timespent2);
+	sval += 1;
+	*sval = 0;
+	return sval - buf + 1;
+}
+
+/* MSB 8 bits are register address[module reg offset] and LSB 8 bits the value */
+static ssize_t
+set_mod(int mod, struct device *dev, const char *buf, size_t count)
+{
+	u16 val = (u16) simple_strtoul(buf, NULL, 16);
+	printk("Reg=0x%02x, val=0x%02x,mod=%d\n", (val & 0xFF00) >> 8,
+	       (val & 0x00FF), mod);
+	if (twl4030_i2c_write_u8(mod, (val & 0x00FF), (val & 0xFF00) >> 8) < 0) {
+		printk("FAILED\n");
+	} else {
+		printk("SUCCESS\n");
+	}
+	return count;
+}
+
+/* function generator macros */
+#define C_SHOW_MOD(MOD)\
+static ssize_t show_mod##MOD(struct device *dev, struct device_attribute *attr, char *buf)\
+{\
+	return show_mod(MOD, dev, buf);\
+}\
+
+#define C_SET_MOD(MOD)\
+static ssize_t set_mod##MOD(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)\
+{\
+	return set_mod(MOD, dev, buf, count);\
+}\
+
+#define MAK_MOD(MOD) \
+C_SET_MOD(MOD)\
+C_SHOW_MOD(MOD)\
+static DEVICE_ATTR(twl4030_mod##MOD, S_IWUSR | S_IRUGO, &show_mod##MOD, &set_mod##MOD);\
+
+#define TWL4030_SYS_DEV_CREAT(MOD)\
+		device_create_file(&twl4030_debug_dev.dev, &dev_attr_twl4030_mod##MOD);
+		
+#ifdef CONFIG_SOUND_SERVICES_ENABLE
+		
+ssize_t show_sound_services(struct device *dev, struct device_attribute *attr,	char *buf)
+{
+	int res;
+	char *sval = buf;
+	
+	res = twl4030_sndsrv_status();
+	if (res == 0){
+		sval += sprintf (sval, "Status OFF\n");
+	}
+	else if (res == 1){
+		sval += sprintf (sval, "Status ON\n");
+	}
+	else {
+		printk ( KERN_ERR "Sound Services: vibrator status read error !!!  \n");
+		return res;
+	}
+	
+	res = twl4030_sndsrv_get_dtcyl();
+	
+	switch (res){
+		case VIB_DUTY_CYCLE_100:
+			sval += sprintf (sval, "duty cycle = 100%% \n");
+			break;
+	
+		case VIB_DUTY_CYCLE_75:
+			sval += sprintf (sval, "duty cycle = 75%% \n");
+			break;
+		
+		case VIB_DUTY_CYCLE_50:
+			sval += sprintf (sval, "duty cycle = 50%% \n");
+			break;
+	
+		case VIB_DUTY_CYCLE_25:
+			sval += sprintf (sval, "duty cycle = 25%% \n");
+			break;
+	  
+		default:
+			printk ( KERN_ERR "Sound Services: vibrator duty cycle read error !!! \n");
+			return res;
+	}
+	
+	sval+= 1;
+	*sval=0;
+	
+	return sval - buf + 1;
+}
+
+static DEVICE_ATTR(sound_services, S_IRUGO, &show_sound_services, NULL);
+
+#define TWL4030_SYS_DEV_SOUND_SERVICES \
+	device_create_file(&twl4030_debug_dev.dev, &dev_attr_sound_services);\
+
+#else
+
+#define TWL4030_SYS_DEV_SOUND_SERVICES  
+
+#endif
 
+
+
+
+MAK_MOD(0)
+    MAK_MOD(1)
+    MAK_MOD(2)
+    MAK_MOD(3)
+    MAK_MOD(4)
+    MAK_MOD(5)
+    MAK_MOD(6)
+    MAK_MOD(7)
+    MAK_MOD(8)
+    MAK_MOD(9)
+    MAK_MOD(10)
+    MAK_MOD(11)
+    MAK_MOD(12)
+    MAK_MOD(13)
+    MAK_MOD(14)
+    MAK_MOD(15)
+    MAK_MOD(16)
+    MAK_MOD(17)
+    MAK_MOD(18)
+    MAK_MOD(19)
+    MAK_MOD(20)
+    MAK_MOD(21)
+#define TWL_SYS_DEV()\
+	TWL4030_SYS_DEV_CREAT(0)\
+	TWL4030_SYS_DEV_CREAT(1)\
+	TWL4030_SYS_DEV_CREAT(2)\
+	TWL4030_SYS_DEV_CREAT(3)\
+	TWL4030_SYS_DEV_CREAT(4)\
+	TWL4030_SYS_DEV_CREAT(5)\
+	TWL4030_SYS_DEV_CREAT(6)\
+	TWL4030_SYS_DEV_CREAT(7)\
+	TWL4030_SYS_DEV_CREAT(8)\
+	TWL4030_SYS_DEV_CREAT(9)\
+	TWL4030_SYS_DEV_CREAT(10)\
+	TWL4030_SYS_DEV_CREAT(11)\
+	TWL4030_SYS_DEV_CREAT(12)\
+	TWL4030_SYS_DEV_CREAT(13)\
+	TWL4030_SYS_DEV_CREAT(14)\
+	TWL4030_SYS_DEV_CREAT(15)\
+	TWL4030_SYS_DEV_CREAT(16)\
+	TWL4030_SYS_DEV_CREAT(17)\
+	TWL4030_SYS_DEV_CREAT(18)\
+	TWL4030_SYS_DEV_CREAT(19)\
+	TWL4030_SYS_DEV_CREAT(20)\
+	TWL4030_SYS_DEV_CREAT(21)\
+	TWL4030_SYS_DEV_SOUND_SERVICES\
+
+#endif
 /**** Helper functions */
 static int
 twl4030_detect_client(struct i2c_adapter *adapter, unsigned char sid);
@@ -150,12 +491,8 @@ struct twl4030_client {
 	const unsigned char address;
 	const char adapter_index;
 	unsigned char inuse;
-
-	/* max numb of i2c_msg required is for read =2 */
-	struct i2c_msg xfer_msg[2];
-
-	/* To lock access to xfer_msg */
-	struct semaphore xfer_lock;
+	struct i2c_msg xfer_msg[2];	/* max numb of i2c_msg required is for read =2 */
+	struct semaphore xfer_lock;	/* To lock access to xfer_msg */
 };
 
 /* Module Mapping */
@@ -166,84 +503,119 @@ struct twl4030mapping {
 
 /* mapping the module id to slave id and base address */
 static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
-	{ TWL4030_SLAVENUM_NUM0, TWL4030_BASEADD_USB },
-	{ TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_AUDIO_VOICE },
-	{ TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_GPIO },
-	{ TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_INTBR },
-	{ TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_PIH },
-	{ TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_TEST },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_KEYPAD },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_MADC },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_INTERRUPTS },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_LED },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_MAIN_CHARGE },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PRECHARGE },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWM0 },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWM1 },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWMA },
-	{ TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWMB },
-	{ TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_BACKUP },
-	{ TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_INT },
-	{ TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_PM_MASTER },
-	{ TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_PM_RECIEVER },
-	{ TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_RTC },
-	{ TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_SECURED_REG },
+	{TWL4030_SLAVENUM_NUM0,
+	 TWL4030_BASEADD_USB /* TWL4030_MODULE_USB        */ },
+
+	{TWL4030_SLAVENUM_NUM1,
+	 TWL4030_BASEADD_AUDIO_VOICE /* TWL4030_MODULE_AUDIO_VOICE */ },
+	{TWL4030_SLAVENUM_NUM1,
+	 TWL4030_BASEADD_GPIO /* TWL4030_MODULE_GPIO       */ },
+	{TWL4030_SLAVENUM_NUM1,
+	 TWL4030_BASEADD_INTBR /* TWL4030_MODULE_INTBR      */ },
+	{TWL4030_SLAVENUM_NUM1,
+	 TWL4030_BASEADD_PIH /* TWL4030_MODULE_PIH        */ },
+	{TWL4030_SLAVENUM_NUM1,
+	 TWL4030_BASEADD_TEST /* TWL4030_MODULE_TEST       */ },
+
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_KEYPAD /* TWL4030_MODULE_KEYPAD     */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_MADC /* TWL4030_MODULE_MADC       */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_INTERRUPTS /* TWL4030_MODULE_INTERRUPTS */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_LED /* TWL4030_MODULE_LED        */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_MAIN_CHARGE /* TWL4030_MODULE_MAIN_CHARGE */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_PRECHARGE /* TWL4030_MODULE_PRECHARGE  */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_PWM0 /* TWL4030_MODULE_PWM0       */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_PWM1 /* TWL4030_MODULE_PWM1       */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_PWMA /* TWL4030_MODULE_PWMA       */ },
+	{TWL4030_SLAVENUM_NUM2,
+	 TWL4030_BASEADD_PWMB /* TWL4030_MODULE_PWMB       */ },
+
+	{TWL4030_SLAVENUM_NUM3,
+	 TWL4030_BASEADD_BACKUP /* TWL4030_MODULE_BACKUP     */ },
+	{TWL4030_SLAVENUM_NUM3,
+	 TWL4030_BASEADD_INT /* TWL4030_MODULE_INT        */ },
+	{TWL4030_SLAVENUM_NUM3,
+	 TWL4030_BASEADD_PM_MASTER /* TWL4030_MODULE_PM_MASTER  */ },
+	{TWL4030_SLAVENUM_NUM3,
+	 TWL4030_BASEADD_PM_RECIEVER /* TWL4030_MODULE_PM_RECIEVER */ },
+	{TWL4030_SLAVENUM_NUM3,
+	 TWL4030_BASEADD_RTC /* TWL4030_MODULE_RTC        */ },
+	{TWL4030_SLAVENUM_NUM3,
+	 TWL4030_BASEADD_SECURED_REG /* TWL4030_MODULE_SECURED_REG */ },
 };
 
 static struct twl4030_client twl4030_modules[TWL4030_NUM_SLAVES] = {
 	{
-		.address	= TWL4030_SLAVEID_ID0,
-		.client_name	= TWL_CLIENT_STRING "0",
-		.adapter_index	= CONFIG_I2C_TWL4030_ID,
-	},
+	 .address = TWL4030_SLAVEID_ID0,
+	 .client_name = TWL_CLIENT_STRING "0",
+	 .adapter_index = CONFIG_I2C_TWL4030_ID0,},
 	{
-		.address	= TWL4030_SLAVEID_ID1,
-		.client_name	= TWL_CLIENT_STRING "1",
-		.adapter_index	= CONFIG_I2C_TWL4030_ID,
-	},
+	 .address = TWL4030_SLAVEID_ID1,
+	 .client_name = TWL_CLIENT_STRING "1",
+	 .adapter_index = CONFIG_I2C_TWL4030_ID1,},
 	{
-		.address	= TWL4030_SLAVEID_ID2,
-		.client_name	= TWL_CLIENT_STRING "2",
-		.adapter_index	= CONFIG_I2C_TWL4030_ID,
-	},
+	 .address = TWL4030_SLAVEID_ID2,
+	 .client_name = TWL_CLIENT_STRING "2",
+	 .adapter_index = CONFIG_I2C_TWL4030_ID2,},
 	{
-		.address	= TWL4030_SLAVEID_ID3,
-		.client_name	= TWL_CLIENT_STRING "3",
-		.adapter_index	= CONFIG_I2C_TWL4030_ID,
-	},
+	 .address = TWL4030_SLAVEID_ID3,
+	 .client_name = TWL_CLIENT_STRING "3",
+	 .adapter_index = CONFIG_I2C_TWL4030_ID3,},
 };
 
 /* One Client Driver , 4 Clients */
 static struct i2c_driver twl4030_driver = {
-	.driver.name	= "TWL4030 I2C",
-	.attach_adapter	= twl4030_attach_adapter,
-	.detach_client	= twl4030_detach_client,
+	.driver.name = "TWL4030 I2C",
+	.attach_adapter = twl4030_attach_adapter,
+	.detach_client = twl4030_detach_client,
 };
 
-/*
- * TWL4030 doesn't have PIH mask, hence dummy function for mask
+/* unique client id */
+static unsigned int twl4030_id;
+
+/* TWL4030 doesn't have PIH mask,
+ * hence dummy function for mask
  * and unmask.
  */
 
-static void twl4030_i2c_ackirq(unsigned int irq) {}
-static void twl4030_i2c_disableint(unsigned int irq) {}
-static void twl4030_i2c_enableint(unsigned int irq) {}
+static void twl4030_i2c_ackirq(unsigned int irq){
+	FN_IN;
+	FN_OUT(0);
+}	
+
+static void twl4030_i2c_disableint(unsigned int irq){
+	FN_IN;
+	FN_OUT(0);
+}
 
+static void twl4030_i2c_enableint(unsigned int irq){
+	FN_IN;
+	FN_OUT(0);
+}	
+	
 /* information for processing in the Work Item */
 static struct irq_chip twl4030_irq_chip = {
-	.ack	= twl4030_i2c_ackirq,
-	.mask	= twl4030_i2c_disableint,
-	.unmask	= twl4030_i2c_enableint,
+	.ack = twl4030_i2c_ackirq,
+	.mask = twl4030_i2c_disableint,
+	.unmask = twl4030_i2c_enableint,
 };
 
-/* Global Functions */
-/*
- * @brief twl4030_i2c_write - Writes a n bit register in TWL4030
+/**** Global Functions */
+/**
+ * @brief twl4030_i2c_write - Writes a n bit register in  TWL4030
  *
  * @param mod_no - module number
  * @param *value - an array of num_bytes+1 containing data to write
  * IMPORTANT - Allocate value num_bytes+1 and valid data starts at
- *		 Offset 1.
+ *             Offset 1.
  * @param reg - register address (just offset will do)
  * @param num_bytes - number of bytes to transfer
  *
@@ -255,9 +627,10 @@ int twl4030_i2c_write(u8 mod_no, u8 * va
 	int sid;
 	struct twl4030_client *client;
 	struct i2c_msg *msg;
-
+	FN_IN;
 	if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
 		printk(KERN_ERR "TWL4030: Invalid module Number\n");
+		FN_OUT(EPERM);
 		return -EPERM;
 	}
 	sid = twl4030_map[mod_no].sid;
@@ -265,33 +638,38 @@ int twl4030_i2c_write(u8 mod_no, u8 * va
 
 	if (unlikely(client->inuse != TWL_CLIENT_USED)) {
 		printk(KERN_ERR
-			"TWL4030: I2C Client[%d] is not initialized[%d]\n",
-			sid, __LINE__);
+		       "TWL4030: I2C Client[%d] is not initialized[%d]\n", sid,
+		       __LINE__);
+		FN_OUT(EPERM);
 		return -EPERM;
 	}
 	down(&(client->xfer_lock));
-	/*
-	 * [MSG1]: fill the register address data
-	 * fill the data Tx buffer
+	/* [MSG1]: fill the register address data 
+	 * fill the data Tx buffer 
 	 */
 	msg = &(client->xfer_msg[0]);
 	msg->addr = client->address;
-	msg->len = num_bytes + 1;
-	msg->flags = 0;
+	if ((client->client.flags & I2C_M_HS) == I2C_M_HS)
+		/* DO HS Mode transfer */
+		msg->flags = I2C_M_WR | I2C_M_HS;	/* write the register value */
+	else
+		msg->flags = I2C_M_WR;	/* write the register value */
+	
+	msg->len = num_bytes + 1;	/* only one value */
 	msg->buf = value;
 	/* over write the first byte of buffer with the register address */
 	*value = twl4030_map[mod_no].base + reg;
-	ret = i2c_transfer(client->client.adapter, client->xfer_msg, 1);
+	ret = i2c_transfer(client->client.adapter, client->xfer_msg, 1);	/* one message */
 	up(&(client->xfer_lock));
-
 	/* i2cTransfer returns num messages.translate it pls.. */
-	if (ret >= 0)
-		ret = 0;
+	if (ret>=0)
+		ret=0;
+	FN_OUT(ret);
 	return ret;
 }
 
 /**
- * @brief twl4030_i2c_read - Reads a n bit register in TWL4030
+ * @brief twl4030_i2c_read - Reads a n bit register in  TWL4030
  *
  * @param mod_no - module number
  * @param *value - an array of num_bytes containing data to be read
@@ -307,8 +685,10 @@ int twl4030_i2c_read(u8 mod_no, u8 * val
 	int sid;
 	struct twl4030_client *client;
 	struct i2c_msg *msg;
+	FN_IN;
 	if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
 		printk(KERN_ERR "TWL4030: Invalid module Number\n");
+		FN_OUT(EPERM);
 		return -EPERM;
 	}
 	sid = twl4030_map[mod_no].sid;
@@ -316,34 +696,43 @@ int twl4030_i2c_read(u8 mod_no, u8 * val
 
 	if (unlikely(client->inuse != TWL_CLIENT_USED)) {
 		printk(KERN_ERR
-			"TWL4030: I2C Client[%d] is not initialized[%d]\n",
-			sid, __LINE__);
+		       "TWL4030: I2C Client[%d] is not initialized[%d]\n", sid,
+		       __LINE__);
+		FN_OUT(EPERM);
 		return -EPERM;
 	}
 	down(&(client->xfer_lock));
 	/* [MSG1] fill the register address data */
 	msg = &(client->xfer_msg[0]);
 	msg->addr = client->address;
-	msg->len = 1;
+	if ((client->client.flags & I2C_M_HS) == I2C_M_HS)
+		msg->flags = I2C_M_WR | I2C_M_HS;	/* Read the register value in HS mode */
+	else
+		msg->flags = I2C_M_WR;	/* Read the register value */
+
+	msg->len = 1;		/* only one value */
 	val = twl4030_map[mod_no].base + reg;
 	msg->buf = &val;
 	/* [MSG2] fill the data rx buffer */
 	msg = &(client->xfer_msg[1]);
 	msg->addr = client->address;
-	msg->flags = I2C_M_RD;	/* Read the register value */
+	if ((client->client.flags & I2C_M_HS) == I2C_M_HS)
+		msg->flags = I2C_M_RD | I2C_M_HS;	/* Read the register value in HS mode */
+	else
+		msg->flags = I2C_M_RD;	/* Read the register value */
 	msg->len = num_bytes;	/* only n bytes */
 	msg->buf = value;
-	ret = i2c_transfer(client->client.adapter, client->xfer_msg, 2);
+	ret = i2c_transfer(client->client.adapter, client->xfer_msg, 2);	/* two messages */
 	up(&(client->xfer_lock));
-
 	/* i2cTransfer returns num messages.translate it pls.. */
-	if (ret >= 0)
-		ret = 0;
+	if (ret>=0)
+		ret=0;
+	FN_OUT(ret);
 	return ret;
 }
 
 /**
- * @brief twl4030_i2c_write_u8 - Writes a 8 bit register in TWL4030
+ * @brief twl4030_i2c_write_u8 - Writes a 8 bit register in  TWL4030
  *
  * @param mod_no - module number
  * @param value - the value to be written 8 bit
@@ -355,10 +744,12 @@ int twl4030_i2c_write_u8(u8 mod_no, u8 v
 {
 	int ret;
 	/* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */
-	u8 temp_buffer[2] = { 0 };
+	u8 temp_buffer[2]={0};
+	FN_IN;
 	/* offset 1 contains the data */
-	temp_buffer[1] = value;
-	ret = twl4030_i2c_write(mod_no, temp_buffer, reg, 1);
+	temp_buffer[1]=value;
+	ret = twl4030_i2c_write(mod_no,temp_buffer,reg,1) ;
+	FN_OUT(ret);
 	return ret;
 }
 
@@ -373,15 +764,17 @@ int twl4030_i2c_write_u8(u8 mod_no, u8 v
  */
 int twl4030_i2c_read_u8(u8 mod_no, u8 * value, u8 reg)
 {
-	int ret = 0;
-	ret = twl4030_i2c_read(mod_no, value, reg, 1);
+	int ret=0;
+	FN_IN;
+	ret = twl4030_i2c_read(mod_no,value,reg,1);
+	FN_OUT(ret);
 	return ret;
 }
 
 /**** Helper Functions */
 
 /*
- * do_twl4030_module_irq() is the desc->handle method for each of the twl4030
+ * do_twl4030_module_irq() is the desc->handle method for each of the twl4030 
  * module interrupts.  It executes in kernel thread context.
  * On entry, cpu interrupts are disabled.
  */
@@ -390,13 +783,10 @@ static void do_twl4030_module_irq(unsign
 	struct irqaction *action;
 	const unsigned int cpu = smp_processor_id();
 
-	/*
-	 * Earlier this was desc->triggered = 1;
-	 */
-	desc->status = IRQ_INPROGRESS;
+	desc->status |= IRQ_LEVEL;
 
 	/*
-	 * The desc->handle method would normally call the desc->chip->ack
+	 * The desc->handle method would normally call the desc->chip->ack 
 	 * method here, but we won't bother since our ack method is NULL.
 	 */
 
@@ -409,71 +799,87 @@ static void do_twl4030_module_irq(unsign
 			int status = 0;
 			int retval = 0;
 
+			//desc->status |= IRQ_INPROGRESS;
+
 			local_irq_enable();
 
 			do {
-				/* Call the ISR with cpu interrupts enabled */
+				/* Call the ISR with cpu interrupts enabled. */
 				ret = action->handler(irq, action->dev_id);
 				if (ret == IRQ_HANDLED)
 					status |= action->flags;
 				retval |= ret;
 				action = action->next;
 			} while (action);
-
-			if (status & IRQF_SAMPLE_RANDOM)
+		
+			if (status & SA_SAMPLE_RANDOM)
 				add_interrupt_randomness(irq);
-
+	
 			local_irq_disable();
 
-			if (retval != IRQ_HANDLED)
+			if (retval != IRQ_HANDLED) {
 				printk(KERN_ERR "ISR for TWL4030 module"
-					" irq %d can't handle interrupt\n", irq);
+					" irq %d can't handle interrupt\n", 
+					irq);
+			}
 
 			/*
-			 * Here is where we should call the unmask method, but
+			 * Here is where we should call the unmask method, but 
 			 * again we won't bother since it is NULL.
 			 */
-		} else
+		} else {
 			printk(KERN_CRIT "TWL4030 module irq %d has no ISR"
-					" but can't be masked!\n", irq);
-	} else
+				" but can't be masked!\n", irq);
+		}
+		//desc->status &= ~IRQ_INPROGRESS;
+	} else {
 		printk(KERN_CRIT "TWL4030 module irq %d is disabled but can't"
-				" be masked!\n", irq);
+			" be masked!\n", irq);
+	}
 }
 
 /*
- * twl4030_irq_thread() runs as a kernel thread.  It queries the twl4030
- * interrupt controller to see which modules are generating interrupt requests
+ * twl4030_irq_thread() runs as a kernel thread.  It queries the twl4030 
+ * interrupt controller to see which modules are generating interrupt requests 
  * and then calls the desc->handle method for each module requesting service.
  */
 static int twl4030_irq_thread(void *data)
 {
-	int irq = (int)data;
+	struct sched_param param;
+	int irq = (int) data;
 	irq_desc_t *desc = irq_desc + irq;
 	static unsigned i2c_errors;
 	const static unsigned max_i2c_errors = 100;
 
+	daemonize("twl4030-irq");
+
+	current->flags |= PF_NOFREEZE;
+
+	param.sched_priority = CONFIG_TWL4030_IRQ_PRIO;
+	sys_sched_setscheduler(current->pid, SCHED_FIFO, &param);
+
 	while (!kthread_should_stop()) {
 		int ret;
 		int module_irq;
 		u8 pih_isr;
 
-		ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
-					  REG_PIH_ISR_P1);
+		ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr, 
+			REG_PIH_ISR_P1);
 		if (ret) {
 			printk(KERN_WARNING "I2C error %d while reading TWL4030"
-					" PIH ISR register.\n", ret);
+				" PIH ISR register.\n", ret);
 			if (++i2c_errors >= max_i2c_errors) {
 				printk(KERN_ERR "Maximum I2C error count"
-						" exceeded.  Terminating %s.\n",
-						__FUNCTION__);
+					" exceeded.  Terminating %s.\n", 
+					__FUNCTION__);
 				break;
 			}
 			continue;
 		}
 
-		for (module_irq = IH_TWL4030_BASE; 0 != pih_isr;
-			 pih_isr >>= 1, module_irq++) {
+		for (module_irq = IH_TWL4030_BASE; 0 != pih_isr; 
+			pih_isr >>= 1, module_irq++)
+		{
 			if (pih_isr & 0x1) {
 				irq_desc_t *d = irq_desc + module_irq;
 
@@ -487,6 +893,7 @@ static int twl4030_irq_thread(void *data
 
 		local_irq_disable();
 
+		//desc->status &= ~IRQ_INPROGRESS;
 		set_current_state(TASK_INTERRUPTIBLE);
 		desc->chip->unmask(irq);
 
@@ -501,21 +908,18 @@ static int twl4030_irq_thread(void *data
 /*
  * do_twl4030_irq() is the desc->handle method for the twl4030 interrupt.
  * This is a chained interrupt, so there is no desc->action method for it.
- * Now we need to query the interrupt controller in the twl4030 to determine
- * which module is generating the interrupt request.  However, we can't do i2c
- * transactions in interrupt context, so we must defer that work to a kernel
- * thread.  All we do here is acknowledge and mask the interrupt and wakeup
+ * Now we need to query the interrupt controller in the twl4030 to determine 
+ * which module is generating the interrupt request.  However, we can't do i2c 
+ * transactions in interrupt context, so we must defer that work to a kernel 
+ * thread.  All we do here is acknowledge and mask the interrupt and wakeup 
  * the kernel thread.
  */
 static void do_twl4030_irq(unsigned int irq, irq_desc_t *desc)
 {
 	const unsigned int cpu = smp_processor_id();
-	struct task_struct *thread = (struct task_struct *)desc->chip_data;
+	struct task_struct *thread = get_irq_data(irq);
 
-	/*
-	 * Earlier this was desc->triggered = 1;
-	 */
-	desc->status = IRQ_INPROGRESS;
+	desc->status |= IRQ_LEVEL;	
 
 	/*
 	 * Acknowledge, clear _AND_ disable the interrupt.
@@ -525,6 +929,8 @@ static void do_twl4030_irq(unsigned int 
 	if (!desc->depth) {
 		kstat_cpu(cpu).irqs[irq]++;
 
+		//desc->status |= IRQ_INPROGRESS;
+
 		if (thread && thread->state != TASK_RUNNING)
 			wake_up_process(thread);
 	}
@@ -535,46 +941,54 @@ static int twl4030_detect_client(struct 
 {
 	int err = 0;
 	struct twl4030_client *client;
+
+	FN_IN;
 	if (unlikely(sid >= TWL4030_NUM_SLAVES)) {
 		printk(KERN_ERR "TWL4030: sid[%d] >MOD_LAST[%d]\n", sid,
-				TWL4030_NUM_SLAVES);
+		       TWL4030_NUM_SLAVES);
+		FN_OUT(EPERM);
 		return -EPERM;
 	}
 
 	/* Check basic functionality */
 	if (!(err = i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA |
-						I2C_FUNC_SMBUS_WRITE_BYTE))) {
+					    I2C_FUNC_SMBUS_WRITE_BYTE))) {
 		printk(KERN_WARNING
-			"TWL4030: SlaveID=%d functionality check failed\n", sid);
+		       "TWL4030: SlaveID=%d functionality check failed\n", sid);
+		FN_OUT(err);
 		return err;
 	}
 	client = &(twl4030_modules[sid]);
 	if (unlikely(client->inuse)) {
 		printk(KERN_ERR "TWL4030: Client is already in Use.....\n");
 		printk("%s[ID=0x%x] NOT attached to I2c Adapter %s\n",
-			client->client_name, client->address, adapter->name);
+		       client->client_name, client->address, adapter->name);
+		FN_OUT(EPERM);
 		return -EPERM;
 	}
 
 	memset(&(client->client), 0, sizeof(struct i2c_client));
 
-	client->client.addr	= client->address;
-	client->client.adapter	= adapter;
-	client->client.driver	= &twl4030_driver;
-
+	client->client.addr = client->address;
+	client->client.adapter = adapter;
+	client->client.driver = &twl4030_driver;
+	if ((adapter->flags & I2C_FUNC_HIGH_SPEED) == I2C_FUNC_HIGH_SPEED) {
+		client->client.flags = I2C_M_HS;	/* We are HS capable */
+	} 
 	memcpy(&(client->client.name), client->client_name,
-			sizeof(TWL_CLIENT_STRING) + 1);
-	printk("TWL4030: TRY attach Slave %s on Adapter %s[%d][%x]\n",
-				client->client_name, adapter->name, err, err);
-	if ((err = i2c_attach_client(&(client->client))))
+	       sizeof(TWL_CLIENT_STRING) + 1);
+//XXX	client->client.data = (void *)client;
+	if ((err = i2c_attach_client(&(client->client)))) {
 		printk(KERN_WARNING
-			"TWL4030: Couldn't attach Slave %s on Adapter "
-			"%s[%d][%x]\n",
-			client->client_name, adapter->name, err, err);
-	else {
+		       "TWL4030: Couldn't attach Slave %s on Adapter %s[%d][%x]\n",
+		       client->client_name, adapter->name, err, err);
+	} else {
+		D1( "TWL4030: %s[ID=0x%x] attached to I2c Adapter %s\n",
+		       client->client_name, client->address, adapter->name);
 		client->inuse = TWL_CLIENT_USED;
 		init_MUTEX(&client->xfer_lock);
 	}
+	FN_OUT(err);
 	return err;
 }
 
@@ -583,40 +997,43 @@ static int twl4030_attach_adapter(struct
 {
 	int i;
 	int ret = 0;
-	static int twl_i2c_adapter = 1;
+	static int twl_i2c_adapter = 0;
+	FN_IN;
 	for (i = 0; i < TWL4030_NUM_SLAVES; i++) {
 		/* Check if I need to hook on to this adapter or not */
 		if (twl4030_modules[i].adapter_index == twl_i2c_adapter) {
-			if ((ret = twl4030_detect_client(adapter, i)))
+			if ((ret = twl4030_detect_client(adapter, i))) {
 				goto free_client;
+			}
 		}
 	}
 	twl_i2c_adapter++;
 
-	/*
-	 * Check if the PIH module is initialized, if yes, then init
+	/* Check if the PIH module is initialized, if yes, then init
 	 * the T2 Interrupt subsystem
 	 */
 	if ((twl4030_modules[twl4030_map[TWL4030_MODULE_PIH].sid].inuse ==
-		TWL_CLIENT_USED) && (twl_irq_used != USED)) {
+	     TWL_CLIENT_USED) && (twl_irq_used != USED)) {
 		twl_init_irq();
 		twl_irq_used = USED;
 	}
+	FN_OUT(0);
 	return 0;
-
-free_client:
+      free_client:
 	printk(KERN_ERR
-		"TWL4030: TWL_CLIENT(Idx=%d] REGISTRATION FAILED=%d[0x%x]\n", i,
-			ret, ret);
-
+	       "TWL4030: TWL_CLIENT(Idx=%d] REGISTRATION FAILED=%d[0x%x]\n", i,
+	       ret, ret);
 	/* ignore current slave..it never got registered */
 	i--;
 	while (i >= 0) {
 		/* now remove all those from the current adapter... */
-		if (twl4030_modules[i].adapter_index == twl_i2c_adapter)
-			(void)twl4030_detach_client(&(twl4030_modules[i].client));
+		if (twl4030_modules[i].adapter_index == twl_i2c_adapter) {
+			(void)
+			    twl4030_detach_client(&(twl4030_modules[i].client));
+		}
 		i--;
 	}
+	FN_OUT(ret);
 	return ret;
 }
 
@@ -624,71 +1041,83 @@ free_client:
 static int twl4030_detach_client(struct i2c_client *iclient)
 {
 	int err;
+	//XXX struct twl4030_client *client = (struct twl4030_client *)iclient->data;
+	FN_IN;
 	if ((err = i2c_detach_client(iclient))) {
 		printk(KERN_ERR
-				"TWL4030: Client deregistration failed, client not detached.\n");
+		       "TWL4030: Client deregistration failed, client not detached.\n");
+		FN_OUT(err);
 		return err;
 	}
+
+	/* Free 'em up */
+	//XXX client->inuse = TWL_CLIENT_FREE;
+	FN_OUT(0);
+
 	return 0;
 }
 
-struct task_struct *start_twl4030_irq_thread(int irq)
+struct task_struct *
+start_twl4030_irq_thread(int irq)
 {
 	struct task_struct *thread;
 
-	thread = kthread_create(twl4030_irq_thread, (void *)irq,
-				"twl4030 irq %d", irq);
-	if (!thread)
-		printk(KERN_ERR "%s: could not create twl4030 irq %d thread!\n",
+	thread = kthread_create(twl4030_irq_thread, (void *) irq, 
+			"twl4030-irq");
+	if (!thread) {
+		printk(KERN_ERR 
+			"%s: could not create twl4030 irq %d thread!\n", 
 			__FUNCTION__, irq);
+	}
 
 	return thread;
 }
 
 /*
- * These three functions should be part of Voltage frame work
- * added here to complete the functionality for now.
- */
+ *  * These three functions should be part of Voltage frame work
+ *   * added here to complete the functionality for now.
+ *    */
 static int protect_pm_master(void)
 {
-	int e = 0;
-	e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK,
-			R_PROTECT_KEY);
-	return e;
+        int e = 0;
+        e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK,
+		                        R_PROTECT_KEY);
+        return e;
 }
 
 static int unprotect_pm_master(void)
 {
-	int e = 0;
-	e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1,
-			R_PROTECT_KEY);
-	e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2,
-			R_PROTECT_KEY);
-	return e;
+        int e = 0;
+        e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1,
+			                        R_PROTECT_KEY);
+        e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2,
+			                        R_PROTECT_KEY);
+        return e;
 }
 
 int power_companion_init(void)
 {
-	struct clk *osc;
-	u32 rate, ctrl = HFCLK_FREQ_26_MHZ;
-	int e = 0;
+        struct clk *osc;
+        u32 rate, ctrl = HFCLK_FREQ_26_MHZ;
+        int e = 0;
 
 	osc = clk_get(NULL,"osc_ck");
-	rate = clk_get_rate(osc);
-	clk_put(osc);
+        rate = clk_get_rate(osc);
+        clk_put(osc);
 
 	switch(rate) {
-		case 19200000 : ctrl = HFCLK_FREQ_19p2_MHZ; break;
-		case 26000000 : ctrl = HFCLK_FREQ_26_MHZ; break;
-		case 38400000 : ctrl = HFCLK_FREQ_38p4_MHZ; break;
-	}
+                case 19200000 : ctrl = HFCLK_FREQ_19p2_MHZ; break;
+                case 26000000 : ctrl = HFCLK_FREQ_26_MHZ; break;
+                case 38400000 : ctrl = HFCLK_FREQ_38p4_MHZ; break;
+        }
 
 	ctrl |= HIGH_PERF_SQ;
-	e |= unprotect_pm_master();
-			/* effect->MADC+USB ck en */
-	e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT);
-	e |= protect_pm_master();
-
+       	e |= unprotect_pm_master();
+       
+	/* effect->MADC+USB ck en */
+        e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT);
+        e |= protect_pm_master();
+	
 	return e;
 }
 
@@ -697,206 +1126,373 @@ static void twl_init_irq(void)
 	int i = 0;
 	int res = 0;
 	int line = 0;
-	/*
-	 * We end up with interrupts from other modules before
+	FN_IN;
+
+	/* We end up with interrupts from other modules before
 	 * they get a chance to handle them...
 	 */
-	/* PWR_ISR1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);
+	/* HACK ALERT - No Body to handle power ISR yet... */
+	/* POWER HACK (BEGIN) */
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);	/* PWR_ISR1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* PWR_ISR2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);	/* PWR_ISR2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* PWR_IMR1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x1);
+	/* MASK PWR -we will need this */
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x1);	/* PWR_IMR1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* PWR_IMR2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x3);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x3);	/* PWR_IMR2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
 	/* Clear off any other pending interrupts on power */
-	/* PWR_ISR1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);	/* PWR_ISR1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* PWR_ISR2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);	/* PWR_ISR2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
 	/* POWER HACK (END) */
 	/* Slave address 0x4A */
-
-	/* BCIIMR1_1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x3);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x3);	/* BCIIMR1_1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* BCIIMR1_2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x4);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x4);	/* BCIIMR1_2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* BCIIMR2_1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x7);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x7);	/* BCIIMR2_1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* BCIIMR2_2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x8);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x8);	/* BCIIMR2_2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
 	/* MAD C */
-	/* MADC_IMR1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x62);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x62);	/* MADC_IMR1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* MADC_IMR2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x64);
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x64);	/* MADC_IMR2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
 	/* key Pad */
-	/* KEYPAD - IMR1 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xFF, (0x12));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xFF, (0x12));	/* KEYPAD - IMR1 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-	{
-		u8 clear;
-		/* Clear ISR */
-		twl4030_i2c_read_u8(TWL4030_MODULE_KEYPAD, &clear, 0x11);
-		twl4030_i2c_read_u8(TWL4030_MODULE_KEYPAD, &clear, 0x11);
-	}
-
-	/* KEYPAD - IMR2 */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xFF, (0x14));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xFF, (0x14));	/* KEYPAD - IMR2 */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
 
 	/* Slave address 0x49 */
-	/* GPIO_IMR1A */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1C));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1C));	/* GPIO_IMR1A */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
 
-	/* GPIO_IMR2A */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1D));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1D));	/* GPIO_IMR2A */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
 
-	/* GPIO_IMR3A */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1E));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1E));	/* GPIO_IMR3A */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* GPIO_IMR1B */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x22));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x22));	/* GPIO_IMR1B */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* GPIO_IMR2B */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x23));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x23));	/* GPIO_IMR2B */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
-
-	/* GPIO_IMR3B */
-	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x24));
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x24));	/* GPIO_IMR3B */
 	if (res < 0) {
 		line = __LINE__;
 		goto irq_exit_path;
 	}
 
 	/* install an irq handler for each of the PIH modules */
-	for (i = IH_TWL4030_BASE; i < IH_TWL4030_END; i++) {
-		set_irq_chip(i, &twl4030_irq_chip);
-		set_irq_handler(i, do_twl4030_module_irq);
-		set_irq_flags(i, IRQF_VALID);
+	for (i = IH_TWL4030_BASE; i <= IH_TWL4030_END; i++) {
+			set_irq_chip(i, &twl4030_irq_chip);
+			set_irq_handler(i, do_twl4030_module_irq);
+			set_irq_flags(i, IRQF_VALID);
 	}
 
 	/* install an irq handler to demultiplex the TWL4030 interrupt */
 	set_irq_data(TWL4030_IRQNUM, start_twl4030_irq_thread(TWL4030_IRQNUM));
-	set_irq_type(TWL4030_IRQNUM, IRQT_FALLING);
 	set_irq_chained_handler(TWL4030_IRQNUM, do_twl4030_irq);
+	
+	power_companion_init();  /* finish power and clock init */
 
-	res = power_companion_init();
-	if (res < 0) {
-		line = __LINE__;
-		goto irq_exit_path;
-	}
-
-irq_exit_path:
-	if (res)
+      irq_exit_path:
+	if (res) {
 		printk(KERN_ERR
-			"TWL4030: Unable to register interrupt "
-			"subsystem[%d][%d]\n", res, line);
+		       "TWL4030: Unable to register interrupt subsystem[%d][%d]\n",
+		       res, line);
+	}
+	FN_OUT(res);
 }
 
 static int __init twl4030_init(void)
 {
 	int res;
-	if ((res = i2c_register_driver(THIS_MODULE, &twl4030_driver))) {
-		printk(KERN_ERR "TWL4030: Driver registration failed \n");
+	FN_IN;
+
+	if ((res = i2c_add_driver(&twl4030_driver))) {
+		printk(KERN_ERR
+		       "TWL4030: Driver registration failed, module not inserted.\n");
+		FN_OUT(res);
 		return res;
 	}
+#if (TWL4030_LOG_LEVEL >= 1)
+	{
+		/* debug dump */
+		int mod = 0;
+		for (mod = 0; mod <= TWL4030_MODULE_LAST; mod++) {
+			u8 sid = twl4030_map[mod].sid;
+			u8 sadd = twl4030_modules[sid].address;
+			printk
+			    ("W8 - mod=%d[0x%x], sid=%d[0x%x] sad=%d[0x%x], modRegBaseAdd=%d[0x%x] \n",
+			     mod, mod, sid, sid, sadd, sadd,
+			     twl4030_map[mod].base, twl4030_map[mod].base);
+		}
+	}
+#endif
+
+#ifdef CONFIG_I2C_TWL4030_DBG_SYSFS
+	{
+		int ret = 0;
+		/* A dummy device */
+		ret = platform_device_register(&twl4030_debug_dev);
+		if (ret != 0) {
+			printk(KERN_ERR "Platform dev_register failed =%d\n", ret);
+			ret = -ENODEV;
+		} else {
+			TWL_SYS_DEV();
+		}
+	}
+#endif
+
+#ifdef CONFIG_SOUND_SERVICES_ENABLE
+
+	twl4030_sndsrv_set_dtcyl(CONFIG_SOUND_SERVICES_DUTY_CYL);
+
+#endif 
+
 	printk(KERN_INFO "TWL4030: Driver registration complete.\n");
+	FN_OUT(res);
 	return res;
 }
 
 static void __exit twl4030_exit(void)
 {
-	if (i2c_del_driver(&twl4030_driver))
+	FN_IN;
+	if (i2c_del_driver(&twl4030_driver)) {
 		printk(KERN_ERR
-			"TWL4030: Driver remove failed, module not removed\n");
+		       "TWL4030: Driver remove failed, module not removed.\n");
+	}
 	twl_irq_used = FREE;
+
+	FN_OUT(0);
+}
+
+#ifdef CONFIG_SOUND_SERVICES_ENABLE
+
+/* Sound Services API's functions*/
+/* this fuction handles the vibrator*/
+
+/*Turns the vibrator ON
+ * returns -EPERM if something fails
+ * or 0 if it succeeds */
+int twl4030_sndsrv_on(void)
+{
+	int res;
+	u8 RdReg;
+
+	/*TURNING ON VIBRATOR*/	
+	res = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECIEVER, &RdReg, VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to read VIBRATOR_CFG \n");
+		return -EPERM;
+	}	
+	
+	RdReg |= 0x0C;	
+	
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, RdReg, VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to write VIBRATOR_CFG \n");
+		return -EPERM;
+	}
+	
+	/*TURNING ON VAUX1*/
+	RdReg = VAUX1_ON;
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, RdReg, VAUX1_REMAP_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to write VAUX1_REMAP \n");
+		return -EPERM;
+	}
+		
+	return 0;
 }
 
+/*Turns the vibrator OFF 
+ * returns -EPERM if something fails
+ * or 0 if it succeeds */
+int twl4030_sndsrv_off(void)
+{
+	int res;
+	u8 RdReg;
+	
+	/*TURNING OFF VAUX1*/
+	RdReg = VAUX1_OFF;
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, RdReg, VAUX1_REMAP_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to write VAUX1_REMAP \n");
+		return -EPERM;
+	}
+		
+	/*TURNING OFF VIBRATOR*/	
+	res = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECIEVER, &RdReg, VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to read VIBRATOR_CFG \n");
+		return -EPERM;
+	}	
+	
+	RdReg &= 0x03;	
+	
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, RdReg, VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to write VIBRATOR_CFG \n");
+		return -EPERM;
+	}
+	
+	return 0;	
+}
+
+/*Returns the vibrator status
+ * 0 if vibrator is OFF
+ * 1 if it is ON
+ * or -EPERM if somethings fails*/
+int twl4030_sndsrv_status(void)
+{
+	int res;
+	u8 RdReg;
+	
+	/* VAUX1_DEV_GRP*/
+	res = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECIEVER, &RdReg , VAUX1_DEV_GRP_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to read VAUX1_DEV_GRP \n");
+		return -EPERM;
+	}
+	
+	RdReg &= 0x0F;
+	
+	if (RdReg > 0x0E || RdReg < 0x09){
+		return 0;
+	}
+	return 1;
+}
+
+/*Configures the vibrators duty cycle
+ * @param duty_cycle - the duty cycle for the sound services PWM,
+ * 					  interms of: 
+ * 								0x00 - 100 %
+ * 								0x01 - 75%
+ * 								0x02 - 50%
+ * 								0x03 - 25%
+ * 
+ * retunrs 0 if it success
+ * or -EPERM if somethings fails*/
+int twl4030_sndsrv_set_dtcyl(u8 duty_cycle)
+{
+	int res;
+	u8 RdReg;
+	
+	if (duty_cycle & 0xFC){
+		printk(KERN_ERR "SOUND SERVICES: Wrong value for Vibrator Duty cycle \n");
+		return -EPERM;
+	}
+	
+	/*Reading  VIBRATOR_CFG*/
+	res = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECIEVER, &RdReg , VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to read VIBRATOR_CFG \n");
+		return -EPERM;
+	}
+	
+	RdReg &= 0xFC;
+	RdReg += duty_cycle;
+	
+	/*writing VIBRATOR_CFG*/	
+	res = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, RdReg, VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to write VIBRATOR_CFG \n");
+		return -EPERM;
+	}	
+	
+	return 0;
+}
+
+/*Returns the vibrator duty cycle
+ * returns -EPERM if something fails*/
+
+int twl4030_sndsrv_get_dtcyl(void)
+{
+	int res;
+	u8 RdReg;
+	
+	/*Reading  VIBRATOR_CFG*/
+	res = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECIEVER, &RdReg , VIB_CFG_REG);
+	if (res < 0) {
+		printk(KERN_ERR "SOUND SERVICES: Fail to read VIBRATOR_CFG \n");
+		return -EPERM;
+	}
+	
+	return (int)RdReg & 0x03;
+	
+}
+
+EXPORT_SYMBOL(twl4030_sndsrv_on);
+EXPORT_SYMBOL(twl4030_sndsrv_off);
+EXPORT_SYMBOL(twl4030_sndsrv_status);
+EXPORT_SYMBOL(twl4030_sndsrv_set_dtcyl);
+EXPORT_SYMBOL(twl4030_sndsrv_get_dtcyl);
+
+#endif
+ 
 subsys_initcall(twl4030_init);
 module_exit(twl4030_exit);
 
diff -purN linux-omap/drivers/i2c/chips/twl4030_gpio.c lin_for_twl/drivers/i2c/chips/twl4030_gpio.c
--- linux-omap/drivers/i2c/chips/twl4030_gpio.c	1969-12-31 18:00:00.000000000 -0600
+++ lin_for_twl/drivers/i2c/chips/twl4030_gpio.c	2007-02-27 11:49:18.000000000 -0600
@@ -0,0 +1,1036 @@
+/*
+ * linux/drivers/i2c/chips/twl4030_gpio.c
+ *
+ * Copyright (C) 2006 Texas Instruments, Inc.
+ * Copyright (C) 2006 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+/*** Includes */
+#include <linux/module.h>
+#include <linux/kernel_stat.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/random.h>
+#include <linux/syscalls.h>
+#include <linux/kthread.h>
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+
+#include <asm/arch/twl4030.h>
+#include <asm/arch/irqs.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+
+#include <linux/device.h>
+
+/****************************************
+*  GPIO Block Register definitions
+****************************************/
+
+/**** Register Definitions */
+#define REG_GPIODATAIN1			(0x0)
+#define REG_GPIODATAIN2			(0x1)
+#define REG_GPIODATAIN3			(0x2)
+#define REG_GPIODATADIR1		(0x3)
+#define REG_GPIODATADIR2		(0x4)
+#define REG_GPIODATADIR3		(0x5)
+#define REG_GPIODATAOUT1		(0x6)
+#define REG_GPIODATAOUT2		(0x7)
+#define REG_GPIODATAOUT3		(0x8)
+#define REG_CLEARGPIODATAOUT1		(0x9)
+#define REG_CLEARGPIODATAOUT2		(0xA)
+#define REG_CLEARGPIODATAOUT3		(0xB)
+#define REG_SETGPIODATAOUT1		(0xC)
+#define REG_SETGPIODATAOUT2		(0xD)
+#define REG_SETGPIODATAOUT3		(0xE)
+#define REG_GPIO_DEBEN1			(0xF)
+#define REG_GPIO_DEBEN2			(0x10)
+#define REG_GPIO_DEBEN3			(0x11)
+#define REG_GPIO_CTRL			(0x12)
+#define REG_GPIOPUPDCTR1		(0x13)
+#define REG_GPIOPUPDCTR2		(0x14)
+#define REG_GPIOPUPDCTR3		(0x15)
+#define REG_GPIOPUPDCTR4		(0x16)
+#define REG_GPIOPUPDCTR5		(0x17)
+//#define REG_GPIO_TEST			(0x18)
+#define REG_GPIO_ISR1A			(0x19)
+#define REG_GPIO_ISR2A			(0x1A)
+#define REG_GPIO_ISR3A			(0x1B)
+#define REG_GPIO_IMR1A			(0x1C)
+#define REG_GPIO_IMR2A			(0x1D)
+#define REG_GPIO_IMR3A			(0x1E)
+#define REG_GPIO_ISR1B			(0x1F)
+#define REG_GPIO_ISR2B			(0x20)
+#define REG_GPIO_ISR3B			(0x21)
+#define REG_GPIO_IMR1B			(0x22)
+#define REG_GPIO_IMR2B			(0x23)
+#define REG_GPIO_IMR3B			(0x24)
+//#define REG_GPIO_SIR1			(0x25)
+//#define REG_GPIO_SIR2			(0x26)
+//#define REG_GPIO_SIR3			(0x27)
+#define REG_GPIO_EDR1			(0x28)
+#define REG_GPIO_EDR2			(0x29)
+#define REG_GPIO_EDR3			(0x2A)
+#define REG_GPIO_EDR4			(0x2B)
+#define REG_GPIO_EDR5			(0x2C)
+#define REG_GPIO_SIH_CTRL		(0x2D)
+
+/**** BitField Definitions */
+
+/***** Data banks : 3 banks for 8 gpios each */
+#define DATA_BANK_MAX			8
+#define GET_GPIO_DATA_BANK(x)		((x)/DATA_BANK_MAX)
+#define GET_GPIO_DATA_OFF(x)		((x)%DATA_BANK_MAX)
+
+/* GPIODATADIR Fields each block 0-7 */
+#define BIT_GPIODATADIR_GPIOxDIR(x)		(x)
+#define MASK_GPIODATADIR_GPIOxDIR(x)		(0x01<<(x))
+/* GPIODATAIN Fields each block 0-7 */
+#define BIT_GPIODATAIN_GPIOxIN(x)		(x)
+#define MASK_GPIODATAIN_GPIOxIN(x)		(0x01<<(x))
+/* GPIODATAOUT Fields each block 0-7 */
+#define BIT_GPIODATAOUT_GPIOxOUT(x)		(x)
+#define MASK_GPIODATAOUT_GPIOxOUT(x)		(0x01<<(x))
+/* CLEARGPIODATAOUT Fields */
+#define BIT_CLEARGPIODATAOUT_GPIOxOUT(x)	(x)
+#define MASK_CLEARGPIODATAOUT_GPIOxOUT(x)	(0x01<<(x))
+/* SETGPIODATAOUT Fields */
+#define BIT_SETGPIODATAOUT_GPIOxOUT(x)		(x)
+#define MASK_SETGPIODATAOUT_GPIOxOUT(x)		(0x01<<(x))
+/* GPIO_DEBEN Fields */
+#define BIT_GPIO_DEBEN_GPIOxDEB(x)		(x)
+#define MASK_GPIO_DEBEN_GPIOxDEB(x)		(0x01<<(x))
+/* GPIO_ISR1A Fields */
+#define BIT_GPIO_ISR_GPIOxISR(x)		(x)
+#define MASK_GPIO_ISR_GPIOxISR(x)		(0x01<<(x))
+/* GPIO_IMR1A Fields */
+#define BIT_GPIO_IMR1A_GPIOxIMR(x)		(x)
+#define MASK_GPIO_IMR1A_GPIOxIMR(x)		(0x01<<(x))
+/* GPIO_SIR1 Fields */
+#define BIT_GPIO_SIR1_GPIOxSIR(x)		(x)
+#define MASK_GPIO_SIR1_GPIO0SIR			(0x01<<(x))
+
+/**** Control banks : 5 banks for 4 gpios each */
+#define DATA_CTL_MAX			4
+#define GET_GPIO_CTL_BANK(x)		((x)/DATA_CTL_MAX)
+#define GET_GPIO_CTL_OFF(x)		((x)%DATA_CTL_MAX)
+#define GPIO_BANK_MAX			GET_GPIO_CTL_BANK(TWL4030_GPIO_MAX)
+/* GPIOPUPDCTRx Fields 5 banks of 4 gpios each */
+#define BIT_GPIOPUPDCTR1_GPIOxPD(x)	(2 *(x))
+#define MASK_GPIOPUPDCTR1_GPIOxPD(x)	(0x01<<(2*(x)))
+#define BIT_GPIOPUPDCTR1_GPIOxPU(x)	((x) + 1)
+#define MASK_GPIOPUPDCTR1_GPIOxPU(x)	(0x01<<(((2*(x)) + 1)))
+/* GPIO_EDR1 Fields */
+#define BIT_GPIO_EDR1_GPIOxFALLING(x)	(2 *(x))
+#define MASK_GPIO_EDR1_GPIOxFALLING(x)	(0x01<<(2*(x)))
+#define BIT_GPIO_EDR1_GPIOxRISING(x)	((x) + 1)
+#define MASK_GPIO_EDR1_GPIOxRISING(x)	(0x01<<(((2*(x)) + 1)))
+
+/************ Non equation fields */
+/* GPIO_SIH_CTRL Fields */
+#define BIT_GPIO_SIH_CTRL_EXCLEN	(0x000)
+#define MASK_GPIO_SIH_CTRL_EXCLEN	(0x00000001)
+#define BIT_GPIO_SIH_CTRL_PENDDIS	(0x001)
+#define MASK_GPIO_SIH_CTRL_PENDDIS	(0x00000002)
+#define BIT_GPIO_SIH_CTRL_COR		(0x002)
+#define MASK_GPIO_SIH_CTRL_COR		(0x00000004)
+
+/* GPIO_CTRL Fields */
+#define BIT_GPIO_CTRL_GPIO0CD1		(0x000)
+#define MASK_GPIO_CTRL_GPIO0CD1		(0x00000001)
+#define BIT_GPIO_CTRL_GPIO1CD2		(0x001)
+#define MASK_GPIO_CTRL_GPIO1CD2		(0x00000002)
+#define BIT_GPIO_CTRL_GPIO_ON		(0x002)
+#define MASK_GPIO_CTRL_GPIO_ON		(0x00000004)
+
+/* Mask for GPIO registers when aggregated into a 32-bit integer */
+#define GPIO_32_MASK			0x0003ffff
+
+/***** debug defines */
+/* Debug - four macros:
+ * FN_IN, FN_OUT(value),D1,D2,D3 enabled based on log level
+ */
+
+/* Log level standard used here:
+ * Log level 3 all messages
+ * Log level 2 all entry-exit points
+ * Log level 1 major messages
+ * Log level 0 no messages
+ */
+#define TWL4030_LOG_LEVEL	0 
+/* detail - 0 - no detail
+ *          1 - function name
+ *          2 - function name, line number
+ * prefix is added to every log message
+ */
+#define TWL4030_DETAIL	2
+
+/* kernel log level*/
+//#define TWL4030_K_LOG_LEVEL KERN_DEBUG
+#define TWL4030_K_LOG_LEVEL
+
+#if ( TWL4030_DETAIL > 0 )
+#define DL1 "%s "
+#define DR1 ,__FUNCTION__
+#else
+#define DL1
+#define DR1
+#endif
+#if ( TWL4030_DETAIL > 1 )
+#define DL2 "[%d] "
+#define DR2 ,__LINE__
+#else
+#define DL2
+#define DR2
+#endif
+
+#define D(format,...)\
+	printk(TWL4030_K_LOG_LEVEL DL1 DL2 format "\n" DR1 DR2, ## __VA_ARGS__)
+
+#if (TWL4030_LOG_LEVEL >= 1)
+#define D1(ARGS...) D(ARGS)
+#else
+#define D1(ARGS...)
+#endif
+#if (TWL4030_LOG_LEVEL >= 2)
+#define D2(ARGS...) D(ARGS)
+#else
+#define D2(ARGS...)
+#endif
+#if (TWL4030_LOG_LEVEL >= 3)
+#define D3(ARGS...) D(ARGS)
+#else
+#define D3(ARGS...)
+#endif
+
+#if (TWL4030_LOG_LEVEL >= 2)
+#define FN_IN printk("%s Entry\n",__FUNCTION__);
+#define FN_OUT(ARG) printk("%s[%d]:Exit(%d)\n",__FUNCTION__,__LINE__,ARG);
+#else
+#define FN_IN
+#define FN_OUT(ARG)
+#endif
+
+/**** Data structures */
+/* Global static functions */
+static struct semaphore gpio_sem;
+/* store usage of each GPIO. - each bit represents one GPIO */
+static unsigned int gpio_usage_count;
+/* shadow the imr register */
+static unsigned int gpio_imr_shadow;
+/* bitmask of pending requests to unmask gpio interrupts */
+static unsigned int gpio_pending_unmask;
+/* pointer to gpio unmask thread struct */
+static struct task_struct *gpio_unmask_thread;
+
+static inline int gpio_twl4030_read(u8 address);
+static inline int gpio_twl4030_write(u8 address, u8 data);
+
+/*
+ * Helper functions to read and write the GPIO ISR and IMR registers as
+ * 32-bit integers.
+ * Functions return 0 on success, non-zero otherwise.
+ * The caller must hold a lock on gpio_sem.
+ */
+
+static int gpio_read_isr(unsigned int *isr)
+{
+	int ret;
+
+	*isr = 0;
+	ret = twl4030_i2c_read(TWL4030_MODULE_GPIO, (u8 *) isr,
+			REG_GPIO_ISR1A, 3);
+	le32_to_cpup(isr);
+	*isr &= GPIO_32_MASK;
+
+	return ret;
+}
+
+static int gpio_write_isr(unsigned int isr)
+{
+	int ret;
+
+	isr &= GPIO_32_MASK;
+	/*
+	 * The buffer passed to the twl4030_i2c_write() routine must have an
+	 * extra byte at the beginning reserved for its internal use.
+	 */
+	isr <<= 8;
+	isr = cpu_to_le32(isr);
+	ret = twl4030_i2c_write(TWL4030_MODULE_GPIO, (u8 *) &isr,
+			       REG_GPIO_ISR1A, 3);
+	return ret;
+}
+
+static int gpio_write_imr(unsigned int imr)
+{
+	int ret;
+
+	imr &= GPIO_32_MASK;
+	/*
+	 * The buffer passed to the twl4030_i2c_write() routine must have an
+	 * extra byte at the beginning reserved for its internal use.
+	 */
+	imr <<= 8;
+	imr = cpu_to_le32(imr);
+	ret = twl4030_i2c_write(TWL4030_MODULE_GPIO, (u8 *) &imr,
+			       REG_GPIO_IMR1A, 3);
+	return ret;
+}
+
+/*
+ * These routines are analagous to the irqchip methods, but they are designed
+ * to be called from thread context with cpu interrupts enabled and with no
+ * locked spinlocks.  We call these routines from our custom IRQ handler
+ * instead of the usual irqchip methods.
+ */
+static void twl4030_gpio_mask_and_ack(unsigned int irq)
+{
+	int gpio = irq - IH_TWL4030_GPIO_BASE;
+
+	down(&gpio_sem);
+	/* mask */
+	gpio_imr_shadow |= (1 << gpio);
+	gpio_write_imr(gpio_imr_shadow);
+	/* ack */
+	gpio_write_isr(1 << gpio);
+	up(&gpio_sem);
+}
+
+static void twl4030_gpio_unmask(unsigned int irq)
+{
+	int gpio = irq - IH_TWL4030_GPIO_BASE;
+
+	down(&gpio_sem);
+	gpio_imr_shadow &= ~(1 << gpio);
+	gpio_write_imr(gpio_imr_shadow);
+	up(&gpio_sem);
+}
+
+/*
+ * These are the irqchip methods for the TWL4030 GPIO interrupts.
+ * Our IRQ handle method doesn't call these, but they will be called by
+ * other routines such as setup_irq() and enable_irq().  They are called
+ * with cpu interrupts disabled and with a lock on the irq_controller_lock
+ * spinlock.  This complicates matters, because accessing the TWL4030 GPIO
+ * interrupt controller requires I2C bus transactions that can't be initiated
+ * in this context.  Our solution is to defer accessing the interrupt
+ * controller to a kernel thread.  We only need to support the unmask method.
+ */
+
+static void twl4030_gpio_mask_and_ack_irqchip(unsigned int irq) {}
+static void twl4030_gpio_mask_irqchip(unsigned int irq) {}
+
+static void twl4030_gpio_unmask_irqchip(unsigned int irq)
+{
+	int gpio = irq - IH_TWL4030_GPIO_BASE;
+
+	gpio_pending_unmask |= (1 << gpio);
+	if (gpio_unmask_thread && gpio_unmask_thread->state != TASK_RUNNING)
+		wake_up_process(gpio_unmask_thread);
+}
+
+static struct irq_chip twl4030_gpio_irq_chip = {
+	.ack	= twl4030_gpio_mask_and_ack_irqchip,
+	.mask	= twl4030_gpio_mask_irqchip,
+	.unmask	= twl4030_gpio_unmask_irqchip,
+};
+
+/*
+ * These are the irqchip methods for the TWL4030 PIH GPIO module interrupt.
+ * The PIH module doesn't have interrupt masking capability, so these
+ * methods are NULL.
+ */
+static void twl4030_gpio_module_ack(unsigned int irq) {}
+static void twl4030_gpio_module_mask(unsigned int irq) {}
+static void twl4030_gpio_module_unmask(unsigned int irq) {}
+static struct irq_chip twl4030_gpio_module_irq_chip = {
+	.ack = twl4030_gpio_module_ack,
+	.mask = twl4030_gpio_module_mask,
+	.unmask = twl4030_gpio_module_unmask,
+};
+
+/**** GLOBAL FUNCTIONS ***/
+
+/**
+ * @brief twl4030_request_gpio
+ *
+ * @param gpio
+ *
+ * @return
+ */
+int twl4030_request_gpio(int gpio)
+{
+	int ret = 0;
+	FN_IN;
+	if (unlikely(gpio >= TWL4030_GPIO_MAX)) {
+		D1(" Invalid GPIO num %d instead of %d\n", gpio,
+		TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	down(&gpio_sem);
+	if (gpio_usage_count & (0x1 << gpio)) {
+		D1("Busy gpio %d requested\n", gpio);
+		ret = -EBUSY;
+	} else {
+		u8 clear_pull[6] = { 0, 0, 0, 0, 0, 0 };
+		/* First time usage? - switch on GPIO module */
+		if (!gpio_usage_count) {
+			ret =
+			gpio_twl4030_write(REG_GPIO_CTRL,
+					MASK_GPIO_CTRL_GPIO_ON);
+			ret = gpio_twl4030_write(REG_GPIO_SIH_CTRL, 0x00);
+		}
+		if (!ret) {
+			gpio_usage_count |= (0x1 << gpio);
+		}
+		ret =
+		twl4030_i2c_write(TWL4030_MODULE_GPIO, clear_pull,
+				REG_GPIOPUPDCTR1, 5);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_free_gpio
+ *
+ * @param gpio
+ *
+ * @return
+ */
+int twl4030_free_gpio(int gpio)
+{
+	int ret = 0;
+	FN_IN;
+	if (unlikely(gpio >= TWL4030_GPIO_MAX)) {
+		D1(" Invalid GPIO num %d instead of %d\n", gpio,
+		TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	down(&gpio_sem);
+	if ((gpio_usage_count & (0x1 << gpio)) == 0) {
+		D1("Attempt to free already free gpio %d\n", gpio);
+		ret = -EPERM;
+	} else {
+		gpio_usage_count &= ~(0x1 << gpio);
+	}
+	/* Last time usage? - switch off GPIO module */
+	if (!gpio_usage_count) {
+		ret = gpio_twl4030_write(REG_GPIO_CTRL, 0x0);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_set_gpio_direction
+ *
+ * @param gpio
+ * @param is_input
+ *
+ * @return
+ */
+int twl4030_set_gpio_direction(int gpio, int is_input)
+{
+	u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
+	u8 d_msk = MASK_GPIODATADIR_GPIOxDIR(GET_GPIO_DATA_OFF(gpio));
+	u8 reg = 0;
+	u8 base = 0;
+	int ret = 0;
+	FN_IN;
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio)))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted \n", gpio, TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	base = REG_GPIODATADIR1 + d_bnk;
+
+	down(&gpio_sem);
+	ret = gpio_twl4030_read(base);
+	if (ret >= 0) {
+		if (is_input) {
+			reg = (u8) ((ret) & ~(d_msk));
+		} else {
+			reg = (u8) ((ret) | (d_msk));
+		}
+		ret = gpio_twl4030_write(base, reg);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_set_gpio_dataout
+ *
+ * @param gpio
+ * @param enable
+ *
+ * @return
+ */
+int twl4030_set_gpio_dataout(int gpio, int enable)
+{
+	u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
+	u8 d_msk = MASK_GPIODATAOUT_GPIOxOUT(GET_GPIO_DATA_OFF(gpio));
+	u8 base = 0;
+	int ret = 0;
+	FN_IN;
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio)))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted \n", gpio, TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	if (enable) {
+		base = REG_SETGPIODATAOUT1 + d_bnk;
+	} else {
+		base = REG_CLEARGPIODATAOUT1 + d_bnk;
+	}
+	down(&gpio_sem);
+	ret = gpio_twl4030_write(base, d_msk);
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_get_gpio_datain
+ *
+ * @param gpio
+ *
+ * @return
+ */
+int twl4030_get_gpio_datain(int gpio)
+{
+	u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
+	u8 d_off = BIT_GPIODATAIN_GPIOxIN(GET_GPIO_DATA_OFF(gpio));
+	u8 base = 0;
+	int ret = 0;
+	FN_IN;
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio)))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted \n", gpio, TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	base = REG_GPIODATAIN1 + d_bnk;
+	down(&gpio_sem);
+	ret = gpio_twl4030_read(base);
+	up(&gpio_sem);
+	if (ret > 0) {
+		D2("Actual read val=0x%x\n", ret);
+		ret = (ret >> d_off) & 0x1;
+	}
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_set_gpio_pull
+ *
+ * @param gpio
+ * @param pull_dircn
+ *
+ * @return
+ */
+int twl4030_set_gpio_pull(int gpio, int pull_dircn)
+{
+	u8 c_bnk = GET_GPIO_CTL_BANK(gpio);
+	u8 c_off = GET_GPIO_CTL_OFF(gpio);
+	u8 c_msk = 0;
+	u8 reg = 0;
+	u8 base = 0;
+	int ret = 0;
+	FN_IN;
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio)))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted \n", gpio, TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	base = REG_GPIOPUPDCTR1 + c_bnk;
+	if (pull_dircn == TWL4030_GPIO_PULL_DOWN) {
+		c_msk = MASK_GPIOPUPDCTR1_GPIOxPD(c_off);
+	} else if (pull_dircn == TWL4030_GPIO_PULL_UP) {
+		c_msk = MASK_GPIOPUPDCTR1_GPIOxPU(c_off);
+	}
+	D3("GPIIO=%x COFF=%x CBNK=%x, c_msk=%x p_dir=%d", gpio, c_off,
+	c_bnk, c_msk, pull_dircn);
+	down(&gpio_sem);
+	ret = gpio_twl4030_read(base);
+	if (ret >= 0) {
+		/* clear the previous up/down values */
+		reg = (u8) (ret);
+		reg &= ~(MASK_GPIOPUPDCTR1_GPIOxPU(c_off) |
+			MASK_GPIOPUPDCTR1_GPIOxPD(c_off));
+		D3("reg=%x ret=%d c_msk=0x%x", reg, ret, c_msk);
+		reg |= c_msk;
+		ret = gpio_twl4030_write(base, reg);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_set_gpio_edge_ctrl
+ *
+ * @param gpio
+ * @param edge
+ *
+ * @return
+ */
+int twl4030_set_gpio_edge_ctrl(int gpio, int edge)
+{
+	u8 c_bnk = GET_GPIO_CTL_BANK(gpio);
+	u8 c_off = GET_GPIO_CTL_OFF(gpio);
+	u8 c_msk = 0;
+	u8 reg = 0;
+	u8 base = 0;
+	int ret = 0;
+	FN_IN;
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio)))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted \n", gpio, TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	base = REG_GPIO_EDR1 + c_bnk;
+	if (edge & TWL4030_GPIO_EDGE_RISING) {
+		c_msk |= MASK_GPIO_EDR1_GPIOxRISING(c_off);
+	}
+	if (edge & TWL4030_GPIO_EDGE_FALLING) {
+		c_msk |= MASK_GPIO_EDR1_GPIOxFALLING(c_off);
+	}
+	down(&gpio_sem);
+	ret = gpio_twl4030_read(base);
+	if (ret >= 0) {
+		/* clear the previous rising/falling values */
+		reg =
+		(u8) (ret &
+			~(MASK_GPIO_EDR1_GPIOxFALLING(c_off) |
+			MASK_GPIO_EDR1_GPIOxRISING(c_off)));
+		reg |= c_msk;
+		ret = gpio_twl4030_write(base, reg);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_set_gpio_debounce
+ *
+ * @param gpio
+ * @param enable
+ *
+ * @return
+ */
+int twl4030_set_gpio_debounce(int gpio, int enable)
+{
+	u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
+	u8 d_msk = MASK_GPIO_DEBEN_GPIOxDEB(GET_GPIO_DATA_OFF(gpio));
+	u8 reg = 0;
+	u8 base = 0;
+	int ret = 0;
+	FN_IN;
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio)))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted \n", gpio, TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+	base = REG_GPIO_DEBEN1 + d_bnk;
+	down(&gpio_sem);
+	ret = gpio_twl4030_read(base);
+	if (ret >= 0) {
+		if (enable) {
+			reg = (u8) ((ret) | (d_msk));
+		} else {
+			reg = (u8) ((ret) & ~(d_msk));
+		}
+		ret = gpio_twl4030_write(base, reg);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief twl4030_set_gpio_card_detect
+ *
+ * @param gpio
+ * @param cd
+ * @param enable
+ *
+ * @return
+ */
+int twl4030_set_gpio_card_detect(int gpio, int enable)
+{
+	u8 reg = 0;
+	u8 msk = (1 << gpio);
+	int ret = 0;
+	FN_IN;
+	/* Only GPIO 0 or 1 can be used for CD feature.. */
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & (0x1 << gpio))
+		|| (gpio >= TWL4030_GPIO_MAX_CD))) {
+		D1("Invalid GPIO num %d instead of %d "
+		"OR unused GPIO attempted non CD GPIO used \n", gpio,
+		TWL4030_GPIO_MAX);
+		return -EPERM;
+	}
+
+	down(&gpio_sem);
+	ret = gpio_twl4030_read(REG_GPIO_CTRL);
+	if (ret >= 0) {
+		if (enable) {
+			reg = (u8) (ret | msk);
+		} else {
+			reg = (u8) (ret & ~msk);
+		}
+		ret = gpio_twl4030_write(REG_GPIO_CTRL, reg);
+	}
+	up(&gpio_sem);
+	FN_OUT(ret);
+	return (ret);
+}
+
+/**** MODULE FUNCTIONS ***/
+
+/**
+ * @brief gpio_twl4030_write
+ *
+ * @param address
+ * @param data
+ *
+ * @return  0 if successful
+ */
+static inline int gpio_twl4030_write(u8 address, u8 data)
+{
+	int ret = 0;
+	/* DEBUG */
+	D2("GPIO add[0x%02x a.k.a.0x%02X]<=0x%02x", address, address + 0x98,
+	data);
+	ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, data, address);
+	if (ret >= 0) {
+#if 0
+		/* PARANOIA Check - what if we wrote and it did not Go there?? */
+		u8 data1;
+		ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &data1, address);
+		if (ret < 0) {
+			printk(KERN_ERR "re-read failed\n");
+		} else {
+			if (data1 != data) {
+				printk
+				("Write mismatch - wrote %x read %x"
+				" from reg %x\n", data, data1, address);
+			}
+		}
+#endif
+		ret = 0;
+	} else {
+		D2(":Write[0x%x]Error %d\n", address, ret);
+	}
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief gpio_twl4030_read
+ *
+ * @param address
+ *
+ * @return  data if successful else return negative error value
+ */
+static inline int gpio_twl4030_read(u8 address)
+{
+	u8 data;
+	int ret = 0;
+	ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address);
+	if (ret >= 0) {
+		ret = data;
+	} else {
+		D2("TWL4030:Audio:Read[0x%x] Error %d\n", address, ret);
+	}
+	return ret;
+}
+
+/*
+ * gpio_unmask_thread() runs as a kernel thread.  It is awakened by the unmask
+ * method for the GPIO interrupts.  It unmasks all of the GPIO interrupts
+ * specified in the gpio_pending_unmask bitmask.  We have to do the unmasking
+ * in a kernel thread rather than directly in the unmask method because of the
+ * need to access the TWL4030 via the I2C bus.  Note that we don't need to be
+ * concerned about race conditions where the request to unmask a GPIO interrupt
+ * has already been cancelled before this thread does the unmasking.  If a GPIO
+ * interrupt is improperly unmasked, then the IRQ handler for it will mask it
+ * when an interrupt occurs.
+ */
+static int twl4030_gpio_unmask_thread(void *data)
+{
+	struct sched_param param;
+
+	current->flags |= PF_NOFREEZE;
+
+//	param.sched_priority = 26;
+//	sys_sched_setscheduler(current->pid, SCHED_FIFO, &param);
+
+	while (!kthread_should_stop()) {
+		int irq;
+		unsigned int gpio_unmask;
+
+		local_irq_disable();
+		gpio_unmask = gpio_pending_unmask;
+		gpio_pending_unmask = 0;
+		local_irq_enable();
+
+		for (irq = IH_TWL4030_GPIO_BASE; 0 != gpio_unmask;
+			gpio_unmask >>= 1, irq++)
+		{
+			if (gpio_unmask & 0x1)
+				twl4030_gpio_unmask(irq);
+		}
+
+		local_irq_disable();
+		if (!gpio_pending_unmask)
+			set_current_state(TASK_INTERRUPTIBLE);
+		local_irq_enable();
+
+		schedule();
+	}
+	set_current_state(TASK_RUNNING);
+	return 0;
+}
+
+/*
+ * do_twl4030_gpio_irq() is the desc->handle method for each of the twl4030
+ * gpio interrupts.  It executes in kernel thread context.
+ * On entry, cpu interrupts are enabled.
+ */
+static void do_twl4030_gpio_irq(unsigned int irq, irq_desc_t *desc)
+{
+	struct irqaction *action;
+	const unsigned int cpu = smp_processor_id();
+	
+	desc->status |= IRQ_LEVEL; 
+
+	/*
+	 * Acknowledge, clear _AND_ disable the interrupt.
+	 */
+	twl4030_gpio_mask_and_ack(irq);
+
+	if (!desc->depth) {
+		kstat_cpu(cpu).irqs[irq]++;
+
+		action = desc->action;
+		if (action) {
+			int ret;
+			int status = 0;
+			int retval = 0;
+
+			do {
+				/* Call the ISR with cpu interrupts enabled. */
+				ret = action->handler(irq, action->dev_id);
+
+				if (ret == IRQ_HANDLED)
+					status |= action->flags;
+				retval |= ret;
+				action = action->next;
+			} while (action);
+
+			if (retval != IRQ_HANDLED) {
+				printk(KERN_ERR "ISR for TWL4030 GPIO"
+					" irq %d can't handle interrupt\n",
+					irq);
+			}
+
+			if (!desc->depth)
+				twl4030_gpio_unmask(irq);
+		}
+	}
+}
+
+/*
+ * do_twl4030_gpio_module_irq() is the desc->handle method for the twl4030 gpio
+ * module interrupt.  It executes in kernel thread context.
+ * This is a chained interrupt, so there is no desc->action method for it.
+ * We query the gpio module interrupt controller in the twl4030 to determine
+ * which gpio lines are generating interrupt requests, and then call the
+ * desc->handle method for each gpio that needs service.
+ * On entry, cpu interrupts are disabled.
+ */
+static void do_twl4030_gpio_module_irq(unsigned int irq, irq_desc_t *desc)
+{
+	const unsigned int cpu = smp_processor_id();
+
+	desc->status |= IRQ_LEVEL;
+
+	/*
+	* The desc->handle method would normally call the desc->chip->ack
+	* method here, but we won't bother since our ack method is NULL.
+	*/
+
+	if (!desc->depth) {
+		int gpio_irq;
+		unsigned int gpio_isr;
+
+		kstat_cpu(cpu).irqs[irq]++;
+		local_irq_enable();
+
+		down(&gpio_sem);
+		if (gpio_read_isr(&gpio_isr))
+			gpio_isr = 0;
+		up(&gpio_sem);
+
+		for (gpio_irq = IH_TWL4030_GPIO_BASE; 0 != gpio_isr;
+			gpio_isr >>= 1, gpio_irq++)
+		{
+			if (gpio_isr & 0x1) {
+				irq_desc_t *d = irq_desc + gpio_irq;
+
+				d->handle_irq(gpio_irq, d);
+			}
+		}
+
+		local_irq_disable();
+		/*
+		 * Here is where we should call the unmask method, but again we
+		 * won't bother since it is NULL.
+		 */
+	}
+}
+
+/**
+ * @brief gpio_twl4030_init
+ *
+ * @return
+ */
+static int __init gpio_twl4030_init(void)
+{
+	int ret;
+	int irq = 0;
+
+	FN_IN;
+	/* init the global locking sem */
+	sema_init(&gpio_sem, 1);
+
+	/* All GPIO interrupts are initially masked */
+	gpio_pending_unmask = 0;
+	gpio_imr_shadow = GPIO_32_MASK;
+	ret = gpio_write_imr(gpio_imr_shadow);
+
+	if (!ret) {
+		/*
+		* Create a kernel thread to handle deferred unmasking of gpio
+		* interrupts.
+		*/
+		gpio_unmask_thread = kthread_create(twl4030_gpio_unmask_thread,
+			NULL, "twl4030 gpio");
+		if (!gpio_unmask_thread) {
+			printk(KERN_ERR
+				"%s: could not create twl4030 gpio unmask thread!\n",
+				__FUNCTION__);
+			ret = -ENOMEM;
+		}
+	}
+
+	if (!ret) {
+		/* install an irq handler for each of the gpio interrupts */
+		for (irq = IH_TWL4030_GPIO_BASE; irq < IH_TWL4030_GPIO_END;
+			irq++)
+		{
+			D3("setting for IRQ=%d\n", irq);
+			set_irq_chip(irq, &twl4030_gpio_irq_chip);
+			set_irq_handler(irq, do_twl4030_gpio_irq);
+			set_irq_flags(irq, IRQF_VALID);
+		}
+
+		/*
+		 * Install an irq handler to demultiplex the gpio module
+		 * interrupt.
+		 */
+		set_irq_chip(TWL4030_MODIRQ_GPIO,
+			&twl4030_gpio_module_irq_chip);
+		set_irq_chained_handler(TWL4030_MODIRQ_GPIO,
+			do_twl4030_gpio_module_irq);
+	}
+
+	printk(KERN_INFO "TWL4030 GPIO Demux: IRQ Range %d to %d,"
+		" Initialization %s\n", IH_TWL4030_GPIO_BASE,
+		IH_TWL4030_GPIO_END, (ret) ? "Failed" : "Success");
+	FN_OUT(ret);
+	return ret;
+}
+
+/**
+ * @brief gpio_twl4030_exit
+ *
+ * @return
+ */
+static void __exit gpio_twl4030_exit(void)
+{
+	int irq;
+
+	FN_IN;
+
+	/* uninstall the gpio demultiplexing interrupt handler */
+	set_irq_handler(TWL4030_MODIRQ_GPIO, NULL);
+	set_irq_flags(TWL4030_MODIRQ_GPIO, 0);
+
+	/* uninstall the irq handler for each of the gpio interrupts */
+	for (irq = IH_TWL4030_GPIO_BASE; irq < IH_TWL4030_GPIO_END; irq++)
+	{
+		set_irq_handler(irq, NULL);
+		set_irq_flags(irq, 0);
+	}
+
+	/* stop the gpio unmask kernel thread */
+	if (gpio_unmask_thread) {
+		kthread_stop(gpio_unmask_thread);
+		gpio_unmask_thread = NULL;
+	}
+
+	FN_OUT(0);
+	return;
+}
+
+module_init(gpio_twl4030_init);
+module_exit(gpio_twl4030_exit);
+
+EXPORT_SYMBOL(twl4030_request_gpio);
+EXPORT_SYMBOL(twl4030_free_gpio);
+EXPORT_SYMBOL(twl4030_set_gpio_direction);
+EXPORT_SYMBOL(twl4030_set_gpio_dataout);
+EXPORT_SYMBOL(twl4030_get_gpio_datain);
+EXPORT_SYMBOL(twl4030_set_gpio_pull);
+EXPORT_SYMBOL(twl4030_set_gpio_edge_ctrl);
+EXPORT_SYMBOL(twl4030_set_gpio_debounce);
+EXPORT_SYMBOL(twl4030_set_gpio_card_detect);
+
+MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_DESCRIPTION("GPIO interface for TWL4030");
+MODULE_LICENSE("GPL");
