No build reason found for standard:loongarch64

File linux-2.6.34-moorestown-aava-specific-changes.patch of Package kernel

From: Prajwal Mohan <prajwal.karur.mohan@intel.com>
Date: Tue, 27 Apr 2010 11:23:00 -0700
Subject: [PATCH] Aava specific patches

This driver is from aava

Signed-off-by: Prajwal Mohan <prajwal.karur.mohan@intel.com>
Patch-mainline: 2.6.34
---
Index: linux-2.6.33/drivers/misc/mrst_test_ipc/ipc_module.c
===================================================================
--- linux-2.6.33.orig/drivers/misc/mrst_test_ipc/ipc_module.c
+++ linux-2.6.33/drivers/misc/mrst_test_ipc/ipc_module.c
@@ -44,8 +44,13 @@
 #include <linux/uaccess.h>
 #include <linux/time.h>
 
+
+
 #include <asm/ipc_defs.h>
 
+#include <linux/device.h>
+#include <linux/ipc_module.h>
+
 static u32 major;
 #define MAX_FW_SIZE 264192
 
@@ -53,9 +58,11 @@ int init_ipc_driver(void);
 int ipc_ioctl(struct inode *inode, struct file *filp, u32 cmd,
 						unsigned long arg);
 const struct file_operations ipc_fops = {
+owner:THIS_MODULE,
 ioctl:ipc_ioctl,
 };
 
+static struct class *mid_ipc_class;
 
 int ipc_ioctl(struct inode *inode, struct file *filp, u32 cmd,
 						unsigned long arg)
@@ -71,6 +78,18 @@ int ipc_ioctl(struct inode *inode, struc
 	u8 *fw_buf = NULL ;
 
 	switch (cmd) {
+	case IPC_IOC_PMIC_REG_READ:
+		cmd = IPC_PMIC_REGISTER_READ;
+		break;
+	case IPC_IOC_PMIC_REG_WRITE:
+		cmd = IPC_PMIC_REGISTER_WRITE;
+		break;
+	default:
+		printk(KERN_INFO "ioctl <UNRECOGNIZED> received\n");
+		break;
+	}
+
+	switch (cmd) {
 	case IPC_PMIC_REGISTER_READ:
 		{
 			printk(KERN_INFO
@@ -169,6 +188,8 @@ int ipc_ioctl(struct inode *inode, struc
 
 static int __init ipc_module_init(void)
 {
+	struct device *dev;
+
 	printk(KERN_INFO "Init ipc_module\n");
 
 	major = register_chrdev(0, "mid_ipc", &ipc_fops);
@@ -177,6 +198,23 @@ static int __init ipc_module_init(void)
 		return major;
 	}
 
+	mid_ipc_class = class_create(THIS_MODULE, "mid_ipc");
+	if (IS_ERR(mid_ipc_class)) {
+		unregister_chrdev(major, "mid_ipc");
+		return PTR_ERR(mid_ipc_class);
+	}
+
+	dev = device_create(mid_ipc_class,
+			    NULL,
+			    MKDEV(major, 0),
+			    NULL,
+			    "mid_ipc" );
+	if (IS_ERR(dev)) {
+		class_destroy(mid_ipc_class);
+		unregister_chrdev(major, "mid_ipc");
+		return PTR_ERR(dev);
+	}
+
 	init_ipc_driver ( ) ;
  return SUCCESS;
 
@@ -184,6 +222,8 @@ static int __init ipc_module_init(void)
 
 static void __exit ipc_module_exit(void)
 {
+	device_destroy(mid_ipc_class, MKDEV(major, 0));
+	class_destroy(mid_ipc_class);
 	unregister_chrdev(major, "mid_ipc");
 }
 
Index: linux-2.6.33/include/linux/Kbuild
===================================================================
--- linux-2.6.33.orig/include/linux/Kbuild
+++ linux-2.6.33/include/linux/Kbuild
@@ -385,3 +385,5 @@ unifdef-y += xfrm.h
 objhdr-y += version.h
 header-y += wimax.h
 header-y += wimax/
+header-y += ipc_module.h
+
Index: linux-2.6.33/drivers/gpio/gpiolib.c
===================================================================
--- linux-2.6.33.orig/drivers/gpio/gpiolib.c
+++ linux-2.6.33/drivers/gpio/gpiolib.c
@@ -228,11 +228,14 @@ static ssize_t gpio_direction_show(struc
 
 	if (!test_bit(FLAG_EXPORT, &desc->flags))
 		status = -EIO;
-	else
-		status = sprintf(buf, "%s\n",
-			test_bit(FLAG_IS_OUT, &desc->flags)
-				? "out" : "in");
-
+	else {
+		status = sprintf(buf,
+				 "%s\n",
+				 gpio_get_direction( (desc - gpio_desc) ) ==
+				 DIRECTION_OUT ?
+					"out" :
+					"in");
+	}
 	mutex_unlock(&sysfs_lock);
 	return status;
 }
@@ -1507,6 +1510,29 @@ void gpio_set_value_cansleep(unsigned gp
 }
 EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
 
+enum gpio_direction gpio_get_direction(unsigned gpio)
+{
+	struct gpio_chip	*chip;
+	struct gpio_desc	*desc = &gpio_desc[gpio];
+
+	chip = gpio_to_chip(gpio);
+	might_sleep_if(extra_checks && chip->can_sleep);
+
+	if (chip->get_direction) {
+		if (chip->get_direction(chip, gpio - chip->base) ==
+								DIRECTION_IN) {
+			clear_bit(FLAG_IS_OUT, &desc->flags);
+			return DIRECTION_IN;
+		} else {
+			set_bit(FLAG_IS_OUT, &desc->flags);
+			return DIRECTION_OUT;
+		}
+	}
+	return test_bit(FLAG_IS_OUT, &desc->flags) ?
+		DIRECTION_OUT :
+		DIRECTION_IN;
+}
+EXPORT_SYMBOL_GPL(gpio_get_direction);
 
 #ifdef CONFIG_DEBUG_FS
 
Index: linux-2.6.33/drivers/gpio/langwell_gpio.c
===================================================================
--- linux-2.6.33.orig/drivers/gpio/langwell_gpio.c
+++ linux-2.6.33/drivers/gpio/langwell_gpio.c
@@ -107,6 +107,19 @@ static int lnw_gpio_direction_output(str
 	return 0;
 }
 
+static enum gpio_direction lnw_gpio_get_direction(struct gpio_chip *chip,
+						   unsigned offset)
+{
+	struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+	u8 reg = offset / 32;
+	void __iomem *gpdr;
+
+	gpdr = (void __iomem *)(&lnw->reg_base->GPDR[reg]);
+	if (readl(gpdr) & BIT(offset % 32))
+		return DIRECTION_OUT;
+	return DIRECTION_IN;
+}
+
 static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
 	struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
@@ -240,6 +253,7 @@ static int __devinit lnw_gpio_probe(stru
 	lnw->chip.label = dev_name(&pdev->dev);
 	lnw->chip.direction_input = lnw_gpio_direction_input;
 	lnw->chip.direction_output = lnw_gpio_direction_output;
+	lnw->chip.get_direction = lnw_gpio_get_direction;
 	lnw->chip.get = lnw_gpio_get;
 	lnw->chip.set = lnw_gpio_set;
 	lnw->chip.to_irq = lnw_gpio_to_irq;
Index: linux-2.6.33/drivers/gpio/langwell_pmic_gpio.c
===================================================================
--- linux-2.6.33.orig/drivers/gpio/langwell_pmic_gpio.c
+++ linux-2.6.33/drivers/gpio/langwell_pmic_gpio.c
@@ -165,15 +165,33 @@ static int pmic_gpio_direction_output(st
 	return rc;
 }
 
-static int pmic_gpio_get(struct gpio_chip *chip, unsigned offset)
+static enum gpio_direction pmic_gpio_get_direction(struct gpio_chip *chip,
+						    unsigned offset)
 {
-	/* we only have 8 GPIO can use as input */
 	if (offset > 8) {
-		printk(KERN_ERR
-			"%s: only pin 0-7 support input\n", __func__);
-		return -1;
+		/* GPOWSs and GPOs are always outputs */
+		return DIRECTION_OUT;
 	}
-	return ipc_read_char(GPIO0 + offset) & GPIO_DIN;
+	if (ipc_read_char(GPIO0 + offset) & GPIO_DIR)
+		return DIRECTION_IN;
+	return DIRECTION_OUT;
+}
+
+static int pmic_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset < 8) {
+		/* GPIOSW: Get state according to direction */
+		if (pmic_gpio_get_direction( chip, offset ) == DIRECTION_IN)
+			return (ipc_read_char(GPIO0 + offset) & GPIO_DIN);
+		return (ipc_read_char(GPIO0 + offset) & GPIO_DOU);
+	} else if (offset < 16) {
+		/* GPOSW */
+		return (ipc_read_char(GPOSWCTL0 + offset - 8) & GPOSW_DOU);
+	} else if (offset < 24) {
+		/* GPO */
+		return (ipc_read_char(GPO) & (1 << (offset - 16)));
+	}
+	return 0;
 }
 
 static void pmic_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -284,6 +302,7 @@ static int __devinit pmic_gpio_probe(str
 	pg->chip.label = "langwell_pmic";
 	pg->chip.direction_input = pmic_gpio_direction_input;
 	pg->chip.direction_output = pmic_gpio_direction_output;
+	pg->chip.get_direction = pmic_gpio_get_direction;
 	pg->chip.get = pmic_gpio_get;
 	pg->chip.set = pmic_gpio_set;
 	pg->chip.to_irq = pmic_gpio_to_irq;
Index: linux-2.6.33/drivers/gpio/pca953x.c
===================================================================
--- linux-2.6.33.orig/drivers/gpio/pca953x.c
+++ linux-2.6.33/drivers/gpio/pca953x.c
@@ -144,6 +144,24 @@ static int pca953x_gpio_direction_output
 	return 0;
 }
 
+static enum gpio_direction pca953x_gpio_get_direction(struct gpio_chip *gc,
+						      unsigned off)
+{
+	struct pca953x_chip *chip;
+	uint16_t reg_val;
+	int ret;
+
+	chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+	ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &reg_val);
+	if (ret == 0) {
+		if ( reg_val & (1u << off) )
+			return DIRECTION_IN;
+		return DIRECTION_OUT;
+	}
+	return DIRECTION_IN;
+}
+
 static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
 {
 	struct pca953x_chip *chip;
@@ -199,6 +217,7 @@ static void pca953x_setup_gpio(struct pc
 
 	gc->direction_input  = pca953x_gpio_direction_input;
 	gc->direction_output = pca953x_gpio_direction_output;
+	gc->get_direction = pca953x_gpio_get_direction;
 	gc->get = pca953x_gpio_get_value;
 	gc->set = pca953x_gpio_set_value;
 	gc->to_irq = pca953x_gpio_to_irq;
Index: linux-2.6.33/include/asm-generic/gpio.h
===================================================================
--- linux-2.6.33.orig/include/asm-generic/gpio.h
+++ linux-2.6.33/include/asm-generic/gpio.h
@@ -101,6 +101,8 @@ struct gpio_chip {
 	char			**names;
 	unsigned		can_sleep:1;
 	unsigned		exported:1;
+	enum gpio_direction	(*get_direction)(struct gpio_chip *chip,
+						 unsigned offset);
 };
 
 extern const char *gpiochip_is_requested(struct gpio_chip *chip,
@@ -120,6 +122,7 @@ extern void gpio_free(unsigned gpio);
 
 extern int gpio_direction_input(unsigned gpio);
 extern int gpio_direction_output(unsigned gpio, int value);
+extern enum gpio_direction gpio_get_direction(unsigned gpio);
 
 extern int gpio_get_value_cansleep(unsigned gpio);
 extern void gpio_set_value_cansleep(unsigned gpio, int value);
Index: linux-2.6.33/include/linux/gpio.h
===================================================================
--- linux-2.6.33.orig/include/linux/gpio.h
+++ linux-2.6.33/include/linux/gpio.h
@@ -3,6 +3,11 @@
 
 /* see Documentation/gpio.txt */
 
+enum gpio_direction {
+	DIRECTION_IN = 0,
+	DIRECTION_OUT = 1,
+};
+
 #ifdef CONFIG_GENERIC_GPIO
 #include <asm/gpio.h>
 
@@ -126,6 +131,13 @@ static inline int irq_to_gpio(unsigned i
 	return -EINVAL;
 }
 
+static inline enum gpio_direction gpio_get_direction(unsigned gpio)
+{
+	/* GPIO can never have been requested or set as {in,out}put */
+	WARN_ON(1);
+	return DIRECTION_IN;
+}
+
 #endif
 
 #endif /* __LINUX_GPIO_H */
Index: linux-2.6.33/include/linux/ipc_module.h
===================================================================
--- /dev/null
+++ linux-2.6.33/include/linux/ipc_module.h
@@ -0,0 +1,60 @@
+/*
+ * include/linux/ipc_module.h
+ *
+ * Copyright (C) 2009 Aava Mobile Oy
+ * Written by Mikko Kovanen <mikko.kovanen@aavamobile.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ */
+
+#ifndef IPC_MODULE_H
+#define IPC_MODULE_H
+
+#include <linux/types.h>
+
+#ifndef __IPC_DEFS_H__
+#define E_INVALID_CMD           -249
+#define E_READ_USER_CMD         -250
+#define E_READ_USER_DATA        -251
+#define E_WRITE_USER_DATA       -252
+#define E_PMIC_MALLOC           -253
+
+#define MAX_PMICREGS            5
+#define MAX_PMIC_MOD_REGS       4
+
+struct pmicreg {
+	__u16 register_address;
+	__u8 value;
+};
+
+struct ipc_pmic_reg_data {
+	_Bool ioc;
+	struct pmicreg pmic_reg_data[MAX_PMICREGS];
+	__u8 num_entries;
+};
+#endif /* __IPC_DEFS_H__ */
+
+#define IPC_IOC_MAGIC   'a'
+
+
+#define IPC_IOC_PMIC_REG_READ	_IOR(IPC_IOC_MAGIC, \
+					0, \
+					struct ipc_pmic_reg_data)
+
+#define IPC_IOC_PMIC_REG_WRITE  _IOW(IPC_IOC_MAGIC, \
+					1, \
+					struct ipc_pmic_reg_data)
+
+#endif /* IPC_MODULE_H */
+
Index: linux-2.6.33/drivers/input/keyboard/mrst_keypad.c
===================================================================
--- linux-2.6.33.orig/drivers/input/keyboard/mrst_keypad.c
+++ linux-2.6.33/drivers/input/keyboard/mrst_keypad.c
@@ -40,6 +40,9 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
+/*jhuot start*/
+#include <asm/ipc_defs.h>
+/*jhuot end*/
 
 /*
  * Keypad Controller registers
@@ -116,10 +119,10 @@ MODULE_DEVICE_TABLE(pci, keypad_pci_tbl)
 #define keypad_writel(off, v)	writel((v), keypad->mmio_base + (off))
 
 #define MAX_MATRIX_KEY_NUM	(8 * 8)
-#define MAX_DIRECT_KEY_NUM	(4)
+#define MAX_DIRECT_KEY_NUM	(2)
 
-#define MAX_MATRIX_KEY_ROWS	(8)
-#define MAX_MATRIX_KEY_COLS	(8)
+#define MAX_MATRIX_KEY_ROWS	(7)
+#define MAX_MATRIX_KEY_COLS	(7)
 #define DEBOUNCE_INTERVAL	100
 
 #define KEY_HALFSHUTTER		KEY_PROG1
@@ -167,7 +170,7 @@ static unsigned int mrst_keycode_fn[MAX_
 
 /* direct key map */
 static unsigned int mrst_direct_keycode[MAX_DIRECT_KEY_NUM] = {
-	KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_HALFSHUTTER, KEY_FULLSHUTTER,
+	KEY_VOLUMEUP, KEY_VOLUMEDOWN, //KEY_HALFSHUTTER, KEY_FULLSHUTTER,
 };
 
 struct mrst_keypad {
@@ -430,6 +433,8 @@ scan:
 			if ((bits_changed & (1 << row)) == 0)
 				continue;
 
+			printk(KERN_INFO "BUTTONS: "
+				"report key row %d, col %d\n", row, col);
 			input_report_key(keypad->input_dev,
 				lookup_matrix_keycode(keypad, row, col),
 				new_state[col] & (1 << row));
@@ -513,6 +518,8 @@ static void mrst_keypad_scan_direct(stru
 
 	for (i = 0; i < keypad->direct_key_num; i++) {
 		if (bits_changed & (1 << i)) {
+			printk(KERN_INFO "BUTTONS: "
+				"scan_direct %d\n", keypad->direct_key_map[i]);
 			input_report_key(keypad->input_dev,
 					 keypad->direct_key_map[i],
 					 (new_state & (1 << i)));
@@ -528,10 +535,13 @@ static irqreturn_t mrst_keypad_irq_handl
 	struct mrst_keypad *keypad = dev_id;
 	unsigned long kpc = keypad_readl(KPC);
 
+	printk(KERN_INFO "BUTTONS: irq_handler, kpc %lu\n", kpc);
 	if (kpc & KPC_DI)
+		printk(KERN_INFO "BUTTONS: mrst_keypad_scan_direct\n");
 		mrst_keypad_scan_direct(keypad);
 
 	if (kpc & KPC_MI)
+		printk(KERN_INFO "BUTTONS: mrst_keypad_scan_matrix\n");
 		mrst_keypad_scan_matrix(keypad);
 
 	return IRQ_HANDLED;
@@ -544,13 +554,47 @@ static int mrst_keypad_gpio_init(void)
 	    MAX_MATRIX_KEY_COLS + MAX_DIRECT_KEY_NUM;
 
 	/* explicitely tell which pins have been occupied... */
+/*
 	for (i = KEYPAD_MATRIX_GPIO_IN_PIN; i < pins; i++, cnt++) {
 		err = gpio_request(i, NULL);
 		if (err) {
 			printk(KERN_ERR "GPIO pin %d failed to request.\n", i);
 			goto err_request;
 		}
-	}
+	}*/
+
+	for (i = 0; i < MAX_MATRIX_KEY_ROWS; i++){
+		err = gpio_request(KEYPAD_MATRIX_GPIO_IN_PIN + i,NULL);
+
+		if (err) {
+			printk(KERN_ERR "GPIO pin %d failed to request.\n", i);
+			goto err_request;
+		}
+
+    }
+
+	for (i = 0; i < MAX_MATRIX_KEY_COLS; i++)
+    {
+		err = gpio_request(KEYPAD_MATRIX_GPIO_OUT_PIN + i, NULL);
+		if (err) {
+			printk(KERN_ERR "GPIO pin %d failed to request.\n", i);
+			goto err_request;
+		}
+
+    }
+
+	for (i = 0; i < MAX_DIRECT_KEY_NUM; i++)
+    {
+		err = gpio_request(KEYPAD_DIRECT_GPIO_IN_PIN + i,NULL);
+
+		if (err) {
+			printk(KERN_ERR "GPIO pin %d failed to request.\n", i);
+			goto err_request;
+		}
+
+
+    }
+
 
 	for (i = 0; i < MAX_MATRIX_KEY_ROWS; i++)
 		gpio_direction_input(KEYPAD_MATRIX_GPIO_IN_PIN + i);
@@ -642,6 +686,9 @@ static int __devinit mrst_keypad_probe(s
 	struct mrst_keypad *keypad;
 	struct input_dev *input_dev;
 	int error;
+/*	jhuot start */
+	struct ipc_io_bus_master_regs *p_reg_data;
+/*	jhuot end */
 
 #ifndef MODULE
 	printk(KERN_INFO MRST_KEYPAD_DRIVER_NAME "\n");
@@ -711,6 +758,18 @@ static int __devinit mrst_keypad_probe(s
 		goto failed_free_dev;
 	}
 
+
+/*	jhuot start */
+	/* Enable 75 kOhm internal pull-ups for KBD_DKIN0 and KBD_DKIN1 */
+	/*bus: 0x4h, address: 0x20h, bits 0...3 */
+	p_reg_data = kzalloc(sizeof(struct ipc_io_bus_master_regs), GFP_KERNEL);
+	/*01 = W, 04 = bus, 20 = address*/
+	p_reg_data->ctrl_reg_addr = 0x01040020;
+	/*b3-b0 = 1010 (75kOhm pull-ups) = 0xAh*/
+	p_reg_data->ctrl_reg_data = 0xA;
+	ipc_program_io_bus_master(p_reg_data);
+/*	jhuot end */
+
 	/* Register the input device */
 	error = input_register_device(input_dev);
 	if (error) {
Index: linux-2.6.33/drivers/gpu/drm/mrst/Kconfig
===================================================================
--- linux-2.6.33.orig/drivers/gpu/drm/mrst/Kconfig
+++ linux-2.6.33/drivers/gpu/drm/mrst/Kconfig
@@ -23,6 +23,20 @@ config IMG_DOES_NOT_SUPPORT_MENLOW
 	help
 	  Choose Menlow
 
+config DRM_MRST_AAVA
+	bool "Aava platform specific MIPI display"
+	depends on DRM_MRST
+	default n
+	help
+	  Choose Aava platform MIPI display, temp option
+
+config DRM_MRST_CDK
+	bool "Aava platform specific MIPI display"
+	depends on DRM_MRST && !DRM_MRST_AAVA
+	default y
+	help
+	  Choose CDK
+
 config PVR_RELEASE
 	string "Build IMG kernel services as release"
 	depends on DRM_MRST
Index: linux-2.6.33/drivers/misc/Makefile
===================================================================
--- linux-2.6.33.orig/drivers/misc/Makefile
+++ linux-2.6.33/drivers/misc/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_SGI_XP)		+= sgi-xp/
 obj-$(CONFIG_SGI_GRU)		+= sgi-gru/
 obj-$(CONFIG_CS5535_MFGPT)	+= cs5535-mfgpt.o
 obj-$(CONFIG_HP_ILO)		+= hpilo.o
-obj-$(CONFIG_MRST)            += intel_mrst.o
+obj-$(CONFIG_X86_MRST)            += intel_mrst.o
 obj-$(CONFIG_ISL29003)		+= isl29003.o
 obj-$(CONFIG_MRST_RAR_HANDLER)	+= memrar.o
 memrar-y			:= memrar_allocator.o memrar_handler.o
Index: linux-2.6.33/drivers/misc/intel_mrst.c
===================================================================
--- linux-2.6.33.orig/drivers/misc/intel_mrst.c
+++ linux-2.6.33/drivers/misc/intel_mrst.c
@@ -112,6 +112,48 @@ static int intel_mrst_sdio_EVP_power_dow
 
 static int intel_mrst_sdio_8688_power_up(void)
 {
+/*ouljhuot start*/
+/*WLAN / BT power-up sequence:*/
+/*1. power (GPO4) & reset (GPO3) low*/
+/*2. power (GPO4) high*/
+/*3. reset (GPO3) high*/
+
+/*GPS power-up sequence:*/
+/*1. power (GPO1) & reset (GPO2) low*/
+/*2. VDD_IO and VDD_LP_PLLREG_IN high*/
+/*VDD_IO & VDD_LP_PLLREG_IN == VPMIC_1V8*/
+/*3. usleep(1) (tvddio_nreset min. 500ns)*/
+/*4. reset (GPO2) high*/
+/*5. VDD_COREREG_IN and VDD_RFREG_IN high*/
+	/*VDD_COREREG_IN == VWLAN_GPS_1V8 (GYMXIO)*/
+	/*VDD_RFREG_IN == VGPS_ANA_3V3 (GYMX33)*/
+/*6. power (GPO1) high*/
+/*7. msleep(1);*/
+	unsigned int temp = 0;
+
+	/* Register 0xf4 has 4 GPIO lines connected to the MRVL 8688 * IFX GPS:
+	 *     bit 4: WiFi PDn
+	 *     bit 3: WiFi RESETn
+	 *     bit 2: GPS RESET_N
+	 *     bit 1: GPS PD_N*/
+
+	/*WLAN POWER and RESET low*/
+	intel_mrst_pmic_read(0xf4, &temp);
+	temp &= ~0x18;
+	intel_mrst_pmic_write(0xf4, temp);
+/*	msleep(1);*/
+
+	/*GPS RESET low & POWER low*/
+	intel_mrst_pmic_read(0xf4, &temp);
+	temp &= ~0x6;
+	intel_mrst_pmic_write(0xf4, temp);
+/*	usleep(1);*/
+
+	msleep(1);
+	/*GPS RESET high*/
+	temp |= 0x4;
+	intel_mrst_pmic_write(0xf4, temp);
+/*ouljhuot end*/
 	intel_mrst_pmic_write(0x37, 0x3f); /* Set VDDQ for Marvell 8688 */
 	intel_mrst_pmic_write(0x4a, 0x3f); /* Set GYMXIOCNT for Marvell 8688 */
 	intel_mrst_pmic_write(0x4e, 0x3f); /* Set GYMX33CNT for Marvell 8688 */
@@ -124,6 +166,22 @@ static int intel_mrst_sdio_8688_power_up
 	intel_mrst_pmic_write(0x4c, 0x27); /* Enable V1p8_VWYMXARF for
 					      MRVL8688 */
 
+
+/*ouljhuot start*/
+	/*WLAN POWER high*/
+	temp |= 0x10;
+	intel_mrst_pmic_write(0xf4, temp);
+
+	/*WLAN RESET high*/
+	temp |= 0x8;
+	intel_mrst_pmic_write(0xf4, temp);
+
+	/*GPS POWER high*/
+	temp |= 0x2;
+	intel_mrst_pmic_write(0xf4, temp);
+/*	msleep(16);*/
+/*ouljhuot end*/
+
 	return 0;
 }
 
@@ -153,6 +211,35 @@ static int intel_mrst_bringup_8688_sdio2
 	return 0;
 }
 
+
+
+
+ /*ouljhuot start*/
+static int intel_mrst_sdio_gps_power_up(void)
+  {
+  	unsigned int temp = 0;
+  
+	/*GPS RESET low & POWER low*/
+	intel_mrst_pmic_read(0xf4, &temp);
+	temp &= ~0x6;
+  	intel_mrst_pmic_write(0xf4, temp);
+	msleep(1);
+	/*GPS RESET high*/
+	temp |= 0x4;
+  	intel_mrst_pmic_write(0xf4, temp);
+  
+	intel_mrst_pmic_write(0x4a, 0x3f); /* Ensure GYMXIOCNT */
+	intel_mrst_pmic_write(0x4e, 0x3f); /* Ensure GYMX33CNT */
+  
+	/*GPS POWER high*/
+	temp |= 0x2;
+	intel_mrst_pmic_write(0xf4, temp);
+	/* Wait to settle */
+	msleep(16);
+  
+  	return 0;
+  }
+
 static int intel_mrst_bringup_EVP_sdio2_Option_spi(void)
 {
 	unsigned int temp = 0;
@@ -199,7 +286,10 @@ static int __init intel_mrst_module_init
 
 	printk(KERN_INFO "intel_mrst_module_init: bringing up power for "
 	       "8688 WLAN on SDIO2 & IFX GPS over SPI...\n");
-	ret = intel_mrst_bringup_8688_sdio2();
+/*ouljhuot start*/
+	ret = intel_mrst_sdio_8688_power_up();
+/*	ret = intel_mrst_sdio_gps_power_up();*/
+/*ouljhuot end*/
 
 #endif /* CONFIG_8688_RC */
 
Index: linux-2.6.33/drivers/hwmon/lis331dl.c
===================================================================
--- linux-2.6.33.orig/drivers/hwmon/lis331dl.c
+++ linux-2.6.33/drivers/hwmon/lis331dl.c
@@ -45,6 +45,8 @@ MODULE_LICENSE("GPL v2");
 #define ACCEL_NORMAL_MODE 0
 #define ACCEL_MEMORY_REBOOT 1
 
+#define POS_READ_MAX_RETRY (5)
+
 /* internal return values */
 
 struct acclero_data {
@@ -93,9 +95,24 @@ static ssize_t x_pos_show(struct device 
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	int ret_val;
+	int retry = 0;
 
+x_retry:
 	ret_val = i2c_smbus_read_byte_data(client, 0x29);
-	return sprintf(buf, "%d\n", ret_val);
+	if (ret_val == -ETIMEDOUT) {
+		dev_dbg(dev, "x pos read timed out, retry %d\n", retry);
+		retry++;
+		if (retry <= POS_READ_MAX_RETRY) {
+			msleep(10);
+			goto x_retry;
+		} else {
+			ret_val = 0;
+			dev_err(dev, "x pos read failed %d retries\n", retry);
+		}
+	}
+	/* ouljkorh, 09.11.2009, change start */
+	return sprintf(buf, "%d\n", (signed char)ret_val);
+	/* ouljkorh, 09.11.2009, change end */
 }
 
 static ssize_t y_pos_show(struct device *dev,
@@ -103,9 +120,24 @@ static ssize_t y_pos_show(struct device 
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	int ret_val;
+	int retry = 0;
 
+y_retry:
 	ret_val = i2c_smbus_read_byte_data(client, 0x2B);
-	return sprintf(buf, "%d\n", ret_val);
+	if (ret_val == -ETIMEDOUT) {
+		dev_dbg(dev, "y pos read timed out, retry %d\n", retry);
+		retry++;
+		if (retry <= POS_READ_MAX_RETRY) {
+			msleep(10);
+			goto y_retry;
+		} else {
+			ret_val = 0;
+			dev_err(dev, "y pos read failed %d retries\n", retry);
+		}
+	}
+	/* ouljkorh, 09.11.2009, change start */
+	return sprintf(buf, "%d\n", (signed char)ret_val);
+	/* ouljkorh, 09.11.2009, change end */
 }
 
 static ssize_t z_pos_show(struct device *dev,
@@ -113,9 +145,24 @@ static ssize_t z_pos_show(struct device 
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	int ret_val;
+	int retry = 0;
 
+z_retry:
 	ret_val = i2c_smbus_read_byte_data(client, 0x2D);
-	return sprintf(buf, "%d\n", ret_val);
+	if (ret_val == -ETIMEDOUT) {
+		dev_dbg(dev, "z pos read timed out, retry %d\n", retry);
+		retry++;
+		if (retry <= POS_READ_MAX_RETRY) {
+			msleep(10);
+			goto z_retry;
+		} else {
+			ret_val = 0;
+			dev_err(dev, "z pos read failed %d retries\n", retry);
+		}
+	}
+	/* ouljkorh, 09.11.2009, change start */
+	return sprintf(buf, "%d\n", (signed char)ret_val);
+	/* ouljkorh, 09.11.2009, change end */
 }
 
 static ssize_t xyz_pos_show(struct device *dev,
@@ -123,11 +170,38 @@ static ssize_t xyz_pos_show(struct devic
 {
 	int x, y, z;
 	struct i2c_client *client = to_i2c_client(dev);
+	int retry = 0;
 
+xyz_retry:
+	if (retry > POS_READ_MAX_RETRY) {
+		dev_err(dev, "xyz read retry failed\n");
+		x = y = z = 0;
+		return sprintf(buf, "(%d,%d,%d)\n", (signed char)x,
+			(signed char)y, (signed char)z);
+	}
+	retry++;
 	x = i2c_smbus_read_byte_data(client, 0x29);
+	if (x == -ETIMEDOUT) {
+		msleep(100);
+		goto xyz_retry;
+	}
+	msleep(100);
 	y = i2c_smbus_read_byte_data(client, 0x2B);
+	if (y == -ETIMEDOUT) {
+		msleep(100);
+		goto xyz_retry;
+	}
+	msleep(100);
 	z = i2c_smbus_read_byte_data(client, 0x2D);
-	return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
+	if (z == -ETIMEDOUT) {
+		msleep(100);
+		goto xyz_retry;
+	}
+
+	/* ouljkorh, 09.11.2009, change start */
+	return sprintf(buf, "(%d,%d,%d)\n", (signed char)x,
+		(signed char)y, (signed char)z);
+	/* ouljkorh, 09.11.2009, change end */
 }
 
 static ssize_t data_rate_store(struct device *dev,
Index: linux-2.6.33/drivers/usb/gadget/u_serial.c
===================================================================
--- linux-2.6.33.orig/drivers/usb/gadget/u_serial.c
+++ linux-2.6.33/drivers/usb/gadget/u_serial.c
@@ -783,11 +783,6 @@ static int gs_open(struct tty_struct *tt
 	port->open_count = 1;
 	port->openclose = false;
 
-	/* low_latency means ldiscs work in tasklet context, without
-	 * needing a workqueue schedule ... easier to keep up.
-	 */
-	tty->low_latency = 1;
-
 	/* if connected, start the I/O stream */
 	if (port->port_usb) {
 		struct gserial	*gser = port->port_usb;
Index: linux-2.6.33/drivers/i2c/busses/i2c-mrst.c
===================================================================
--- linux-2.6.33.orig/drivers/i2c/busses/i2c-mrst.c
+++ linux-2.6.33/drivers/i2c/busses/i2c-mrst.c
@@ -37,7 +37,7 @@
 
 #include "i2c-mrst.h"
 
-#define MAX_T_POLL_COUNT	4000	/* FIXME */
+#define MAX_T_POLL_COUNT	8000	/* FIXME */
 #define DEF_BAR		0
 #define VERSION		"Version 0.5"
 
Index: linux-2.6.33/arch/x86/kernel/mrst.c
===================================================================
--- linux-2.6.33.orig/arch/x86/kernel/mrst.c
+++ linux-2.6.33/arch/x86/kernel/mrst.c
@@ -23,6 +23,9 @@
 #include <linux/input.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
+/*jhuot, added for MAX3107 data*/
+#include <linux/spi/mrst_spi.h>
+
 
 #include <asm/string.h>
 #include <asm/setup.h>
@@ -267,6 +270,27 @@ void __init x86_mrst_early_setup(void)
 #define MRST_SPI2_CS_START	4
 static struct langwell_pmic_gpio_platform_data pmic_gpio_pdata;
 
+#ifdef CONFIG_SERIAL_MAX3107
+static struct mrst_spi_chip spi_slave0 = {
+	.poll_mode = 1,
+	.enable_dma = 0,
+	.type = SPI_FRF_SPI,
+};
+
+static struct spi_board_info mrst_spi_board_info[] __initdata = {
+	{
+		/* the modalias must be the same as spi device driver name */
+		.modalias = "max3107",	/* spi_driver name driving device */
+		.max_speed_hz = 3125000,/* default value */
+		.bus_num = 0,		/* SPI0 */
+		.chip_select = 0,	/* Framework chip select. */
+		.platform_data = NULL,	/* fill later */
+		.controller_data = &spi_slave0,
+		.irq = 0x13d,
+	},
+};
+#endif
+
 static int __init sfi_parse_spib(struct sfi_table_header *table)
 {
 	struct sfi_table_simple *sb;
@@ -290,31 +314,48 @@ static int __init sfi_parse_spib(struct 
 		pr_info("Moorestown SPI devices info:\n");
 
 	for (i = 0, j = 0; i < num; i++, pentry++) {
-		strncpy(info[j].modalias, pentry->name, 16);
-		info[j].irq = pentry->irq_info;
-		info[j].bus_num = pentry->host_num;
-		info[j].chip_select = pentry->cs;
-		info[j].max_speed_hz = 3125000;	/* hard coded */
-		if (info[i].chip_select >= MRST_SPI2_CS_START) {
-			/* these SPI2 devices are not exposed to system as PCI
-			 * devices, but they have separate RTE entry in IOAPIC
-			 * so we have to enable them one by one here
-			 */
-			ioapic = mp_find_ioapic(info[j].irq);
-			irq_attr.ioapic = ioapic;
-			irq_attr.ioapic_pin = info[j].irq;
-			irq_attr.trigger = 1;
-			irq_attr.polarity = 1;
-			io_apic_set_pci_routing(NULL, info[j].irq,
+#ifdef CONFIG_SERIAL_MAX3107
+		if (j != 1) {	/*other devices info*/
+#endif
+			strncpy(info[j].modalias, pentry->name, 16);
+			info[j].irq = pentry->irq_info;
+			info[j].bus_num = pentry->host_num;
+			info[j].chip_select = pentry->cs;
+			info[j].max_speed_hz = 3125000;	/* hard coded */
+			if (info[i].chip_select >= MRST_SPI2_CS_START) {
+				/* these SPI2 devices are not exposed to system as PCI
+				 * devices, but they have separate RTE entry in IOAPIC
+				 * so we have to enable them one by one here
+				 */
+				ioapic = mp_find_ioapic(info[j].irq);
+				irq_attr.ioapic = ioapic;
+				irq_attr.ioapic_pin = info[j].irq;
+				irq_attr.trigger = 1;
+				irq_attr.polarity = 1;
+				io_apic_set_pci_routing(NULL, info[j].irq,
 							&irq_attr);
-		}
-		info[j].platform_data = pentry->dev_info;
+			}
 
-		if (!strcmp(pentry->name, "pmic_gpio")) {
-			memcpy(&pmic_gpio_pdata, pentry->dev_info, 8);
-			pmic_gpio_pdata.gpiointr = 0xffffeff8;
-			info[j].platform_data = &pmic_gpio_pdata;
+			info[j].platform_data = pentry->dev_info;
+
+			if (!strcmp(pentry->name, "pmic_gpio")) {
+				memcpy(&pmic_gpio_pdata, pentry->dev_info, 8);
+				pmic_gpio_pdata.gpiointr = 0xffffeff8;
+				info[j].platform_data = &pmic_gpio_pdata;
+			}
+#ifdef CONFIG_SERIAL_MAX3107
+		} else {	/*MAX3107 info*/
+			info[j] = mrst_spi_board_info[0];
+		}
+			
+#endif
+		/* jhuot edit start: change GPS chip select from 2 to 3 */
+		if (info[j].bus_num == 0 && info[j].chip_select == 2) {
+			info[j].chip_select = 3;
+		} else if (info[j].bus_num == 0 && info[j].chip_select == 3) {
+			info[j].chip_select = 2;
 		}
+		/* jhuot edit end */
 		pr_info("info[%d]: name = %16s, irq = 0x%04x, bus = %d, "
 			"cs = %d\n", j, info[j].modalias, info[j].irq,
 			info[j].bus_num, info[j].chip_select);
Index: linux-2.6.33/drivers/serial/Kconfig
===================================================================
--- linux-2.6.33.orig/drivers/serial/Kconfig
+++ linux-2.6.33/drivers/serial/Kconfig
@@ -540,6 +540,21 @@ config SERIAL_S5PC100
 	help
 	  Serial port support for the Samsung S5PC100 SoCs
 
+config SERIAL_MAX3107
+	tristate "MAX3107 support"
+	depends on SPI
+	select SERIAL_CORE
+	help
+          MAX3107 chip support
+
+config MAX3107_LOW_POWER
+	boolean "Enable very low power consumption scheme for Max3107"
+	default n
+	depends on SERIAL_MAX3107
+	help
+	  Adds hardware suspend for MAX3107 instead of sleep/auto-sleep,
+	  but causes longer latency in wake-up (re-initialization of the chip).
+
 config SERIAL_MAX3100
 	tristate "MAX3100 support"
 	depends on SPI
Index: linux-2.6.33/drivers/serial/Makefile
===================================================================
--- linux-2.6.33.orig/drivers/serial/Makefile
+++ linux-2.6.33/drivers/serial/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.
 obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
 obj-$(CONFIG_SERIAL_S5PC100) += s3c6400.o
 obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
+obj-$(CONFIG_SERIAL_MAX3107) += max3107.o
 obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
 obj-$(CONFIG_SERIAL_MUX) += mux.o
 obj-$(CONFIG_SERIAL_68328) += 68328serial.o
Index: linux-2.6.33/drivers/serial/max3107.c
===================================================================
--- /dev/null
+++ linux-2.6.33/drivers/serial/max3107.c
@@ -0,0 +1,1484 @@
+/*
+ *  max3107.c - spi uart protocol driver for Maxim 3107
+ *	Based on 	max3100.c
+ *	by Christian Pellegrin <chripell@evolware.org>
+ *	and 		max3110.c
+ *	by Feng Tang <feng.tang@intel.com>
+ *
+ *  Copyright (C) Aavamobile 2009
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  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
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/mrst_spi.h>
+#include <linux/freezer.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/serial_max3107.h>
+
+/* Debug trace definitions */
+#define DBG_LEVEL 0
+
+#if (DBG_LEVEL > 0)
+#define DBG_TRACE(format,args...) printk(KERN_ERR "%s: " format, \
+						__FUNCTION__ , ## args)
+#else
+#define DBG_TRACE(format,args...)
+#endif
+
+#if (DBG_LEVEL > 1)
+#define DBG_TRACE_SPI_DATA
+#endif
+
+struct max3107_port {
+	/* UART port structure */
+	struct uart_port port;
+
+	/* SPI device structure */
+	struct spi_device *spi;
+
+	/* GPIO chip stucture */
+	struct gpio_chip chip;
+
+	/* Workqueue that does all the magic */
+	struct workqueue_struct *workqueue;
+	struct work_struct work;
+
+	/* Lock for shared data */
+	spinlock_t data_lock;
+
+	/* Device configuration */
+	int ext_clk;		/* 1 if external clock used */
+	int loopback;		/* Current loopback mode state */
+	int baud;			/* Current baud rate */
+
+	/* State flags */
+	int suspended;		/* Indicates suspend mode */
+	int tx_fifo_empty;	/* Flag for TX FIFO state */
+	int rx_enabled;		/* Flag for receiver state */
+	int tx_enabled;		/* Flag for transmitter state */
+
+	/* Shared data */
+	u16 irqen_reg;		/* Current IRQ enable register value */
+	u16 mode1_reg;		/* Current mode1 register value*/
+	int mode1_commit;	/* Flag for setting new mode1 register value */
+	u16 lcr_reg;		/* Current LCR register value */
+	int lcr_commit;		/* Flag for setting new LCR register value */
+	u32 brg_cfg;		/* Current Baud rate generator config  */
+	int brg_commit;		/* Flag for setting new baud rate generator
+				 * config
+				 */
+
+	int handle_irq;		/* Indicates that IRQ should be handled */
+};
+
+/* Platform data structure */
+struct max3107_plat {
+	/* Loopback mode enable */
+	int loopback;
+	/* External clock enable */
+	int ext_clk;
+	/* HW suspend function */
+	void (*max3107_hw_suspend) (struct max3107_port *s, int suspend);
+	/* Polling mode enable */
+	int polled_mode;
+	/* Polling period if polling mode enabled */
+	int poll_time;
+};
+
+
+/* Perform SPI transfer for write/read of device register(s) */
+static int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len)
+{
+	struct spi_message spi_msg;
+	struct spi_transfer spi_xfer;
+
+	DBG_TRACE("enter\n");
+
+	/* Initialize SPI ,message */
+	spi_message_init(&spi_msg);
+
+	/* Initialize SPI transfer */
+	memset(&spi_xfer, 0, sizeof spi_xfer);
+	spi_xfer.len = len;
+	spi_xfer.tx_buf = tx;
+	spi_xfer.rx_buf = rx;
+	spi_xfer.speed_hz = MAX3107_SPI_SPEED;
+
+	/* Add SPI transfer to SPI message */
+	spi_message_add_tail(&spi_xfer, &spi_msg);
+
+#ifdef DBG_TRACE_SPI_DATA
+	{
+		int i;
+		printk("tx len %d:\n", spi_xfer.len);
+		for (i = 0 ; i < spi_xfer.len && i < 32 ; i++) {
+			printk(" %x", ((u8*)spi_xfer.tx_buf)[i]);
+		}
+		printk("\n");
+	}
+#endif
+
+	/* Perform synchronous SPI transfer */
+	if (spi_sync(s->spi, &spi_msg)) {
+		dev_err(&s->spi->dev, "spi_sync failure\n");
+		return -EIO;
+	}
+
+#ifdef DBG_TRACE_SPI_DATA
+	if (spi_xfer.rx_buf) {
+		int i;
+		printk("rx len %d:\n", spi_xfer.len);
+		for (i = 0 ; i < spi_xfer.len && i < 32 ; i++) {
+			printk(" %x", ((u8*)spi_xfer.rx_buf)[i]);
+		}
+		printk("\n");
+	}
+#endif
+	return 0;
+}
+
+/* Puts received data to circular buffer */
+static void put_data_to_circ_buf(struct max3107_port *s, unsigned char *data,
+					int len)
+{
+	struct uart_port *port = &s->port;
+	struct tty_struct *tty;
+
+	DBG_TRACE("enter\n");
+
+	if (!port->state) {
+		/* UART is not open */
+		dev_warn(&s->spi->dev, "UART is closed\n");
+		return;
+	}
+
+	tty = port->state->port.tty;
+	if (!tty) {
+		/* TTY is not open */
+		dev_warn(&s->spi->dev, "TTY is closed\n");
+		return;
+	}
+
+	/* Insert received data */
+	tty_insert_flip_string(tty, data, len);
+	/* Update RX counter */
+	port->icount.rx += len;
+}
+
+/* Handle data receiving */
+static void max3107_handlerx(struct max3107_port *s, u16 rxlvl)
+{
+	int i;
+	int j;
+	int len;				/* SPI transfer buffer length */
+	u16 buf[MAX3107_RX_FIFO_SIZE+2];	/* SPI transfer buffer
+						 * +2 for RX FIFO interrupt
+						 * disabling and RX level query
+						 */
+	u8 valid_str[MAX3107_RX_FIFO_SIZE];
+
+	DBG_TRACE("enter\n");
+
+	if (!s->rx_enabled) {
+		/* RX is disabled */
+		return;
+	}
+
+	if (rxlvl == 0) {
+		/* RX fifo is empty */
+		return;
+	} else if (rxlvl >= MAX3107_RX_FIFO_SIZE) {
+		dev_warn(&s->spi->dev, "Possible RX FIFO overrun %d\n", rxlvl);
+		/* Ensure sanity of RX level */
+		rxlvl = MAX3107_RX_FIFO_SIZE;
+	}
+
+	while (rxlvl) {
+		DBG_TRACE("rxlvl %d\n", rxlvl);
+		/* Clear buffer */
+		memset(buf, 0, sizeof(buf));
+		len = 0;
+		if (s->irqen_reg & MAX3107_IRQ_RXFIFO_BIT) {
+			/* First disable RX FIFO interrupt */
+			DBG_TRACE("Disabling RX INT\n");
+			buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
+			spin_lock(&s->data_lock);
+			s->irqen_reg &= ~MAX3107_IRQ_RXFIFO_BIT;
+			buf[0] |= s->irqen_reg;
+			spin_unlock(&s->data_lock);
+			len++;
+		}
+		/* Just increase the length by amount of words in FIFO since
+		 * buffer was zeroed and SPI transfer of 0x0000 means reading
+		 * from RX FIFO
+		 */
+		len += rxlvl;
+		/* Append RX level query */
+		buf[len] = MAX3107_RXFIFOLVL_REG;
+		len++;
+
+		/* Perform the SPI transfer */
+		if (max3107_rw(s, (u8 *)buf, (u8 *)buf, len*2)) {
+			dev_err(&s->spi->dev,
+				"SPI transfer for RX handling failed\n");
+			return;
+		}
+
+		/* Skip RX FIFO interrupt disabling word if it was added */
+		j = ((len-1)-rxlvl);
+		/* Read received words */
+		for (i = 0; i < rxlvl; i++, j++) {
+			valid_str[i] = (u8)buf[j];
+		}
+		put_data_to_circ_buf(s, valid_str, rxlvl);
+		/* Get new RX level */
+		rxlvl = (buf[len-1] & MAX3107_SPI_RX_DATA_MASK);
+	}
+
+	if (s->rx_enabled) {
+		/* RX still enabled, re-enable RX FIFO interrupt */
+		DBG_TRACE("Enabling RX INT\n");
+		buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
+		spin_lock(&s->data_lock);
+		s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT;
+		buf[0] |= s->irqen_reg;
+		spin_unlock(&s->data_lock);
+		if (max3107_rw(s, (u8 *)buf, NULL, 2)) {
+			dev_err(&s->spi->dev,
+				"RX FIFO interrupt enabling failed\n");
+		}
+	}
+
+	/* Push the received data to receivers */
+	tty_flip_buffer_push(s->port.state->port.tty);
+}
+
+
+/* Handle data sending */
+static void max3107_handletx(struct max3107_port *s)
+{
+	struct circ_buf *xmit = &s->port.state->xmit;
+	int i;
+	int len;				/* SPI transfer buffer length */
+	u16 buf[MAX3107_TX_FIFO_SIZE+3];	/* SPI transfer buffer
+						 * +3 for TX FIFO empty
+						 * interrupt disabling and
+						 * enabling and TX enabling
+						 */
+
+	DBG_TRACE("enter\n");
+
+	if (!s->tx_fifo_empty) {
+		/* Don't send more data before previous data is sent */
+		return;
+	}
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port)) {
+		/* No data to send or TX is stopped */
+		return;
+	}
+
+	/* Get length of data pending in circular buffer */
+	len = uart_circ_chars_pending(xmit);
+	if (len) {
+		/* Limit to size of TX FIFO */
+		if (len > MAX3107_TX_FIFO_SIZE)
+			len = MAX3107_TX_FIFO_SIZE;
+
+		DBG_TRACE("txlen %d\n", len);
+
+		/* Update TX counter */
+		s->port.icount.tx += len;
+
+		/* TX FIFO will no longer be empty */
+		s->tx_fifo_empty = 0;
+
+		i = 0;
+		if (s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT) {
+			/* First disable TX empty interrupt */
+			DBG_TRACE("Disabling TE INT\n");
+			buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
+			spin_lock(&s->data_lock);
+			s->irqen_reg &= ~MAX3107_IRQ_TXEMPTY_BIT;
+			buf[i] |= s->irqen_reg;
+			spin_unlock(&s->data_lock);
+			i++;
+			len++;
+		}
+
+		/* Add data to send */
+		for ( ; i < len ; i++ ) {
+			buf[i] = (MAX3107_WRITE_BIT | MAX3107_THR_REG);
+			buf[i] |= ((u16)xmit->buf[xmit->tail] &
+						MAX3107_SPI_TX_DATA_MASK);
+			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		}
+
+		if (!(s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT)) {
+			/* Enable TX empty interrupt */
+			DBG_TRACE("Enabling TE INT\n");
+			buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
+			spin_lock(&s->data_lock);
+			s->irqen_reg |= MAX3107_IRQ_TXEMPTY_BIT;
+			buf[i] |= s->irqen_reg;
+			spin_unlock(&s->data_lock);
+			i++;
+			len++;
+		}
+		if (!s->tx_enabled) {
+			/* Enable TX */
+			DBG_TRACE("Enable TX\n");
+			buf[i] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
+			spin_lock(&s->data_lock);
+			s->mode1_reg &= ~MAX3107_MODE1_TXDIS_BIT;
+			buf[i] |= s->mode1_reg;
+			spin_unlock(&s->data_lock);
+			s->tx_enabled = 1;
+			i++;
+			len++;
+		}
+
+		/* Perform the SPI transfer */
+		if (max3107_rw(s, (u8 *)buf, NULL, len*2)) {
+			dev_err(&s->spi->dev,
+				"SPI transfer for TX handling failed\n");
+			return;
+		}
+	}
+
+	/* Indicate wake up if circular buffer is getting low on data */
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&s->port);
+
+}
+
+/* Handle interrupts
+ * Also reads and returns current RX FIFO level
+ */
+static u16 handle_interrupt(struct max3107_port *s)
+{
+	u16 buf[4];	/* Buffer for SPI transfers */
+	u8 irq_status;
+	u16 rx_level;
+
+	DBG_TRACE("enter\n");
+
+	/* Read IRQ status register */
+	buf[0] = MAX3107_IRQSTS_REG;
+	/* Read status IRQ status register */
+	buf[1] = MAX3107_STS_IRQSTS_REG;
+	/* Read LSR IRQ status register */
+	buf[2] = MAX3107_LSR_IRQSTS_REG;
+	/* Query RX level */
+	buf[3] = MAX3107_RXFIFOLVL_REG;
+
+	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 8)) {
+		dev_err(&s->spi->dev,
+			"SPI transfer for interrupt handling failed\n");
+		return 0;
+	}
+
+	irq_status = (u8)buf[0];
+	DBG_TRACE("IRQSTS %x\n", irq_status);
+	rx_level = (buf[3] & MAX3107_SPI_RX_DATA_MASK);
+
+	if (irq_status & MAX3107_IRQ_LSR_BIT) {
+		/* LSR interrupt */
+		if ( buf[2] & MAX3107_LSR_RXTO_BIT ) {
+			/* RX timeout interrupt,
+			 * handled by normal RX handling
+			 */
+			DBG_TRACE("RX TO INT\n");
+		}
+	}
+
+	if (irq_status & MAX3107_IRQ_TXEMPTY_BIT) {
+		/* Tx empty interrupt,
+		 * disable TX and set tx_fifo_empty flag
+		 */
+		DBG_TRACE("TE INT, disabling TX\n");
+		buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
+		spin_lock(&s->data_lock);
+		s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT;
+		buf[0] |= s->mode1_reg;
+		spin_unlock(&s->data_lock);
+		if (max3107_rw(s, (u8 *)buf, NULL, 2))
+			dev_err(&s->spi->dev,
+				"SPI transfer for TX disabling failed\n");
+		s->tx_enabled = 0;
+		s->tx_fifo_empty = 1;
+	}
+
+	if (irq_status & MAX3107_IRQ_RXFIFO_BIT) {
+		/* RX FIFO interrupt,
+		 * handled by normal RX handling
+		 */
+		DBG_TRACE("RFIFO INT\n");
+	}
+
+	/* Return RX level */
+	return rx_level;
+}
+
+/* Trigger work thread*/
+static void max3107_dowork(struct max3107_port *s)
+{
+	if (!work_pending(&s->work) && !freezing(current) && !s->suspended)
+		queue_work(s->workqueue, &s->work);
+}
+
+/* Work thread */
+static void max3107_work(struct work_struct *w)
+{
+	struct max3107_port *s = container_of(w, struct max3107_port, work);
+	u16 rxlvl = 0;
+	int len;	/* SPI transfer buffer length */
+	u16 buf[5];	/* Buffer for SPI transfers */
+
+	DBG_TRACE("enter\n");
+
+	/* Start by reading current RX FIFO level */
+	buf[0] = MAX3107_RXFIFOLVL_REG;
+	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
+		dev_err(&s->spi->dev,
+			"SPI transfer for RX level query failed\n");
+		rxlvl = 0;
+	} else {
+		rxlvl = (buf[0] & MAX3107_SPI_RX_DATA_MASK);
+	}
+
+	do {
+		DBG_TRACE("rxlvl %d\n", rxlvl);
+
+		/* Handle RX */
+		max3107_handlerx(s, rxlvl);
+		rxlvl = 0;
+
+		if (s->handle_irq) {
+			/* Handle pending interrupts
+			 * We also get new RX FIFO level since new data may
+			 * have been received while pushing received data to
+			 * receivers
+			 */
+			s->handle_irq = 0;
+			rxlvl = handle_interrupt(s);
+		}
+
+		/* Handle TX */
+		max3107_handletx(s);
+
+		/* Handle configuration changes */
+		len = 0;
+		spin_lock(&s->data_lock);
+		if (s->mode1_commit) {
+			DBG_TRACE("mode1_commit\n");
+			buf[len] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
+			buf[len++] |= s->mode1_reg;
+			s->mode1_commit = 0;
+		}
+		if (s->lcr_commit) {
+			DBG_TRACE("lcr_commit\n");
+			buf[len] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG);
+			buf[len++] |= s->lcr_reg;
+			s->lcr_commit = 0;
+		}
+		if (s->brg_commit) {
+			DBG_TRACE("brg_commit\n");
+			buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG);
+			buf[len++] |= ((s->brg_cfg >> 16) &
+						MAX3107_SPI_TX_DATA_MASK);
+			buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG);
+			buf[len++] |= ((s->brg_cfg >> 8) &
+						MAX3107_SPI_TX_DATA_MASK);
+			buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG);
+			buf[len++] |= ((s->brg_cfg) & 0xff);
+			s->brg_commit = 0;
+		}
+		spin_unlock(&s->data_lock);
+
+		if (len > 0) {
+			if (max3107_rw(s, (u8 *)buf, NULL, len*2))
+				dev_err(&s->spi->dev,
+					"SPI transfer for config failed\n");
+		}
+
+		/* Reloop if interrupt handling indicated data in RX FIFO */
+	} while (rxlvl);
+
+}
+
+/* Set sleep mode */
+static void max3107_set_sleep(struct max3107_port *s, int mode)
+{
+	u16 buf[1];	/* Buffer for SPI transfer */
+
+	DBG_TRACE("enter, mode %d\n", mode);
+
+	buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
+	spin_lock(&s->data_lock);
+	switch (mode) {
+	case MAX3107_DISABLE_FORCED_SLEEP:
+			s->mode1_reg &= ~MAX3107_MODE1_FORCESLEEP_BIT;
+			break;
+	case MAX3107_ENABLE_FORCED_SLEEP:
+			s->mode1_reg |= MAX3107_MODE1_FORCESLEEP_BIT;
+			break;
+	case MAX3107_DISABLE_AUTOSLEEP:
+			s->mode1_reg &= ~MAX3107_MODE1_AUTOSLEEP_BIT;
+			break;
+	case MAX3107_ENABLE_AUTOSLEEP:
+			s->mode1_reg |= MAX3107_MODE1_AUTOSLEEP_BIT;
+			break;
+	default:
+		spin_unlock(&s->data_lock);
+		dev_warn(&s->spi->dev, "invalid sleep mode\n");
+		return;
+	}
+	buf[0] |= s->mode1_reg;
+	spin_unlock(&s->data_lock);
+
+	if (max3107_rw(s, (u8 *)buf, NULL, 2))
+		dev_err(&s->spi->dev, "SPI transfer for sleep mode failed\n");
+
+	if (mode == MAX3107_DISABLE_AUTOSLEEP ||
+		mode == MAX3107_DISABLE_FORCED_SLEEP ) {
+		msleep(MAX3107_WAKEUP_DELAY);
+	}
+}
+
+/* Perform full register initialization */
+static void max3107_register_init(struct max3107_port *s)
+{
+	int len = 0;	/* SPI transfer buffer length */
+	u16 buf[11];	/* Buffer for SPI transfers */
+
+	DBG_TRACE("enter\n");
+
+	/* 1. Configure baud rate, 9600 as default */
+	s->baud = 9600;
+	if (s->ext_clk)
+		s->brg_cfg = MAX3107_BRG_B9600;
+	else
+		s->brg_cfg = MAX3107_BRG_IB9600;
+	buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG);
+	buf[len++] |= ((s->brg_cfg >> 16) & MAX3107_SPI_TX_DATA_MASK);
+	buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG);
+	buf[len++] |= ((s->brg_cfg >> 8) & MAX3107_SPI_TX_DATA_MASK);
+	buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG);
+	buf[len++] |= ((s->brg_cfg) & 0xff);
+
+	/* 2. Configure LCR register, 8N1 mode by default */
+	s->lcr_reg = MAX3107_LCR_WORD_LEN_8;
+	buf[len] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG);
+	buf[len++] |= s->lcr_reg;
+
+	/* 3. Configure MODE 1 register */
+	s->mode1_reg = 0;
+	/* Enable IRQ pin */
+	s->mode1_reg |= MAX3107_MODE1_IRQSEL_BIT;
+	/* Disable TX */
+	s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT;
+	s->tx_enabled = 0;
+	/* RX is enabled */
+	s->rx_enabled = 1;
+	buf[len] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
+	buf[len++] |= s->mode1_reg;
+
+	/* 4. Configure MODE 2 register */
+	buf[len] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG);
+	if (s->loopback) {
+		/* Enable loopback */
+		buf[len] |= MAX3107_MODE2_LOOPBACK_BIT;
+	}
+	/* Reset FIFOs */
+	buf[len++] |= MAX3107_MODE2_FIFORST_BIT;
+	s->tx_fifo_empty = 1;
+
+	/* 5. Configure FIFO trigger level register */
+	buf[len] = (MAX3107_WRITE_BIT | MAX3107_FIFOTRIGLVL_REG);
+	/* RX FIFO trigger for 16 words, TX FIFO trigger not used */
+	buf[len++] |= (MAX3107_FIFOTRIGLVL_RX(16) | MAX3107_FIFOTRIGLVL_TX(0));
+
+	/* 6. Configure flow control levels */
+	buf[len] = (MAX3107_WRITE_BIT | MAX3107_FLOWLVL_REG);
+	/* Flow control halt level 96, resume level 48 */
+	buf[len++] |= (MAX3107_FLOWLVL_RES(48) | MAX3107_FLOWLVL_HALT(96));
+
+	/* 7. Configure flow control */
+	buf[len] = (MAX3107_WRITE_BIT | MAX3107_FLOWCTRL_REG);
+	/* Enable auto CTS and auto RTS flow control */
+	buf[len++] |= (MAX3107_FLOWCTRL_AUTOCTS_BIT |
+						MAX3107_FLOWCTRL_AUTORTS_BIT);
+
+	/* 8. Configure RX timeout register */
+	buf[len] = (MAX3107_WRITE_BIT | MAX3107_RXTO_REG);
+	/* Timeout after 48 character intervals */
+	buf[len++] |= 0x0030;
+
+	/* 9. Configure LSR interrupt enable register */
+	buf[len] = (MAX3107_WRITE_BIT | MAX3107_LSR_IRQEN_REG);
+	/* Enable RX timeout interrupt */
+	buf[len++] |= MAX3107_LSR_RXTO_BIT;
+
+	/* Perform SPI transfer */
+	if (max3107_rw(s, (u8 *)buf, NULL, len*2))
+		dev_err(&s->spi->dev, "SPI transfer for init failed\n");
+
+	len = 0;
+	/* 10. Clear IRQ status register by reading it */
+	buf[len++] = MAX3107_IRQSTS_REG;
+
+	/* 11. Configure interrupt enable register */
+	/* Enable LSR interrupt */
+	s->irqen_reg = MAX3107_IRQ_LSR_BIT;
+	/* Enable RX FIFO interrupt */
+	s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT;
+	buf[len] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
+	buf[len++] |= s->irqen_reg;
+
+	/* 12. Clear FIFO reset that was set in step 6 */
+	buf[len] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG);
+	if (s->loopback) {
+		/* Keep loopback enabled */
+		buf[len] |= MAX3107_MODE2_LOOPBACK_BIT;
+	}
+	buf[len++] |= 0x0000;
+
+	/* Perform SPI transfer */
+	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, len*2))
+		dev_err(&s->spi->dev, "SPI transfer for init failed\n");
+
+}
+
+/* IRQ handler */
+static irqreturn_t max3107_irq(int irqno, void *dev_id)
+{
+	struct max3107_port *s = dev_id;
+
+	if (irqno != s->spi->irq) {
+		/* Unexpected IRQ */
+		return IRQ_NONE;
+	}
+
+	/* Indicate irq */
+	s->handle_irq = 1;
+
+	/* Trigger work thread */
+	max3107_dowork(s);
+
+	return IRQ_HANDLED;
+}
+
+/* HW suspension function
+ *
+ * Currently autosleep is used to decrease current consumption, alternative
+ * approach would be to set the chip to reset mode if UART is not being
+ * used but that would mess the GPIOs
+ *
+ */
+static void max3107_hw_susp(struct max3107_port *s, int suspend)
+{
+	DBG_TRACE("enter, suspend %d\n", suspend);
+
+	if (suspend) {
+		/* Suspend requested,
+		 * enable autosleep to decrease current consumption
+		 */
+		s->suspended = 1;
+		max3107_set_sleep(s, MAX3107_ENABLE_AUTOSLEEP);
+	} else {
+		/* Resume requested,
+		 * disable autosleep
+		 */
+		s->suspended = 0;
+		max3107_set_sleep(s, MAX3107_DISABLE_AUTOSLEEP);
+	}
+}
+
+/* Modem status IRQ enabling */
+static void max3107_enable_ms(struct uart_port *port)
+{
+	/* Modem status not supported */
+}
+
+/* Data send function */
+static void max3107_start_tx(struct uart_port *port)
+{
+	struct max3107_port *s = container_of(port, struct max3107_port, port);
+
+	DBG_TRACE("enter\n");
+
+	/* Trigger work thread for sending data */
+	max3107_dowork(s);
+}
+
+/* Function for checking that there is no pending transfers */
+static unsigned int max3107_tx_empty(struct uart_port *port)
+{
+	struct max3107_port *s = container_of(port, struct max3107_port, port);
+
+	DBG_TRACE("returning %d\n",
+		  (s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit)));
+	return (s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit));
+}
+
+/* Function for stopping RX */
+static void max3107_stop_rx(struct uart_port *port)
+{
+	struct max3107_port *s = container_of(port, struct max3107_port, port);
+
+	DBG_TRACE("enter\n");
+
+	/* Set RX disabled in MODE 1 register */
+	spin_lock(&s->data_lock);
+	s->mode1_reg |= MAX3107_MODE1_RXDIS_BIT;
+	s->mode1_commit = 1;
+	spin_unlock(&s->data_lock);
+	/* Set RX disabled */
+	s->rx_enabled = 0;
+	/* Trigger work thread for doing the actual configuration change */
+	max3107_dowork(s);
+}
+
+/* Function for returning control pin states */
+static unsigned int max3107_get_mctrl(struct uart_port *port)
+{
+	/* DCD and DSR are not wired and CTS/RTS is handled automatically
+	 * so just indicate DSR and CAR asserted
+	 */
+	return (TIOCM_DSR | TIOCM_CAR);
+}
+
+/* Function for setting control pin states */
+static void max3107_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	/* DCD and DSR are not wired and CTS/RTS is hadnled automatically
+	 * so do nothing
+	 */
+}
+
+/* Function for configuring UART parameters */
+static void max3107_set_termios(struct uart_port *port,
+				struct ktermios *termios,
+				struct ktermios *old)
+{
+	struct max3107_port *s = container_of(port, struct max3107_port, port);
+	struct tty_struct *tty;
+	int baud;
+	u16 new_lcr = 0;
+	u32 new_brg = 0;
+
+	DBG_TRACE("enter\n");
+
+	if (!port->state) {
+		/* UART is not open */
+		dev_warn(&s->spi->dev, "UART is closed\n");
+		return;
+	}
+
+	tty = port->state->port.tty;
+	if (!tty) {
+		/* TTY is not open */
+		dev_warn(&s->spi->dev, "TTY is closed\n");
+		return;
+	}
+
+	if (old) {
+		if ((termios->c_cflag == old->c_cflag) &&
+			(RELEVANT_IFLAG(termios->c_iflag) ==
+				RELEVANT_IFLAG(old->c_iflag))) {
+			/* Nothing relevant is changing */
+			return;
+		}
+	}
+
+	/* Get new LCR register values */
+	/* Word size */
+	if ((termios->c_cflag & CSIZE) == CS7)
+		new_lcr |= MAX3107_LCR_WORD_LEN_7;
+	else
+		new_lcr |= MAX3107_LCR_WORD_LEN_8;
+
+	/* Parity */
+	if (termios->c_cflag & PARENB) {
+		new_lcr |= MAX3107_LCR_PARITY_BIT;
+		if (!(termios->c_cflag & PARODD))
+			new_lcr |= MAX3107_LCR_EVENPARITY_BIT;
+	}
+
+	/* Stop bits */
+	if (termios->c_cflag & CSTOPB) {
+		/* 2 stop bits */
+		new_lcr |= MAX3107_LCR_STOPLEN_BIT;
+	}
+
+	/* Mask termios capabilities we don't support */
+	termios->c_cflag &= ~CMSPAR;
+
+	/* Set status ignore mask */
+	s->port.ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		s->port.ignore_status_mask |= MAX3107_ALL_ERRORS;
+
+	/* Set low latency to immediately handle pushed data */
+	s->port.state->port.tty->low_latency = 1;
+
+	/* Get new baud rate generator configuration */
+	baud = tty_get_baud_rate(tty);
+	switch (baud) {
+	case 300:
+		new_brg = s->ext_clk ? MAX3107_BRG_B300 : MAX3107_BRG_IB300;
+		break;
+	case 600:
+		new_brg = s->ext_clk ? MAX3107_BRG_B600 : MAX3107_BRG_IB600;
+		break;
+	case 1200:
+		new_brg = s->ext_clk ? MAX3107_BRG_B1200 : MAX3107_BRG_IB1200;
+		break;
+	case 2400:
+		new_brg = s->ext_clk ? MAX3107_BRG_B2400 : MAX3107_BRG_IB2400;
+		break;
+	case 4800:
+		new_brg = s->ext_clk ? MAX3107_BRG_B4800 : MAX3107_BRG_IB4800;
+		break;
+	case 9600:
+		new_brg = s->ext_clk ? MAX3107_BRG_B9600 : MAX3107_BRG_IB9600;
+		break;
+	case 19200:
+		new_brg = s->ext_clk ? MAX3107_BRG_B19200 : MAX3107_BRG_IB19200;
+		break;
+	case 38400:
+		new_brg = s->ext_clk ? MAX3107_BRG_B38400 : MAX3107_BRG_IB38400;
+		break;
+	case 57600:
+		new_brg = s->ext_clk ? MAX3107_BRG_B57600 : MAX3107_BRG_IB57600;
+		break;
+	case 115200:
+		new_brg = s->ext_clk ? MAX3107_BRG_B115200 : MAX3107_BRG_IB115200;
+		break;
+	case 230400:
+		new_brg = s->ext_clk ? MAX3107_BRG_B230400 : MAX3107_BRG_IB230400;
+		break;
+	case 460800:
+		new_brg = s->ext_clk ? MAX3107_BRG_B460800 : MAX3107_BRG_IB460800;
+		break;
+	case 921600:
+		new_brg = s->ext_clk ? MAX3107_BRG_B921600 : MAX3107_BRG_IB921600;
+		break;
+	default:
+		/* Use previous */
+		baud = s->baud;
+		new_brg = s->brg_cfg;
+		tty_termios_encode_baud_rate(termios, baud, baud);
+	}
+	s->baud = baud;
+
+	/* Update timeout according to new baud rate */
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	spin_lock(&s->data_lock);
+	if (s->lcr_reg != new_lcr) {
+		s->lcr_reg = new_lcr;
+		s->lcr_commit = 1;
+	}
+	if (s->brg_cfg != new_brg) {
+		s->brg_cfg = new_brg;
+		s->brg_commit = 1;
+	}
+	spin_unlock(&s->data_lock);
+
+	/* Trigger work thread for doing the actual configuration change */
+	max3107_dowork(s);
+}
+
+/* Port shutdown function */
+static void max3107_shutdown(struct uart_port *port)
+{
+	struct max3107_port *s = container_of(port, struct max3107_port, port);
+
+	DBG_TRACE("enter\n");
+
+	if (s->suspended) {
+		/* Resume HW */
+		max3107_hw_susp(s, 0);
+	}
+
+	/* Free the interrupt */
+	free_irq(s->spi->irq, s);
+
+	if (s->workqueue) {
+		/* Flush and destroy work queue */
+		flush_workqueue(s->workqueue);
+		destroy_workqueue(s->workqueue);
+		s->workqueue = NULL;
+	}
+
+	/* Suspend HW */
+	max3107_hw_susp(s, 1);
+}
+
+/* Port startup function */
+static int max3107_startup(struct uart_port *port)
+{
+	struct max3107_port *s = container_of(port, struct max3107_port, port);
+
+	DBG_TRACE("enter\n");
+
+	/* Initialize work queue */
+	s->workqueue = create_freezeable_workqueue("max3107");
+	if (!s->workqueue) {
+		dev_err(&s->spi->dev, "Workqueue creation failed\n");
+		return -EBUSY;
+	}
+	INIT_WORK(&s->work, max3107_work);
+
+	/* Setup IRQ */
+	if (request_irq(s->spi->irq, max3107_irq, IRQF_TRIGGER_FALLING,
+			"max3107", s)) {
+		dev_err(&s->spi->dev, "IRQ reguest failed\n");
+		destroy_workqueue(s->workqueue);
+		s->workqueue = NULL;
+		return -EBUSY;
+	}
+
+	/* Resume HW */
+	max3107_hw_susp(s, 0);
+
+	/* Init registers */
+	max3107_register_init(s);
+
+	return 0;
+}
+
+/* Port type function */
+static const char *max3107_type(struct uart_port *port)
+{
+	struct max3107_port *s = container_of(port, struct max3107_port, port);
+	return s->spi->modalias;
+}
+
+/* Port release function */
+static void max3107_release_port(struct uart_port *port)
+{
+	/* Do nothing */
+}
+
+/* Port request function */
+static int max3107_request_port(struct uart_port *port)
+{
+	/* Do nothing */
+	return 0;
+}
+
+/* Port config function */
+static void max3107_config_port(struct uart_port *port, int flags)
+{
+	struct max3107_port *s = container_of(port, struct max3107_port, port);
+
+	/* Use PORT_MAX3100 since we are at least int the same serie */
+	s->port.type = PORT_MAX3100;
+}
+
+/* Port verify function */
+static int max3107_verify_port(struct uart_port *port,
+				struct serial_struct *ser)
+{
+	if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3100)
+		return 0;
+
+	return -EINVAL;
+}
+
+/* Port stop TX function */
+static void max3107_stop_tx(struct uart_port *port)
+{
+	/* Do nothing */
+}
+
+/* Port break control function */
+static void max3107_break_ctl(struct uart_port *port, int break_state)
+{
+	/* We don't support break control, do nothing */
+}
+
+/* GPIO direction query function */
+static enum gpio_direction max3107_gpio_get_direction(struct gpio_chip *chip,
+														unsigned offset)
+{
+	struct max3107_port *s = container_of(chip, struct max3107_port, chip);
+	u16 buf[1];	/* Buffer for SPI transfer */
+
+	DBG_TRACE("enter\n");
+
+	if (offset >= MAX3107_GPIO_COUNT) {
+		dev_err(&s->spi->dev, "Invalid GPIO\n");
+		return -EINVAL;
+	}
+
+	/* Read current GPIO configuration register */
+	buf[0] = MAX3107_GPIOCFG_REG;
+	/* Perform SPI transfer */
+	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
+		dev_err(&s->spi->dev,
+			"SPI transfer for GPIO config read failed\n");
+		return -EIO;
+	}
+	buf[0] &= MAX3107_SPI_RX_DATA_MASK;
+
+	/* Check the direction bit */
+	if (buf[0] & (0x0001 << offset))
+		return DIRECTION_OUT;
+	return DIRECTION_IN;
+}
+
+/* GPIO direction to input function */
+static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+	struct max3107_port *s = container_of(chip, struct max3107_port, chip);
+	u16 buf[1];		/* Buffer for SPI transfer */
+
+	DBG_TRACE("enter\n");
+
+	if (offset >= MAX3107_GPIO_COUNT) {
+		dev_err(&s->spi->dev, "Invalid GPIO\n");
+		return -EINVAL;
+	}
+
+	/* Read current GPIO configuration register */
+	buf[0] = MAX3107_GPIOCFG_REG;
+	/* Perform SPI transfer */
+	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
+		dev_err(&s->spi->dev,
+			"SPI transfer for GPIO config read failed\n");
+		return -EIO;
+	}
+	buf[0] &= MAX3107_SPI_RX_DATA_MASK;
+
+	/* Set GPIO to input */
+	buf[0] &= ~(0x0001 << offset);
+
+	/* Write new GPIO configuration register value */
+	buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
+	/* Perform SPI transfer */
+	if (max3107_rw(s, (u8 *)buf, NULL, 2)) {
+		dev_err(&s->spi->dev,
+			"SPI transfer for GPIO config write failed\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+/* GPIO direction to output function */
+static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
+					int value)
+{
+	struct max3107_port *s = container_of(chip, struct max3107_port, chip);
+	u16 buf[2];	/* Buffer for SPI transfers */
+
+	DBG_TRACE("enter\n");
+
+	if (offset >= MAX3107_GPIO_COUNT) {
+		dev_err(&s->spi->dev, "Invalid GPIO\n");
+		return -EINVAL;
+	}
+
+	/* Read current GPIO configuration and data registers */
+	buf[0] = MAX3107_GPIOCFG_REG;
+	buf[1] = MAX3107_GPIODATA_REG;
+	/* Perform SPI transfer */
+	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
+		dev_err(&s->spi->dev,
+			"SPI transfer for GPIO config and data read failed\n");
+		return -EIO;
+	}
+	buf[0] &= MAX3107_SPI_RX_DATA_MASK;
+	buf[1] &= MAX3107_SPI_RX_DATA_MASK;
+
+	/* Set GPIO to output */
+	buf[0] |= (0x0001 << offset);
+	/* Set value */
+	if (value)
+		buf[1] |= (0x0001 << offset);
+	else
+		buf[1] &= ~(0x0001 << offset);
+
+	/* Write new GPIO configuration and data register values */
+	buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
+	buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
+	/* Perform SPI transfer */
+	if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
+		dev_err(&s->spi->dev,
+			"SPI transfer for GPIO config and data write failed\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+/* GPIO value query function */
+static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct max3107_port *s = container_of(chip, struct max3107_port, chip);
+	u16 buf[1];	/* Buffer for SPI transfer */
+
+	DBG_TRACE("enter\n");
+
+	if (offset >= MAX3107_GPIO_COUNT) {
+		dev_err(&s->spi->dev, "Invalid GPIO\n");
+		return -EINVAL;
+	}
+
+	/* Read current GPIO data register */
+	buf[0] = MAX3107_GPIODATA_REG;
+	/* Perform SPI transfer */
+	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
+		dev_err(&s->spi->dev,
+			"SPI transfer for GPIO data read failed\n");
+		return -EIO;
+	}
+	buf[0] &= MAX3107_SPI_RX_DATA_MASK;
+
+	/* Return value */
+	return buf[0] & (0x0001 << offset);
+}
+
+/* GPIO value set function */
+static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct max3107_port *s = container_of(chip, struct max3107_port, chip);
+	u16 buf[2];	/* Buffer for SPI transfers */
+
+	DBG_TRACE("enter\n");
+
+	if (offset >= MAX3107_GPIO_COUNT) {
+		dev_err(&s->spi->dev, "Invalid GPIO\n");
+		return;
+	}
+
+	/* Read current GPIO configuration registers*/
+	buf[0] = MAX3107_GPIODATA_REG;
+	buf[1] = MAX3107_GPIOCFG_REG;
+	/* Perform SPI transfer */
+	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
+		dev_err(&s->spi->dev,
+			"SPI transfer for GPIO data and config read failed\n");
+		return;
+	}
+	buf[0] &= MAX3107_SPI_RX_DATA_MASK;
+	buf[1] &= MAX3107_SPI_RX_DATA_MASK;
+
+	if (!(buf[1] & (0x0001 << offset))) {
+		/* Configured as input, can't set value */
+		dev_warn(&s->spi->dev,
+				"Trying to set value for input GPIO\n");
+		return;
+	}
+
+	/* Set value */
+	if (value)
+		buf[0] |= (0x0001 << offset);
+	else
+		buf[0] &= ~(0x0001 << offset);
+
+	/* Write new GPIO data register value */
+	buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
+	/* Perform SPI transfer */
+	if (max3107_rw(s, (u8 *)buf, NULL, 2)) {
+		dev_err(&s->spi->dev,
+			"SPI transfer for GPIO data write failed\n");
+	}
+}
+
+/* Platform data */
+static struct max3107_plat max3107_plat_data = {
+	.loopback 		= 0,
+	.ext_clk 		= 1,
+#ifdef CONFIG_MAX3107_LOW_POWER
+	.max3107_hw_suspend 	= &max3107_hw_susp,
+#endif	/* CONFIG_MAX3107_LOW_POWER */
+	.polled_mode 		= 0,
+	.poll_time 		= 0,
+};
+
+/* Port functions */
+static struct uart_ops max3107_ops = {
+	.tx_empty	= max3107_tx_empty,
+	.set_mctrl	= max3107_set_mctrl,
+	.get_mctrl	= max3107_get_mctrl,
+	.stop_tx	= max3107_stop_tx,
+	.start_tx	= max3107_start_tx,
+	.stop_rx	= max3107_stop_rx,
+	.enable_ms	= max3107_enable_ms,
+	.break_ctl	= max3107_break_ctl,
+	.startup	= max3107_startup,
+	.shutdown	= max3107_shutdown,
+	.set_termios	= max3107_set_termios,
+	.type		= max3107_type,
+	.release_port	= max3107_release_port,
+	.request_port	= max3107_request_port,
+	.config_port	= max3107_config_port,
+	.verify_port	= max3107_verify_port,
+};
+
+/* UART driver data */
+static struct uart_driver max3107_uart_driver = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "ttyMAX",
+	.dev_name	= "ttyMAX",
+	.major		= MAX3107_MAJOR,
+	.minor		= MAX3107_MINOR,
+	.nr		= 1,
+};
+
+/* GPIO chip data */
+static struct gpio_chip max3107_gpio_chip = {
+	.owner			= THIS_MODULE,
+	.get_direction		= max3107_gpio_get_direction,
+	.direction_input	= max3107_gpio_direction_in,
+	.direction_output	= max3107_gpio_direction_out,
+	.get			= max3107_gpio_get,
+	.set			= max3107_gpio_set,
+	.can_sleep		= 1,
+	.base			= MAX3107_GPIO_BASE,
+	.ngpio			= MAX3107_GPIO_COUNT,
+};
+
+/* Device probe function */
+static int __devinit max3107_probe(struct spi_device *spi)
+{
+	struct max3107_port *s;
+	struct max3107_plat *pdata = &max3107_plat_data;
+	u16 buf[2];	/* Buffer for SPI transfers */
+	int retval;
+
+	DBG_TRACE("enter\n");
+
+	/* Reset the chip */
+	if (gpio_request(MAX3107_RESET_GPIO, "max3107")) {
+		printk(KERN_ERR "Requesting RESET GPIO failed\n");
+		return -EIO;
+	}
+	if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) {
+		printk(KERN_ERR "Setting RESET GPIO to 0 failed\n");
+		gpio_free(MAX3107_RESET_GPIO);
+		return -EIO;
+	}
+	msleep(MAX3107_RESET_DELAY);
+	if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) {
+		printk(KERN_ERR "Setting RESET GPIO to 1 failed\n");
+		gpio_free(MAX3107_RESET_GPIO);
+		return -EIO;
+	}
+	gpio_free(MAX3107_RESET_GPIO);
+	msleep(MAX3107_WAKEUP_DELAY);
+
+	/* Allocate port structure */
+	s = kzalloc(sizeof(*s), GFP_KERNEL);
+	if (!s) {
+		printk(KERN_ERR "Allocating port structure failed\n");
+		return -ENOMEM;
+	}
+
+	/* Initialize shared data lock */
+	spin_lock_init(&s->data_lock);
+
+	/* SPI intializations */
+	dev_set_drvdata(&spi->dev, s);
+	spi->mode = SPI_MODE_0;
+	spi->dev.platform_data = pdata;
+	spi->bits_per_word = 16;
+	s->ext_clk = pdata->ext_clk;
+	s->loopback = pdata->loopback;
+	spi_setup(spi);
+	s->spi = spi;
+
+	/* Check REV ID to ensure we are talking to what we expect */
+	buf[0] = MAX3107_REVID_REG;
+	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
+		dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n");
+		return -EIO;
+	}
+	if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 &&
+		(buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) {
+		dev_err(&s->spi->dev, "REVID %x does not match\n",
+				(buf[0] & MAX3107_SPI_RX_DATA_MASK) );
+		return -ENODEV;
+	}
+
+	/* Disable all interrupts */
+	buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG | 0x0000);
+	buf[0] |= 0x0000;
+
+	/* Configure clock source */
+	buf[1] = (MAX3107_WRITE_BIT | MAX3107_CLKSRC_REG);
+	if (s->ext_clk) {
+		/* External clock */
+		buf[1] |= MAX3107_CLKSRC_EXTCLK_BIT;
+	}
+	/* PLL bypass */
+	buf[1] |= MAX3107_CLKSRC_PLLBYP_BIT;
+
+	/* Perform SPI transfer */
+	if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
+		dev_err(&s->spi->dev, "SPI transfer for init failed\n");
+		return -EIO;
+	}
+
+
+	/* Register UART driver */
+	retval = uart_register_driver(&max3107_uart_driver);
+	if (retval) {
+		dev_err(&s->spi->dev, "Registering UART driver failed\n");
+		return retval;
+	}
+
+	/* Initialize UART port data */
+	s->port.fifosize = 128;
+	s->port.ops = &max3107_ops;
+	s->port.line = 0;
+	s->port.dev = &spi->dev;
+	s->port.uartclk = 9600;
+	s->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+	s->port.irq = s->spi->irq;
+	/* Use PORT_MAX3100 since we are at least int the same serie */
+	s->port.type = PORT_MAX3100;
+
+	/* Add UART port */
+	retval = uart_add_one_port(&max3107_uart_driver, &s->port);
+	if (retval < 0) {
+		dev_err(&s->spi->dev, "Adding UART port failed\n");
+		return retval;
+	}
+
+	/* Initialize GPIO chip data */
+	s->chip = max3107_gpio_chip;
+	s->chip.label = spi->modalias;
+	s->chip.dev = &spi->dev;
+
+	/* Add GPIO chip */
+	retval = gpiochip_add(&s->chip);
+	if (retval) {
+		dev_err(&s->spi->dev, "Adding GPIO chip failed\n");
+		return retval;
+	}
+
+	/* Go to suspend mode */
+	max3107_hw_susp(s, 1);
+
+	return 0;
+}
+
+/* Driver remove function */
+static int __devexit max3107_remove(struct spi_device *spi)
+{
+	struct max3107_port *s = dev_get_drvdata(&spi->dev);
+
+	DBG_TRACE("enter\n");
+
+	/* Remove GPIO chip */
+	if (gpiochip_remove(&s->chip))
+		dev_warn(&s->spi->dev, "Removing GPIO chip failed\n");
+
+	/* Remove port */
+	if (uart_remove_one_port(&max3107_uart_driver, &s->port))
+		dev_warn(&s->spi->dev, "Removing UART port failed\n");
+
+	/* Unregister UART driver */
+	uart_unregister_driver(&max3107_uart_driver);
+
+	/* Free port structure */
+	kfree(s);
+
+	return 0;
+}
+
+/* Driver suspend function */
+static int max3107_suspend(struct spi_device *spi, pm_message_t state)
+{
+#ifdef CONFIG_PM
+	struct max3107_port *s = dev_get_drvdata(&spi->dev);
+
+	DBG_TRACE("enter\n");
+
+	/* Suspend UART port */
+	uart_suspend_port(&max3107_uart_driver, &s->port);
+
+	/* Go to suspend mode */
+	max3107_hw_susp(s, 1);
+#endif	/* CONFIG_PM */
+	return 0;
+}
+
+/* Driver resume function */
+static int max3107_resume(struct spi_device *spi)
+{
+#ifdef CONFIG_PM
+	struct max3107_port *s = dev_get_drvdata(&spi->dev);
+
+	DBG_TRACE("enter\n");
+
+	/* Resume from suspend */
+	max3107_hw_susp(s, 0);
+
+	/* Resume UART port */
+	uart_resume_port(&max3107_uart_driver, &s->port);
+#endif	/* CONFIG_PM */
+	return 0;
+}
+
+/* Spi driver data */
+static struct spi_driver max3107_driver = {
+	.driver = {
+		.name		= "max3107",
+		.bus		= &spi_bus_type,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= max3107_probe,
+	.remove		= __devexit_p(max3107_remove),
+	.suspend	= max3107_suspend,
+	.resume		= max3107_resume,
+};
+
+/* Driver init function */
+static int __init max3107_init(void)
+{
+	DBG_TRACE("enter\n");
+	return spi_register_driver(&max3107_driver);
+}
+
+/* Driver exit function */
+static void __exit max3107_exit(void)
+{
+	DBG_TRACE("enter\n");
+	spi_unregister_driver(&max3107_driver);
+}
+
+module_init(max3107_init);
+module_exit(max3107_exit);
+
+MODULE_DESCRIPTION("MAX3107 driver");
+MODULE_AUTHOR("Aavamobile");
+MODULE_ALIAS("max3107-spi-uart");
+MODULE_LICENSE("GPLv2");
Index: linux-2.6.33/drivers/spi/mrst_spi.c
===================================================================
--- linux-2.6.33.orig/drivers/spi/mrst_spi.c
+++ linux-2.6.33/drivers/spi/mrst_spi.c
@@ -1364,8 +1364,16 @@ static struct pci_driver mrst_spi_driver
 	.resume	=	mrst_spi_resume,
 };
 
+/*
+ * spi_register_master will call scan board info, and MRST
+ * should only have one board_info registered
+ */
 static int __init mrst_spi_init(void)
 {
+/*#ifdef CONFIG_SERIAL_MAX3107*/
+/*	spi_register_board_info(mrst_spi_board_info,*/
+/*				ARRAY_SIZE(mrst_spi_board_info));*/
+/*#endif*/
 	return pci_register_driver(&mrst_spi_driver);
 }
 
Index: linux-2.6.33/include/linux/serial_max3107.h
===================================================================
--- /dev/null
+++ linux-2.6.33/include/linux/serial_max3107.h
@@ -0,0 +1,352 @@
+/*
+ * max3107.h - spi uart protocol driver header for Maxim 3107
+ *
+ * Copyright (C) Aavamobile 2009
+ * Based on serial_max3100.h by Christian Pellegrin
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_SERIAL_MAX3107_H
+#define _LINUX_SERIAL_MAX3107_H
+
+/* Serial definitions */
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+/* Serial error status definitions */
+#define MAX3107_PARITY_ERROR	1
+#define MAX3107_FRAME_ERROR	2
+#define MAX3107_OVERRUN_ERROR	4
+#define MAX3107_ALL_ERRORS	(MAX3107_PARITY_ERROR | \
+				 MAX3107_FRAME_ERROR | \
+				 MAX3107_OVERRUN_ERROR)
+
+
+/* TTY definitions */
+#define MAX3107_MAJOR	TTY_MAJOR
+#define MAX3107_MINOR	65
+
+
+/* GPIO definitions */
+#define MAX3107_GPIO_BASE	88
+#define MAX3107_GPIO_COUNT	4
+
+
+/* GPIO connected to chip's reset pin */
+#define MAX3107_RESET_GPIO	87
+
+
+/* Chip reset delay */
+#define MAX3107_RESET_DELAY	10
+
+/* Chip wakeup delay */
+#define MAX3107_WAKEUP_DELAY	50
+
+
+/* Sleep mode definitions */
+#define MAX3107_DISABLE_FORCED_SLEEP	0
+#define MAX3107_ENABLE_FORCED_SLEEP	1
+#define MAX3107_DISABLE_AUTOSLEEP	2
+#define MAX3107_ENABLE_AUTOSLEEP	3
+
+
+/* Definitions for register access with SPI transfers
+ *
+ * SPI transfer format:
+ *
+ * Master to slave bits xzzzzzzzyyyyyyyy
+ * Slave to master bits aaaaaaaabbbbbbbb
+ *
+ * where:
+ * x = 0 for reads, 1 for writes
+ * z = register address
+ * y = new register value if write, 0 if read
+ * a = unspecified
+ * b = register value if read, unspecified if write
+ */
+
+/* SPI speed */
+#define MAX3107_SPI_SPEED	(3125000 * 2)
+
+/* Write bit */
+#define MAX3107_WRITE_BIT	(1 << 15)
+
+/* SPI TX data mask */
+#define MAX3107_SPI_RX_DATA_MASK	(0x00ff)
+
+/* SPI RX data mask */
+#define MAX3107_SPI_TX_DATA_MASK	(0x00ff)
+
+/* Register access masks */
+#define MAX3107_RHR_REG			(0x0000) /* RX FIFO */
+#define MAX3107_THR_REG			(0x0000) /* TX FIFO */
+#define MAX3107_IRQEN_REG		(0x0100) /* IRQ enable */
+#define MAX3107_IRQSTS_REG		(0x0200) /* IRQ status */
+#define MAX3107_LSR_IRQEN_REG		(0x0300) /* LSR IRQ enable */
+#define MAX3107_LSR_IRQSTS_REG		(0x0400) /* LSR IRQ status */
+#define MAX3107_SPCHR_IRQEN_REG		(0x0500) /* Special char IRQ enable */
+#define MAX3107_SPCHR_IRQSTS_REG	(0x0600) /* Special char IRQ status */
+#define MAX3107_STS_IRQEN_REG		(0x0700) /* Status IRQ enable */
+#define MAX3107_STS_IRQSTS_REG		(0x0800) /* Status IRQ status */
+#define MAX3107_MODE1_REG		(0x0900) /* MODE1 */
+#define MAX3107_MODE2_REG		(0x0a00) /* MODE2 */
+#define MAX3107_LCR_REG			(0x0b00) /* LCR */
+#define MAX3107_RXTO_REG		(0x0c00) /* RX timeout */
+#define MAX3107_HDPIXDELAY_REG		(0x0d00) /* Auto transceiver delays */
+#define MAX3107_IRDA_REG		(0x0e00) /* IRDA settings */
+#define MAX3107_FLOWLVL_REG		(0x0f00) /* Flow control levels */
+#define MAX3107_FIFOTRIGLVL_REG		(0x1000) /* FIFO IRQ trigger levels */
+#define MAX3107_TXFIFOLVL_REG		(0x1100) /* TX FIFO level */
+#define MAX3107_RXFIFOLVL_REG		(0x1200) /* RX FIFO level */
+#define MAX3107_FLOWCTRL_REG		(0x1300) /* Flow control */
+#define MAX3107_XON1_REG		(0x1400) /* XON1 character */
+#define MAX3107_XON2_REG		(0x1500) /* XON2 character */
+#define MAX3107_XOFF1_REG		(0x1600) /* XOFF1 character */
+#define MAX3107_XOFF2_REG		(0x1700) /* XOFF2 character */
+#define MAX3107_GPIOCFG_REG		(0x1800) /* GPIO config */
+#define MAX3107_GPIODATA_REG		(0x1900) /* GPIO data */
+#define MAX3107_PLLCFG_REG		(0x1a00) /* PLL config */
+#define MAX3107_BRGCFG_REG		(0x1b00) /* Baud rate generator conf */
+#define MAX3107_BRGDIVLSB_REG		(0x1c00) /* Baud rate divisor LSB */
+#define MAX3107_BRGDIVMSB_REG		(0x1d00) /* Baud rate divisor MSB */
+#define MAX3107_CLKSRC_REG		(0x1e00) /* Clock source */
+#define MAX3107_REVID_REG		(0x1f00) /* Revision identification */
+
+/* IRQ register bits */
+#define MAX3107_IRQ_LSR_BIT	(1 << 0) /* LSR interrupt */
+#define MAX3107_IRQ_SPCHR_BIT	(1 << 1) /* Special char interrupt */
+#define MAX3107_IRQ_STS_BIT	(1 << 2) /* Status interrupt */
+#define MAX3107_IRQ_RXFIFO_BIT	(1 << 3) /* RX FIFO interrupt */
+#define MAX3107_IRQ_TXFIFO_BIT	(1 << 4) /* TX FIFO interrupt */
+#define MAX3107_IRQ_TXEMPTY_BIT	(1 << 5) /* TX FIFO empty interrupt */
+#define MAX3107_IRQ_RXEMPTY_BIT	(1 << 6) /* RX FIFO empty interrupt */
+#define MAX3107_IRQ_CTS_BIT	(1 << 7) /* CTS interrupt */
+
+/* LSR register bits */
+#define MAX3107_LSR_RXTO_BIT	(1 << 0) /* RX timeout */
+#define MAX3107_LSR_RXOVR_BIT	(1 << 1) /* RX overrun */
+#define MAX3107_LSR_RXPAR_BIT	(1 << 2) /* RX parity error */
+#define MAX3107_LSR_FRERR_BIT	(1 << 3) /* Frame error */
+#define MAX3107_LSR_RXBRK_BIT	(1 << 4) /* RX break */
+#define MAX3107_LSR_RXNOISE_BIT	(1 << 5) /* RX noise */
+#define MAX3107_LSR_UNDEF6_BIT	(1 << 6) /* Undefined/not used */
+#define MAX3107_LSR_CTS_BIT	(1 << 7) /* CTS pin state */
+
+/* Special character register bits */
+#define MAX3107_SPCHR_XON1_BIT		(1 << 0) /* XON1 character */
+#define MAX3107_SPCHR_XON2_BIT		(1 << 1) /* XON2 character */
+#define MAX3107_SPCHR_XOFF1_BIT		(1 << 2) /* XOFF1 character */
+#define MAX3107_SPCHR_XOFF2_BIT		(1 << 3) /* XOFF2 character */
+#define MAX3107_SPCHR_BREAK_BIT		(1 << 4) /* RX break */
+#define MAX3107_SPCHR_MULTIDROP_BIT	(1 << 5) /* 9-bit multidrop addr char */
+#define MAX3107_SPCHR_UNDEF6_BIT	(1 << 6) /* Undefined/not used */
+#define MAX3107_SPCHR_UNDEF7_BIT	(1 << 7) /* Undefined/not used */
+
+/* Status register bits */
+#define MAX3107_STS_GPIO0_BIT		(1 << 0) /* GPIO 0 interrupt */
+#define MAX3107_STS_GPIO1_BIT		(1 << 1) /* GPIO 1 interrupt */
+#define MAX3107_STS_GPIO2_BIT		(1 << 2) /* GPIO 2 interrupt */
+#define MAX3107_STS_GPIO3_BIT		(1 << 3) /* GPIO 3 interrupt */
+#define MAX3107_STS_UNDEF4_BIT		(1 << 4) /* Undefined/not used */
+#define MAX3107_STS_CLKREADY_BIT	(1 << 5) /* Clock ready */
+#define MAX3107_STS_SLEEP_BIT		(1 << 6) /* Sleep interrupt */
+#define MAX3107_STS_UNDEF7_BIT		(1 << 7) /* Undefined/not used */
+
+/* MODE1 register bits */
+#define MAX3107_MODE1_RXDIS_BIT		(1 << 0) /* RX disable */
+#define MAX3107_MODE1_TXDIS_BIT		(1 << 1) /* TX disable */
+#define MAX3107_MODE1_TXHIZ_BIT		(1 << 2) /* TX pin three-state */
+#define MAX3107_MODE1_RTSHIZ_BIT	(1 << 3) /* RTS pin three-state */
+#define MAX3107_MODE1_TRNSCVCTRL_BIT	(1 << 4) /* Transceiver ctrl enable */
+#define MAX3107_MODE1_FORCESLEEP_BIT	(1 << 5) /* Force sleep mode */
+#define MAX3107_MODE1_AUTOSLEEP_BIT	(1 << 6) /* Auto sleep enable */
+#define MAX3107_MODE1_IRQSEL_BIT	(1 << 7) /* IRQ pin enable */
+
+/* MODE2 register bits */
+#define MAX3107_MODE2_RST_BIT		(1 << 0) /* Chip reset */
+#define MAX3107_MODE2_FIFORST_BIT	(1 << 1) /* FIFO reset */
+#define MAX3107_MODE2_RXTRIGINV_BIT	(1 << 2) /* RX FIFO INT invert */
+#define MAX3107_MODE2_RXEMPTINV_BIT	(1 << 3) /* RX FIFO empty INT invert */
+#define MAX3107_MODE2_SPCHR_BIT		(1 << 4) /* Special chr detect enable */
+#define MAX3107_MODE2_LOOPBACK_BIT	(1 << 5) /* Internal loopback enable */
+#define MAX3107_MODE2_MULTIDROP_BIT	(1 << 6) /* 9-bit multidrop enable */
+#define MAX3107_MODE2_ECHOSUPR_BIT	(1 << 7) /* ECHO suppression enable */
+
+/* LCR register bits */
+#define MAX3107_LCR_LENGTH0_BIT		(1 << 0) /* Word length bit 0 */
+#define MAX3107_LCR_LENGTH1_BIT		(1 << 1) /* Word length bit 1
+						  *
+						  * Word length bits table:
+						  * 00 -> 5 bit words
+						  * 01 -> 6 bit words
+						  * 10 -> 7 bit words
+						  * 11 -> 8 bit words
+						  */
+#define MAX3107_LCR_STOPLEN_BIT		(1 << 2) /* STOP length bit
+						  *
+						  * STOP length bit table:
+						  * 0 -> 1 stop bit
+						  * 1 -> 1-1.5 stop bits if
+						  *      word length is 5,
+						  *      2 stop bits otherwise
+						  */
+#define MAX3107_LCR_PARITY_BIT		(1 << 3) /* Parity bit enable */
+#define MAX3107_LCR_EVENPARITY_BIT	(1 << 4) /* Even parity bit enable */
+#define MAX3107_LCR_FORCEPARITY_BIT	(1 << 5) /* 9-bit multidrop parity */
+#define MAX3107_LCR_TXBREAK_BIT		(1 << 6) /* TX break enable */
+#define MAX3107_LCR_RTS_BIT		(1 << 7) /* RTS pin control */
+#define MAX3107_LCR_WORD_LEN_5		(0x0000)
+#define MAX3107_LCR_WORD_LEN_6		(0x0001)
+#define MAX3107_LCR_WORD_LEN_7		(0x0002)
+#define MAX3107_LCR_WORD_LEN_8		(0x0003)
+
+
+/* IRDA register bits */
+#define MAX3107_IRDA_IRDAEN_BIT		(1 << 0) /* IRDA mode enable */
+#define MAX3107_IRDA_SIR_BIT		(1 << 1) /* SIR mode enable */
+#define MAX3107_IRDA_SHORTIR_BIT	(1 << 2) /* Short SIR mode enable */
+#define MAX3107_IRDA_MIR_BIT		(1 << 3) /* MIR mode enable */
+#define MAX3107_IRDA_RXINV_BIT		(1 << 4) /* RX logic inversion enable */
+#define MAX3107_IRDA_TXINV_BIT		(1 << 5) /* TX logic inversion enable */
+#define MAX3107_IRDA_UNDEF6_BIT		(1 << 6) /* Undefined/not used */
+#define MAX3107_IRDA_UNDEF7_BIT		(1 << 7) /* Undefined/not used */
+
+/* Flow control trigger level register masks */
+#define MAX3107_FLOWLVL_HALT_MASK	(0x000f) /* Flow control halt level */
+#define MAX3107_FLOWLVL_RES_MASK	(0x00f0) /* Flow control resume level */
+#define MAX3107_FLOWLVL_HALT(words)	((words/8) & 0x000f)
+#define MAX3107_FLOWLVL_RES(words)	(((words/8) & 0x000f) << 4)
+
+/* FIFO interrupt trigger level register masks */
+#define MAX3107_FIFOTRIGLVL_TX_MASK	(0x000f) /* TX FIFO trigger level */
+#define MAX3107_FIFOTRIGLVL_RX_MASK	(0x00f0) /* RX FIFO trigger level */
+#define MAX3107_FIFOTRIGLVL_TX(words)	((words/8) & 0x000f)
+#define MAX3107_FIFOTRIGLVL_RX(words)	(((words/8) & 0x000f) << 4)
+
+/* Flow control register bits */
+#define MAX3107_FLOWCTRL_AUTORTS_BIT	(1 << 0) /* Auto RTS flow ctrl enable */
+#define MAX3107_FLOWCTRL_AUTOCTS_BIT	(1 << 1) /* Auto CTS flow ctrl enable */
+#define MAX3107_FLOWCTRL_GPIADDR_BIT	(1 << 2) /* Enables that GPIO inputs
+						  * are used in conjunction with
+						  * XOFF2 for definition of
+						  * special character */
+#define MAX3107_FLOWCTRL_SWFLOWEN_BIT	(1 << 3) /* Auto SW flow ctrl enable */
+#define MAX3107_FLOWCTRL_SWFLOW0_BIT	(1 << 4) /* SWFLOW bit 0 */
+#define MAX3107_FLOWCTRL_SWFLOW1_BIT	(1 << 5) /* SWFLOW bit 1
+						  *
+						  * SWFLOW bits 1 & 0 table:
+						  * 00 -> no transmitter flow
+						  *       control
+						  * 01 -> receiver compares
+						  *       XON2 and XOFF2
+						  *       and controls
+						  *       transmitter
+						  * 10 -> receiver compares
+						  *       XON1 and XOFF1
+						  *       and controls
+						  *       transmitter
+						  * 11 -> receiver compares
+						  *       XON1, XON2, XOFF1 and
+						  *       XOFF2 and controls
+						  *       transmitter
+						  */
+#define MAX3107_FLOWCTRL_SWFLOW2_BIT	(1 << 6) /* SWFLOW bit 2 */
+#define MAX3107_FLOWCTRL_SWFLOW3_BIT	(1 << 7) /* SWFLOW bit 3
+						  *
+						  * SWFLOW bits 3 & 2 table:
+						  * 00 -> no received flow
+						  *       control
+						  * 01 -> transmitter generates
+						  *       XON2 and XOFF2
+						  * 10 -> transmitter generates
+						  *       XON1 and XOFF1
+						  * 11 -> transmitter generates
+						  *       XON1, XON2, XOFF1 and
+						  *       XOFF2
+						  */
+
+/* GPIO configuration register bits */
+#define MAX3107_GPIOCFG_GP0OUT_BIT	(1 << 0) /* GPIO 0 output enable */
+#define MAX3107_GPIOCFG_GP1OUT_BIT	(1 << 1) /* GPIO 1 output enable */
+#define MAX3107_GPIOCFG_GP2OUT_BIT	(1 << 2) /* GPIO 2 output enable */
+#define MAX3107_GPIOCFG_GP3OUT_BIT	(1 << 3) /* GPIO 3 output enable */
+#define MAX3107_GPIOCFG_GP0OD_BIT	(1 << 4) /* GPIO 0 open-drain enable */
+#define MAX3107_GPIOCFG_GP1OD_BIT	(1 << 5) /* GPIO 1 open-drain enable */
+#define MAX3107_GPIOCFG_GP2OD_BIT	(1 << 6) /* GPIO 2 open-drain enable */
+#define MAX3107_GPIOCFG_GP3OD_BIT	(1 << 7) /* GPIO 3 open-drain enable */
+
+/* GPIO DATA register bits */
+#define MAX3107_GPIODATA_GP0OUT_BIT	(1 << 0) /* GPIO 0 output value */
+#define MAX3107_GPIODATA_GP1OUT_BIT	(1 << 1) /* GPIO 1 output value */
+#define MAX3107_GPIODATA_GP2OUT_BIT	(1 << 2) /* GPIO 2 output value */
+#define MAX3107_GPIODATA_GP3OUT_BIT	(1 << 3) /* GPIO 3 output value */
+#define MAX3107_GPIODATA_GP0IN_BIT	(1 << 4) /* GPIO 0 input value */
+#define MAX3107_GPIODATA_GP1IN_BIT	(1 << 5) /* GPIO 1 input value */
+#define MAX3107_GPIODATA_GP2IN_BIT	(1 << 6) /* GPIO 2 input value */
+#define MAX3107_GPIODATA_GP3IN_BIT	(1 << 7) /* GPIO 3 input value */
+
+/* PLL configuration register masks */
+#define MAX3107_PLLCFG_PREDIV_MASK	(0x003f) /* PLL predivision value */
+#define MAX3107_PLLCFG_PLLFACTOR_MASK	(0x00c0) /* PLL multiplication factor */
+
+/* Baud rate generator configuration register masks and bits */
+#define MAX3107_BRGCFG_FRACT_MASK	(0x000f) /* Fractional portion of
+						  * Baud rate generator divisor
+						  */
+#define MAX3107_BRGCFG_2XMODE_BIT	(1 << 4) /* Double baud rate */
+#define MAX3107_BRGCFG_4XMODE_BIT	(1 << 5) /* Quadruple baud rate */
+#define MAX3107_BRGCFG_UNDEF6_BIT	(1 << 6) /* Undefined/not used */
+#define MAX3107_BRGCFG_UNDEF7_BIT	(1 << 7) /* Undefined/not used */
+
+/* Clock source register bits */
+#define MAX3107_CLKSRC_INTOSC_BIT	(1 << 0) /* Internal osc enable */
+#define MAX3107_CLKSRC_CRYST_BIT	(1 << 1) /* Crystal osc enable */
+#define MAX3107_CLKSRC_PLL_BIT		(1 << 2) /* PLL enable */
+#define MAX3107_CLKSRC_PLLBYP_BIT	(1 << 3) /* PLL bypass */
+#define MAX3107_CLKSRC_EXTCLK_BIT	(1 << 4) /* External clock enable */
+#define MAX3107_CLKSRC_UNDEF5_BIT	(1 << 5) /* Undefined/not used */
+#define MAX3107_CLKSRC_UNDEF6_BIT	(1 << 6) /* Undefined/not used */
+#define MAX3107_CLKSRC_CLK2RTS_BIT	(1 << 7) /* Baud clk to RTS pin */
+
+
+/* HW definitions */
+#define MAX3107_RX_FIFO_SIZE	128
+#define MAX3107_TX_FIFO_SIZE	128
+#define MAX3107_REVID1		0x00a0
+#define MAX3107_REVID2		0x00a1
+
+
+/* Baud rate generator configuration values for external clock */
+#define MAX3107_BRG_B300	(0x0A9400 | 0x05)
+#define MAX3107_BRG_B600	(0x054A00 | 0x03)
+#define MAX3107_BRG_B1200	(0x02A500 | 0x01)
+#define MAX3107_BRG_B2400	(0x015200 | 0x09)
+#define MAX3107_BRG_B4800	(0x00A900 | 0x04)
+#define MAX3107_BRG_B9600	(0x005400 | 0x0A)
+#define MAX3107_BRG_B19200	(0x002A00 | 0x05)
+#define MAX3107_BRG_B38400	(0x001500 | 0x03)
+#define MAX3107_BRG_B57600	(0x000E00 | 0x02)
+#define MAX3107_BRG_B115200	(0x000700 | 0x01)
+#define MAX3107_BRG_B230400	(0x000300 | 0x08)
+#define MAX3107_BRG_B460800	(0x000100 | 0x0c)
+#define MAX3107_BRG_B921600	(0x000100 | 0x1c)
+
+/* Baud rate generator configuration values for internal clock */
+#define MAX3107_BRG_IB300	(0x008000 | 0x00)
+#define MAX3107_BRG_IB600	(0x004000 | 0x00)
+#define MAX3107_BRG_IB1200	(0x002000 | 0x00)
+#define MAX3107_BRG_IB2400	(0x001000 | 0x00)
+#define MAX3107_BRG_IB4800	(0x000800 | 0x00)
+#define MAX3107_BRG_IB9600	(0x000400 | 0x00)
+#define MAX3107_BRG_IB19200	(0x000200 | 0x00)
+#define MAX3107_BRG_IB38400	(0x000100 | 0x00)
+#define MAX3107_BRG_IB57600	(0x000000 | 0x0B)
+#define MAX3107_BRG_IB115200	(0x000000 | 0x05)
+#define MAX3107_BRG_IB230400	(0x000000 | 0x03)
+#define MAX3107_BRG_IB460800	(0x000000 | 0x00)
+#define MAX3107_BRG_IB921600	(0x000000 | 0x00)
+
+#endif /* _LINUX_SERIAL_MAX3107_H */
Index: linux-2.6.33/include/drm/drm_mode.h
===================================================================
--- linux-2.6.33.orig/include/drm/drm_mode.h
+++ linux-2.6.33/include/drm/drm_mode.h
@@ -160,9 +160,9 @@ struct drm_mode_get_encoder {
 #define DRM_MODE_CONNECTOR_DisplayPort	10
 #define DRM_MODE_CONNECTOR_HDMIA	11
 #define DRM_MODE_CONNECTOR_HDMIB	12
-#define DRM_MODE_CONNECTOR_TV		13
+#define DRM_MODE_CONNECTOR_TV		15
 #define DRM_MODE_CONNECTOR_eDP		14
-#define DRM_MODE_CONNECTOR_MIPI		15
+#define DRM_MODE_CONNECTOR_MIPI		13
 
 struct drm_mode_get_connector {
 
Index: linux-2.6.33/include/sound/intel_sst_ioctl.h
===================================================================
--- linux-2.6.33.orig/include/sound/intel_sst_ioctl.h
+++ linux-2.6.33/include/sound/intel_sst_ioctl.h
@@ -361,4 +361,9 @@ struct snd_sst_dbufs  {
 #define SNDRV_SST_SET_TARGET_DEVICE _IOW('L', 0x21, \
 					struct snd_sst_target_device *)
 
+#define SNDRV_SST_AAVA_HACK _IO('L', 0x22)
+
+/*Test utility for testing comms */
+#define SNDRV_LPE_TEST_COMMS _IOW('L', 0x23, int)
+
 #endif /* __INTEL_SST_IOCTL_H__ */
Index: linux-2.6.33/sound/pci/sst/Makefile
===================================================================
--- linux-2.6.33.orig/sound/pci/sst/Makefile
+++ linux-2.6.33/sound/pci/sst/Makefile
@@ -2,7 +2,7 @@
 # Makefile for Intel MID Audio drivers
 #
 EXTRA_CFLAGS=-g -DCONFIG_MRST_RAR_HANDLER
-snd-intel-sst-objs := intel_sst.o intel_sst_ipc.o intel_sst_stream.o intel_sst_interface.o intel_sst_dsp.o intel_sst_pvt.o
+snd-intel-sst-objs := intel_sst.o intel_sst_ipc.o intel_sst_stream.o intel_sst_interface.o intel_sst_dsp.o intel_sst_pvt.o koski_audio_conf.o
 snd-intelmid-objs := intelmid.o intelmid_v0_control.o intelmid_v1_control.o intelmid_v2_control.o intelmid_ctrl.o intelmid_pvt.o
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_INTEL_SST) += snd-intel-sst.o
Index: linux-2.6.33/sound/pci/sst/intel_sst_interface.c
===================================================================
--- linux-2.6.33.orig/sound/pci/sst/intel_sst_interface.c
+++ linux-2.6.33/sound/pci/sst/intel_sst_interface.c
@@ -54,6 +54,7 @@
 #include "intel_sst_fw_ipc.h"
 #include "intel_sst_common.h"
 
+#include "koski_audio_conf.h"
 #define AM_MODULE 1
 #define STREAM_MODULE 0
 
@@ -1232,6 +1233,33 @@ int intel_sst_ioctl(struct inode *i_node
 		}
 		break;
 	}
+    case _IOC_NR(SNDRV_SST_AAVA_HACK):
+    	{
+        	pr_debug("SNDRV_SST_AAVA_HACK recieved\n");
+        	sst_drv_ctx->scard_ops->set_pcm_audio_params(999999, 2);
+        	break;
+    	}
+
+	case _IOC_NR(SNDRV_LPE_TEST_COMMS): {
+		int *coms = (int *)arg;
+			pr_debug("SNDRV_LPE_TEST_COMMS recieved!\n");
+		if (*coms == 1) {
+			/* Activate voice port */
+			sst_drv_ctx->scard_ops->set_pcm_voice_params();
+			sst_drv_ctx->scard_ops->set_voice_port(ACTIVATE);
+		} else if (*coms == 2) {
+			/* Deactivate voice port */
+			sst_drv_ctx->scard_ops->set_voice_port(DEACTIVATE);
+
+		} else if (*coms == 3) {
+			/* Set voice parameters */
+			sst_drv_ctx->scard_ops->set_voice_port(DEACTIVATE);
+		}
+
+			retval = 0;
+		break;
+	}
+
 	case _IOC_NR(SNDRV_SST_SET_VOL): {
 		struct snd_sst_vol *set_vol;
 		struct snd_sst_vol *rec_vol = (struct snd_sst_vol *)arg;
@@ -1482,6 +1510,10 @@ int intel_sst_ioctl(struct inode *i_node
 		pr_debug("SNDRV_SST_SET_TARGET_PLAYBACK DEVICE recieved!\n");
 		target_device =	(struct snd_sst_target_device *)arg;
 		BUG_ON(!target_device);
+//#ifdef KOSKI_AUDIO
+#if 1
+    configure_koski_audio(target_device->device_route);
+#else
 		if (minor != AM_MODULE) {
 			dev_err(&sst_drv_ctx->pci->dev,\
 			"Time:%8ld::%8ld >> SST: %s %d ERR: called for non +\
@@ -1491,6 +1523,7 @@ int intel_sst_ioctl(struct inode *i_node
 			break;
 		}
 		retval = sst_target_device_select(target_device);
+#endif
 		break;
 	}
 
Index: linux-2.6.33/sound/pci/sst/intelmid.c
===================================================================
--- linux-2.6.33.orig/sound/pci/sst/intelmid.c
+++ linux-2.6.33/sound/pci/sst/intelmid.c
@@ -47,6 +47,7 @@
 #include "intelmid_snd_control.h"
 #include "intelmid.h"
 #include "intelmid_ctrl.h"
+#include "koski_audio_conf.h"
 
 MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
@@ -65,6 +66,7 @@ MODULE_PARM_DESC(card_id, "ID string for
 
 int	sst_card_vendor_id;
 int audio_interrupt_enable = 0;
+volatile int koski_jack;
 
 /* Data path functionalities */
 static struct snd_pcm_hardware snd_intelmad_stream = {
@@ -452,6 +454,7 @@ void sst_process_mad_jack_detection(stru
 				{0x18b, 0x10, MASK4},
 	};
 	struct sc_reg_access sc_access_read = {0,};
+	struct sc_reg_access sc_access_write_koski[1] = {{0,},};
 
 	struct sc_reg_access sc_access_write[] = {
 				{0x198, 0x00, 0x0},
@@ -463,6 +466,7 @@ void sst_process_mad_jack_detection(stru
 			mad_jack_detect->intelmaddata;
 
 	intsts = mad_jack_detect->intsts;
+	printk("*******************************************\n");
 
 	switch (intelmaddata->sstdrv_ops->vendor_id) {
 	case SND_FS:
@@ -522,13 +526,13 @@ void sst_process_mad_jack_detection(stru
 					sc_access_read.reg_addr = 0x201;
 					sst_sc_reg_access(&sc_access_read, PMIC_READ, 1);
 					value = (sc_access_read.value);
-					pr_debug("value returned = 0x%x\n", value);
+					printk("JKSNS value returned = 0x%x\n", value);
 				}
-				if (value & 0xc0) {
+				if (value == 0xc0) {
 					/*accessory is removed */
 
 					if (intelmaddata->jack[0].jack_status) {
-						pr_debug("MAD headset detected\n");
+						/* pr_debug("MAD headset detected\n");*/
 						/* send headphone detect/undetect */
 						jack = &intelmaddata->jack[0].jack;
 						present = 0;
@@ -536,7 +540,7 @@ void sst_process_mad_jack_detection(stru
 					}
 
 					if (intelmaddata->jack[1].jack_status) {
-						pr_debug("MAD headphone detected\n");
+						/* pr_debug("MAD headphone detected\n");*/
 						/* send headphone detect/undetect */
 						jack = &intelmaddata->jack[1].jack;
 						present = 0;
@@ -545,11 +549,11 @@ void sst_process_mad_jack_detection(stru
 
 
 				}
-				if (value & 0x00) {
+				if (value == 0x00) {
 
 					if (intelmaddata->jack[1].jack_status) {
 						/*button pressed */
-						pr_debug("MAD headphone detected\n");
+						/* pr_debug("MAD headphone detected\n");*/
 						/* send headphone detect/undetect */
 						jack = &intelmaddata->jack[2].jack;
 						present = 1;
@@ -558,7 +562,7 @@ void sst_process_mad_jack_detection(stru
 						buttonpressflag = 1;
 
 					} else {
-						pr_debug("MAD headphone detected\n");
+						/* pr_debug("MAD headphone detected\n");*/
 						/* send headphone detect/undetect */
 						jack = &intelmaddata->jack[0].jack;
 						present = 1;
@@ -566,8 +570,8 @@ void sst_process_mad_jack_detection(stru
 						jack_event_flag = 1;
 					}
 				}
-				if (value & 0x40) {
-					pr_debug("MAD headset detected\n");
+				if (value == 0x40) {
+					/* pr_debug("MAD headset detected\n");*/
 					/* send headphone detect/undetect */
 					jack = &intelmaddata->jack[1].jack;
 					present = 1;
@@ -576,6 +580,12 @@ void sst_process_mad_jack_detection(stru
 				}
 
 		}
+
+		sc_access_write_koski[0].reg_addr = 0x204;
+		sc_access_write_koski[0].value = 0xe;
+		sst_sc_reg_access(sc_access_write_koski, PMIC_WRITE, 1);
+		printk("MX Audio interrupt enable... DONE\n");
+
 		break;
 	case SND_NC:
 		if (intelmaddata->pmic_status == PMIC_INIT) {
@@ -619,11 +629,38 @@ void sst_process_mad_jack_detection(stru
 
 	if (!jack) {
 		pr_debug("MAD error jack empty \n");
-
-	} else {
-		pr_debug("MAD sending jack report for = %d!!!\n", present);
+	}
+	else
+	{
+		if (present)
+		{
+			printk("Jack... YES\n");
+			set_output_device(OUTPUT_HEADSET);
+			koski_jack = 1;
+		}
+		else
+		{
+			printk("Jack... NO\n");
+			set_output_device(OUTPUT_SPEAKER);
+			koski_jack = 0;
+		}
 		if (jack)
-			pr_debug("MAD sending jack report for = %d !!!\n", jack->type);
+		{
+			switch (jack->type) {
+			case SND_JACK_HEADPHONE:
+				printk("SND_JACK_HEADPHONE\n");
+				break;
+			case SND_JACK_HEADSET:
+				printk("SND_JACK_HEADSET\n");
+				break;
+			case SND_JACK_HS_SHORT_PRESS:
+				printk("SND_JACK_HS_SHORT_PRESS\n");
+				break;
+			case SND_JACK_HS_LONG_PRESS:
+				printk("SND_JACK_HS_LONG_PRESS\n");
+				break;
+			}
+		}
 		if (jack_event_flag)
 			snd_jack_report(jack, present);
 		if (buttonpressflag)
Index: linux-2.6.33/sound/pci/sst/intelmid_ctrl.c
===================================================================
--- linux-2.6.33.orig/sound/pci/sst/intelmid_ctrl.c
+++ linux-2.6.33/sound/pci/sst/intelmid_ctrl.c
@@ -43,11 +43,17 @@
 #include "intelmid_snd_control.h"
 #include "intelmid.h"
 
+extern int	sst_card_vendor_id;
+
 static char *out_names[] = {"Headphones",
-				"Internal speakers"};
+				"Internal speakers",
+				"Receiver Koski"
+				};
 static char *in_names[] = {"HS_MIC",
-				"AMIC",
-				"DMIC"};
+			 	"AMIC",
+				"DMIC",
+				"LINE_IN Koski"
+				};
 
 struct snd_pmic_ops *intelmad_vendor_ops[MAX_VENDORS] = {
 	&snd_pmic_ops_fs,
Index: linux-2.6.33/sound/pci/sst/intelmid_snd_control.h
===================================================================
--- linux-2.6.33.orig/sound/pci/sst/intelmid_snd_control.h
+++ linux-2.6.33/sound/pci/sst/intelmid_snd_control.h
@@ -75,12 +75,14 @@ enum SND_INPUT_DEVICE {
 	HS_MIC,
 	AMIC,
 	DMIC,
+	LINE_IN,
 	IN_UNDEFINED
 };
 
 enum SND_OUTPUT_DEVICE {
 	STEREO_HEADPHONE,
 	INTERNAL_SPKR,
+	RECEIVER,
 	OUT_UNDEFINED
 };
 
@@ -100,8 +102,11 @@ enum pmic_controls {
 	PMIC_SND_RIGHT_PB_VOL =			0x0011,
 	PMIC_SND_LEFT_HP_MUTE =			0x0012,
 	PMIC_SND_RIGHT_HP_MUTE =	 	0x0013,
-	PMIC_SND_LEFT_SPEAKER_MUTE =		0x0014,
-	PMIC_SND_RIGHT_SPEAKER_MUTE =		0x0015,
+	PMIC_SND_LEFT_SPEAKER_MUTE =	0x0014,
+	PMIC_SND_RIGHT_SPEAKER_MUTE =	0x0015,
+	PMIC_SND_RECEIVER_VOL = 		0x0016,
+	PMIC_SND_RECEIVER_MUTE = 		0x0017,
+
 /* Other controls */
 	PMIC_SND_MUTE_ALL = 			0x0020,
 	PMIC_MAX_CONTROLS =			0x0020,
Index: linux-2.6.33/sound/pci/sst/intelmid_v1_control.c
===================================================================
--- linux-2.6.33.orig/sound/pci/sst/intelmid_v1_control.c
+++ linux-2.6.33/sound/pci/sst/intelmid_v1_control.c
@@ -1,9 +1,10 @@
 /*
- *  intel_sst_v1_control.c - Intel SST Driver for audio engine
+ *  intel_sst_v3_control.c - Intel SST Driver for audio engine
  *
  *  Copyright (C) 2008-09 Intel Corp
  *  Authors:	Vinod Koul <vinod.koul@intel.com>
  *  		Harsha Priya <priya.harsha@intel.com>
+ *  		Meena Kannan <kurinji.meena.kannan@intel.com>
  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -21,7 +22,7 @@
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
- *  This file contains the control operations of vendor 2
+ *  This file contains the control operations of vendor 3
  */
 
 #include <linux/cdev.h>
@@ -45,6 +46,7 @@
 #include "intel_sst_fw_ipc.h"
 #include "intel_sst_common.h"
 #include "intelmid_snd_control.h"
+#include <linux/gpio.h>
 
 enum _reg_v2 {
 
@@ -59,6 +61,7 @@ enum _reg_v2 {
 	HP_OP_SINGLE_ENDED = 0x224,
 	ENABLE_OPDEV_CTRL = 0x226,
 	ENABLE_DEV_AND_USE_XTAL = 0x227,
+	MX_JACK_DETECT = 0x225,
 
 	/* Max audio subsystem (PQ49) MAX 8921 */
 	AS_IP_MODE_CTL = 0xF9,
@@ -73,117 +76,525 @@ enum _reg_v2 {
 	VOL_CTRL_LT = 0x21c,
 	VOL_CTRL_RT = 0x21d,
 
+	MAX_GPOCTL = 0xF4,
+
 };
 
+
+enum {FALSE=0, TRUE};
+
+#define KOSKI_VOICE_CODEC_ENABLE 46
+/*
+ * mx_print_regs
+ *
+ */
+void mx_print_regs(void)
+{
+	struct sc_reg_access sc_access[1] = {{0,},};
+
+	int i = 0;
+	int retval = 0;
+
+	pr_debug("Printing out MX Audio registers:\n");
+	pr_debug("REG  VALUE\n");
+
+	sc_access[0].reg_addr = MAX_GPOCTL;
+	retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
+	pr_debug("0x%x 0x%x\n", sc_access[0].reg_addr, sc_access[0].value);
+
+	for( i = 0xf9; i <= 0xff; i++ )
+	{
+		sc_access[0].reg_addr = i;
+		retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
+		pr_debug("0x%x 0x%x\n", sc_access[0].reg_addr,
+			sc_access[0].value);
+	}
+
+	for( i = 0x200; i <= 0x227; i++ )
+	{
+		sc_access[0].reg_addr = i;
+		retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
+		pr_debug("0x%x 0x%x\n", sc_access[0].reg_addr,
+			sc_access[0].value);
+	}
+
+}
+
+
+/*
+ * mx_koski_get_output_dev
+ *
+ */
+int mx_koski_get_output_dev(void)
+{
+	struct sc_reg_access sc_access[1] = {{0,},};
+	int retval = 0, temp_value;
+
+	sc_access[0].reg_addr = AS_CONFIG;
+	retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
+	if (0 != retval) {
+		/* pmic communication fails */
+		pr_debug("pmic commn failed \n");
+		return retval;
+	}
+	temp_value = sc_access[0].value;
+
+	if (temp_value & 0x1)
+	{
+		pr_debug("output device RECEIVER\n");
+	}
+	else if ((temp_value & 0x4) || (temp_value & 0x8))
+	{
+		pr_debug("output device HEADSET\n");
+	}
+	else if ((temp_value & 0x10) || (temp_value & 0x20))
+	{
+		pr_debug("output device SPEAKERS\n");
+	}
+	else
+	{
+		pr_debug("output device NOT CONFIGURED!!!\n");
+	}
+
+	return temp_value;
+
+}
+
+
+/*
+ * mx_change_gpoctl_reg
+ *
+ * Pull down GPO pins as they interfere I2S
+ */
+void mx_change_gpoctl_reg(bool set)
+{
+	struct sc_reg_access sc_access[1] = {{0,},};
+	int retval = 0;
+
+	return;
+
+	sc_access[0].reg_addr = MAX_GPOCTL;
+	retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
+
+	pr_debug("0x%x 0x%x\n", sc_access[0].reg_addr, sc_access[0].value);
+
+	if(set)
+    	{
+        	/* Pull up GPO5 and GPO6*/
+        	sc_access[0].value = sc_access[0].value | 0x60;
+        	retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 1);
+    	}
+    	else
+    	{
+        	/* Pull down GPO5 and GPO6*/
+        	sc_access[0].value = sc_access[0].value & 0x9F;
+        	retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 1);
+    	}
+
+	if (0 != retval) {
+		pr_debug("pmic communication failed \n");
+	}
+}
+
+/*
+ * mx_koski_write_reg
+ *
+ */
+void mx_koski_write_reg(void)
+{
+	int retval = 0;
+	struct sc_reg_access sc_access[1] = {{0,},};
+    int fd;
+    char buf[1];
+    char address[10] = "";
+    char value[10] = "";
+    int i = 0;
+    bool address_full = FALSE;
+    long i_address = 0;
+	long i_value = 0;
+
+    mm_segment_t old_fs = get_fs();
+    set_fs(KERNEL_DS);
+
+    fd = sys_open("/root/testi.txt", O_RDONLY, 0);
+    if (fd >= 0)
+    {
+       	printk(KERN_DEBUG);
+       	while (sys_read(fd, buf, 1) == 1)
+       	{
+       		printk("%c", buf[0]);
+       		if( buf[0] != ' ')
+       		{
+       			if (!address_full)
+       			{
+           			address[i] = buf[0];
+       			}
+       			else
+       			{
+           			value[i] = buf[0];
+       			}
+       			i++;
+       			if( i > 9 )
+       			{
+           			pr_debug("FILE READ FAILED, char count exceeded!!!\n");
+           			break;
+       			}
+      		}
+       		else
+       		{
+       			pr_debug("Space found!\n");
+       			if (!address_full)
+       			{
+           			pr_debug("Address found!\n");
+           			address[i] = 0;
+           			address_full = TRUE;
+           			strict_strtol (	address, 16, &i_address);
+           			pr_debug("Address found = %s %ld\n", address, i_address);
+
+       			}
+       			else
+       			{
+           			value[i] = 0;
+           			strict_strtol (	value, 16, &i_value);
+           			pr_debug("Value found = %s %ld\n", value, i_value);
+       			}
+       			i=0;
+      		}
+    	}
+
+        printk("\n");
+        sys_close(fd);
+
+    }
+
+    set_fs(old_fs);
+
+    pr_debug("SET REG called... address = %lx value = %lx\n",
+		i_address, i_value);
+	sc_access[0].reg_addr =	(int)i_address;
+	sc_access[0].value = (int)i_value;
+    retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 1);
+
+	if (0 != retval)
+		pr_debug("pmic communication failed \n");
+	pr_debug("******** \n");
+    mx_print_regs();
+    pr_debug("******** \n");
+}
+
+/*
+ * mx_init_card
+ *
+ */
 int mx_init_card(void)
 {
-	struct sc_reg_access sc_access[] = {
+	int retval = 0;
+
+    int err=0;
+	/* Default initialization is for voice call.
+		Codec I2S0 is in slave mode. */
+    struct sc_reg_access sc_access[] = {
 		{0x200, 0x80, 0x00},
 		{0x201, 0xC0, 0x00},
 		{0x202, 0x00, 0x00},
 		{0x203, 0x00, 0x00},
-		{0x204, 0x02, 0x00},
-		{0x205, 0x10, 0x00},
-		{0x206, 0x60, 0x00},
-		{0x207, 0x00, 0x00},
-		{0x208, 0x90, 0x00},
-		{0x209, 0x51, 0x00},
+		{0x204, 0x0e, 0x00}, /* JAck detection: 0c -> 0e */
+		{0x205, 0x20, 0x00}, /* 0x10 -> 0x20 Koski scale external clock */
+		{0x206, 0x8f, 0x00}, /* PLL, 8kHz DAI1*/
+		{0x207, 0x21, 0x00}, /* 8kHz DAI1 */
+		{0x208, 0x18, 0x00}, /* DAI1 slave: DLY1 and HIZOFF1 enabled */
+		{0x209, 0x32, 0x00},
 		{0x20a, 0x00, 0x00},
-		{0x20b, 0x10, 0x00},
-		{0x20c, 0x00, 0x00},
-		{0x20d, 0x00, 0x00},
-		{0x20e, 0x11, 0x00},
+		{0x20b, 0x5A, 0x00}, /* 0x10 -> 0x5A Koski */
+		{0x20c, 0xBE, 0x00}, /* 0x00 -> 0xBE Koski */
+		{0x20d, 0x00, 0x00}, /* DAI2 'off' */
+		{0x20e, 0x40, 0x00},
 		{0x20f, 0x00, 0x00},
 		{0x210, 0x84, 0x00},
-		{0x211, 0x33, 0x00},
+		{0x211, 0x33, 0x00}, /* Voice filter */
 		{0x212, 0x00, 0x00},
 		{0x213, 0x00, 0x00},
 		{0x214, 0x41, 0x00},
 		{0x215, 0x00, 0x00},
 		{0x216, 0x00, 0x00},
-		{0x217, 0x00, 0x00},
-		{0x218, 0x03, 0x00},
-		{0x219, 0x03, 0x00},
-		{0x21a, 0x00, 0x00},
-		{0x21b, 0x00, 0x00},
+		{0x217, 0x20, 0x00},
+		{0x218, 0x00, 0x00},
+		{0x219, 0x00, 0x00},
+		{0x21a, 0x40, 0x00},
+		{0x21b, 0x40, 0x00},
 		{0x21c, 0x09, 0x00},
 		{0x21d, 0x09, 0x00},
 		{0x21e, 0x00, 0x00},
 		{0x21f, 0x00, 0x00},
-		{0x220, 0x54, 0x00},
-		{0x221, 0x54, 0x00},
-		{0x222, 0x50, 0x00},
-		{0x223, 0x00, 0x00},
-		{0x224, 0x04, 0x00},
-		{0x225, 0x80, 0x00},
-		{0x226, 0x0F, 0x00},
-		{0x227, 0x88, 0x00},
+		{0x220, 0x00, 0x00}, /* Microphone configurations */
+		{0x221, 0x00, 0x00}, /* Microphone configurations */
+		{0x222, 0x50, 0x00}, /* Microphone configurations */
+		{0x223, 0x21, 0x00}, /* Jack detection: 20 -> 21 */
+		{0x224, 0x00, 0x00},
+		{0x225, 0x80, 0x00}, /* Jack detection: 00 -> 80 */
+		{0x226, 0x3C, 0x00}, /* 0x0F -> 0x3C Internal speaker as default */
+		{0x227, 0x00, 0x00}, /* 0x88 -> 0x80; Koski select external clock */
 		{0xf9, 0x40, 0x00},
-		{0xfa, 0x1F, 0x00},
-		{0xfb, 0x00, 0x00},
-		{0xfc, 0x00, 0x00},
-		{0xfd, 0x00, 0x00},
-		{0xfe, 0x00, 0x00},
-		{0xff, 0x00, 0x00},
+		{0xfa, 0x19, 0x00},  /* 0x1F -> 0x19 Koski Left speaker volume */
+		{0xfb, 0x19, 0x00},  /* 0x00 -> 0x19 Koski Right speaker volume */
+		{0xfc, 0x12, 0x00},
+		{0xfd, 0x12, 0x00},
+		{0xfe, 0x00, 0x00},  /* 0x00 -> Koski output mixer for stereo */
+		{0xff, 0xB0, 0x00},  /* 0x00 -> 0x81 Koski enable receiver */
 	};
+
 	snd_pmic_ops_mx.card_status = SND_CARD_INIT_DONE;
-	return sst_sc_reg_access(sc_access, PMIC_WRITE, 47);
+	retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 47);
+
+    mx_change_gpoctl_reg(TRUE);
+    mx_change_gpoctl_reg(FALSE);
+
+    /*init clock sig to voice codec*/
+    err = gpio_request(KOSKI_VOICE_CODEC_ENABLE, "sound_voice_codec");
+
+    if (err)
+    {
+        printk("Error enabling voice codec clock\n");
+    }
+    else
+    {
+        gpio_direction_output(KOSKI_VOICE_CODEC_ENABLE, 1);
+        printk("Voice codec clock enabled\n");
+    }
+
+    mx_print_regs();
+
+    return retval;
 }
 
-int mx_power_up_pb(void)
+/*
+ * mx_init_capture_card
+ *
+ */
+int mx_init_capture_card(void)
 {
+	/* Sample rate set to 8000Hz */
 	struct sc_reg_access sc_access[] = {
-		{0x226, 0x0C, MASK3|MASK2},
-		{0x227, 0x88, MASK7|MASK3},
+		{0x200, 0xC0, 0x0},
+		{0x201, 0xC0, 0x0},
+		{0x202, 0x00, 0x0},
+		{0x203, 0x00, 0x0},
+		{0x204, 0x0e, 0x0}, /* changed from 0x0E*//*jack interrupt enabled*/
+		{0x205, 0x20, 0x0}, /* changed from 0x10*/
+		{0x206, 0x8f, 0x0}, /* changed from 0x00*/
+		{0x207, 0x21, 0x0}, /* changed from 0x00*/
+		{0x208, 0x90, 0x0}, /* changed from 0x00*/
+		{0x209, 0x32, 0x0}, /* changed from 0x00*/
+		{0x20a, 0x00, 0x0},
+		{0x20b, 0x8f, 0x0}, /* changed from 0x58*/
+		{0x20c, 0x21, 0x0}, /* changed from 0x33*/
+		{0x20d, 0x90, 0x0},
+		{0x20e, 0x22, 0x0}, /* changed from 0x52*/
+		{0x20f, 0x00, 0x0},
+		{0x210, 0x84, 0x0}, /* changed from 0x21*/
+		{0x211, 0x00, 0x0}, /* changed from 0x80*/
+		{0x212, 0x00, 0x0},
+		{0x213, 0x00, 0x0},
+		{0x214, 0x41, 0x0},
+		{0x215, 0x81, 0x0}, /* changed from 0x00*/
+		{0x216, 0x00, 0x0},
+		{0x217, 0x00, 0x0},
+		{0x218, 0x00, 0x0},
+		{0x219, 0x00, 0x0},
+		{0x21a, 0x00, 0x0},
+		{0x21b, 0x00, 0x0},
+		{0x21c, 0x09, 0x0},
+		{0x21d, 0x09, 0x0},
+		{0x21e, 0x00, 0x0},
+		{0x21f, 0x00, 0x0},
+		{0x220, 0x00, 0x0},
+		{0x221, 0x00, 0x0},
+		{0x222, 0x00, 0x0},
+		{0x223, 0x31, 0x0}, /* changed from 0x00*//*jack interrupt enabled*/
+		{0x224, 0x40, 0x0},
+		{0x225, 0x80, 0x0}, /*jack interrupt enabled*/
+		{0x226, 0xC0, 0x0},
+		{0x227, 0x80, 0x0}, /* changed from 0x88*/
+		{0xf9, 0x40, 0x0},
+		{0xfa, 0x1F, 0x0},
+		{0xfb, 0x1F, 0x0}, /* changed from 0x00*/
+		{0xfc, 0x00, 0x0},
+		{0xfd, 0x00, 0x0},
+		{0xfe, 0x00, 0x0},
+		{0xff, 0xa0, 0x0},
 	};
+
 	int retval = 0;
 
-	if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
-		retval = mx_init_card();
-	if (retval)
+	pr_debug("mx_init_capture_card called...\n");
+
+	retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 47);
+	if (0 != retval) {
+		/* pmic communication fails */
+		pr_debug("pmic commn failed \n");
 		return retval;
-	return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+	}
+
+	mx_change_gpoctl_reg(TRUE);
+	mx_print_regs();
+
+	pr_debug("Capture configuration complete!!\n");
+	return 0;
 }
 
-int mx_power_up_cp(void)
+/*
+ * mx_init_playback_card
+ *
+ */
+int mx_init_playback_card(int sel_output)
 {
+
+	/* Default settings for playback from Langwell I2S1. */
+	/* Output is routed to stereo speakers. */
+
 	struct sc_reg_access sc_access[] = {
-		{0x226, 0x03, MASK1|MASK0},
-		{0x227, 0x88, MASK7|MASK3},
+		{0x200, 0x00, 0x0},
+		{0x201, 0xC0, 0x0},
+		{0x202, 0x00, 0x0},
+		{0x203, 0x00, 0x0},
+		{0x204, 0x0e, 0x0},
+		{0x205, 0x20, 0x0},
+		{0x206, 0x00, 0x0},
+		{0x207, 0x00, 0x0},
+		{0x208, 0x00, 0x0},
+		{0x209, 0x51, 0x0},
+		{0x20a, 0x00, 0x0},
+		{0x20b, 0x5a, 0x0},
+		{0x20c, 0xbe, 0x0},
+		{0x20d, 0x90, 0x0},
+		{0x20e, 0x51, 0x0},
+		{0x20f, 0x00, 0x0},
+		{0x210, 0x21, 0x0},
+		{0x211, 0x00, 0x0},
+		{0x212, 0x00, 0x0},
+		{0x213, 0x00, 0x0},
+		{0x214, 0x41, 0x0},
+		{0x215, 0x81, 0x0},
+		{0x216, 0x00, 0x0},
+		{0x217, 0x00, 0x0},
+		{0x218, 0x00, 0x0},
+		{0x219, 0x00, 0x0},
+		{0x21a, 0x00, 0x0},
+		{0x21b, 0x00, 0x0},
+		//{0x21c, 0x09, 0x0},
+		//{0x21d, 0x09, 0x0},
+		{0x21e, 0x00, 0x0},
+		{0x21f, 0x00, 0x0},
+		{0x220, 0x00, 0x0},
+		{0x221, 0x00, 0x0},
+		{0x222, 0x00, 0x0},
+		{0x223, 0x01, 0x0}, /* Jack detection: 00 -> 01 */
+		{0x224, 0x40, 0x0},
+		{0x225, 0x80, 0x0}, /* JAck detection: 00 -> 80 */
+		{0x226, 0x3c, 0x0},
+		{0x227, 0x80, 0x0},
+		{0xf9, 0x40, 0x0},
+		{0xfa, 0x19, 0x0},
+		{0xfb, 0x19, 0x0},
+		//{0xfc, 0x00, 0x0},
+		//{0xfd, 0x00, 0x0},
+		{0xfe, 0x00, 0x0}, /* 0x60 -> 0x00 Output mixer for stereo */
+		{0xff, sel_output, 0x0}, /* Removed sel_output */
 	};
+
+#ifdef KOSKI_JACK_DETECTION
+	struct sc_reg_access sc_access_hs_pb[] = {
+			{0xff, 0x8c, 0x0},
+			{0xfc, 0x10, 0x0},
+			{0xfd, 0x10, 0x0},
+	};
+#endif
+
 	int retval = 0;
 
-	if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
-		retval = mx_init_card();
-	if (retval)
+	printk("mx_init_playback_card called...\n");
+
+
+	retval = sst_sc_reg_access(sc_access, PMIC_WRITE, sizeof(sc_access)/4);
+	if (0 != retval) {
+		/* pmic communication fails */
+		pr_debug("pmic commn failed \n");
 		return retval;
+	}
+
+#ifdef KOSKI_JACK_DETECTION
+	/* Check if Jack is present */
+	if (koski_jack)
+	{
+		pr_debug("Koski Jack present!\n");
+
+		retval = sst_sc_reg_access(sc_access_hs_pb, PMIC_WRITE, 3);
+		if (0 != retval) {
+			/* pmic communication fails */
+			pr_debug("pmic commn failed \n");
+			return retval;
+		}
+	}
+#endif
+
+	mx_print_regs();
 
-	return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+	pr_debug("Playback configuration complete!!\n");
+	return 0;
 }
 
-int mx_power_down_pb(void)
+/*
+ * mx_power_up_pb
+ *
+ */
+int mx_power_up_pb(void)
 {
-/*	struct sc_reg_access sc_access[] = {
-		{0x226, 0x00, MASK3|MASK2},
+
+#if 0
+	struct sc_reg_access sc_access[] = {
+		{0x226, 0x3C, MASK3|MASK2}, /* 0x0F -> 0x3C Koski enable internal speaker as default */
+		{0x227, 0x80, MASK7|MASK3}, /* 0x88 -> 0x80; Koski select external clock */
 	};
+#endif
+
+	int temp_val = 0;
 	int retval = 0;
 
+    printk("mx_power_up_pb\n");
+
 	if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
 		retval = mx_init_card();
 	if (retval)
 		return retval;
 
-	return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
-	Turning Off this code, as power off coausing first few frames
-	to be cutt off... */
+	temp_val = mx_koski_get_output_dev();
+	pr_debug("Selected output temp_val = 0x%x\n", temp_val);
+
+	mx_init_playback_card(temp_val);
+
+	/* Set selected output_device */
+	temp_val = 0;
+	temp_val = mx_koski_get_output_dev();
+	pr_debug("Selected output for Playback: temp_val = 0x%x\n", temp_val);
+
 	return 0;
+
 }
 
-int mx_power_down_cp(void)
+
+/*
+ * mx_power_up_cp
+ *
+ */
+int mx_power_up_cp(void)
 {
-/*	struct sc_reg_access sc_access[] = {
-		{0x226, 0x00, MASK1|MASK0},
+#if 0
+	struct sc_reg_access sc_access[] = {
+		{0x226, 0x03, MASK1|MASK0},
+		{0x227, 0x80, MASK7|MASK3}, /* 0x88 -> 0x80; Koski select external clock */
 	};
+#endif
+
 	int retval = 0;
 
 	if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
@@ -191,39 +602,103 @@ int mx_power_down_cp(void)
 	if (retval)
 		return retval;
 
-	return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
-*/
+	mx_init_capture_card();
+
 	return 0;
+
 }
 
-int mx_power_down(void)
+
+/*
+ * mx_power_down_pb
+ *
+ */
+int mx_power_down_pb(void)
 {
-/*	struct sc_reg_access sc_access[] = {
-		{0x227, 0x00, MASK7},
-	};
-	int retval = 0;
+    int retval = 0;
 
-	if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
-		retval = mx_init_card();
-	if (retval)
+	struct sc_reg_access sc_access[1] = {{0,},};
+
+	sc_access[0].reg_addr =	0x227;
+	sc_access[0].value = 0x00;
+
+
+	retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 1);
+	if (0 != retval) {
+		/* pmic communication fails */
+		printk("pmic commn failed \n");
 		return retval;
+	}
 
-	return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
-*/	return 0;
+	return 0;
 }
 
+
+/*
+ * mx_power_down_cp
+ *
+ */
+int mx_power_down_cp(void)
+{
+	return 0;
+}
+
+
+/*
+ * mx_power_down
+ *
+ */
+int mx_power_down(void)
+{
+	return 0;
+}
+
+
+/*
+ * mx_set_voice_port
+ *
+ */
 int mx_set_voice_port(int status)
 {
 	int retval = 0;
 
+	struct sc_reg_access sc_access[1] = {{0,},};
+
 	if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
 		retval = mx_init_card();
 	if (retval)
 		return retval;
 
+	if (status == ACTIVATE)
+	{
+		pr_debug("Voice port... ACTIVATE\n");
+		sc_access[0].reg_addr =	0x227;
+		sc_access[0].value = 0x80;
+	}
+	else if (status == DEACTIVATE)
+	{
+		pr_debug("Voice port... DEACTIVATE\n");
+		sc_access[0].reg_addr =	0x227;
+		sc_access[0].value = 0x00;
+	}
+
+	retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 1);
+	if (0 != retval) {
+		/* pmic communication fails */
+		pr_debug("pmic commn failed \n");
+		return retval;
+	}
+
+	mx_print_regs();
+
 	return retval;
 }
 
+
+/*
+ * mx_set_audio_port
+ *
+ */
 int mx_set_audio_port(int status)
 {
 	int retval = 0;
@@ -232,89 +707,220 @@ int mx_set_audio_port(int status)
 		retval = mx_init_card();
 	if (retval)
 		return retval;
+
+	if (status == ACTIVATE)
+	{
+		pr_debug("Activating audio port...\n");
+	}
+	else if (status == DEACTIVATE)
+	{
+		pr_debug("De-activating audio port...\n");
+	}
+
+	/* Configurations for playback */
+	mx_init_playback_card(0xb0);
+
+	pr_debug("Audio port configuration complete!!\n");
+
 	return retval;
 }
+
+
+/*
+ * mx_set_pcm_voice_params
+ *
+ */
 int mx_set_pcm_voice_params(void)
 {
 	int retval = 0;
 
+    struct sc_reg_access sc_access[] = {
+		{0x200, 0x80, 0x00},
+		{0x201, 0xC0, 0x00},
+		{0x202, 0x00, 0x00},
+		{0x203, 0x00, 0x00},
+		{0x204, 0x0c, 0x00},
+		{0x205, 0x20, 0x00}, /* 0x10 -> 0x20 Koski scale external clock */
+		{0x206, 0x8f, 0x00}, /* PLL, 8kHz DAI1*/
+		{0x207, 0x21, 0x00}, /* 8kHz DAI1 */
+		{0x208, 0x18, 0x00}, /* DAI1 slave: DLY1 and HIZOFF1 enabled */
+		{0x209, 0x32, 0x00},
+		{0x20a, 0x00, 0x00},
+		{0x20b, 0x5A, 0x00}, /* 0x10 -> 0x5A Koski */
+		{0x20c, 0xBE, 0x00}, /* 0x00 -> 0xBE Koski */
+		{0x20d, 0x00, 0x00}, /* DAI2 'off' */
+		{0x20e, 0x40, 0x00},
+		{0x20f, 0x00, 0x00},
+		{0x210, 0x84, 0x00},
+		{0x211, 0x33, 0x00}, /* Voice filter */
+		{0x212, 0x00, 0x00},
+		{0x213, 0x00, 0x00},
+		{0x214, 0x41, 0x00},
+		{0x215, 0x00, 0x00},
+		{0x216, 0x00, 0x00},
+		{0x217, 0x20, 0x00},
+		{0x218, 0x00, 0x00},
+		{0x219, 0x00, 0x00},
+		{0x21a, 0x40, 0x00},
+		{0x21b, 0x40, 0x00},
+		{0x21c, 0x09, 0x00},
+		{0x21d, 0x09, 0x00},
+		{0x21e, 0x00, 0x00},
+		{0x21f, 0x00, 0x00},
+		{0x220, 0x00, 0x00}, /* Microphone configurations */
+		{0x221, 0x00, 0x00}, /* Microphone configurations */
+		{0x222, 0x50, 0x00}, /* Microphone configurations */
+		{0x223, 0x20, 0x00}, /* Microphone configurations */
+		{0x224, 0x00, 0x00},
+		{0x225, 0x00, 0x00},
+		{0x226, 0x3C, 0x00}, /* 0x0F -> 0x3C Koski enable internal speaker as default */
+		{0x227, 0x00, 0x00}, /* 0x88 -> 0x80; Koski select external clock */
+		{0xf9, 0x40, 0x00},
+		{0xfa, 0x19, 0x00},  /* 0x1F -> 0x19 Koski Left speaker volume */
+		{0xfb, 0x19, 0x00},  /* 0x00 -> 0x19 Koski Right speaker volume */
+		{0xfc, 0x12, 0x00},
+		{0xfd, 0x12, 0x00},
+		{0xfe, 0x00, 0x00},  /* 0x00 -> Koski output mixer for stereo */
+		{0xff, 0x81, 0x00},  /* 0x00 -> 0x81 Koski enable receiver */
+	};
+
+	pr_debug("mx_set_pcm_voice_params called...\n");
+
 	if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
 		retval = mx_init_card();
 	if (retval)
 		return retval;
 
+	retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 47);
+	if (0 != retval) {
+		/* pmic communication fails */
+		pr_debug("pmic commn failed \n");
+		return retval;
+	}
+
+	mx_print_regs();
+
+	pr_debug("Voice parameters configuration complete!!\n");
+
 	return retval;
 }
 
+/*
+ * mx_set_pcm_audio_params
+ *
+ */
 int mx_set_pcm_audio_params(int sfreq, int word_size)
 {
 	int config1 = 0, config2 = 0;
-	struct sc_reg_access sc_access[3];
 	int retval = 0;
+	struct sc_reg_access sc_access[4] = {{0,},};
+
+	pr_debug("called...\n");
 
 	if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
 		retval = mx_init_card();
 	if (retval)
 		return retval;
 
+    if(sfreq == 999999)
+    {
+       	mx_koski_write_reg();
+    }
+    else
+    {
+		pr_debug("called... sfreq = %d word_size = %d\n", sfreq, word_size);
+
+		switch (sfreq) {
+		case 8000:
+			config1 = 0x20;
+			config2 = 0x0f;
+			break;
+		case 11025:
+			config1 = 0x14;
+			config2 = 0xd8;
+			break;
+		case 12000:
+			config1 = 0x16;
+			config2 = 0xaf;
+			break;
+		case 16000:
+			config1 = 0x1e;
+			config2 = 0x3f;
+			break;
+		case 22050:
+			config1 = 0x29;
+			config2 = 0xaf;
+			break;
+		case 24000:
+			config1 = 0x2d;
+			config2 = 0x5f;
+			break;
+		case 32000:
+			config1 = 0x3c;
+			config2 = 0x7f;
+			break;
+		case 44100:
+			config1 = 0x53;
+			config2 = 0x5f;
+			break;
+		case 48000:
+			/* for Koski Capture */
+			config1 = 0x5a;
+			config2 = 0xbe;
+			break;
+		}
 
-	switch (sfreq) {
-	case 8000:
-		config1 = 0x10;
-		config2 = 0x00;
-		break;
-	case 11025:
-		config1 = 0x16;
-		config2 = 0x0d;
-		break;
-	case 12000:
-		config1 = 0x18;
-		config2 = 0x00;
-		break;
-	case 16000:
-		config1 = 0x20;
-		config2 = 0x00;
-		break;
-	case 22050:
-		config1 = 0x2c;
-		config2 = 0x1a;
-		break;
-	case 24000:
-		config1 = 0x30;
-		config2 = 0x00;
-		break;
-	case 32000:
-		config1 = 0x40;
-		config2 = 0x00;
-		break;
-	case 44100:
-		config1 = 0x58;
-		config2 = 0x33;
-		break;
-	case 48000:
-		config1 = 0x60;
-		config2 = 0x00;
-		break;
-	}
+		sc_access[0].reg_addr =	SET_MASTER_AND_LR_CLK1;
+		sc_access[0].value = config1;
+		sc_access[1].reg_addr = SET_MASTER_AND_LR_CLK2;
+		sc_access[1].value = config2;
+
+		pr_debug(" MASTER CLK 1 config1 = %x\n", config1);
+		pr_debug(" MASTER CLK 2 config2 = %x\n", config2);
+
+		switch (word_size) {
+		case 16:
+			/* for Koski Capture */
+			config1 = 0x22;
+			config2 = 0x32;
+			break;
+		case 24:
+			config1 = 0x52;
+			config2 = 0x32;
+			break;
+		}
 
-	sc_access[0].reg_addr =	0x206;
-	sc_access[0].value = config1;
-	sc_access[1].reg_addr = 0x207;
-	sc_access[1].value = config2;
+		pr_debug("config1 = %x\n", config1);
+		pr_debug("config2 = %x\n", config2);
 
-	if (word_size == 16)
-		sc_access[2].value = 0x31;
-	else if (word_size == 24)
-		sc_access[2].value = 0x32;
+		sc_access[2].reg_addr = DIGITAL_INTERFACE_TO_DAI2;
+		sc_access[2].value = config1;
+		sc_access[3].reg_addr = CLK_AND_FS2;
+		sc_access[3].value = config2;
+
+		retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 4);
+		if (0 != retval)
+			pr_debug("pmic communication failed \n");
+
+	}/* if else */
+
+	pr_debug("******** \n");
+    mx_print_regs();
+    pr_debug("******** \n");
+
+	return retval;
 
-	sc_access[2].reg_addr = 0x209;
-	return sst_sc_reg_access(sc_access, PMIC_WRITE, 3);
 }
 
-int mx_set_selected_output_dev(u8 dev_id)
+
+/*
+ * mx_set_selected_output_dev
+ *
+ */
+int mx_set_selected_output_dev(int dev_id)
 {
-	struct sc_reg_access sc_access[2];
-	int num_reg;
+	struct sc_reg_access sc_access[4];
+	int num_reg = 0;
 	int retval = 0;
 
 	if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
@@ -323,34 +929,82 @@ int mx_set_selected_output_dev(u8 dev_id
 		return retval;
 
 	pr_debug("mx_set_selected_output_dev dev_id:0x%x\n", dev_id);
+
 	switch (dev_id) {
 	case STEREO_HEADPHONE:
+		pr_debug("STEREO_HEADPHONE selected\n");
+
 		sc_access[0].reg_addr = 0x226;
-		sc_access[0].value = 0x0C;
-		sc_access[0].mask = 0x3F;
+		sc_access[0].value = 0x3C;
+		sc_access[0].mask = 0x3C;
 
 		sc_access[1].reg_addr = 0xFF;
-		sc_access[1].value = 0x00;
-		sc_access[1].mask = 0xA0;
-		num_reg = 2;
+		sc_access[1].value = 0x8C;
+		sc_access[1].mask = 0xff;
+
+		/* Enable stereo headphones  - Begin */
+		/* Volume Left Un-Mute */
+		sc_access[2].reg_addr = 0xFD;
+		sc_access[2].value = 0x1A;
+		sc_access[2].mask = 0xff;
+
+		/* Volume right Un-Mute */
+		sc_access[3].reg_addr = 0xFC;
+		sc_access[3].value = 0x1A;
+		sc_access[3].mask = 0xff;
+
+		num_reg = 4;
 		break;
 	case INTERNAL_SPKR:
+		pr_debug("INTERNAL_SPKR selected\n");
+
 		sc_access[0].reg_addr = 0x226;
-		sc_access[0].value = 0x3F;
-		sc_access[0].mask = 0x3F;
+		sc_access[0].value = 0x3C;
+		sc_access[0].mask = 0xff;
 
 		sc_access[1].reg_addr = 0xFF;
-		sc_access[1].value = 0xA0;
-		sc_access[1].mask = 0xA0;
-		num_reg = 2;
+		sc_access[1].value = 0xB0;
+		sc_access[1].mask = 0xff;
+
+		sc_access[2].reg_addr = 0xFD;
+		sc_access[2].value = 0x00;
+		sc_access[2].mask = 0xff;
+
+		sc_access[3].reg_addr = 0xFC;
+		sc_access[3].value = 0x00;
+		sc_access[3].mask = 0xff;
+
+		num_reg = 4;
+		break;
+	case RECEIVER:
+		pr_debug("RECEIVER Koski selected\n");
+
+		/* configuration - AS enable, receiver enable */
+		sc_access[0].reg_addr = 0xFF;
+		sc_access[0].value = 0x81;
+		sc_access[0].mask = 0xff;
+
+		/* Line output (L&R), DAC output (L&R) enable */
+		sc_access[1].reg_addr = 0x226;
+		sc_access[1].value = 0x3C;
+		sc_access[1].mask = 0xff;
+        num_reg = 2;
 		break;
 	}
+
+	mx_print_regs();
+
 	return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_reg);
 }
 
-int mx_set_selected_input_dev(u8 dev_id)
+
+/*
+ * mx_set_selected_input_dev
+ *
+ */
+int mx_set_selected_input_dev(int dev_id)
 {
-	struct sc_reg_access sc_access[2];
+	struct sc_reg_access sc_access[13];
 	int num_reg = 0;
 	int retval = 0;
 
@@ -363,29 +1017,96 @@ int mx_set_selected_input_dev(u8 dev_id)
 
 	switch (dev_id) {
 	case AMIC:
-		sc_access[0].reg_addr = 0x223;
-		sc_access[0].value = 0x00;
-		sc_access[0].mask = 0x00;
-		sst_sc_reg_access(sc_access, PMIC_WRITE, 1);
+		pr_debug("Not supported in mono\n");
 		return 0;
 
 	case HS_MIC:
-		sc_access[0].reg_addr = 0x223;
-		sc_access[0].value = 0x00;
-		sc_access[0].mask = 0x00;
-		num_reg = 1;
+		pr_debug("HS_MIC selected \n");
+
+		/* configuration - AS enable, receiver enable */
+		sc_access[0].reg_addr = 0xFF;
+		sc_access[0].value = 0x8c;
+		sc_access[0].mask = 0x8c;
+
+		sc_access[1].reg_addr = 0x226;
+		sc_access[1].value = 0x3C;
+		sc_access[1].mask = 0x3C;
+        num_reg = 2;
+
 		break;
 	case DMIC:
-		sc_access[0].reg_addr = 0x223;
-		sc_access[0].value = 0x30;
-		sc_access[0].mask = 0x30;
-		num_reg = 1;
+		pr_debug("DMIC selected \n");
+
+		/* configuration - AS enable, receiver enable */
+		sc_access[0].reg_addr = 0xFF;
+		sc_access[0].value = 0x8C;
+		sc_access[0].mask = 0x8C;
+
+		/* Line output (L&R), DAC output (L&R) enable */
+		sc_access[1].reg_addr = 0x226;
+		sc_access[1].value = 0x3C;
+		sc_access[1].mask = 0x3C;
+
+		sc_access[2].reg_addr = 0x206;
+		sc_access[2].value = 0x5a;
+		sc_access[2].mask = 0x5a;
+
+		sc_access[3].reg_addr = 0x207;
+		sc_access[3].value = 0xbe;
+		sc_access[3].mask = 0xbe;
+
+		sc_access[4].reg_addr = 0x208;
+		sc_access[4].value = 0x90;
+		sc_access[4].mask = 0x90;
+
+		sc_access[5].reg_addr = 0x209;
+		sc_access[5].value = 0x32;
+		sc_access[5].mask = 0x32;
+
+		sc_access[6].reg_addr = 0x20b;
+		sc_access[6].value = 0x00;
+		sc_access[6].mask = 0x00;
+
+		sc_access[7].reg_addr = 0x20d;
+		sc_access[7].value = 0x90;
+		sc_access[7].mask = 0x90;
+
+		sc_access[8].reg_addr = 0x20e;
+		sc_access[8].value = 0x22;
+		sc_access[8].mask = 0x22;
+
+		sc_access[9].reg_addr = 0x210;
+		sc_access[9].value = 0x84;
+		sc_access[9].mask = 0x84;
+
+		sc_access[10].reg_addr = 0x215;
+		sc_access[10].value = 0x81;
+		sc_access[10].mask = 0x81;
+
+		sc_access[11].reg_addr = 0x223;
+		sc_access[11].value = 0x30;
+		sc_access[11].mask = 0x30;
+		num_reg = 12;
+		break;
+	case LINE_IN:
+		pr_debug("LINE_IN selected \n");
+
+		/* Line output (L&R), DAC output (L&R) enable */
+		sc_access[0].reg_addr = 0x226;
+		sc_access[0].value = 0xFC;
+		sc_access[0].mask = 0xFC;
+        num_reg = 1;
 		break;
 	}
 	return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_reg);
 }
 
-int mx_set_mute(int dev_id, u8 value)
+
+/*
+ * mx_set_mute
+ *
+ */
+int mx_set_mute(int dev_id, int value)
 {
 	struct sc_reg_access sc_access[6];
 	int num_reg = 0;
@@ -404,19 +1125,16 @@ int mx_set_mute(int dev_id, u8 value)
 	case PMIC_SND_HP_MIC_MUTE:
 		sc_access[0].reg_addr =	0x220;
 		sc_access[1].reg_addr =	0x221;
-		sc_access[2].reg_addr =	0x223;
 			if (value == MUTE) {
 				sc_access[0].value = 0x00;
 				sc_access[1].value = 0x00;
-				sc_access[2].value = 0x10;
 			} else {
-				sc_access[0].value = 0x20;
-				sc_access[1].value = 0x20;
+				sc_access[0].value = 0x40;
+				sc_access[1].value = 0x40;
 			}
 		sc_access[0].mask = MASK5|MASK6;
 		sc_access[1].mask = MASK5|MASK6;
-		sc_access[2].mask = MASK5|MASK4;
-		num_reg = 3;
+		num_reg = 2;
 		break;
 
 	case PMIC_SND_LEFT_SPEAKER_MUTE:
@@ -439,7 +1157,15 @@ int mx_set_mute(int dev_id, u8 value)
 		sc_access[0].mask = MASK6;
 		num_reg = 1;
 		break;
-
+	case PMIC_SND_RECEIVER_MUTE:
+		sc_access[0].reg_addr = VOL_CTRL_RT;
+		if (value == MUTE)
+			sc_access[0].value = 0x40;
+		else
+			sc_access[0].value = 0x00;
+		sc_access[0].mask = MASK6;
+		num_reg = 1;
+		break;
 	case PMIC_SND_MUTE_ALL:
 		sc_access[0].reg_addr = VOL_CTRL_RT;
 		sc_access[1].reg_addr = VOL_CTRL_LT;
@@ -451,8 +1177,8 @@ int mx_set_mute(int dev_id, u8 value)
 			sc_access[3].value = 0x00;
 		} else {
 			sc_access[0].value = sc_access[1].value = 0x00;
-			sc_access[2].value = 0x20;
-			sc_access[3].value = 0x20;
+			sc_access[2].value = 0x40;
+			sc_access[3].value = 0x40;
 		}
 		sc_access[0].mask = sc_access[1].mask = MASK6;
 		sc_access[2].mask = MASK5|MASK6;
@@ -464,7 +1190,12 @@ int mx_set_mute(int dev_id, u8 value)
 	return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_reg);
 }
 
-int mx_set_vol(int dev_id, u8 value)
+
+/*
+ * mx_set_vol
+ *
+ */
+int mx_set_vol(int dev_id, int value)
 {
 	struct sc_reg_access sc_access[2] = {{0},};
 	int num_reg = 0;
@@ -477,10 +1208,13 @@ int mx_set_vol(int dev_id, u8 value)
 
 	pr_debug("mx_set_vol dev_id:0x%x , value:%d \n", dev_id, value);
 	switch (dev_id) {
+	case PMIC_SND_RECEIVER_VOL:
+		return 0;
+		break;
 	case PMIC_SND_CAPTURE_VOL:
 		sc_access[0].reg_addr =	0x220;
 		sc_access[1].reg_addr =	0x221;
-		sc_access[0].value = sc_access[1].value = -value;
+		sc_access[0].value = sc_access[1].value = (-value) | 0x40;
 		sc_access[0].mask = sc_access[1].mask =
 			(MASK0|MASK1|MASK2|MASK3|MASK4);
 		num_reg = 2;
@@ -501,7 +1235,12 @@ int mx_set_vol(int dev_id, u8 value)
 	return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_reg);
 }
 
-int mx_get_mute(int dev_id, u8 *value)
+
+/*
+ *mx_get_mute
+ *
+ */
+int mx_get_mute(int dev_id, int *value)
 {
 	struct sc_reg_access sc_access[4] = {{0},};
 	int retval = 0, num_reg = 0, mask = 0;
@@ -527,7 +1266,6 @@ int mx_get_mute(int dev_id, u8 *value)
 		else
 			*value = MUTE;
 		return retval;
-
 	case PMIC_SND_LEFT_HP_MUTE:
 	case PMIC_SND_LEFT_SPEAKER_MUTE:
 		sc_access[0].reg_addr = VOL_CTRL_LT;
@@ -567,7 +1305,11 @@ int mx_get_mute(int dev_id, u8 *value)
 	return retval;
 }
 
-int mx_get_vol(int dev_id, u8 *value)
+/*
+ * mx_get_vol
+ *
+ */
+int mx_get_vol(int dev_id, int *value)
 {
 	struct sc_reg_access sc_access = {0,};
 	int retval = 0, mask = 0, num_reg = 0;
@@ -620,4 +1362,3 @@ struct snd_pmic_ops snd_pmic_ops_mx = {
 	.power_down_pmic_cp =	mx_power_down_cp,
 	.power_down_pmic = 	mx_power_down,
 };
-
Index: linux-2.6.33/sound/pci/sst/koski_audio_conf.c
===================================================================
--- /dev/null
+++ linux-2.6.33/sound/pci/sst/koski_audio_conf.c
@@ -0,0 +1,431 @@
+/*
+ *  koski_audio_conf.c - koski audio configure part for audio engine
+ *
+ *  Copyright (C) 2009 aavamobile
+ *  Authors:	Samuli.konttila <samuli.konttila@aavamobile.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; version 2 of the License.
+ *
+ *  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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/cdev.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/workqueue.h>
+#include <linux/pci.h>
+#include <linux/firmware.h>
+#include <sound/intel_lpe.h>
+#include <sound/intel_sst_ioctl.h>
+#include "intel_sst_fw_ipc.h"
+#include "intel_sst_common.h"
+#include "intelmid_snd_control.h"
+#include "koski_audio_conf.h"
+
+
+
+/*Suported interface
+
+
+Voicecall -> receiver
+Voicecall -> speaker
+Voicecall -> Bluetooth
+
+Voicecall + mix -> receiver
+Voicecall + mix -> speaker
+Voicecall + mix -> Bluetooth
+
+
+
+*/
+#define TABLE_LEN(reg_table) sizeof(reg_table)/4
+
+int koski_voice_call = 0;
+extern volatile int koski_jack;
+
+    struct sc_reg_access voice_call_on[] = {
+		{0x200, 0x80, 0x00},
+		{0x201, 0xC0, 0x00},
+		{0x202, 0x00, 0x00},
+		{0x203, 0x00, 0x00},
+		{0x204, 0x0e, 0x00}, /* Jack detection: 0c -> 0e */
+		{0x205, 0x20, 0x00}, /* 0x10 -> 0x20 Koski scale external clock */
+		{0x206, 0x8f, 0x00}, /* PLL, 8kHz DAI1*/
+		{0x207, 0x21, 0x00}, /* 8kHz DAI1 */
+		{0x208, 0x18, 0x00}, /* DAI1 slave: DLY1 and HIZOFF1 enabled */
+		{0x209, 0x32, 0x00},
+		{0x20a, 0x00, 0x00},
+		{0x20b, 0x5A, 0x00}, /* 0x10 -> 0x5A Koski */
+		{0x20c, 0xBE, 0x00}, /* 0x00 -> 0xBE Koski */
+		{0x20d, 0x00, 0x00}, /* DAI2 'off' */
+		{0x20e, 0x40, 0x00},
+		{0x20f, 0x00, 0x00},
+		{0x210, 0x84, 0x00},
+		{0x211, 0x33, 0x00}, /* Voice filter */
+		{0x212, 0x00, 0x00},
+		{0x213, 0x00, 0x00},
+		{0x214, 0x41, 0x00},
+		{0x215, 0x00, 0x00},
+		{0x216, 0x00, 0x00},
+		{0x217, 0x20, 0x00},
+		{0x218, 0x00, 0x00},
+		{0x219, 0x00, 0x00},
+		{0x21a, 0x40, 0x00},
+		{0x21b, 0x40, 0x00},
+		{0x21e, 0x00, 0x00},
+		{0x21f, 0x00, 0x00},
+		{0x220, 0x00, 0x00}, /* Microphone configurations */
+		{0x221, 0x00, 0x00}, /* Microphone configurations */
+		{0x222, 0x50, 0x00}, /* Microphone configurations */
+		{0x223, 0x21, 0x00}, /* Jack detection: 20 -> 21 */
+		{0x224, 0x00, 0x00},
+		{0x225, 0x80, 0x00}, /* JAck detection: 00 -> 80 */
+		{0x226, 0x3C, 0x00}, /* 0x0F -> 0x3C Koski enable internal speaker as default */
+		{0x227, 0x80, 0x00}, /* 0x88 -> 0x80; Koski select external clock */
+		{0xf9, 0x40, 0x00},
+		{0xfa, 0x19, 0x00},  /* 0x1F -> 0x19 Koski Left speaker volume */
+		{0xfb, 0x19, 0x00},  /* 0x00 -> 0x19 Koski Right speaker volume */
+		{0xfe, 0x00, 0x00},  /* 0x00 -> Koski output mixer for stereo */
+		{0xff, 0x81, 0x00},  /* 0x00 -> 0x81 Koski enable receiver */
+	};
+
+struct sc_reg_access voice_call_on_hs[] = {
+		{0x200, 0x80, 0x00},
+		{0x201, 0xC0, 0x00},
+		{0x202, 0x00, 0x00},
+		{0x203, 0x00, 0x00},
+		{0x204, 0x0e, 0x00},
+		{0x205, 0x20, 0x00}, /* 0x10 -> 0x20 Koski scale external clock */
+		{0x206, 0x8f, 0x00}, /* PLL, 8kHz DAI1*/
+		{0x207, 0x21, 0x00}, /* 8kHz DAI1 */
+		{0x208, 0x58, 0x00}, /* DAI1 slave: DLY1 and HIZOFF1 enabled */
+		{0x209, 0x32, 0x00},
+		{0x20a, 0x00, 0x00},
+		{0x20b, 0x5A, 0x00}, /* 0x10 -> 0x5A Koski */
+		{0x20c, 0xBE, 0x00}, /* 0x00 -> 0xBE Koski */
+		{0x20d, 0x00, 0x00}, /* DAI2 'off' */
+		{0x20e, 0x40, 0x00},
+		{0x20f, 0x00, 0x00},
+		{0x210, 0x84, 0x00},
+		{0x211, 0x33, 0x00}, /* Voice filter */
+		{0x212, 0x00, 0x00},
+		{0x213, 0x00, 0x00},
+		{0x214, 0x41, 0x00},
+		{0x215, 0x00, 0x00},
+		{0x216, 0x00, 0x00},
+		{0x217, 0x20, 0x00},
+		{0x218, 0x00, 0x00},
+		{0x219, 0x00, 0x00},
+		{0x21a, 0x40, 0x00},
+		{0x21b, 0x40, 0x00},
+		{0x21c, 0x09, 0x00},
+		{0x21d, 0x09, 0x00},
+		{0x21e, 0x00, 0x00},
+		{0x21f, 0x00, 0x00},
+		{0x220, 0x00, 0x00}, /* Microphone configurations */
+		{0x221, 0x40, 0x00}, /* Microphone configurations */
+		{0x222, 0x10, 0x00}, /* Microphone configurations */
+		{0x223, 0x01, 0x00}, /* Microphone configurations */
+		{0x224, 0x00, 0x00},
+		{0x225, 0x80, 0x00},
+		{0x226, 0x3f, 0x00}, /* 0x0F -> 0x3C Koski enable internal speaker as default */
+		{0x227, 0x80, 0x00}, /* 0x88 -> 0x80; Koski select external clock */
+		{0xf9, 0x40, 0x00},
+		{0xfa, 0x00, 0x00},  /* 0x1F -> 0x19 Koski Left speaker volume */
+		{0xfb, 0x00, 0x00},  /* 0x00 -> 0x19 Koski Right speaker volume */
+		{0xfc, 0x10, 0x00},  /* 0x1F -> 0x19 Koski Left speaker volume */
+		{0xfd, 0x10, 0x00},  /* 0x00 -> 0x19 Koski Right speaker volume */
+		{0xfe, 0x00, 0x00},  /* 0x00 -> Koski output mixer for stereo */
+		{0xff, 0x8c, 0x00},  /* 0x00 -> 0x81 Koski enable receiver */
+	};
+
+struct sc_reg_access voice_call_off[] = {
+		{0x227, 0x00, 0x00},
+	};
+
+struct sc_reg_access output_receiver[] = {
+		{0xff, 0x81, 0x00},
+	};
+
+struct sc_reg_access output_speaker[] = {
+	    {0xff, 0xb0, 0x00},
+	};
+
+struct sc_reg_access output_bluetooth[] = {
+    	    {0xff, 0x00, 0x00},
+            {0x208, 0x00, 0x00},
+            {0x209, 0x00, 0x00},
+	};
+
+
+struct sc_reg_access output_headset[] = {
+		{0x208, 0x58, 0x00},
+		{0x21b, 0x40, 0x00},
+		{0x21c, 0x0c, 0x00},
+		{0x221, 0x40, 0x00},
+		{0x222, 0x10, 0x00},
+		{0x223, 0x00, 0x00},
+		{0x224, 0x00, 0x00},
+		{0x226, 0x3f, 0x00},
+        {0xfc, 0x12, 0x00},
+		{0xfd, 0x12, 0x00},
+        {0xff, 0x8c, 0x00},
+	};
+
+
+struct sc_reg_access call_mute[] = {
+            {0x220, 0x00, MASK5|MASK6},
+            {0x221, 0x00, MASK5|MASK6},
+        	{0x223, 0x00, 0xff},
+	};
+
+
+
+struct sc_reg_access call_unmute[] = {
+            {0x220, 0x40, MASK5|MASK6},
+            {0x221, 0x40, MASK5|MASK6},
+        	{0x223, 0x20, 0xff},
+	};
+
+struct sc_reg_access output_headset_pb[] = {
+		{0xfd, 0x10, 0x00},
+		{0xfc, 0x10, 0x00},
+		{0xff, 0x8c, 0x00},
+	};
+
+struct sc_reg_access output_speaker_pb[] = {
+		{0xfd, 0x10, 0x00},
+		{0xfc, 0x10, 0x00},
+		{0xff, 0xb0, 0x00},
+	};
+
+/* Print out MAX Codec registers */
+void mx_print_regs_(void)
+{
+	struct sc_reg_access sc_access[1] = {{0,},};
+
+	int i = 0;
+	int retval = 0;
+
+	printk("Printing out MX Audio registers:\n");
+	printk("REG  VALUE\n");
+
+	sc_access[0].reg_addr = 0xF4;
+	retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
+	printk("0x%x 0x%x\n", sc_access[0].reg_addr, sc_access[0].value);
+
+
+	for( i = 0xf9; i <= 0xff; i++ )
+	{
+		sc_access[0].reg_addr = i;
+		retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
+		printk("0x%x 0x%x\n", sc_access[0].reg_addr,
+			sc_access[0].value);
+	}
+
+	for( i = 0x200; i <= 0x227; i++ )
+	{
+		sc_access[0].reg_addr = i;
+		retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
+		printk("0x%x 0x%x\n", sc_access[0].reg_addr,
+			sc_access[0].value);
+	}
+
+
+}
+
+
+
+int set_voice_call(bool start)
+{
+    int retval = 0;
+    struct sc_reg_access *reg_table;
+    int table_len=0;
+
+    if(start){
+        /*start voice call*/
+        printk("set_voice_call table_len = %d\n",sizeof(voice_call_on)/4);
+
+		if (koski_jack)
+		{
+			reg_table = voice_call_on_hs;
+			table_len = sizeof(voice_call_on_hs)/4;
+		}
+		else
+		{
+			reg_table = voice_call_on;
+			table_len = sizeof(voice_call_on)/4;
+		}
+		koski_voice_call = 1;
+    }
+    else{
+        printk("set_voice_call table_len\n",sizeof(voice_call_off)/4);
+        reg_table = voice_call_off;
+        table_len = sizeof(voice_call_off)/4;
+		koski_voice_call = 0;
+    }
+
+    retval = sst_sc_reg_access(reg_table, PMIC_WRITE, table_len);
+
+	if (0 != retval) {
+        /* pmic communication fails */
+        pr_debug("pmic commn failed \n");
+        return retval;
+	}
+
+    return retval;
+}
+
+
+int set_output_device(enum output_devices output_dev)
+{
+	int retval = 0;
+    struct sc_reg_access *reg_table;
+    int table_len=0;
+
+    if (output_dev>=OUTPUT_ERROR){
+        pr_debug("Invalid output devices\n");
+        return -1;
+    }
+
+    switch (output_dev){
+        case OUTPUT_RECEIVER:
+            printk("set output OUTPUT_RECEIVER\n");
+            reg_table = output_receiver;
+            table_len = sizeof(output_receiver)/4;
+        break;
+        case OUTPUT_SPEAKER:
+            printk("set output OUTPUT_SPEAKER\n");
+            if(!koski_voice_call)
+			{
+				reg_table = output_speaker_pb;
+				table_len = sizeof(output_speaker_pb)/4;
+			}
+			else
+			{
+				printk("Koski voice call\n");
+				//reg_table = output_speaker;
+				reg_table = voice_call_on;
+				//table_len = sizeof(output_speaker)/4;
+				table_len = sizeof(voice_call_on)/4;
+			}
+        break;
+        case OUTPUT_BLUETOOTH:
+            printk("set output OUTPUT_BLUETOOTH\n");
+            reg_table = output_bluetooth;
+            table_len = sizeof(output_bluetooth)/4;
+        break;
+        case OUTPUT_HEADSET:
+            printk("set output OUTPUT_HEADSET\n");
+            if(!koski_voice_call)
+			{
+				reg_table = output_headset_pb;
+				table_len = sizeof(output_headset_pb)/4;
+			}
+			else
+			{
+				printk("Koski voice call\n");
+				//reg_table = output_headset;
+				reg_table = voice_call_on_hs;
+				//table_len = sizeof(output_headset)/4;
+				table_len = sizeof(voice_call_on_hs)/4;
+			}
+        break;
+        default:
+            printk("set output OUTPUT_ERROR\n");
+            return -1;
+        break;
+    }
+
+
+    retval = sst_sc_reg_access(reg_table, PMIC_WRITE, table_len);
+
+	if (0 != retval) {
+        /* pmic communication fails */
+        printk("pmic commn failed \n");
+        return retval;
+	}
+	//mx_print_regs_();
+    return retval;
+}
+
+
+
+int load_reg_table(struct sc_reg_access *reg_table,int table_len)
+{
+	int retval = 0;
+
+    printk("load_reg_table table len=%d\n",table_len);
+
+    retval = sst_sc_reg_access(reg_table, PMIC_READ_MODIFY, table_len);
+
+	if (0 != retval) {
+        /* pmic communication fails */
+        printk("pmic commn failed \n");
+        return retval;
+	}
+    mx_print_regs_();
+    return retval;
+}
+
+int configure_koski_audio(int conf_type)
+{
+    int output_type,audio_type;
+    output_type = (conf_type)>>8;
+    audio_type = (conf_type) & 0x00ff;
+
+    printk("configure_koski_audio audio_type:%d output_type:%d\n",audio_type,output_type);
+
+        if (audio_type== VOICE_CALL_ON)
+        {
+            set_voice_call(true);
+        }
+        else if (audio_type==VOICE_CALL_OFF)
+            set_voice_call(false);
+        else if (audio_type==FM_RADIO_ON)
+            set_voice_call(false);
+        else if (audio_type==FM_RADIO_OFF)
+            set_voice_call(false);
+        else if (audio_type==VOICE_CALL_MUTE)
+        {
+            printk("VOICE_CALL_MUTE \n");
+            load_reg_table(call_mute,TABLE_LEN(call_mute));
+        }
+        else if (audio_type==VOICE_CALL_UNMUTE)
+        {
+            printk("VOICE_CALL_UNMUTE \n");
+            load_reg_table(call_unmute,TABLE_LEN(call_unmute));
+        }
+        if (output_type!=0)
+            set_output_device(output_type);
+
+    return 0;
+}
+
+
+
+
+
Index: linux-2.6.33/sound/pci/sst/koski_audio_conf.h
===================================================================
--- /dev/null
+++ linux-2.6.33/sound/pci/sst/koski_audio_conf.h
@@ -0,0 +1,59 @@
+#ifndef __KOSKI_AUDIO_CONF_H
+#define __KOSKI_AUDIO_CONF_H
+/*
+ *  koski_audio_conf.c - koski audio configure part for audio engine
+ *
+ *  Copyright (C) 2009 aavamobile
+ *  Authors:	Samuli.konttila <samuli.konttila@aavamobile.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; version 2 of the License.
+ *
+ *  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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#define KOSKI_JACK_DETECTION
+
+enum koski_conf_type {
+	VOICE_CALL_ON=1,
+	VOICE_CALL_OFF,
+    FM_RADIO_ON,
+    FM_RADIO_OFF,
+    VOICE_CALL_MUTE,
+    VOICE_CALL_UNMUTE,
+};
+
+enum output_devices {
+	OUTPUT_RECEIVER=1,
+	OUTPUT_SPEAKER,
+	OUTPUT_BLUETOOTH,
+	OUTPUT_HEADSET,
+	OUTPUT_ERROR
+};
+
+
+
+
+
+int configure_koski_audio(int conf_type);
+int set_voice_call(bool start);
+
+int set_output_device(enum output_devices output_dev);
+
+#endif
+
+
+
+
Index: linux-2.6.33/drivers/spi/hh2serial.c
===================================================================
--- linux-2.6.33.orig/drivers/spi/hh2serial.c
+++ linux-2.6.33/drivers/spi/hh2serial.c
@@ -1,7 +1,17 @@
+/******************************************************************************
+
+                               Copyright (c) 2009
+                            Infineon Technologies AG
+                     Am Campeon 1-12; 81726 Munich, Germany
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
 /*
- *  HH2 SPI Serial driver
+ *  HH2 SPI Serial driver Version 0.2 Beta
  *
- *  Copyright (C) 2009 Markus Burvall (Markus.Burvall@swedenconnectivity.com)
+ *  Written by: 2009 Markus Burvall (Markus.Burvall@swedenconnectivity.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
@@ -10,15 +20,10 @@
  */
 
 
-#define DEBUG 1
-
-//#define HH2_TTY_ECHO
-//#define HH2_TTY_SEND_POLL
-//#define HH2_NO_SPI
 #define HH2SERIAL_SPI_16BIT
-//#define HH2SERIAL_ENABLE_DEBUG
 #define HH2SERIAL_SPI_POLL
 
+/*#define HH2SERIAL_SHOW_ERRORS*/
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -66,6 +71,7 @@ struct hh2serial_dev {
     atomic_t tty_need_read;
     atomic_t spi_irq_pending;
     int mthread_up;
+    int hhRxBufferBytes;
 };
 
 static const char driver_name[] = "hh2serial";
@@ -89,13 +95,7 @@ static struct hh2serial_dev priv0;
 #define GPSD_DREAD                0xC0    /* bit 7 and 6 */
 #define GPSD_CRWRITE              0x00    /* All zero */
 
-#ifdef HH2SERIAL_SPI_16BIT
-/*      HH2 DATA OPERATIONS      */
-#define GPSD_16BIT_SRREAD               0x8000    /* bit 7 */
-#define GPSD_16BIT_DWRITE               0x4000    /* bit 6 */
-#define GPSD_16BIT_DREAD                0xC000    /* bit 7 and 6 */
-#define GPSD_16BIT_CRWRITE              0x0000    /* All zero */
-#endif
+
 
 /*      HH2 STATUS REGISTER      */
 #define GPSS_TCNT                 0x1F    /* bits [4..0] */
@@ -192,9 +192,7 @@ int hh2serial_spi_get_rx_len(struct hh2s
         buf_ptr = x.rx_buf;
 
 #ifdef HH2SERIAL_ENABLE_DEBUG
-        printk(KERN_INFO "hh2serial RD:%02X, %02X\n",
-            *buf_ptr,
-            buf_ptr[1]);
+        printk(KERN_INFO "hh2serial RD:%02X, %02X\n", *buf_ptr, buf_ptr[1]);
 #endif
 
 #ifndef HH2SERIAL_SPI_16BIT
@@ -203,33 +201,56 @@ int hh2serial_spi_get_rx_len(struct hh2s
         ret = *buf_ptr & GPSS_TCNT;
 
         /* Check buffer overrun or underrun errors */
+#ifdef HH2SERIAL_SHOW_ERRORS
         if (*buf_ptr & GPSS_TERR)
             printk(KERN_INFO "hh2serial HH2 transmitter underrun!\n");
 
         if (*buf_ptr & GPSS_RERR)
             printk(KERN_INFO "hh2serial HH2 receiver overrun!\n");
-
+#endif
+		if (*buf_ptr & GPSS_REMPTY)
+		{
+			hh2serial->hhRxBufferBytes = HH2SERIAL_SPI_MAX_BYTES;
+#ifdef HH2SERIAL_ENABLE_DEBUG
+            printk(KERN_INFO "hh2serial HH2 rx empty!\n");
+#endif
+		}
 #else
         /* 16 bit second byte is status register */
         /* Available bytes */
         ret = buf_ptr[1] & GPSS_TCNT;
 
         /* Check buffer overrun or underrun errors */
+#ifdef HH2SERIAL_SHOW_ERRORS
         if (buf_ptr[1] & GPSS_TERR)
             printk(KERN_INFO "hh2serial HH2 transmitter underrun!\n");
 
         if (buf_ptr[1] & GPSS_RERR)
             printk(KERN_INFO "hh2serial HH2 receiver overrun!\n");
 #endif
+
+		if (buf_ptr[1] & GPSS_REMPTY)
+		{
+			hh2serial->hhRxBufferBytes = HH2SERIAL_SPI_MAX_BYTES;
+#ifdef HH2SERIAL_ENABLE_DEBUG
+            printk(KERN_INFO "hh2serial HH2 rx empty!\n");
+#endif
+		}
+#endif
         /* Take care of errors */
         /* FIX ME */
 
 #ifdef HH2SERIAL_ENABLE_DEBUG
-        printk(KERN_INFO "hh2serial SR:%02X, rx len %d\n",
-            buf_ptr[1],
-            ret);
+        printk(KERN_INFO "hh2serial SR:%02X, rx len %d\n", buf_ptr[1], ret);
 #endif
     }
+	else
+	{
+#ifdef HH2SERIAL_SHOW_ERRORS
+printk(KERN_INFO "hh2serial Rd_status, spi_sync failed: %d\n",ret);
+#endif
+		ret = 0;
+	}
 
     kfree(local_buf);
     return ret;
@@ -332,11 +353,22 @@ int hh2serial_spi_read(struct hh2serial_
         available_rd = *buf_ptr & GPSS_TCNT;
 
         /* Check buffer overrun or underrun errors */
+#ifdef HH2SERIAL_SHOW_ERRORS
         if (*buf_ptr & GPSS_TERR)
             printk(KERN_INFO "hh2serial HH2 transmitter underrun!\n");
 
         if (*buf_ptr & GPSS_RERR)
             printk(KERN_INFO "hh2serial HH2 receiver overrun!\n");
+#endif
+
+		if (*buf_ptr & GPSS_REMPTY)
+		{
+			hh2serial->hhRxBufferBytes = HH2SERIAL_SPI_MAX_BYTES;
+#ifdef HH2SERIAL_ENABLE_DEBUG
+            printk(KERN_INFO "hh2serial HH2 rx empty!\n");
+#endif
+
+		}
 #else
         /* 16 bit second byte is status register */
         /* Every other byte is status register */
@@ -345,6 +377,7 @@ int hh2serial_spi_read(struct hh2serial_
         available_rd = (buf_ptr[len_inc_hdr-1] & GPSS_TCNT) - 1;
 
         /* Check buffer overrun or underrun errors */
+#ifdef HH2SERIAL_SHOW_ERRORS
         if (buf_ptr[len_inc_hdr-1] & GPSS_TERR)
             printk(KERN_INFO "hh2serial HH2 transmitter underrun!\n");
 
@@ -352,6 +385,14 @@ int hh2serial_spi_read(struct hh2serial_
             printk(KERN_INFO "hh2serial HH2 receiver overrun!\n");
 #endif
 
+		if (buf_ptr[len_inc_hdr-1] & GPSS_REMPTY)
+		{
+			hh2serial->hhRxBufferBytes = HH2SERIAL_SPI_MAX_BYTES;
+#ifdef HH2SERIAL_ENABLE_DEBUG
+            printk(KERN_INFO "hh2serial HH2 rx empty!\n");
+#endif
+		}
+#endif
 
 #ifdef HH2SERIAL_ENABLE_DEBUG
         printk(KERN_INFO "hh2serial_spi_read len inc hdr wr:%d, avail rd %d, cs_change:%d\n",
@@ -388,6 +429,13 @@ int hh2serial_spi_read(struct hh2serial_
 #endif
 
     }
+	else
+	{
+#ifdef HH2SERIAL_SHOW_ERRORS
+printk(KERN_INFO "hh2serial spi_read, spi_sync failed: %d\n",status);
+#endif
+
+	}
 
     kfree(local_buf);
     return status;
@@ -435,8 +483,8 @@ int hh2serial_spi_write(struct hh2serial
     x.len = len_inc_hdr;
     spi_message_add_tail(&x, &message);
 
-    /* Allocate and make room for 1 byte header */
-    local_buf = kzalloc(HH2SERIAL_BUFSIZE+1, GFP_KERNEL);
+    /* Allocate and make room for 1 byte header(RX and TX) */
+    local_buf = kzalloc(HH2SERIAL_BUFSIZE+2, GFP_KERNEL);
     if (!local_buf)
         return -ENOMEM;
 
@@ -453,7 +501,6 @@ int hh2serial_spi_write(struct hh2serial
         int byte_index = 2;
         while (byte_index < len_inc_hdr)
         {
-
             local_buf[byte_index] = txbuf[byte_index];
             local_buf[byte_index+1] = GPSD_DWRITE;
             byte_index = byte_index + 2;
@@ -495,24 +542,55 @@ int hh2serial_spi_write(struct hh2serial
         available_rd = *buf_ptr & GPSS_TCNT;
 
         /* Check buffer overrun or underrun errors */
+#ifdef HH2SERIAL_SHOW_ERRORS
         if (*buf_ptr & GPSS_TERR)
             printk(KERN_INFO "hh2serial HH2 transmitter underrun!\n");
 
         if (*buf_ptr & GPSS_RERR)
             printk(KERN_INFO "hh2serial HH2 receiver overrun!\n");
+#endif
+		if (*buf_ptr & GPSS_REMPTY)
+		{
+			/* Buffer was empty but len bytes has been written after that */
+			hh2serial->hhRxBufferBytes = HH2SERIAL_SPI_MAX_BYTES-len;
+#ifdef HH2SERIAL_ENABLE_DEBUG
+            printk(KERN_INFO "hh2serial HH2 rx empty!\n");
+#endif
+		}
+		else
+		{
+			hh2serial->hhRxBufferBytes -= len;
+		}
 #else
+		/* FIXME_Only last status is interesting or? */
+		/* Might have to check every status register to se if empty */
         /* 16 bit second byte is status register */
         /* Available bytes */
-        available_rd = buf_ptr[1] & GPSS_TCNT;
+        available_rd = buf_ptr[len_inc_hdr-1] & GPSS_TCNT;
 
         /* Check buffer overrun or underrun errors */
-        if (buf_ptr[1] & GPSS_TERR)
+#ifdef HH2SERIAL_SHOW_ERRORS
+        if (buf_ptr[len_inc_hdr-1] & GPSS_TERR)
             printk(KERN_INFO "hh2serial HH2 transmitter underrun!\n");
 
-        if (buf_ptr[1] & GPSS_RERR)
+        if (buf_ptr[len_inc_hdr-1] & GPSS_RERR)
             printk(KERN_INFO "hh2serial HH2 receiver overrun!\n");
 #endif
 
+		if (buf_ptr[len_inc_hdr-1] & GPSS_REMPTY)
+		{
+			/* Buffer was empty but one byte has been written after that */
+			hh2serial->hhRxBufferBytes = HH2SERIAL_SPI_MAX_BYTES-1;
+#ifdef HH2SERIAL_ENABLE_DEBUG
+            printk(KERN_INFO "hh2serial HH2 rx empty!\n");
+#endif
+		}
+		else
+		{
+			/* Only 8 bit of every 16 is data */
+			hh2serial->hhRxBufferBytes -= (len/2);
+		}
+#endif
 
 #ifdef HH2SERIAL_ENABLE_DEBUG
         printk(KERN_INFO "hh2serial_spi_write:%02X, %02X\n",
@@ -526,9 +604,14 @@ int hh2serial_spi_write(struct hh2serial
 
         *spiAvailData = available_rd;
 
-
     }
+	else
+	{
+#ifdef HH2SERIAL_SHOW_ERRORS
+printk(KERN_INFO "hh2serial spi_write, spi_sync failed: %d\n",status);
+#endif
 
+	}
 
 
     kfree(local_buf);
@@ -616,61 +699,77 @@ static inline void hh2serial_write_circ_
 #ifdef HH2SERIAL_ENABLE_DEBUG
         printk(KERN_INFO "Bytes in circ buffer: %d\n", left);
 #endif
-        while (left) {
-            /* MrB Change below to 1 and word length to 16 to write 16 bit
-               word by word */
-#ifndef HH2SERIAL_SPI_16BIT
-            len = (left >= HH2SERIAL_SPI_MAX_BYTES) ? HH2SERIAL_SPI_MAX_BYTES : left;
-#else
-            len = (left >= HH2SERIAL_SPI_MAX_BYTES) ? HH2SERIAL_SPI_MAX_BYTES : left;
-#endif
-
-            memset(obuf, 0, len);
-            memset(ibuf, 0, len);
-            for (i = 0; i < len; i++) {
+        while (left || (rxlen > 0)) {
 
-                obuf[i] = (u8)xmit->buf[xmit->tail];
-
-                xmit->tail = (xmit->tail + 1) &
-                        (UART_XMIT_SIZE - 1);
-            }
-#ifndef HH2SERIAL_SPI_16BIT
+			if (left)
+			{
+				 /* FIXME len = MIN(left , hhRxBufferBytes)
+					if len 0 is then only read status register and read */
+
+				len = (left >= priv->hhRxBufferBytes) ? priv->hhRxBufferBytes : left;
+
+
+				if (len > 0)
+				{
+					memset(obuf, 0, len);
+					memset(ibuf, 0, len);
+					for (i = 0; i < len; i++) {
+
+						obuf[i] = (u8)xmit->buf[xmit->tail];
+
+						xmit->tail = (xmit->tail + 1) &
+								(UART_XMIT_SIZE - 1);
+					}
+	#ifndef HH2SERIAL_SPI_16BIT
+
+					/* FIXME check status */
+					hh2serial_spi_write(priv, (u8 *)obuf,
+								&rxlen, len);
+
+	#else
+					/* len * 2 since 16 bits instead of 8 bits */
+					/* FIXME check status */
+					hh2serial_spi_write(priv, (u8 *)obuf,
+								&rxlen, len*2);
+
+	#endif
+					left -= len;
+				}
+				else /* Read rx len */
+				{
+	#ifdef HH2SERIAL_SHOW_ERRORS
+					printk(KERN_INFO "hh2serial wr buf2spi, rxBuf full?\n");
+	#endif
+					rxlen = hh2serial_spi_get_rx_len(priv);
 
-            hh2serial_spi_write(priv, (u8 *)obuf,
-                        &rxlen, len);
 
-#else
-            /* len * 2 since 16 bits instead of 8 bits */
-            hh2serial_spi_write(priv, (u8 *)obuf,
-                        &rxlen, len*2);
-
-#endif
-            left -= len;
-        }
+				}
+			}
 #ifdef HH2SERIAL_ENABLE_DEBUG
         printk(KERN_INFO "hh2serial: Bytes avail to read: %d\n", rxlen);
 #endif
         /* Read if available bytes */
         /* FIXME: Could add a maximum read loop here */
-        while (rxlen > 0)
-        {
-
-            len = rxlen;
-#ifndef HH2SERIAL_SPI_16BIT
-            hh2serial_spi_read(priv, (u8 *)ibuf, &rxlen, len);
-#else
-            hh2serial_spi_read(priv, (u8 *)ibuf, &rxlen, len*2);
-#endif
-
-            for (i = 0, j = 0; i < len; i++) {
-                valid_str[j++] = (u8)(ibuf[i]);
-            }
+			if (rxlen > 0)
+			{
 
-            if (j)
-                hh2serial_write2tty(priv, valid_str, j);
-
-            priv->port.icount.tx += len;
-        }
+				len = rxlen;
+	#ifndef HH2SERIAL_SPI_16BIT
+				hh2serial_spi_read(priv, (u8 *)ibuf, &rxlen, len);
+	#else
+				hh2serial_spi_read(priv, (u8 *)ibuf, &rxlen, len*2);
+	#endif
+
+				for (i = 0, j = 0; i < len; i++) {
+					valid_str[j++] = (u8)(ibuf[i]);
+				}
+
+				if (j)
+					hh2serial_write2tty(priv, valid_str, j);
+
+				priv->port.icount.tx += len;
+			}
+		}
     }
 }
 #endif
@@ -793,7 +892,7 @@ static int hh2serial_main_thread(void *_
             /* Read from tty send to spi */
 #ifdef HH2SERIAL_ENABLE_DEBUG
             printk(KERN_INFO "hh2serial: Read from tty send to spi\n");
-#endif
+#endif          
             /* Read from tty send to spi */
             /* Receive data from spi send to UART */
 
@@ -1153,11 +1252,13 @@ static int hh2serial_startup(struct uart
     struct hh2serial_dev *priv = container_of(port, struct hh2serial_dev, port);
     FUNC_ENTER();
 
+	/* Initialize RxBuffer to 0 */
+	priv->hhRxBufferBytes = 0;
 #ifdef HH2SERIAL_SPI_POLL
     priv->poll_thread = kthread_run(hh2serial_poll_thread,
                     priv, "hh2serial_poll");
     if (IS_ERR(priv->poll_thread)) {
-        printk(KERN_INFO "hh2serial Failed to start poll thread: %ld",
+        printk(KERN_INFO "hh2serial Failed to start poll thread: %ld", 
             PTR_ERR(priv->poll_thread));
     }
 #endif
openSUSE Build Service is sponsored by