Index: linux-2.6.15-rc2/sound/soc/pxa/spitz.c
===================================================================
--- linux-2.6.15-rc2.orig/sound/soc/pxa/spitz.c	2005-12-08 18:14:46.503858096 +0000
+++ linux-2.6.15-rc2/sound/soc/pxa/spitz.c	2005-12-09 00:05:44.201306248 +0000
@@ -1,5 +1,5 @@
 /*
- * spitz.c  --  SoC audio for Spitz
+ * spitz.c  --  SoC audio for Sharp SL-Cxx00 models Spitz, Borzoi and Akita
  *
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
@@ -13,10 +13,7 @@
  *  option) any later version.
  *
  *  Revision history
- *    5th Dec 2005   Initial version.
- * 
- * TODO:
- *   Fill in (or delete) the gaps.
+ *    30th Nov 2005   Initial version.
  * 
  */
  
@@ -36,86 +33,113 @@
 #include <asm/hardware/scoop.h>
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/hardware.h>
-#include <asm/arch/corgi.h>
+#include <asm/arch/akita.h>
 #include <asm/arch/spitz.h>
-
-
-#include <asm/arch/audio.h>
-
+#include <asm/mach-types.h>
 #include "../codecs/wm8750.h"
 #include "pxa2xx-pcm.h"
 
-/*
- * Debug
- */
- 
-#define PFX "corgi-soc"
-#define CORGI_DEBUG 0
+static struct workqueue_struct *spitz_hp_workq = NULL;
+static struct work_struct spitz_hp_event_work;
 
-#ifdef CORGI_DEBUG
-#define dbg(format, arg...) printk(KERN_DEBUG PFX ": " format "\n" , ## arg)
-#else
-#define dbg(format, arg...) do {} while (0)
-#endif
-#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg)
-
-static struct timer_list corgi_hp_timer;
-
-static irqreturn_t corgi_hp_isr(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t spitz_hp_isr(int irq, void *dev_id, struct pt_regs *fp)
 {
 	/* Delay the event slightly to debounce */
-	mod_timer(&corgi_hp_timer, jiffies + msecs_to_jiffies(500));
+	queue_delayed_work(spitz_hp_workq, &spitz_hp_event_work, msecs_to_jiffies(500));
 
 	return IRQ_HANDLED;
 }
 
 #define READ_GPIO_BIT(x)    (GPLR(x) & GPIO_bit(x))
 
-static void corgi_hp_event(unsigned long data)
+static void spitz_hp_work(void *data)
 {
-	int hp_status = (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0);
+	int hp_status = (READ_GPIO_BIT(SPITZ_GPIO_AK_INT) != 0);
 	struct snd_soc_codec *codec = (struct snd_soc_codec *)data;
 	
 	printk("HP Status: %d\n", hp_status);
-
-	corgikbd_report_hp(hp_status);
+	spitzkbd_report_hp(hp_status);
 	
-	/* FIXME - Richard can you check, this will change dpm status */
-	if(hp_status == 1) {
-		snd_soc_dpm_set_connection(codec, "ROUT", 0);
-		snd_soc_dpm_set_connection(codec, "LOUT", 0);
-		snd_soc_dpm_set_connection(codec, "LHPOUT", 1);
-		snd_soc_dpm_set_connection(codec, "RHPOUT", 1);
+	/* change the dpm status depending on the insertion */
+	if (hp_status == 1) {
+		snd_soc_dpm_set_connection(codec, "LOUT1", 1);
+		snd_soc_dpm_set_connection(codec, "ROUT1", 1);
+		snd_soc_dpm_set_connection(codec, "RINPUT1", 1);
+		snd_soc_dpm_set_connection(codec, "LINPUT1", 1);
 	} else {
-		snd_soc_dpm_set_connection(codec, "ROUT", 1);
-		snd_soc_dpm_set_connection(codec, "LOUT", 1);
-		snd_soc_dpm_set_connection(codec, "LHPOUT", 0);
-		snd_soc_dpm_set_connection(codec, "RHPOUT", 0);
+		snd_soc_dpm_set_connection(codec, "LOUT1", 0);
+		snd_soc_dpm_set_connection(codec, "ROUT1", 0);
+		snd_soc_dpm_set_connection(codec, "RINPUT1", 0);
+		snd_soc_dpm_set_connection(codec, "LINPUT1", 0);
 	}
 	snd_soc_dpm_sync(codec);
 }
 
-int corgi_get_snd_scoop(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int spitz_get_snd_scoop(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	unsigned short reg = kcontrol->private_value;
-	ucontrol->value.integer.value[0] = ((read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPWR) & reg) != 0);
+	
+	ucontrol->value.integer.value[0] = ((read_scoop_reg(&spitzscoop_device.dev, SCOOP_GPWR) & reg) == 0);
 	return 0;
 }
 
-int corgi_put_snd_scoop(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int spitz_put_snd_scoop(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	unsigned short reg = kcontrol->private_value & 0xffff;
+	
+	if (ucontrol->value.integer.value[0])
+		reset_scoop_gpio(&spitzscoop_device.dev, reg);
+	else
+		set_scoop_gpio(&spitzscoop_device.dev, reg);
+	return 0;
+}
+
+int spitz_get_snd_scoop2(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	unsigned short reg = kcontrol->private_value;
+	
+	ucontrol->value.integer.value[0] = ((read_scoop_reg(&spitzscoop2_device.dev, SCOOP_GPWR) & reg) == 0);
+	return 0;
+}
 
+int spitz_put_snd_scoop2(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	unsigned short reg = kcontrol->private_value & 0xffff;
+	
 	if (ucontrol->value.integer.value[0])
-		set_scoop_gpio(&corgiscoop_device.dev, reg);
+		reset_scoop_gpio(&spitzscoop2_device.dev, reg);
 	else
-		reset_scoop_gpio(&corgiscoop_device.dev, reg);
+		set_scoop_gpio(&spitzscoop2_device.dev, reg);
 	return 0;
 }
 
-/* corgi machine dpm widgets */
+#ifdef CONFIG_MACH_AKITA
+static int akita_ioexp_status;
+
+int akita_get_snd_ioexp(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	unsigned short reg = kcontrol->private_value;
+	ucontrol->value.integer.value[0] = akita_ioexp_status;
+	return 0;
+}
+
+int akita_put_snd_ioexp(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	unsigned short reg = kcontrol->private_value & 0xffff;
+	
+	if (ucontrol->value.integer.value[0]) {
+		akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_MIC_BIAS);
+		akita_ioexp_status = 0;
+        } else {
+		akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_MIC_BIAS);
+		akita_ioexp_status = 1;		
+	}
+
+	return 0;
+}
+#endif
+
+/* spitz machine dpm widgets */
 static const struct snd_soc_dpm_widget wm8750_dpm_widgets[] = {
 SND_SOC_DPM_HP("Headphone Jack"),
 SND_SOC_DPM_MIC("Mic1 Jack"),
@@ -125,12 +149,12 @@
 static const char* intercon[][3] = {
 	
 	/* headphone connected to LOUT1, ROUT1 */
-	{"Headphone Jack", NULL, "LHPOUT"},
-	{"Headphone Jack", NULL, "RHPOUT"},
+	{"Headphone Jack", NULL, "LOUT1"},
+	{"Headphone Jack", NULL, "ROUT1"},
 	
 	/* ext speaker connected to LOUT2, ROUT2 via amp */
-	{"Ext Amp", NULL, "ROUT"},
-	{"Ext Amp", NULL, "LOUT"},
+	{"Ext Amp", NULL , "ROUT2"},
+	{"Ext Amp", NULL , "LOUT2"},
 	
 	/* mic is connected to mic1 - with bias */
 	{"MICIN", NULL, "Mic Bias"},
@@ -140,112 +164,129 @@
 	{NULL, NULL, NULL},
 };
 
-static const snd_kcontrol_new_t wm8750_corgi_controls[] = {
-	SOC_SINGLE_BOOL_EXT("Left Mute Switch", CORGI_SCP_MUTE_L, corgi_get_snd_scoop, corgi_put_snd_scoop),
-	SOC_SINGLE_BOOL_EXT("Right Mute Switch", CORGI_SCP_MUTE_R, corgi_get_snd_scoop, corgi_put_snd_scoop),
-	SOC_SINGLE_BOOL_EXT("Speaker Mute Switch", CORGI_SCP_APM_ON, corgi_get_snd_scoop, corgi_put_snd_scoop),
-	SOC_SINGLE_BOOL_EXT("Mic Bias Switch", CORGI_SCP_MIC_BIAS, corgi_get_snd_scoop, corgi_put_snd_scoop),
+static const snd_kcontrol_new_t wm8750_spitz_controls[] = {
+	SOC_SINGLE_BOOL_EXT("Left Mute Switch", SPITZ_SCP_MUTE_L, spitz_get_snd_scoop, spitz_put_snd_scoop),
+	SOC_SINGLE_BOOL_EXT("Right Mute Switch", SPITZ_SCP_MUTE_R, spitz_get_snd_scoop, spitz_put_snd_scoop),
+};
+
+static const snd_kcontrol_new_t wm8750_spitz_controls2[] = {
+	SOC_SINGLE_BOOL_EXT("Mic Bias Switch", SPITZ_SCP2_MIC_BIAS, spitz_get_snd_scoop2, spitz_put_snd_scoop2),
 };
 
+#ifdef CONFIG_MACH_AKITA
+static const snd_kcontrol_new_t wm8750_akita_controls[] = {
+	SOC_SINGLE_BOOL_EXT("Mic Bias Switch", AKITA_IOEXP_MIC_BIAS, akita_get_snd_ioexp, akita_put_snd_ioexp),
+};
+#endif
+
 /*
- * Logic for a wm8750 as connected on a Sharp SL-C1x00 Device
+ * Logic for a wm8750 as connected on a Sharp SL-Cxx00 Device
  */
-static int corgi_wm8750_init(struct snd_soc_codec *codec)
+static int spitz_wm8750_init(struct snd_soc_codec *codec)
 {
 	int i, err;
 
 	codec->longname = "Corgi Audio Codec";
-	snd_soc_dpm_set_connection(codec, "RLINEIN", 0);
+	snd_soc_dpm_set_connection(codec, "LINPUT2", 0);
+	snd_soc_dpm_set_connection(codec, "RINPUT2", 0);
 
-	/* Add corgi specific controls */
-	for (i = 0; i < ARRAY_SIZE(wm8750_corgi_controls); i++) {
-		if ((err = snd_ctl_add(codec->card, snd_soc_cnew(&wm8750_corgi_controls[i],codec, NULL))) < 0)
+	/* Add spitz specific controls */
+	for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
+		if ((err = snd_ctl_add(codec->card, snd_soc_cnew(&wm8750_spitz_controls[i], codec, NULL))) < 0)
 			return err;
 	}
 
-	/* Add corgi specific widgets */
+	if (machine_is_borzoi() || machine_is_spitz())
+		if ((err = snd_ctl_add(codec->card, snd_soc_cnew(&wm8750_spitz_controls[0], codec, NULL))) < 0)
+			return err;
+
+#ifdef CONFIG_MACH_AKITA
+	if (machine_is_akita())
+		if ((err = snd_ctl_add(codec->card, snd_soc_cnew(&wm8750_akita_controls[0], codec, NULL))) < 0)
+			return err;
+#endif
+
+	/* Add spitz specific widgets */
 	for(i = 0; i < ARRAY_SIZE(wm8750_dpm_widgets); i++) {
 		snd_soc_dpm_new_control(codec, &wm8750_dpm_widgets[i]);
 	}
 	
-	/* Set up corgi specific audio path interconnects */
+	/* Set up spitz specific audio path interconnects */
 	for(i = 0; intercon[i][0] != NULL; i++) {
 		snd_soc_dpm_connect_input(codec, intercon[i][0], intercon[i][1], intercon[i][2]);
 	}
 	
-	corgi_hp_timer.data = (unsigned long)codec;
+	INIT_WORK(&spitz_hp_event_work, spitz_hp_work, codec);
+	spitz_hp_workq = create_singlethread_workqueue("spitzhp");
 	snd_soc_dpm_sync(codec);
 	return 0;
 }
 
 static struct snd_soc_machine_config codecs = {
-	.name = "WM8750", 
-	.sname = "WM8750",
+	.name = "wm8750", 
+	.sname = "wm8750",
 	.iface = &pxa_i2s_interface,
-	.init = corgi_wm8750_init,
+	.init = spitz_wm8750_init,
 };
 
-static struct snd_soc_machine snd_soc_machine_corgi = {
-	.name = "Corgi",
+static struct snd_soc_machine snd_soc_machine_spitz = {
+	.name = "Spitz",
 	.config = &codecs,
 	.nconfigs = 1,
 };
 
-static struct wm8750_setup_data corgi_wm8750_setup = {
+static struct wm8750_setup_data spitz_wm8750_setup = {
 	.i2c_address = 0x1b,
 };
 
-static struct snd_soc_device corgi_snd_devdata = {
-	.machine = &snd_soc_machine_corgi,
+static struct snd_soc_device spitz_snd_devdata = {
+	.machine = &snd_soc_machine_spitz,
 	.platform = &pxa2xx_soc_platform,
 	.codec_dev = &soc_codec_dev_wm8750,
-	.codec_data = &corgi_wm8750_setup,
+	.codec_data = &spitz_wm8750_setup,
 };
 
-static struct platform_device *corgi_snd_device;
+static struct platform_device *spitz_snd_device;
 
-static int __init corgi_init(void) 
+static int __init spitz_init(void) 
 {
 	int ret;
 
-	pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
-	ret = request_irq(CORGI_IRQ_GPIO_AK_INT, corgi_hp_isr, SA_INTERRUPT, "Headphone Detect", corgi_snd_device);
+	pxa_gpio_mode(SPITZ_GPIO_AK_INT | GPIO_IN);
+	ret = request_irq(SPITZ_IRQ_GPIO_AK_INT, spitz_hp_isr, SA_INTERRUPT, "Headphone Detect", spitz_snd_device);
 	if (ret < 0) {
-		printk(KERN_ERR "Could not register corgi headphone irq.\n");
+		printk(KERN_ERR "Could not register spitz headphone irq.\n");
 		return ret;
 	}
-	set_irq_type(CORGI_IRQ_GPIO_AK_INT, IRQT_BOTHEDGE);
-
-	init_timer(&corgi_hp_timer);
-	corgi_hp_timer.function = corgi_hp_event;
+	set_irq_type(SPITZ_IRQ_GPIO_AK_INT, IRQT_BOTHEDGE);
 
-	corgi_snd_device = platform_device_alloc("soc-audio", -1);
-	if (!corgi_snd_device) {
-		free_irq(CORGI_IRQ_GPIO_AK_INT, corgi_snd_device);
+	spitz_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!spitz_snd_device) {
+		free_irq(SPITZ_IRQ_GPIO_AK_INT, spitz_snd_device);
 		return -ENOMEM;
 	}
 
-	platform_set_drvdata(corgi_snd_device, &corgi_snd_devdata);
-	corgi_snd_devdata.dev = &corgi_snd_device->dev;
-	ret = platform_device_add(corgi_snd_device);
+	platform_set_drvdata(spitz_snd_device, &spitz_snd_devdata);
+	spitz_snd_devdata.dev = &spitz_snd_device->dev;
+	ret = platform_device_add(spitz_snd_device);
 
 	if (ret)
-		platform_device_put(corgi_snd_device);
+		platform_device_put(spitz_snd_device);
 
 	return ret;
 }
 
-static void __exit corgi_exit(void) 
+static void __exit spitz_exit(void) 
 {
-	free_irq(CORGI_IRQ_GPIO_AK_INT, corgi_snd_device);
-	del_timer_sync(&corgi_hp_timer);
-	platform_device_unregister(corgi_snd_device);
+	free_irq(SPITZ_IRQ_GPIO_AK_INT, spitz_snd_device);
+	if(spitz_hp_workq)
+		destroy_workqueue(spitz_hp_workq);
+	platform_device_unregister(spitz_snd_device);
 }
 
-module_init(corgi_init);
-module_exit(corgi_exit);
+module_init(spitz_init);
+module_exit(spitz_exit);
 
-/* Module information */ 
 MODULE_AUTHOR("Richard Purdie");
-MODULE_DESCRIPTION("ALSA SoC Corgi");
+MODULE_DESCRIPTION("ALSA SoC Spitz");
 MODULE_LICENSE("GPL");
