ARM: S3C24XX: machine support for Simtec Audio

Add the platform/machine support for the audio devices fitted to
the Simtec range of boards since the move to ASoC.

Signed-off-by: Ben Dooks <ben@simtec.co.uk>
Signed-off-by: Simtec Linux Team <linux@simtec.co.uk>
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 647c9ad..5f78370 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -61,6 +61,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/cpu-freq.h>
+#include <plat/audio-simtec.h>
 
 #include "usb-simtec.h"
 #include "nor-simtec.h"
@@ -608,6 +609,11 @@
 	.need_io	= 1,
 };
 
+static struct s3c24xx_audio_simtec_pdata __initdata bast_audio = {
+	.have_mic	= 1,
+	.have_lout	= 1,
+};
+
 static void __init bast_map_io(void)
 {
 	/* initialise the clocks */
@@ -647,6 +653,7 @@
 
 	usb_simtec_init();
 	nor_simtec_init();
+	simtec_audio_add(NULL, true, &bast_audio);
 
 	s3c_cpufreq_setboard(&bast_cpufreq);
 }
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index 1628cc7..7611472 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -49,6 +49,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/iic.h>
+#include <plat/audio-simtec.h>
 
 #include "usb-simtec.h"
 #include "nor-simtec.h"
@@ -393,6 +394,7 @@
 				ARRAY_SIZE(vr1000_i2c_devs));
 
 	nor_simtec_init();
+	simtec_audio_add(NULL, true, NULL);
 }
 
 MACHINE_START(VR1000, "Thorcom-VR1000")
diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
index 68f3870..b8b9a42 100644
--- a/arch/arm/mach-s3c2440/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -53,8 +53,9 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/audio-simtec.h>
 
-#define COPYRIGHT ", (c) 2005 Simtec Electronics"
+#define COPYRIGHT ", (c) 2005-2009 Simtec Electronics"
 
 static struct map_desc anubis_iodesc[] __initdata = {
   /* ISA IO areas */
@@ -437,6 +438,17 @@
 	}
 };
 
+/* Audio setup */
+static struct s3c24xx_audio_simtec_pdata __initdata anubis_audio = {
+	.have_mic	= 1,
+	.have_lout	= 1,
+	.output_cdclk	= 1,
+	.use_mpllin	= 1,
+	.amp_gpio	= S3C2410_GPB(2),
+	.amp_gain[0]	= S3C2410_GPD(10),
+	.amp_gain[1]	= S3C2410_GPD(11),
+};
+
 static void __init anubis_map_io(void)
 {
 	/* initialise the clocks */
@@ -476,6 +488,7 @@
 static void __init anubis_init(void)
 {
 	s3c_i2c0_set_platdata(NULL);
+	simtec_audio_add(NULL, false, &anubis_audio);
 	platform_add_devices(anubis_devices, ARRAY_SIZE(anubis_devices));
 
 	i2c_register_board_info(0, anubis_i2c_devs,
diff --git a/arch/arm/plat-s3c/include/plat/audio-simtec.h b/arch/arm/plat-s3c/include/plat/audio-simtec.h
index 0f440b9..53a9365 100644
--- a/arch/arm/plat-s3c/include/plat/audio-simtec.h
+++ b/arch/arm/plat-s3c/include/plat/audio-simtec.h
@@ -33,5 +33,5 @@
 	void	(*startup)(void);
 };
 
-extern int simtec_audio_add(const char *codec_name,
+extern int simtec_audio_add(const char *codec_name, bool has_lr_routing,
 			    struct s3c24xx_audio_simtec_pdata *pdata);
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
index 9c7aca4..20fbf93 100644
--- a/arch/arm/plat-s3c24xx/Kconfig
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -178,4 +178,11 @@
 	help
 	  Common machine code for SMDK2410 and SMDK2440
 
+config S3C24XX_SIMTEC_AUDIO
+	bool
+	depends on (ARCH_BAST || MACH_VR1000 || MACH_OSIRIS || MACH_ANUBIS)
+	default y
+	help
+	  Add audio devices for common Simtec S3C24XX boards
+
 endif
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile
index 7780d2d..5dee8c1 100644
--- a/arch/arm/plat-s3c24xx/Makefile
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -55,3 +55,4 @@
 # machine common support
 
 obj-$(CONFIG_MACH_SMDK)		+= common-smdk.o
+obj-$(CONFIG_S3C24XX_SIMTEC_AUDIO)	+= simtec-audio.o
diff --git a/arch/arm/plat-s3c24xx/simtec-audio.c b/arch/arm/plat-s3c24xx/simtec-audio.c
new file mode 100644
index 0000000..6bc832e
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/simtec-audio.c
@@ -0,0 +1,77 @@
+/* linux/arch/arm/plat-s3c24xx/simtec-audio.c
+ *
+ * Copyright (c) 2009 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Audio setup for various Simtec S3C24XX implementations
+ *
+ * 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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/io.h>
+
+#include <mach/bast-map.h>
+#include <mach/bast-irq.h>
+#include <mach/bast-cpld.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-gpio.h>
+
+#include <plat/audio-simtec.h>
+#include <plat/devs.h>
+
+/* platform ops for audio */
+
+static void simtec_audio_startup_lrroute(void)
+{
+	unsigned int tmp;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	tmp = __raw_readb(BAST_VA_CTRL1);
+	tmp &= ~BAST_CPLD_CTRL1_LRMASK;
+	tmp |= BAST_CPLD_CTRL1_LRCDAC;
+	__raw_writeb(tmp, BAST_VA_CTRL1);
+
+	local_irq_restore(flags);
+}
+
+static struct s3c24xx_audio_simtec_pdata simtec_audio_platdata;
+static char our_name[32];
+
+static struct platform_device simtec_audio_dev = {
+	.name	= our_name,
+	.id	= -1,
+	.dev	= {
+		.parent		= &s3c_device_iis.dev,
+		.platform_data	= &simtec_audio_platdata,
+	},
+};
+
+int __init simtec_audio_add(const char *name, bool has_lr_routing,
+			    struct s3c24xx_audio_simtec_pdata *spd)
+{
+	if (!name)
+		name = "tlv320aic23";
+
+	snprintf(our_name, sizeof(our_name)-1, "s3c24xx-simtec-%s", name);
+
+	/* copy platform data so the source can be __initdata */
+	if (spd)
+		simtec_audio_platdata = *spd;
+
+	if (has_lr_routing)
+		simtec_audio_platdata.startup = simtec_audio_startup_lrroute;
+
+	platform_device_register(&s3c_device_iis);
+	platform_device_register(&simtec_audio_dev);
+	return 0;
+}