From a7e2e735dcf98717150d3c8eaa731de8038af05a Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Thu, 8 Jan 2009 21:03:55 +0000 Subject: ASoC: machine driver for Toshiba e750 This patch adds support for the wm9705 ac97 codec as used in the Toshiba e750 PDA. It includes support for powering up / down the external headphone and speaker amplifiers on this machine. Signed-off-by: Ian Molton Signed-off-by: Mark Brown --- sound/soc/pxa/Kconfig | 9 +++ sound/soc/pxa/Makefile | 2 + sound/soc/pxa/e750_wm9705.c | 189 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 sound/soc/pxa/e750_wm9705.c (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index f82e10699471..b9b1a3f5d673 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -61,6 +61,15 @@ 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_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 diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index 08a9f2797729..c7d4cceeed92 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -13,6 +13,7 @@ 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-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 @@ -22,6 +23,7 @@ snd-soc-zylonite-objs := zylonite.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_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 diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c new file mode 100644 index 000000000000..20fbdcfa9f78 --- /dev/null +++ b/sound/soc/pxa/e750_wm9705.c @@ -0,0 +1,189 @@ +/* + * e750-wm9705.c -- SoC audio for e750 + * + * Copyright 2007 (c) Ian Molton + * + * 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 +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#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 "); +MODULE_DESCRIPTION("ALSA SoC driver for e750"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 0465c7aa6fbab89de820442aed449ceb8d9145a6 Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Thu, 8 Jan 2009 21:16:05 +0000 Subject: ASoC: machine driver for Toshiba e800 This patch adds support for the wm9712 ac97 codec as used in the Toshiba e800 PDA. It includes support for powering up / down the external headphone and speaker amplifiers on this machine. Signed-off-by: Ian Molton Signed-off-by: Mark Brown --- sound/soc/pxa/e800_wm9712.c | 116 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 14 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 2e3386dfa0f0..78a1770b986c 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 * * This program is free software; you can redistribute it and/or modify it @@ -13,31 +11,96 @@ #include #include -#include +#include #include #include #include #include -#include #include #include #include +#include + +#include #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) { - .name = "AC97 Aux", - .stream_name = "AC97 Aux", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], -}, + 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) +{ + 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 = { @@ -61,6 +124,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; @@ -69,8 +148,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; } @@ -78,6 +164,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); @@ -86,4 +174,4 @@ module_exit(e800_exit); /* Module information */ MODULE_AUTHOR("Ian Molton "); MODULE_DESCRIPTION("ALSA SoC driver for e800"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 2c782f5981a022f7a238d550af5daa75c8acf382 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 16 Jan 2009 16:35:52 +0000 Subject: ASoC: Implement support for CLK_POUT as MCLK on Zylonite The Zylonite supports switching the MCLK for the WM9713 between the AC97CLK and CLK_POUT outputs of the PXA processor via switch SW15 on the board. This patch adds support for configuring the system to use CLK_POUT. Unfortunately it is not possible to read the state of SW15 from software so this feature is controlled by a module option 'clk_pout' which should be set to a non-zero value to enable the use of CLK_POUT. Signed-off-by: Mark Brown --- sound/soc/pxa/zylonite.c | 101 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 84 insertions(+), 17 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index f8e9ecd589d3..8541b679f6eb 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,17 @@ #include "pxa2xx-ac97.h" #include "pxa-ssp.h" +/* + * There is a physical switch SW15 on the board which changes the MCLK + * for the WM9713 between the standard AC97 master clock and the + * output of the CLK_POUT signal from the PXA. + */ +static int clk_pout; +module_param(clk_pout, int, 0); +MODULE_PARM_DESC(clk_pout, "Use CLK_POUT as WM9713 MCLK (SW15 on board)."); + +static struct clk *pout; + static struct snd_soc_card zylonite; static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = { @@ -61,10 +73,8 @@ static const struct snd_soc_dapm_route audio_map[] = { static int zylonite_wm9713_init(struct snd_soc_codec *codec) { - /* Currently we only support use of the AC97 clock here. If - * CLK_POUT is selected by SW15 then the clock API will need - * to be used to request and enable it here. - */ + if (clk_pout) + snd_soc_dai_set_pll(&codec->dai[0], 0, clk_get_rate(pout), 0); snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, ARRAY_SIZE(zylonite_dapm_widgets)); @@ -85,7 +95,6 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - unsigned int pll_out = 0; unsigned int acds = 0; unsigned int wm9713_div = 0; int ret = 0; @@ -93,16 +102,13 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, switch (params_rate(params)) { case 8000: wm9713_div = 12; - pll_out = 2048000; break; case 16000: wm9713_div = 6; - pll_out = 4096000; break; case 48000: default: wm9713_div = 2; - pll_out = 12288000; acds = 1; break; } @@ -123,10 +129,6 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out); - if (ret < 0) - return ret; - ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); if (ret < 0) return ret; @@ -135,11 +137,12 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - /* Note that if the PLL is in use the WM9713_PCMCLK_PLL_DIV needs - * to be set instead. - */ - ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, - WM9713_PCMDIV(wm9713_div)); + if (clk_pout) + ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV, + WM9713_PCMDIV(wm9713_div)); + else + ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, + WM9713_PCMDIV(wm9713_div)); if (ret < 0) return ret; @@ -173,8 +176,72 @@ static struct snd_soc_dai_link zylonite_dai[] = { }, }; +static int zylonite_probe(struct platform_device *pdev) +{ + int ret; + + if (clk_pout) { + pout = clk_get(NULL, "CLK_POUT"); + if (IS_ERR(pout)) { + dev_err(&pdev->dev, "Unable to obtain CLK_POUT: %ld\n", + PTR_ERR(pout)); + return PTR_ERR(pout); + } + + ret = clk_enable(pout); + if (ret != 0) { + dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n", + ret); + clk_put(pout); + return ret; + } + + dev_dbg(&pdev->dev, "MCLK enabled at %luHz\n", + clk_get_rate(pout)); + } + + return 0; +} + +static int zylonite_remove(struct platform_device *pdev) +{ + if (clk_pout) { + clk_disable(pout); + clk_put(pout); + } + + return 0; +} + +static int zylonite_suspend_post(struct platform_device *pdev, + pm_message_t state) +{ + if (clk_pout) + clk_disable(pout); + + return 0; +} + +static int zylonite_resume_pre(struct platform_device *pdev) +{ + int ret = 0; + + if (clk_pout) { + ret = clk_enable(pout); + if (ret != 0) + dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n", + ret); + } + + return ret; +} + static struct snd_soc_card zylonite = { .name = "Zylonite", + .probe = &zylonite_probe, + .remove = &zylonite_remove, + .suspend_post = &zylonite_suspend_post, + .resume_pre = &zylonite_resume_pre, .platform = &pxa2xx_soc_platform, .dai_link = zylonite_dai, .num_links = ARRAY_SIZE(zylonite_dai), -- cgit v1.2.3 From 28796eaf806502b9bd86cbacf8edbc14c80c14b0 Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Sat, 17 Jan 2009 15:11:06 +0000 Subject: ASoC: machine support for Toshiba e740 PDA This patch provides suupport for the wm9705 AC97 codec on the Toshiba e740. Note: The e740 has a hard headphone switch that turns the speaker off and is not software detectable or controlable. Also both headphone and speaker amps share a common output enable. Signed-off-by: Ian Molton Signed-off-by: Mark Brown --- sound/soc/pxa/Kconfig | 9 ++ sound/soc/pxa/Makefile | 2 + sound/soc/pxa/e740_wm9705.c | 213 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 sound/soc/pxa/e740_wm9705.c (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index b9b1a3f5d673..958ac3fe15d1 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -61,6 +61,15 @@ 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 diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index c7d4cceeed92..97a51a8c936c 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -13,6 +13,7 @@ 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 @@ -23,6 +24,7 @@ snd-soc-zylonite-objs := zylonite.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 diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c new file mode 100644 index 000000000000..ac3617651734 --- /dev/null +++ b/sound/soc/pxa/e740_wm9705.c @@ -0,0 +1,213 @@ +/* + * e740-wm9705.c -- SoC audio for e740 + * + * Copyright 2007 (c) Ian Molton + * + * 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 +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#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 "); +MODULE_DESCRIPTION("ALSA SoC driver for e740"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From c91cf25ebfbf3a5b336cbaa46646d37dd3d33127 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 11:23:32 +0000 Subject: ASoC: Fix merge with PXA tree Fix a merge issue caused by context overlap. Reported-by: Stephen Rothwell Signed-off-by: Mark Brown --- sound/soc/pxa/e800_wm9712.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 78a1770b986c..bc019cdce429 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -18,13 +18,10 @@ #include #include -#include -#include +#include #include #include -#include - #include "../codecs/wm9712.h" #include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" -- cgit v1.2.3 From f6fca2e93c9ad3c704f02aaabe4359a8af16fbbb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 11:40:26 +0000 Subject: ASoC: Remove unneeded e7x0 inclusion of pxa-regs.h and hardware.h pxa-regs.h and hardware.h are not intended for use directly in driver code and references to them have been removed in other code - remove them from the newly added e740 and e750 machine drivers. Signed-off-by: Mark Brown --- sound/soc/pxa/e740_wm9705.c | 2 -- sound/soc/pxa/e750_wm9705.c | 2 -- 2 files changed, 4 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index ac3617651734..7cd2f89d7b10 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c @@ -18,8 +18,6 @@ #include #include -#include -#include #include #include diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index 20fbdcfa9f78..8dceccc5e059 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c @@ -18,8 +18,6 @@ #include #include -#include -#include #include #include -- cgit v1.2.3 From a435869cacbb581920df23411416bed533748bf1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 11:49:45 +0000 Subject: ASoC: Configure SSP port PLL for Zylonite Signed-off-by: Mark Brown --- sound/soc/pxa/zylonite.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index 8541b679f6eb..ec2fb764b241 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -95,6 +95,7 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + unsigned int pll_out = 0; unsigned int acds = 0; unsigned int wm9713_div = 0; int ret = 0; @@ -102,13 +103,16 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, switch (params_rate(params)) { case 8000: wm9713_div = 12; + pll_out = 2048000; break; case 16000: wm9713_div = 6; + pll_out = 4096000; break; case 48000: default: wm9713_div = 2; + pll_out = 12288000; acds = 1; break; } @@ -129,6 +133,10 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; + ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out); + if (ret < 0) + return ret; + ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); if (ret < 0) return ret; -- cgit v1.2.3 From 0664678a84c653bde844c7d91646259a25c6188b Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 3 Feb 2009 21:18:26 +0100 Subject: ASoC: pxa-ssp: fix SSP port request PXA2xx/3xx SSP ports start from 1, not 0. Thus, the probe function requested the wrong SSP port. Correcting this unveiled another bug where ssp_init tries to request the already-requested SSP port again. So this patch replaces the ssp_init/exit calls with their internals from mach-pxa/ssp.c, leaving out the redundant ssp_request and the unneeded IRQ request. Effectively, that leaves us with not much more than enabling/disabling the SSP clock. Signed-off-by: Philipp Zabel Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 73cb6b4c2f2d..4a973ab710be 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -21,6 +21,8 @@ #include #include +#include + #include #include #include @@ -221,9 +223,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, int ret = 0; if (!cpu_dai->active) { - ret = ssp_init(&priv->dev, cpu_dai->id + 1, SSP_NO_IRQ); - if (ret < 0) - return ret; + priv->dev.port = cpu_dai->id + 1; + priv->dev.irq = NO_IRQ; + clk_enable(priv->dev.ssp->clk); ssp_disable(&priv->dev); } return ret; @@ -238,7 +240,7 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, if (!cpu_dai->active) { ssp_disable(&priv->dev); - ssp_exit(&priv->dev); + clk_disable(priv->dev.ssp->clk); } } @@ -751,7 +753,7 @@ static int pxa_ssp_probe(struct platform_device *pdev, if (!priv) return -ENOMEM; - priv->dev.ssp = ssp_request(dai->id, "SoC audio"); + priv->dev.ssp = ssp_request(dai->id + 1, "SoC audio"); if (priv->dev.ssp == NULL) { ret = -ENODEV; goto err_priv; -- cgit v1.2.3 From 8f0dc655f9efa3fc81b8cdaf5aa1f2779f8db46d Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 7 Feb 2009 14:01:58 +0100 Subject: ASoC: Add initial support of Mitac mioa701 device SoC. This machine driver enables sound functions on Mitac mio a701 smartphone. Build upon ASoC v1, it handles : - rear speaker - front speaker - microphone - GSM A global "Mio Mode" switch is not yet provided to cope with audio path setup. As balance on audio chip line is no more assured, an incorrect setup can produce a lot of heat and even fry the battery behind the wm9713 and the speaker amplifier. It doesn't cope with : - headset jack - mio master mode - master volume control This driver is backported from ASoc v2, and amputated from scenario setups and master volume control. [Minor mods for terminology in comments -- broonie] Signed-off-by: Robert Jarzmik Signed-off-by: Mark Brown --- sound/soc/pxa/Kconfig | 9 ++ sound/soc/pxa/Makefile | 2 + sound/soc/pxa/mioa701_wm9713.c | 250 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 261 insertions(+) create mode 100644 sound/soc/pxa/mioa701_wm9713.c (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 958ac3fe15d1..5998ab366e83 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -115,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 97a51a8c936c..8ed881c5e5cc 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -20,6 +20,7 @@ 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 @@ -30,4 +31,5 @@ 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/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c new file mode 100644 index 000000000000..19eda8bbfdaf --- /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 +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#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"); -- cgit v1.2.3 From 44dd2b9168350b82a671ce71666b99208ab2d973 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 5 Feb 2009 17:48:21 +0100 Subject: ASoC: pxa2xx-i2s: remove I2S pin setup This removes the calls to pxa_gpio_mode from the pxa2xx-i2s driver. Pin setup should be done during board init via pxa2xx_mfp_config instead. Signed-off-by: Philipp Zabel Acked-by: Eric Miao Signed-off-by: Mark Brown --- sound/soc/pxa/pxa2xx-i2s.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 517991fb1099..83b59d7fe96e 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -25,20 +25,11 @@ #include #include -#include #include #include "pxa2xx-pcm.h" #include "pxa2xx-i2s.h" -struct pxa2xx_gpio { - u32 sys; - u32 rx; - u32 tx; - u32 clk; - u32 frm; -}; - /* * I2S Controller Register and Bit Definitions */ @@ -106,21 +97,6 @@ static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = { DCMD_BURST32 | DCMD_WIDTH4, }; -static struct pxa2xx_gpio gpio_bus[] = { - { /* I2S SoC Slave */ - .rx = GPIO29_SDATA_IN_I2S_MD, - .tx = GPIO30_SDATA_OUT_I2S_MD, - .clk = GPIO28_BITCLK_IN_I2S_MD, - .frm = GPIO31_SYNC_I2S_MD, - }, - { /* I2S SoC Master */ - .rx = GPIO29_SDATA_IN_I2S_MD, - .tx = GPIO30_SDATA_OUT_I2S_MD, - .clk = GPIO28_BITCLK_OUT_I2S_MD, - .frm = GPIO31_SYNC_I2S_MD, - }, -}; - static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -181,9 +157,6 @@ static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai, if (clk_id != PXA2XX_I2S_SYSCLK) return -ENODEV; - if (pxa_i2s.master && dir == SND_SOC_CLOCK_OUT) - pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys); - return 0; } @@ -194,10 +167,6 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx); - pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx); - pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm); - pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk); BUG_ON(IS_ERR(clk_i2s)); clk_enable(clk_i2s); pxa_i2s_wait(); @@ -398,11 +367,6 @@ static struct platform_driver pxa2xx_i2s_driver = { static int __init pxa2xx_i2s_init(void) { - if (cpu_is_pxa27x()) - gpio_bus[1].sys = GPIO113_I2S_SYSCLK_MD; - else - gpio_bus[1].sys = GPIO32_SYSCLK_I2S_MD; - clk_i2s = ERR_PTR(-ENOENT); return platform_driver_register(&pxa2xx_i2s_driver); } -- cgit v1.2.3 From 9e30d7718bb7402c7bdee631ad2aae2658c324f0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Feb 2009 08:28:04 +0100 Subject: ASoC: Fix forgotten replacements of socdev->codec The snd_soc_codec was moved into socdev->card, but this change wasn't applied in some places. Fixed now. Signed-off-by: Takashi Iwai --- sound/soc/pxa/corgi.c | 2 +- sound/soc/pxa/palm27x.c | 2 +- sound/soc/pxa/poodle.c | 2 +- sound/soc/pxa/spitz.c | 2 +- sound/soc/pxa/tosa.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 1ba25a559524..0d41be33d572 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -100,7 +100,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); diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c index 4a9cf3083af0..29958cd9daec 100644 --- a/sound/soc/pxa/palm27x.c +++ b/sound/soc/pxa/palm27x.c @@ -55,7 +55,7 @@ static void palm27x_ext_control(struct snd_soc_codec *codec) static int palm27x_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 */ palm27x_ext_control(codec); diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 6e9827189fff..3a62d4354ef6 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -77,7 +77,7 @@ static void poodle_ext_control(struct snd_soc_codec *codec) static int poodle_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 */ poodle_ext_control(codec); diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index a3b9e6bdf979..1aafd8c645a1 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -109,7 +109,7 @@ static void spitz_ext_control(struct snd_soc_codec *codec) static int spitz_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 */ spitz_ext_control(codec); diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index c77194f74c9b..09b5bada03b9 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -82,7 +82,7 @@ static void tosa_ext_control(struct snd_soc_codec *codec) static int tosa_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 */ tosa_ext_control(codec); -- cgit v1.2.3 From 5998102b9095fdb7c67755812038612afea315c5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 16 Feb 2009 20:49:16 +0000 Subject: ASoC: Refactor WM8731 device registration Move the WM8731 driver to use a more standard device registration scheme where the device can be registered independantly of the ASoC probe. As a transition measure push the current manual code for registering the WM8731 into the individual machine driver probes. This allows separate patches to update the relevant architecture files with less risk of merge issues. Signed-off-by: Mark Brown --- sound/soc/pxa/corgi.c | 43 ++++++++++++++++++++++++++++++++++++------- sound/soc/pxa/poodle.c | 41 +++++++++++++++++++++++++++++++++++------ 2 files changed, 71 insertions(+), 13 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 0d41be33d572..eaa66915a324 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -317,19 +317,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) @@ -340,6 +365,10 @@ static int __init corgi_init(void) machine_is_husky())) return -ENODEV; + ret = wm8731_i2c_setup(); + 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/poodle.c b/sound/soc/pxa/poodle.c index 3a62d4354ef6..fd683a0b742d 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -283,17 +283,42 @@ static struct snd_soc_card snd_soc_poodle = { .num_links = 1, }; -/* poodle audio private data */ -static struct wm8731_setup_data poodle_wm8731_setup = { - .i2c_bus = 0, - .i2c_address = 0x1b, -}; +/* + * 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; +} /* poodle audio subsystem */ static struct snd_soc_device poodle_snd_devdata = { .card = &snd_soc_poodle, .codec_dev = &soc_codec_dev_wm8731, - .codec_data = &poodle_wm8731_setup, }; static struct platform_device *poodle_snd_device; @@ -305,6 +330,10 @@ static int __init poodle_init(void) if (!machine_is_poodle()) return -ENODEV; + ret = wm8731_i2c_setup(); + if (ret != 0) + return ret; + locomo_gpio_set_dir(&poodle_locomo_device.dev, POODLE_LOCOMO_GPIO_AMP_ON, 0); /* should we mute HP at startup - burning power ?*/ -- cgit v1.2.3 From fc9967576829a01c98e5388410dc12c61006f79f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 18 Feb 2009 12:34:53 +0000 Subject: ASoC: Fix build for corgi and poodle Signed-off-by: Mark Brown --- sound/soc/pxa/corgi.c | 3 ++- sound/soc/pxa/poodle.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index eaa66915a324..146973ae0974 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -365,7 +366,7 @@ static int __init corgi_init(void) machine_is_husky())) return -ENODEV; - ret = wm8731_i2c_setup(); + ret = wm8731_i2c_register(); if (ret != 0) return ret; diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index fd683a0b742d..fb17a0a5a093 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -330,7 +331,7 @@ static int __init poodle_init(void) if (!machine_is_poodle()) return -ENODEV; - ret = wm8731_i2c_setup(); + ret = wm8731_i2c_register(); if (ret != 0) return ret; -- cgit v1.2.3 From d3b894218441ecb1c83e47c682e2d6589ee37a8d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 23 Feb 2009 18:45:19 +0000 Subject: ASoC: Fix Zylonite voice interface stereo configurations We always run in the first timeslot of one. Signed-off-by: Mark Brown --- sound/soc/pxa/zylonite.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index ec2fb764b241..0140a250db24 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -127,9 +127,8 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - ret = snd_soc_dai_set_tdm_slot(cpu_dai, - params_channels(params), - params_channels(params)); + /* We're not really in network mode but the emulation wants this. */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1); if (ret < 0) return ret; -- cgit v1.2.3 From aa4ef01de5f2e7ed948b88f9f1cfc93c8e0c3f25 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 3 Mar 2009 16:10:51 +0100 Subject: ASoC: Use network mode with 2 slots for 16-bit stereo in pxa-ssp/Zylonite For consistency with 24-bit and 32-bit modes, don't send 16-bit stereo in one 32-bit transfer. Use 2 slots instead on Zylonite. It should result in exactly the same behaviour. Now it is possible to use 16-bit single slot transfers in pxa-ssp, which are needed for Magician to get two frame clock pulses per sample (one for each channel). Signed-off-by: Philipp Zabel Tested-by: Mark Brown Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 3 +-- sound/soc/pxa/zylonite.c | 7 +++++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 4a973ab710be..c49bb12b0a65 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -644,8 +644,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, sscr0 |= SSCR0_FPCKE; #endif sscr0 |= SSCR0_DataSize(16); - if (params_channels(params) > 1) - sscr0 |= SSCR0_EDSS; + /* use network mode (2 slots) for 16 bit stereo */ break; case SNDRV_PCM_FORMAT_S24_LE: sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8)); diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index 0140a250db24..9f6116edbb84 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -127,8 +127,11 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - /* We're not really in network mode but the emulation wants this. */ - ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1); + /* Use network mode for stereo, one slot per channel. */ + if (params_channels(params) > 1) + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 2); + else + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1); if (ret < 0) return ret; -- cgit v1.2.3 From 6335d05548eece40092000aa91b64a50310d69d5 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 3 Mar 2009 09:41:00 +0800 Subject: ASoC: make ops a pointer in 'struct snd_soc_dai' Considering the fact that most cpu_dai or codec_dai are using a same 'snd_soc_dai_ops' for several similar interfaces, 'ops' would be better made a pointer instead, to make sharing easier and code a bit cleaner. The patch below is rather preliminary since the asoc tree is being actively developed, and this touches almost every piece of code, (and possibly many others in development need to be changed as well). Building of all codecs are OK, yet to every SoC, I didn't test that. Signed-off-by: Eric Miao Acked-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 65 ++++++++++++--------------------------------- sound/soc/pxa/pxa2xx-ac97.c | 13 ++++----- sound/soc/pxa/pxa2xx-i2s.c | 18 +++++++------ 3 files changed, 34 insertions(+), 62 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 4a973ab710be..3e18064e86b2 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -784,6 +784,19 @@ static void pxa_ssp_remove(struct platform_device *pdev, SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE) +static struct snd_soc_dai_ops pxa_ssp_dai_ops = { + .startup = pxa_ssp_startup, + .shutdown = pxa_ssp_shutdown, + .trigger = pxa_ssp_trigger, + .hw_params = pxa_ssp_hw_params, + .set_sysclk = pxa_ssp_set_dai_sysclk, + .set_clkdiv = pxa_ssp_set_dai_clkdiv, + .set_pll = pxa_ssp_set_dai_pll, + .set_fmt = pxa_ssp_set_dai_fmt, + .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, + .set_tristate = pxa_ssp_set_dai_tristate, +}; + struct snd_soc_dai pxa_ssp_dai[] = { { .name = "pxa2xx-ssp1", @@ -804,18 +817,7 @@ struct snd_soc_dai pxa_ssp_dai[] = { .rates = PXA_SSP_RATES, .formats = PXA_SSP_FORMATS, }, - .ops = { - .startup = pxa_ssp_startup, - .shutdown = pxa_ssp_shutdown, - .trigger = pxa_ssp_trigger, - .hw_params = pxa_ssp_hw_params, - .set_sysclk = pxa_ssp_set_dai_sysclk, - .set_clkdiv = pxa_ssp_set_dai_clkdiv, - .set_pll = pxa_ssp_set_dai_pll, - .set_fmt = pxa_ssp_set_dai_fmt, - .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, - .set_tristate = pxa_ssp_set_dai_tristate, - }, + .ops = &pxa_ssp_dai_ops, }, { .name = "pxa2xx-ssp2", .id = 1, @@ -835,18 +837,7 @@ struct snd_soc_dai pxa_ssp_dai[] = { .rates = PXA_SSP_RATES, .formats = PXA_SSP_FORMATS, }, - .ops = { - .startup = pxa_ssp_startup, - .shutdown = pxa_ssp_shutdown, - .trigger = pxa_ssp_trigger, - .hw_params = pxa_ssp_hw_params, - .set_sysclk = pxa_ssp_set_dai_sysclk, - .set_clkdiv = pxa_ssp_set_dai_clkdiv, - .set_pll = pxa_ssp_set_dai_pll, - .set_fmt = pxa_ssp_set_dai_fmt, - .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, - .set_tristate = pxa_ssp_set_dai_tristate, - }, + .ops = &pxa_ssp_dai_ops, }, { .name = "pxa2xx-ssp3", @@ -867,18 +858,7 @@ struct snd_soc_dai pxa_ssp_dai[] = { .rates = PXA_SSP_RATES, .formats = PXA_SSP_FORMATS, }, - .ops = { - .startup = pxa_ssp_startup, - .shutdown = pxa_ssp_shutdown, - .trigger = pxa_ssp_trigger, - .hw_params = pxa_ssp_hw_params, - .set_sysclk = pxa_ssp_set_dai_sysclk, - .set_clkdiv = pxa_ssp_set_dai_clkdiv, - .set_pll = pxa_ssp_set_dai_pll, - .set_fmt = pxa_ssp_set_dai_fmt, - .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, - .set_tristate = pxa_ssp_set_dai_tristate, - }, + .ops = &pxa_ssp_dai_ops, }, { .name = "pxa2xx-ssp4", @@ -899,18 +879,7 @@ struct snd_soc_dai pxa_ssp_dai[] = { .rates = PXA_SSP_RATES, .formats = PXA_SSP_FORMATS, }, - .ops = { - .startup = pxa_ssp_startup, - .shutdown = pxa_ssp_shutdown, - .trigger = pxa_ssp_trigger, - .hw_params = pxa_ssp_hw_params, - .set_sysclk = pxa_ssp_set_dai_sysclk, - .set_clkdiv = pxa_ssp_set_dai_clkdiv, - .set_pll = pxa_ssp_set_dai_pll, - .set_fmt = pxa_ssp_set_dai_fmt, - .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, - .set_tristate = pxa_ssp_set_dai_tristate, - }, + .ops = &pxa_ssp_dai_ops, }, }; EXPORT_SYMBOL_GPL(pxa_ssp_dai); diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 812c2b4d3e07..11cd0f289c16 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -164,6 +164,10 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000) +static struct snd_soc_dai_ops pxa_ac97_dai_ops = { + .hw_params = pxa2xx_ac97_hw_params, +}; + /* * There is only 1 physical AC97 interface for pxa2xx, but it * has extra fifo's that can be used for aux DACs and ADCs. @@ -189,8 +193,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 2, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .hw_params = pxa2xx_ac97_hw_params,}, + .ops = &pxa_ac97_dai_ops, }, { .name = "pxa2xx-ac97-aux", @@ -208,8 +211,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 1, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .hw_params = pxa2xx_ac97_hw_aux_params,}, + .ops = &pxa_ac97_dai_ops, }, { .name = "pxa2xx-ac97-mic", @@ -221,8 +223,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 1, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .hw_params = pxa2xx_ac97_hw_mic_params,}, + .ops = &pxa_ac97_dai_ops, }, }; diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 83b59d7fe96e..e6c24408c5f9 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -304,6 +304,15 @@ static int pxa2xx_i2s_resume(struct snd_soc_dai *dai) SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) +static struct snd_soc_dai_ops pxa_i2s_dai_ops = { + .startup = pxa2xx_i2s_startup, + .shutdown = pxa2xx_i2s_shutdown, + .trigger = pxa2xx_i2s_trigger, + .hw_params = pxa2xx_i2s_hw_params, + .set_fmt = pxa2xx_i2s_set_dai_fmt, + .set_sysclk = pxa2xx_i2s_set_dai_sysclk, +}; + struct snd_soc_dai pxa_i2s_dai = { .name = "pxa2xx-i2s", .id = 0, @@ -319,14 +328,7 @@ struct snd_soc_dai pxa_i2s_dai = { .channels_max = 2, .rates = PXA2XX_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .startup = pxa2xx_i2s_startup, - .shutdown = pxa2xx_i2s_shutdown, - .trigger = pxa2xx_i2s_trigger, - .hw_params = pxa2xx_i2s_hw_params, - .set_fmt = pxa2xx_i2s_set_dai_fmt, - .set_sysclk = pxa2xx_i2s_set_dai_sysclk, - }, + .ops = &pxa_i2s_dai_ops, }; EXPORT_SYMBOL_GPL(pxa_i2s_dai); -- cgit v1.2.3 From 20a41eac4fbaa22d051d0fbaeaf3315d2d8c4860 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 4 Mar 2009 21:16:57 +0100 Subject: ASoC: Fix name of register bit in pxa-ssp A bit in PXA's SSCR0 register was erroneously named ADC but its name is in fact ACS (audio clock select). Signed-off-by: Daniel Mack Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index c49bb12b0a65..7fc13f03d1d2 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -300,7 +300,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int val; u32 sscr0 = ssp_read_reg(ssp, SSCR0) & - ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC); + ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); dev_dbg(&ssp->pdev->dev, "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n", @@ -328,7 +328,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, case PXA_SSP_CLK_AUDIO: priv->sysclk = 0; ssp_set_scr(&priv->dev, 1); - sscr0 |= SSCR0_ADC; + sscr0 |= SSCR0_ACS; break; default: return -ENODEV; @@ -524,7 +524,7 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* reset port settings */ sscr0 = ssp_read_reg(ssp, SSCR0) & - (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC); + (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7); sspsp = 0; -- cgit v1.2.3 From 7ebc8d56f407184a457dd5fc739cf39e423a25aa Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 2 Jan 2009 19:38:42 +0800 Subject: [ARM] pxa: move DMA registers definitions into 1. Driver code where pxa_request_dma() is called will most likely reference DMA registers as well, and it is really unnecessary to include pxa-regs.h just for this. Move the definitions into and make relevant drivers include it instead of . 2. Introduce DMAC_REGS_VIRT as the virtual address base for these DMA registers. This allows later processors to re-use the same IP while registers may start at different I/O address. Signed-off-by: Eric Miao --- sound/soc/pxa/pxa-ssp.c | 2 +- sound/soc/pxa/pxa2xx-ac97.c | 2 +- sound/soc/pxa/pxa2xx-i2s.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 73cb6b4c2f2d..1dfdf66fb1f3 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include #include diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 812c2b4d3e07..a4a655f7e304 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -20,8 +20,8 @@ #include #include -#include #include +#include #include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 517991fb1099..223de890259e 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include -- cgit v1.2.3 From 5742964e916269e01a3467d2bff2601180b7da3d Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Mon, 19 Jan 2009 15:28:07 +0800 Subject: [ARM] pxa: remove unnecessary #include of pxa-regs.h and hardware.h pxa-regs.h and hardware.h are not intended for use directly in driver code, remove those unnecessary references. Signed-off-by: Eric Miao --- sound/soc/pxa/corgi.c | 2 -- sound/soc/pxa/e800_wm9712.c | 2 -- sound/soc/pxa/em-x270.c | 2 -- sound/soc/pxa/poodle.c | 2 -- sound/soc/pxa/spitz.c | 2 -- sound/soc/pxa/tosa.c | 2 -- 6 files changed, 12 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 1ba25a559524..ec930667feff 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -25,8 +25,6 @@ #include #include -#include -#include #include #include diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 2e3386dfa0f0..ac294c797b7d 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -21,8 +21,6 @@ #include #include -#include -#include #include #include "../codecs/wm9712.h" diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c index fe4a729ea648..949be9c2a01b 100644 --- a/sound/soc/pxa/em-x270.c +++ b/sound/soc/pxa/em-x270.c @@ -29,8 +29,6 @@ #include #include -#include -#include #include #include "../codecs/wm9712.h" diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 6e9827189fff..cad2c4c0ac95 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -26,8 +26,6 @@ #include #include -#include -#include #include #include diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index a3b9e6bdf979..de8778fa8729 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -26,8 +26,6 @@ #include #include -#include -#include #include #include "../codecs/wm8750.h" #include "pxa2xx-pcm.h" diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index c77194f74c9b..050223d04e54 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -30,8 +30,6 @@ #include #include -#include -#include #include #include "../codecs/wm9712.h" -- cgit v1.2.3 From 6b849bcff0004aa5dd216b4d3eb56f51c9df8a72 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 9 Mar 2009 18:18:33 +0000 Subject: ASoC: Convert PXA AC97 driver to probe with the platform device This will break any boards that don't register the AC97 controller device due to using ASoC. Signed-off-by: Mark Brown --- sound/soc/pxa/pxa2xx-ac97.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 812c2b4d3e07..49a2810ca58c 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -106,13 +106,13 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai) static int pxa2xx_ac97_probe(struct platform_device *pdev, struct snd_soc_dai *dai) { - return pxa2xx_ac97_hw_probe(pdev); + return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev)); } static void pxa2xx_ac97_remove(struct platform_device *pdev, struct snd_soc_dai *dai) { - pxa2xx_ac97_hw_remove(pdev); + pxa2xx_ac97_hw_remove(to_platform_device(dai->dev)); } static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, @@ -229,15 +229,45 @@ struct snd_soc_dai pxa_ac97_dai[] = { EXPORT_SYMBOL_GPL(pxa_ac97_dai); EXPORT_SYMBOL_GPL(soc_ac97_ops); -static int __init pxa_ac97_init(void) +static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev) { + int i; + + for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) + pxa_ac97_dai[i].dev = &pdev->dev; + + /* Punt most of the init to the SoC probe; we may need the machine + * driver to do interesting things with the clocking to get us up + * and running. + */ return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); } + +static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); + + return 0; +} + +static struct platform_driver pxa2xx_ac97_driver = { + .probe = pxa2xx_ac97_dev_probe, + .remove = __devexit_p(pxa2xx_ac97_dev_remove), + .driver = { + .name = "pxa2xx-ac97", + .owner = THIS_MODULE, + }, +}; + +static int __init pxa_ac97_init(void) +{ + return platform_driver_register(&pxa2xx_ac97_driver); +} module_init(pxa_ac97_init); static void __exit pxa_ac97_exit(void) { - snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); + platform_driver_unregister(&pxa2xx_ac97_driver); } module_exit(pxa_ac97_exit); -- cgit v1.2.3 From cbf1146d5ee113152c5cdeb54ff9d4b2f0c91736 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 10 Mar 2009 16:41:00 +0100 Subject: ASoC: don't touch pxa-ssp registers when stream is running In pxa_ssp_set_dai_fmt(), check whether there is anything to do at all. If there would be but the SSP port is in use already, bail out. Signed-off-by: Daniel Mack Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 7fc13f03d1d2..52d97c4b82b1 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -522,6 +522,17 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, u32 sscr1; u32 sspsp; + /* check if we need to change anything at all */ + if (priv->dai_fmt == fmt) + return 0; + + /* we can only change the settings if the port is not in use */ + if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) { + dev_err(&ssp->pdev->dev, + "can't change hardware dai format: stream is in use"); + return -EINVAL; + } + /* reset port settings */ sscr0 = ssp_read_reg(ssp, SSCR0) & (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); -- cgit v1.2.3 From eb5f6d753e337834c7ceb07824ee472e43d9a7a2 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 12 Mar 2009 11:07:54 +0100 Subject: ASoC: Replace remaining uses of snd_soc_cnew with snd_soc_add_controls. The drivers are basically duplicating the same code over and over. As snd_soc_cnew is going to be made static some time after the next merge window, we might as well convert them now. Signed-off-by: Philipp Zabel Signed-off-by: Mark Brown --- sound/soc/pxa/corgi.c | 12 +++++------- sound/soc/pxa/palm27x.c | 13 +++++-------- sound/soc/pxa/poodle.c | 12 +++++------- sound/soc/pxa/spitz.c | 12 +++++------- sound/soc/pxa/tosa.c | 12 +++++------- 5 files changed, 25 insertions(+), 36 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 146973ae0974..02263e5d8f03 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -276,18 +276,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, diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c index 29958cd9daec..48a73f64500b 100644 --- a/sound/soc/pxa/palm27x.c +++ b/sound/soc/pxa/palm27x.c @@ -146,19 +146,16 @@ static const struct snd_kcontrol_new palm27x_controls[] = { static int palm27x_ac97_init(struct snd_soc_codec *codec) { - int i, err; + int err; snd_soc_dapm_nc_pin(codec, "OUT3"); snd_soc_dapm_nc_pin(codec, "MONOOUT"); /* add palm27x specific controls */ - for (i = 0; i < ARRAY_SIZE(palm27x_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&palm27x_controls[i], - codec, NULL)); - if (err < 0) - return err; - } + err = snd_soc_add_controls(codec, palm27x_controls, + ARRAY_SIZE(palm27x_controls)); + if (err < 0) + return err; /* add palm27x specific widgets */ snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets, diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index fb17a0a5a093..ef7c6c8dc8f1 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -241,19 +241,17 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = { */ static int poodle_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"); snd_soc_dapm_enable_pin(codec, "MICIN"); /* Add poodle specific controls */ - for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8731_poodle_controls[i], codec, NULL)); - if (err < 0) - return err; - } + err = snd_soc_add_controls(codec, wm8731_poodle_controls, + ARRAY_SIZE(wm8731_poodle_controls)); + if (err < 0) + return err; /* Add poodle specific widgets */ snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets, diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 1aafd8c645a1..6ca9f53080c6 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -278,7 +278,7 @@ static const struct snd_kcontrol_new wm8750_spitz_controls[] = { */ static int spitz_wm8750_init(struct snd_soc_codec *codec) { - int i, err; + int err; /* NC codec pins */ snd_soc_dapm_nc_pin(codec, "RINPUT1"); @@ -290,12 +290,10 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec) snd_soc_dapm_nc_pin(codec, "MONO1"); /* Add spitz specific controls */ - for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8750_spitz_controls[i], codec, NULL)); - if (err < 0) - return err; - } + err = snd_soc_add_controls(codec, wm8750_spitz_controls, + ARRAY_SIZE(wm8750_spitz_controls)); + if (err < 0) + return err; /* Add spitz specific widgets */ snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets, diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 09b5bada03b9..fc781374b1bf 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -188,18 +188,16 @@ static const struct snd_kcontrol_new tosa_controls[] = { static int tosa_ac97_init(struct snd_soc_codec *codec) { - int i, err; + int err; snd_soc_dapm_nc_pin(codec, "OUT3"); snd_soc_dapm_nc_pin(codec, "MONOOUT"); /* add tosa specific controls */ - for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&tosa_controls[i],codec, NULL)); - if (err < 0) - return err; - } + err = snd_soc_add_controls(codec, tosa_controls, + ARRAY_SIZE(tosa_controls)); + if (err < 0) + return err; /* add tosa specific widgets */ snd_soc_dapm_new_controls(codec, tosa_dapm_widgets, -- cgit v1.2.3 From 72d7466468b471f99cefae3c5f4a414bbbaa0bdd Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 12 Mar 2009 11:27:49 +0100 Subject: ASoC: switch PXA SSP driver from network mode to PSP This switches the pxa ssp port usage from network mode to PSP mode. Removed some comments and checks for configured TDM channels. A special case is added to support configuration where BCLK = 64fs. We need to do some black magic in this case which doesn't look nice but there is unfortunately no other option than that. Diagnosed-by: Tim Ruetz Signed-off-by: Daniel Mack Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index d3fa6357a9fd..4dd0d7c57220 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -558,18 +558,17 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - sscr0 |= SSCR0_MOD | SSCR0_PSP; + sscr0 |= SSCR0_PSP; sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: - sspsp |= SSPSP_FSRT; break; case SND_SOC_DAIFMT_NB_IF: - sspsp |= SSPSP_SFRMP | SSPSP_FSRT; + sspsp |= SSPSP_SFRMP; break; case SND_SOC_DAIFMT_IB_IF: - sspsp |= SSPSP_SFRMP; + sspsp |= SSPSP_SFRMP | SSPSP_SCMODE(3); break; default: return -EINVAL; @@ -655,33 +654,56 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, sscr0 |= SSCR0_FPCKE; #endif sscr0 |= SSCR0_DataSize(16); - /* use network mode (2 slots) for 16 bit stereo */ break; case SNDRV_PCM_FORMAT_S24_LE: sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8)); - /* we must be in network mode (2 slots) for 24 bit stereo */ break; case SNDRV_PCM_FORMAT_S32_LE: sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16)); - /* we must be in network mode (2 slots) for 32 bit stereo */ break; } ssp_write_reg(ssp, SSCR0, sscr0); switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - /* Cleared when the DAI format is set */ - sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width); + sspsp = ssp_read_reg(ssp, SSPSP); + + if (((sscr0 & SSCR0_SCR) == SSCR0_SerClkDiv(4)) && + (width == 16)) { + /* This is a special case where the bitclk is 64fs + * and we're not dealing with 2*32 bits of audio + * samples. + * + * The SSP values used for that are all found out by + * trying and failing a lot; some of the registers + * needed for that mode are only available on PXA3xx. + */ + +#ifdef CONFIG_PXA3xx + if (!cpu_is_pxa3xx()) + return -EINVAL; + + sspsp |= SSPSP_SFRMWDTH(width * 2); + sspsp |= SSPSP_SFRMDLY(width * 4); + sspsp |= SSPSP_EDMYSTOP(3); + sspsp |= SSPSP_DMYSTOP(3); + sspsp |= SSPSP_DMYSTRT(1); +#else + return -EINVAL; +#endif + } else + sspsp |= SSPSP_SFRMWDTH(width); + ssp_write_reg(ssp, SSPSP, sspsp); break; default: break; } - /* We always use a network mode so we always require TDM slots + /* When we use a network mode, we always require TDM slots * - complain loudly and fail if they've not been set up yet. */ - if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) { + if ((sscr0 & SSCR0_MOD) && !(ssp_read_reg(ssp, SSTSA) & 0xf)) { dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n"); return -EINVAL; } -- cgit v1.2.3 From 0ce36c5f7f87632f26c8fbefe68b5116eda152d2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 13 Mar 2009 14:26:08 +0000 Subject: ASoC: Fix non-networked I2S mode for PXA SSP Two issues are fixed here: - I2S transmits the left frame with the clock low but I don't seem to get LRCLK out without SFRMDLY being set so invert SFRMP and set a delay. - I2S has a clock cycle prior to the first data byte in each channel so we need to delay the data by one cycle. Tested-by: Daniel Mack Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 4dd0d7c57220..b0bf40973d5b 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -1,4 +1,3 @@ -#define DEBUG /* * pxa-ssp.c -- ALSA Soc Audio Layer * @@ -561,14 +560,15 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, sscr0 |= SSCR0_PSP; sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; + /* See hw_params() */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: + sspsp |= SSPSP_SFRMP; break; case SND_SOC_DAIFMT_NB_IF: - sspsp |= SSPSP_SFRMP; break; case SND_SOC_DAIFMT_IB_IF: - sspsp |= SSPSP_SFRMP | SSPSP_SCMODE(3); + sspsp |= SSPSP_SCMODE(3); break; default: return -EINVAL; @@ -691,8 +691,17 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, #else return -EINVAL; #endif - } else - sspsp |= SSPSP_SFRMWDTH(width); + } else { + /* The frame width is the width the LRCLK is + * asserted for; the delay is expressed in + * half cycle units. We need the extra cycle + * because the data starts clocking out one BCLK + * after LRCLK changes polarity. + */ + sspsp |= SSPSP_SFRMWDTH(width + 1); + sspsp |= SSPSP_SFRMDLY((width + 1) * 2); + sspsp |= SSPSP_DMYSTRT(1); + } ssp_write_reg(ssp, SSPSP, sspsp); break; -- cgit v1.2.3 From 85fab7802a4bc00cc752f430e22a0d9fc41fe199 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 13 Mar 2009 14:27:08 +0000 Subject: ASoC: Fix Zylonite for non-networked SSP mode This also simplifies the code a bit. Signed-off-by: Mark Brown --- sound/soc/pxa/zylonite.c | 55 ++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 30 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index 9f6116edbb84..9a386b4c4ed1 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -96,42 +96,35 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; unsigned int pll_out = 0; - unsigned int acds = 0; unsigned int wm9713_div = 0; int ret = 0; - - switch (params_rate(params)) { + int rate = params_rate(params); + int width = snd_pcm_format_physical_width(params_format(params)); + + /* Only support ratios that we can generate neatly from the AC97 + * based master clock - in particular, this excludes 44.1kHz. + * In most applications the voice DAC will be used for telephony + * data so multiples of 8kHz will be the common case. + */ + switch (rate) { case 8000: wm9713_div = 12; - pll_out = 2048000; break; case 16000: wm9713_div = 6; - pll_out = 4096000; break; case 48000: - default: wm9713_div = 2; - pll_out = 12288000; - acds = 1; break; + default: + /* Don't support OSS emulation */ + return -EINVAL; } - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - if (ret < 0) - return ret; - - ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - if (ret < 0) - return ret; + /* Add 1 to the width for the leading clock cycle */ + pll_out = rate * (width + 1) * 8; - /* Use network mode for stereo, one slot per channel. */ - if (params_channels(params) > 1) - ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 2); - else - ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1); + ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1); if (ret < 0) return ret; @@ -139,14 +132,6 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); - if (ret < 0) - return ret; - - ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1); - if (ret < 0) - return ret; - if (clk_pout) ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV, WM9713_PCMDIV(wm9713_div)); @@ -156,6 +141,16 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + return ret; + return 0; } -- cgit v1.2.3 From 852fd9e50f62b4ea7afe26eee0710464de4801b8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 16 Mar 2009 14:13:12 +0000 Subject: ASoC: Each PXA AC97 DAI needs a separate ops Signed-off-by: Mark Brown --- sound/soc/pxa/pxa2xx-ac97.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'sound/soc/pxa') diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index cf809049272a..01c21c6cdbbc 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -164,10 +164,18 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000) -static struct snd_soc_dai_ops pxa_ac97_dai_ops = { +static struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops = { .hw_params = pxa2xx_ac97_hw_params, }; +static struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = { + .hw_params = pxa2xx_ac97_hw_aux_params, +}; + +static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = { + .hw_params = pxa2xx_ac97_hw_mic_params, +}; + /* * There is only 1 physical AC97 interface for pxa2xx, but it * has extra fifo's that can be used for aux DACs and ADCs. @@ -193,7 +201,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 2, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &pxa_ac97_dai_ops, + .ops = &pxa_ac97_hifi_dai_ops, }, { .name = "pxa2xx-ac97-aux", @@ -211,7 +219,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 1, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &pxa_ac97_dai_ops, + .ops = &pxa_ac97_aux_dai_ops, }, { .name = "pxa2xx-ac97-mic", @@ -223,7 +231,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 1, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &pxa_ac97_dai_ops, + .ops = &pxa_ac97_mic_dai_ops, }, }; -- cgit v1.2.3