aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/pxa
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2009-03-28 20:29:51 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-03-28 20:29:51 +0000
commited40d0c472b136682b2fcba05f89762859c7374f (patch)
tree076b83a26bcd63d6158463735dd34c10bbc591dc /sound/soc/pxa
parent9e495834e59ca9b29f1a1f63b9f5533bb022ac49 (diff)
parent5d80f8e5a9dc9c9a94d4aeaa567e219a808b8a4a (diff)
Merge branch 'origin' into devel
Conflicts: sound/soc/pxa/pxa2xx-i2s.c
Diffstat (limited to 'sound/soc/pxa')
-rw-r--r--sound/soc/pxa/Kconfig27
-rw-r--r--sound/soc/pxa/Makefile6
-rw-r--r--sound/soc/pxa/corgi.c58
-rw-r--r--sound/soc/pxa/e740_wm9705.c211
-rw-r--r--sound/soc/pxa/e750_wm9705.c187
-rw-r--r--sound/soc/pxa/e800_wm9712.c113
-rw-r--r--sound/soc/pxa/mioa701_wm9713.c250
-rw-r--r--sound/soc/pxa/palm27x.c15
-rw-r--r--sound/soc/pxa/poodle.c56
-rw-r--r--sound/soc/pxa/pxa-ssp.c150
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c59
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c54
-rw-r--r--sound/soc/pxa/spitz.c14
-rw-r--r--sound/soc/pxa/tosa.c14
-rw-r--r--sound/soc/pxa/zylonite.c132
15 files changed, 1126 insertions, 220 deletions
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index f82e1069947..5998ab366e8 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -61,6 +61,24 @@ config SND_PXA2XX_SOC_TOSA
Say Y if you want to add support for SoC audio on Sharp
Zaurus SL-C6000x models (Tosa).
+config SND_PXA2XX_SOC_E740
+ tristate "SoC AC97 Audio support for e740"
+ depends on SND_PXA2XX_SOC && MACH_E740
+ select SND_SOC_WM9705
+ select SND_PXA2XX_SOC_AC97
+ help
+ Say Y if you want to add support for SoC audio on the
+ toshiba e740 PDA
+
+config SND_PXA2XX_SOC_E750
+ tristate "SoC AC97 Audio support for e750"
+ depends on SND_PXA2XX_SOC && MACH_E750
+ select SND_SOC_WM9705
+ select SND_PXA2XX_SOC_AC97
+ help
+ Say Y if you want to add support for SoC audio on the
+ toshiba e750 PDA
+
config SND_PXA2XX_SOC_E800
tristate "SoC AC97 Audio support for e800"
depends on SND_PXA2XX_SOC && MACH_E800
@@ -97,3 +115,12 @@ config SND_SOC_ZYLONITE
help
Say Y if you want to add support for SoC audio on the
Marvell Zylonite reference platform.
+
+config SND_PXA2XX_SOC_MIOA701
+ tristate "SoC Audio support for MIO A701"
+ depends on SND_PXA2XX_SOC && MACH_MIOA701
+ select SND_PXA2XX_SOC_AC97
+ select SND_SOC_WM9713
+ help
+ Say Y if you want to add support for SoC audio on the
+ MIO A701.
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 08a9f279772..8ed881c5e5c 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -13,17 +13,23 @@ obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o
snd-soc-corgi-objs := corgi.o
snd-soc-poodle-objs := poodle.o
snd-soc-tosa-objs := tosa.o
+snd-soc-e740-objs := e740_wm9705.o
+snd-soc-e750-objs := e750_wm9705.o
snd-soc-e800-objs := e800_wm9712.o
snd-soc-spitz-objs := spitz.o
snd-soc-em-x270-objs := em-x270.o
snd-soc-palm27x-objs := palm27x.o
snd-soc-zylonite-objs := zylonite.o
+snd-soc-mioa701-objs := mioa701_wm9713.o
obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o
+obj-$(CONFIG_SND_PXA2XX_SOC_E740) += snd-soc-e740.o
+obj-$(CONFIG_SND_PXA2XX_SOC_E750) += snd-soc-e750.o
obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o
obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o
obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
+obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index ec930667fef..d5be2b30cda 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/timer.h>
+#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
@@ -98,7 +99,7 @@ static void corgi_ext_control(struct snd_soc_codec *codec)
static int corgi_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->socdev->codec;
+ struct snd_soc_codec *codec = rtd->socdev->card->codec;
/* check the jack status at stream startup */
corgi_ext_control(codec);
@@ -273,18 +274,16 @@ static const struct snd_kcontrol_new wm8731_corgi_controls[] = {
*/
static int corgi_wm8731_init(struct snd_soc_codec *codec)
{
- int i, err;
+ int err;
snd_soc_dapm_nc_pin(codec, "LLINEIN");
snd_soc_dapm_nc_pin(codec, "RLINEIN");
/* Add corgi specific controls */
- for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
- err = snd_ctl_add(codec->card,
- snd_soc_cnew(&wm8731_corgi_controls[i], codec, NULL));
- if (err < 0)
- return err;
- }
+ err = snd_soc_add_controls(codec, wm8731_corgi_controls,
+ ARRAY_SIZE(wm8731_corgi_controls));
+ if (err < 0)
+ return err;
/* Add corgi specific widgets */
snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
@@ -315,19 +314,44 @@ static struct snd_soc_card snd_soc_corgi = {
.num_links = 1,
};
-/* corgi audio private data */
-static struct wm8731_setup_data corgi_wm8731_setup = {
- .i2c_bus = 0,
- .i2c_address = 0x1b,
-};
-
/* corgi audio subsystem */
static struct snd_soc_device corgi_snd_devdata = {
.card = &snd_soc_corgi,
.codec_dev = &soc_codec_dev_wm8731,
- .codec_data = &corgi_wm8731_setup,
};
+/*
+ * FIXME: This is a temporary bodge to avoid cross-tree merge issues.
+ * New drivers should register the wm8731 I2C device in the machine
+ * setup code (under arch/arm for ARM systems).
+ */
+static int wm8731_i2c_register(void)
+{
+ struct i2c_board_info info;
+ struct i2c_adapter *adapter;
+ struct i2c_client *client;
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = 0x1b;
+ strlcpy(info.type, "wm8731", I2C_NAME_SIZE);
+
+ adapter = i2c_get_adapter(0);
+ if (!adapter) {
+ printk(KERN_ERR "can't get i2c adapter 0\n");
+ return -ENODEV;
+ }
+
+ client = i2c_new_device(adapter, &info);
+ i2c_put_adapter(adapter);
+ if (!client) {
+ printk(KERN_ERR "can't add i2c device at 0x%x\n",
+ (unsigned int)info.addr);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
static struct platform_device *corgi_snd_device;
static int __init corgi_init(void)
@@ -338,6 +362,10 @@ static int __init corgi_init(void)
machine_is_husky()))
return -ENODEV;
+ ret = wm8731_i2c_register();
+ if (ret != 0)
+ return ret;
+
corgi_snd_device = platform_device_alloc("soc-audio", -1);
if (!corgi_snd_device)
return -ENOMEM;
diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c
new file mode 100644
index 00000000000..7cd2f89d7b1
--- /dev/null
+++ b/sound/soc/pxa/e740_wm9705.c
@@ -0,0 +1,211 @@
+/*
+ * e740-wm9705.c -- SoC audio for e740
+ *
+ * Copyright 2007 (c) Ian Molton <spyro@f2s.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 ONLY.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/gpio.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <mach/audio.h>
+#include <mach/eseries-gpio.h>
+
+#include <asm/mach-types.h>
+
+#include "../codecs/wm9705.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-ac97.h"
+
+
+#define E740_AUDIO_OUT 1
+#define E740_AUDIO_IN 2
+
+static int e740_audio_power;
+
+static void e740_sync_audio_power(int status)
+{
+ gpio_set_value(GPIO_E740_WM9705_nAVDD2, !status);
+ gpio_set_value(GPIO_E740_AMP_ON, (status & E740_AUDIO_OUT) ? 1 : 0);
+ gpio_set_value(GPIO_E740_MIC_ON, (status & E740_AUDIO_IN) ? 1 : 0);
+}
+
+static int e740_mic_amp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ if (event & SND_SOC_DAPM_PRE_PMU)
+ e740_audio_power |= E740_AUDIO_IN;
+ else if (event & SND_SOC_DAPM_POST_PMD)
+ e740_audio_power &= ~E740_AUDIO_IN;
+
+ e740_sync_audio_power(e740_audio_power);
+
+ return 0;
+}
+
+static int e740_output_amp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ if (event & SND_SOC_DAPM_PRE_PMU)
+ e740_audio_power |= E740_AUDIO_OUT;
+ else if (event & SND_SOC_DAPM_POST_PMD)
+ e740_audio_power &= ~E740_AUDIO_OUT;
+
+ e740_sync_audio_power(e740_audio_power);
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget e740_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_SPK("Speaker", NULL),
+ SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
+ SND_SOC_DAPM_PGA_E("Output Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+ e740_output_amp_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("Mic Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+ e740_mic_amp_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ {"Output Amp", NULL, "LOUT"},
+ {"Output Amp", NULL, "ROUT"},
+ {"Output Amp", NULL, "MONOOUT"},
+
+ {"Speaker", NULL, "Output Amp"},
+ {"Headphone Jack", NULL, "Output Amp"},
+
+ {"MIC1", NULL, "Mic Amp"},
+ {"Mic Amp", NULL, "Mic (Internal)"},
+};
+
+static int e740_ac97_init(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_nc_pin(codec, "HPOUTL");
+ snd_soc_dapm_nc_pin(codec, "HPOUTR");
+ snd_soc_dapm_nc_pin(codec, "PHONE");
+ snd_soc_dapm_nc_pin(codec, "LINEINL");
+ snd_soc_dapm_nc_pin(codec, "LINEINR");
+ snd_soc_dapm_nc_pin(codec, "CDINL");
+ snd_soc_dapm_nc_pin(codec, "CDINR");
+ snd_soc_dapm_nc_pin(codec, "PCBEEP");
+ snd_soc_dapm_nc_pin(codec, "MIC2");
+
+ snd_soc_dapm_new_controls(codec, e740_dapm_widgets,
+ ARRAY_SIZE(e740_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ snd_soc_dapm_sync(codec);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link e740_dai[] = {
+ {
+ .name = "AC97",
+ .stream_name = "AC97 HiFi",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+ .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI],
+ .init = e740_ac97_init,
+ },
+ {
+ .name = "AC97 Aux",
+ .stream_name = "AC97 Aux",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+ .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX],
+ },
+};
+
+static struct snd_soc_card e740 = {
+ .name = "Toshiba e740",
+ .platform = &pxa2xx_soc_platform,
+ .dai_link = e740_dai,
+ .num_links = ARRAY_SIZE(e740_dai),
+};
+
+static struct snd_soc_device e740_snd_devdata = {
+ .card = &e740,
+ .codec_dev = &soc_codec_dev_wm9705,
+};
+
+static struct platform_device *e740_snd_device;
+
+static int __init e740_init(void)
+{
+ int ret;
+
+ if (!machine_is_e740())
+ return -ENODEV;
+
+ ret = gpio_request(GPIO_E740_MIC_ON, "Mic amp");
+ if (ret)
+ return ret;
+
+ ret = gpio_request(GPIO_E740_AMP_ON, "Output amp");
+ if (ret)
+ goto free_mic_amp_gpio;
+
+ ret = gpio_request(GPIO_E740_WM9705_nAVDD2, "Audio power");
+ if (ret)
+ goto free_op_amp_gpio;
+
+ /* Disable audio */
+ ret = gpio_direction_output(GPIO_E740_MIC_ON, 0);
+ if (ret)
+ goto free_apwr_gpio;
+ ret = gpio_direction_output(GPIO_E740_AMP_ON, 0);
+ if (ret)
+ goto free_apwr_gpio;
+ ret = gpio_direction_output(GPIO_E740_WM9705_nAVDD2, 1);
+ if (ret)
+ goto free_apwr_gpio;
+
+ e740_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!e740_snd_device) {
+ ret = -ENOMEM;
+ goto free_apwr_gpio;
+ }
+
+ platform_set_drvdata(e740_snd_device, &e740_snd_devdata);
+ e740_snd_devdata.dev = &e740_snd_device->dev;
+ ret = platform_device_add(e740_snd_device);
+
+ if (!ret)
+ return 0;
+
+/* Fail gracefully */
+ platform_device_put(e740_snd_device);
+free_apwr_gpio:
+ gpio_free(GPIO_E740_WM9705_nAVDD2);
+free_op_amp_gpio:
+ gpio_free(GPIO_E740_AMP_ON);
+free_mic_amp_gpio:
+ gpio_free(GPIO_E740_MIC_ON);
+
+ return ret;
+}
+
+static void __exit e740_exit(void)
+{
+ platform_device_unregister(e740_snd_device);
+}
+
+module_init(e740_init);
+module_exit(e740_exit);
+
+/* Module information */
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("ALSA SoC driver for e740");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c
new file mode 100644
index 00000000000..8dceccc5e05
--- /dev/null
+++ b/sound/soc/pxa/e750_wm9705.c
@@ -0,0 +1,187 @@
+/*
+ * e750-wm9705.c -- SoC audio for e750
+ *
+ * Copyright 2007 (c) Ian Molton <spyro@f2s.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 ONLY.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/gpio.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <mach/audio.h>
+#include <mach/eseries-gpio.h>
+
+#include <asm/mach-types.h>
+
+#include "../codecs/wm9705.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-ac97.h"
+
+static int e750_spk_amp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ if (event & SND_SOC_DAPM_PRE_PMU)
+ gpio_set_value(GPIO_E750_SPK_AMP_OFF, 0);
+ else if (event & SND_SOC_DAPM_POST_PMD)
+ gpio_set_value(GPIO_E750_SPK_AMP_OFF, 1);
+
+ return 0;
+}
+
+static int e750_hp_amp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ if (event & SND_SOC_DAPM_PRE_PMU)
+ gpio_set_value(GPIO_E750_HP_AMP_OFF, 0);
+ else if (event & SND_SOC_DAPM_POST_PMD)
+ gpio_set_value(GPIO_E750_HP_AMP_OFF, 1);
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget e750_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_SPK("Speaker", NULL),
+ SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
+ SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+ e750_hp_amp_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+ e750_spk_amp_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ {"Headphone Amp", NULL, "HPOUTL"},
+ {"Headphone Amp", NULL, "HPOUTR"},
+ {"Headphone Jack", NULL, "Headphone Amp"},
+
+ {"Speaker Amp", NULL, "MONOOUT"},
+ {"Speaker", NULL, "Speaker Amp"},
+
+ {"MIC1", NULL, "Mic (Internal)"},
+};
+
+static int e750_ac97_init(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_nc_pin(codec, "LOUT");
+ snd_soc_dapm_nc_pin(codec, "ROUT");
+ snd_soc_dapm_nc_pin(codec, "PHONE");
+ snd_soc_dapm_nc_pin(codec, "LINEINL");
+ snd_soc_dapm_nc_pin(codec, "LINEINR");
+ snd_soc_dapm_nc_pin(codec, "CDINL");
+ snd_soc_dapm_nc_pin(codec, "CDINR");
+ snd_soc_dapm_nc_pin(codec, "PCBEEP");
+ snd_soc_dapm_nc_pin(codec, "MIC2");
+
+ snd_soc_dapm_new_controls(codec, e750_dapm_widgets,
+ ARRAY_SIZE(e750_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ snd_soc_dapm_sync(codec);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link e750_dai[] = {
+ {
+ .name = "AC97",
+ .stream_name = "AC97 HiFi",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+ .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI],
+ .init = e750_ac97_init,
+ /* use ops to check startup state */
+ },
+ {
+ .name = "AC97 Aux",
+ .stream_name = "AC97 Aux",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+ .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX],
+ },
+};
+
+static struct snd_soc_card e750 = {
+ .name = "Toshiba e750",
+ .platform = &pxa2xx_soc_platform,
+ .dai_link = e750_dai,
+ .num_links = ARRAY_SIZE(e750_dai),
+};
+
+static struct snd_soc_device e750_snd_devdata = {
+ .card = &e750,
+ .codec_dev = &soc_codec_dev_wm9705,
+};
+
+static struct platform_device *e750_snd_device;
+
+static int __init e750_init(void)
+{
+ int ret;
+
+ if (!machine_is_e750())
+ return -ENODEV;
+
+ ret = gpio_request(GPIO_E750_HP_AMP_OFF, "Headphone amp");
+ if (ret)
+ return ret;
+
+ ret = gpio_request(GPIO_E750_SPK_AMP_OFF, "Speaker amp");
+ if (ret)
+ goto free_hp_amp_gpio;
+
+ ret = gpio_direction_output(GPIO_E750_HP_AMP_OFF, 1);
+ if (ret)
+ goto free_spk_amp_gpio;
+
+ ret = gpio_direction_output(GPIO_E750_SPK_AMP_OFF, 1);
+ if (ret)
+ goto free_spk_amp_gpio;
+
+ e750_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!e750_snd_device) {
+ ret = -ENOMEM;
+ goto free_spk_amp_gpio;
+ }
+
+ platform_set_drvdata(e750_snd_device, &e750_snd_devdata);
+ e750_snd_devdata.dev = &e750_snd_device->dev;
+ ret = platform_device_add(e750_snd_device);
+
+ if (!ret)
+ return 0;
+
+/* Fail gracefully */
+ platform_device_put(e750_snd_device);
+free_spk_amp_gpio:
+ gpio_free(GPIO_E750_SPK_AMP_OFF);
+free_hp_amp_gpio:
+ gpio_free(GPIO_E750_HP_AMP_OFF);
+
+ return ret;
+}
+
+static void __exit e750_exit(void)
+{
+ platform_device_unregister(e750_snd_device);
+ gpio_free(GPIO_E750_SPK_AMP_OFF);
+ gpio_free(GPIO_E750_HP_AMP_OFF);
+}
+
+module_init(e750_init);
+module_exit(e750_exit);
+
+/* Module information */
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("ALSA SoC driver for e750");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c
index ac294c797b7..bc019cdce42 100644
--- a/sound/soc/pxa/e800_wm9712.c
+++ b/sound/soc/pxa/e800_wm9712.c
@@ -1,8 +1,6 @@
/*
* e800-wm9712.c -- SoC audio for e800
*
- * Based on tosa.c
- *
* Copyright 2007 (c) Ian Molton <spyro@f2s.com>
*
* This program is free software; you can redistribute it and/or modify it
@@ -13,7 +11,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/device.h>
+#include <linux/gpio.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -22,20 +20,84 @@
#include <asm/mach-types.h>
#include <mach/audio.h>
+#include <mach/eseries-gpio.h>
#include "../codecs/wm9712.h"
#include "pxa2xx-pcm.h"
#include "pxa2xx-ac97.h"
-static struct snd_soc_card e800;
+static int e800_spk_amp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ if (event & SND_SOC_DAPM_PRE_PMU)
+ gpio_set_value(GPIO_E800_SPK_AMP_ON, 1);
+ else if (event & SND_SOC_DAPM_POST_PMD)
+ gpio_set_value(GPIO_E800_SPK_AMP_ON, 0);
-static struct snd_soc_dai_link e800_dai[] = {
+ return 0;
+}
+
+static int e800_hp_amp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ if (event & SND_SOC_DAPM_PRE_PMU)
+ gpio_set_value(GPIO_E800_HP_AMP_OFF, 0);
+ else if (event & SND_SOC_DAPM_POST_PMD)
+ gpio_set_value(GPIO_E800_HP_AMP_OFF, 1);
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget e800_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_MIC("Mic (Internal1)", NULL),
+ SND_SOC_DAPM_MIC("Mic (Internal2)", NULL),
+ SND_SOC_DAPM_SPK("Speaker", NULL),
+ SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+ e800_hp_amp_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+ e800_spk_amp_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ {"Headphone Jack", NULL, "HPOUTL"},
+ {"Headphone Jack", NULL, "HPOUTR"},
+ {"Headphone Jack", NULL, "Headphone Amp"},
+
+ {"Speaker Amp", NULL, "MONOOUT"},
+ {"Speaker", NULL, "Speaker Amp"},
+
+ {"MIC1", NULL, "Mic (Internal1)"},
+ {"MIC2", NULL, "Mic (Internal2)"},
+};
+
+static int e800_ac97_init(struct snd_soc_codec *codec)
{
- .name = "AC97 Aux",
- .stream_name = "AC97 Aux",
- .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
- .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
-},
+ snd_soc_dapm_new_controls(codec, e800_dapm_widgets,
+ ARRAY_SIZE(e800_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+ snd_soc_dapm_sync(codec);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link e800_dai[] = {
+ {
+ .name = "AC97",
+ .stream_name = "AC97 HiFi",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+ .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
+ .init = e800_ac97_init,
+ },
+ {
+ .name = "AC97 Aux",
+ .stream_name = "AC97 Aux",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+ .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
+ },
};
static struct snd_soc_card e800 = {
@@ -59,6 +121,22 @@ static int __init e800_init(void)
if (!machine_is_e800())
return -ENODEV;
+ ret = gpio_request(GPIO_E800_HP_AMP_OFF, "Headphone amp");
+ if (ret)
+ return ret;
+
+ ret = gpio_request(GPIO_E800_SPK_AMP_ON, "Speaker amp");
+ if (ret)
+ goto free_hp_amp_gpio;
+
+ ret = gpio_direction_output(GPIO_E800_HP_AMP_OFF, 1);
+ if (ret)
+ goto free_spk_amp_gpio;
+
+ ret = gpio_direction_output(GPIO_E800_SPK_AMP_ON, 1);
+ if (ret)
+ goto free_spk_amp_gpio;
+
e800_snd_device = platform_device_alloc("soc-audio", -1);
if (!e800_snd_device)
return -ENOMEM;
@@ -67,8 +145,15 @@ static int __init e800_init(void)
e800_snd_devdata.dev = &e800_snd_device->dev;
ret = platform_device_add(e800_snd_device);
- if (ret)
- platform_device_put(e800_snd_device);
+ if (!ret)
+ return 0;
+
+/* Fail gracefully */
+ platform_device_put(e800_snd_device);
+free_spk_amp_gpio:
+ gpio_free(GPIO_E800_SPK_AMP_ON);
+free_hp_amp_gpio:
+ gpio_free(GPIO_E800_HP_AMP_OFF);
return ret;
}
@@ -76,6 +161,8 @@ static int __init e800_init(void)
static void __exit e800_exit(void)
{
platform_device_unregister(e800_snd_device);
+ gpio_free(GPIO_E800_SPK_AMP_ON);
+ gpio_free(GPIO_E800_HP_AMP_OFF);
}
module_init(e800_init);
@@ -84,4 +171,4 @@ module_exit(e800_exit);
/* Module information */
MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
MODULE_DESCRIPTION("ALSA SoC driver for e800");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
new file mode 100644
index 00000000000..19eda8bbfda
--- /dev/null
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -0,0 +1,250 @@
+/*
+ * Handles the Mitac mioa701 SoC system
+ *
+ * Copyright (C) 2008 Robert Jarzmik
+ *
+ * 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 in 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
+ *
+ * This is a little schema of the sound interconnections :
+ *
+ * Sagem X200 Wolfson WM9713
+ * +--------+ +-------------------+ Rear Speaker
+ * | | | | /-+
+ * | +--->----->---+MONOIN SPKL+--->----+-+ |
+ * | GSM | | | | | |
+ * | +--->----->---+PCBEEP SPKR+--->----+-+ |
+ * | CHIP | | | \-+
+ * | +---<-----<---+MONO |
+ * | | | | Front Speaker
+ * +--------+ | | /-+
+ * | HPL+--->----+-+ |
+ * | | | | |
+ * | OUT3+--->----+-+ |
+ * | | \-+
+ * | |
+ * | | Front Micro
+ * | | +
+ * | MIC1+-----<--+o+
+ * | | +
+ * +-------------------+ ---
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <mach/audio.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/ac97_codec.h>
+
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-ac97.h"
+#include "../codecs/wm9713.h"
+
+#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
+
+#define AC97_GPIO_PULL 0x58
+
+/* Use GPIO8 for rear speaker amplifier */
+static int rear_amp_power(struct snd_soc_codec *codec, int power)
+{
+ unsigned short reg;
+
+ if (power) {
+ reg = snd_soc_read(codec, AC97_GPIO_CFG);
+ snd_soc_write(codec, AC97_GPIO_CFG, reg | 0x0100);
+ reg = snd_soc_read(codec, AC97_GPIO_PULL);
+ snd_soc_write(codec, AC97_GPIO_PULL, reg | (1<<15));
+ } else {
+ reg = snd_soc_read(codec, AC97_GPIO_CFG);
+ snd_soc_write(codec, AC97_GPIO_CFG, reg & ~0x0100);
+ reg = snd_soc_read(codec, AC97_GPIO_PULL);
+ snd_soc_write(codec, AC97_GPIO_PULL, reg & ~(1<<15));
+ }
+
+ return 0;
+}
+
+static int rear_amp_event(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *kctl, int event)
+{
+ struct snd_soc_codec *codec = widget->codec;
+
+ return rear_amp_power(codec, SND_SOC_DAPM_EVENT_ON(event));
+}
+
+/* mioa701 machine dapm widgets */
+static const struct snd_soc_dapm_widget mioa701_dapm_widgets[] = {
+ SND_SOC_DAPM_SPK("Front Speaker", NULL),
+ SND_SOC_DAPM_SPK("Rear Speaker", rear_amp_event),
+ SND_SOC_DAPM_MIC("Headset", NULL),
+ SND_SOC_DAPM_LINE("GSM Line Out", NULL),
+ SND_SOC_DAPM_LINE("GSM Line In", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Front Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* Call Mic */
+ {"Mic Bias", NULL, "Front Mic"},
+ {"MIC1", NULL, "Mic Bias"},
+
+ /* Headset Mic */
+ {"LINEL", NULL, "Headset Mic"},
+ {"LINER", NULL, "Headset Mic"},
+
+ /* GSM Module */
+ {"MONOIN", NULL, "GSM Line Out"},
+ {"PCBEEP", NULL, "GSM Line Out"},
+ {"GSM Line In", NULL, "MONO"},
+
+ /* headphone connected to HPL, HPR */
+ {"Headset", NULL, "HPL"},
+ {"Headset", NULL, "HPR"},
+
+ /* front speaker connected to HPL, OUT3 */
+ {"Front Speaker", NULL, "HPL"},
+ {"Front Speaker", NULL, "OUT3"},
+
+ /* rear speaker connected to SPKL, SPKR */
+ {"Rear Speaker", NULL, "SPKL"},
+ {"Rear Speaker", NULL, "SPKR"},
+};
+
+static int mioa701_wm9713_init(struct snd_soc_codec *codec)
+{
+ unsigned short reg;
+
+ /* Add mioa701 specific widgets */
+ snd_soc_dapm_new_controls(codec, ARRAY_AND_SIZE(mioa701_dapm_widgets));
+
+ /* Set up mioa701 specific audio path audio_mapnects */
+ snd_soc_dapm_add_routes(codec, ARRAY_AND_SIZE(audio_map));
+
+ /* Prepare GPIO8 for rear speaker amplifier */
+ reg = codec->read(codec, AC97_GPIO_CFG);
+ codec->write(codec, AC97_GPIO_CFG, reg | 0x0100);
+
+ /* Prepare MIC input */
+ reg = codec->read(codec, AC97_3D_CONTROL);
+ codec->write(codec, AC97_3D_CONTROL, reg | 0xc000);
+
+ snd_soc_dapm_enable_pin(codec, "Front Speaker");
+ snd_soc_dapm_enable_pin(codec, "Rear Speaker");
+ snd_soc_dapm_enable_pin(codec, "Front Mic");
+ snd_soc_dapm_enable_pin(codec, "GSM Line In");
+ snd_soc_dapm_enable_pin(codec, "GSM Line Out");
+ snd_soc_dapm_sync(codec);
+
+ return 0;
+}
+
+static struct snd_soc_ops mioa701_ops;
+
+static struct snd_soc_dai_link mioa701_dai[] = {
+ {
+ .name = "AC97",
+ .stream_name = "AC97 HiFi",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+ .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI],
+ .init = mioa701_wm9713_init,
+ .ops = &mioa701_ops,
+ },
+ {
+ .name = "AC97 Aux",
+ .stream_name = "AC97 Aux",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+ .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX],
+ .ops = &mioa701_ops,
+ },
+};
+
+static struct snd_soc_card mioa701 = {
+ .name = "MioA701",
+ .platform = &pxa2xx_soc_platform,
+ .dai_link = mioa701_dai,
+ .num_links = ARRAY_SIZE(mioa701_dai),
+};
+
+static struct snd_soc_device mioa701_snd_devdata = {
+ .card = &mioa701,
+ .codec_dev = &soc_codec_dev_wm9713,
+};
+
+static struct platform_device *mioa701_snd_device;
+
+static int mioa701_wm9713_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ if (!machine_is_mioa701())
+ return -ENODEV;
+
+ dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will"
+ "lead to overheating and possible destruction of your device."
+ "Do not use without a good knowledge of mio's board design!\n");
+
+ mioa701_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!mioa701_snd_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(mioa701_snd_device, &mioa701_snd_devdata);
+ mioa701_snd_devdata.dev = &mioa701_snd_device->dev;
+
+ ret = platform_device_add(mioa701_snd_device);
+ if (!ret)
+ return 0;
+
+ platform_device_put(mioa701_snd_device);
+ return ret;
+}
+
+static int __devexit mioa701_wm9713_remove(struct platform_device *pdev)
+{
+ platform_device_unregister(mioa701_snd_device);
+ return 0;
+}
+
+static struct platform_driver mioa701_wm9713_driver = {
+ .probe = mioa701_wm9713_probe,
+ .remove = __devexit_p(mioa701_wm9713_remove),
+ .driver = {
+ .name = "mioa701-wm9713",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init mioa701_asoc_init(void)
+{
+ return platform_driver_register(&mioa701_wm9713_driver);
+}
+
+static void __exit mioa701_asoc_exit(void)
+{
+ platform_driver_unregister(&mioa701_wm9713_driver);
+}
+
+module_init(mioa701_asoc_init);
+module_exit(mioa701_asoc_exit);
+
+/* Module information */
+MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)");
+MODULE_DESCRIPTION("ALSA SoC WM9713 MIO A701");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index 4a9cf3083af..48a73f64500 100644
--- a/