From 927a77476ed37080793f0e9d3211359f2d480d4d Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 31 Dec 2012 11:51:42 +0100 Subject: ASoC: twl4030: Correct the support for Voice port In order to be able to use the Voice port of twl4030 three bits need to be handled in VOICE_IF register: VIF_EN: to enable the voice port (needed for both playback and capture) VIF_DIN_EN: Need to be enabled for playback only (input to the codec) VIF_DOUT_EN: Need to be enabled for capture only (output from codec) Use DAPM_SUPPLY for the VIF_EN bit and add DAPM_AIF_IO/OUT widget to handle the playback/capture bit. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 63b280b0603..79b2f86f61c 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -1306,6 +1306,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_DAC("DAC Left2", NULL, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC("DAC Voice", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("VAIFIN", "Voice Playback", 0, + TWL4030_REG_VOICE_IF, 6, 0), + /* Analog bypasses */ SND_SOC_DAPM_SWITCH("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, &twl4030_dapm_abypassr1_control), @@ -1438,6 +1441,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_ADC("ADC Virtual Left2", NULL, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_ADC("ADC Virtual Right2", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("VAIFOUT", "Voice Capture", 0, + TWL4030_REG_VOICE_IF, 5, 0), + /* Analog/Digital mic path selection. TX1 Left/Right: either analog Left/Right or Digimic0 TX2 Left/Right: either analog Left/Right or Digimic1 */ @@ -1477,6 +1483,7 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_MICBIAS("Mic Bias 2", TWL4030_REG_MICBIAS_CTL, 1, 0), SND_SOC_DAPM_MICBIAS("Headset Mic Bias", TWL4030_REG_MICBIAS_CTL, 2, 0), + SND_SOC_DAPM_SUPPLY("VIF Enable", TWL4030_REG_VOICE_IF, 0, 0, NULL, 0), }; static const struct snd_soc_dapm_route intercon[] = { @@ -1485,17 +1492,16 @@ static const struct snd_soc_dapm_route intercon[] = { {"DAC Left1", NULL, "HiFi Playback"}, {"DAC Right2", NULL, "HiFi Playback"}, {"DAC Left2", NULL, "HiFi Playback"}, - {"DAC Voice", NULL, "Voice Playback"}, + {"DAC Voice", NULL, "VAIFIN"}, /* ADC -> Stream mapping */ {"HiFi Capture", NULL, "ADC Virtual Left1"}, {"HiFi Capture", NULL, "ADC Virtual Right1"}, {"HiFi Capture", NULL, "ADC Virtual Left2"}, {"HiFi Capture", NULL, "ADC Virtual Right2"}, - {"Voice Capture", NULL, "ADC Virtual Left1"}, - {"Voice Capture", NULL, "ADC Virtual Right1"}, - {"Voice Capture", NULL, "ADC Virtual Left2"}, - {"Voice Capture", NULL, "ADC Virtual Right2"}, + {"VAIFOUT", NULL, "ADC Virtual Left2"}, + {"VAIFOUT", NULL, "ADC Virtual Right2"}, + {"VAIFOUT", NULL, "VIF Enable"}, {"Digital L1 Playback Mixer", NULL, "DAC Left1"}, {"Digital R1 Playback Mixer", NULL, "DAC Right1"}, @@ -1510,6 +1516,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"DAC Right1", NULL, "AIF Enable"}, {"DAC Left2", NULL, "AIF Enable"}, {"DAC Right1", NULL, "AIF Enable"}, + {"DAC Voice", NULL, "VIF Enable"}, {"Digital R2 Playback Mixer", NULL, "AIF Enable"}, {"Digital L2 Playback Mixer", NULL, "AIF Enable"}, -- cgit v1.2.3-70-g09d2 From 01df26edaf4d15e1af3300f8a52b11d3f06c5096 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 31 Dec 2012 11:51:43 +0100 Subject: ASoC: zoom2: No need to configure the Voice port anymore The codec driver takes care of these bits. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/zoom2.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'sound') diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index 771bff27ac3..5845d487d27 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c @@ -110,19 +110,6 @@ static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd) return 0; } -static int zoom2_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - unsigned short reg; - - /* Enable voice interface */ - reg = codec->driver->read(codec, TWL4030_REG_VOICE_IF); - reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; - codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg); - - return 0; -} - /* Digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link zoom2_dai[] = { { @@ -146,7 +133,6 @@ static struct snd_soc_dai_link zoom2_dai[] = { .codec_name = "twl4030-codec", .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM, - .init = zoom2_twl4030_voice_init, .ops = &zoom2_ops, }, }; -- cgit v1.2.3-70-g09d2 From 57296cc28cf8aab2e5e63d8f9964718ae29cc229 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 31 Dec 2012 11:51:44 +0100 Subject: ASoC: sdp3430: No need to configure the Voice port anymore The codec driver takes care of these bits. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/sdp3430.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'sound') diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c index b462a2c9385..86e77e9d24c 100644 --- a/sound/soc/omap/sdp3430.c +++ b/sound/soc/omap/sdp3430.c @@ -167,20 +167,6 @@ static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd) return ret; } -static int sdp3430_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - unsigned short reg; - - /* Enable voice interface */ - reg = codec->driver->read(codec, TWL4030_REG_VOICE_IF); - reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; - codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg); - - return 0; -} - - /* Digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link sdp3430_dai[] = { { @@ -204,7 +190,6 @@ static struct snd_soc_dai_link sdp3430_dai[] = { .codec_name = "twl4030-codec", .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM, - .init = sdp3430_twl4030_voice_init, .ops = &sdp3430_ops, }, }; -- cgit v1.2.3-70-g09d2 From e04d6e55fe02351b1ac338d9e8082fcc434610ce Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 31 Dec 2012 11:51:45 +0100 Subject: ASoC: twl4030: Convert MICBIAS to SUPPLY widget In order to avoid breakage update the machine drivers at the same time using twl4030: omap3pandora, sdp3430 and zoom2 Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 10 +++++++--- sound/soc/omap/omap3pandora.c | 8 ++++---- sound/soc/omap/sdp3430.c | 14 +++++++------- sound/soc/omap/zoom2.c | 14 +++++++------- 4 files changed, 25 insertions(+), 21 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 79b2f86f61c..5dd7c81623a 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -1479,9 +1479,13 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("micbias2 select", TWL4030_REG_MICBIAS_CTL, 6, 0, NULL, 0), - SND_SOC_DAPM_MICBIAS("Mic Bias 1", TWL4030_REG_MICBIAS_CTL, 0, 0), - SND_SOC_DAPM_MICBIAS("Mic Bias 2", TWL4030_REG_MICBIAS_CTL, 1, 0), - SND_SOC_DAPM_MICBIAS("Headset Mic Bias", TWL4030_REG_MICBIAS_CTL, 2, 0), + /* Microphone bias */ + SND_SOC_DAPM_SUPPLY("Mic Bias 1", + TWL4030_REG_MICBIAS_CTL, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Mic Bias 2", + TWL4030_REG_MICBIAS_CTL, 1, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Headset Mic Bias", + TWL4030_REG_MICBIAS_CTL, 2, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("VIF Enable", TWL4030_REG_VOICE_IF, 0, 0, NULL, 0), }; diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index 43d950a79ff..805512f2555 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c @@ -144,11 +144,11 @@ static const struct snd_soc_dapm_route omap3pandora_in_map[] = { {"AUXL", NULL, "Line In"}, {"AUXR", NULL, "Line In"}, - {"MAINMIC", NULL, "Mic Bias 1"}, - {"Mic Bias 1", NULL, "Mic (internal)"}, + {"MAINMIC", NULL, "Mic (internal)"}, + {"Mic (internal)", NULL, "Mic Bias 1"}, - {"SUBMIC", NULL, "Mic Bias 2"}, - {"Mic Bias 2", NULL, "Mic (external)"}, + {"SUBMIC", NULL, "Mic (external)"}, + {"Mic (external)", NULL, "Mic Bias 2"}, }; static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd) diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c index 86e77e9d24c..f2e26512d2a 100644 --- a/sound/soc/omap/sdp3430.c +++ b/sound/soc/omap/sdp3430.c @@ -104,19 +104,19 @@ static const struct snd_soc_dapm_widget sdp3430_twl4030_dapm_widgets[] = { }; static const struct snd_soc_dapm_route audio_map[] = { - /* External Mics: MAINMIC, SUBMIC with bias*/ - {"MAINMIC", NULL, "Mic Bias 1"}, - {"SUBMIC", NULL, "Mic Bias 2"}, - {"Mic Bias 1", NULL, "Ext Mic"}, - {"Mic Bias 2", NULL, "Ext Mic"}, + /* External Mics: MAINMIC, SUBMIC with bias */ + {"MAINMIC", NULL, "Ext Mic"}, + {"SUBMIC", NULL, "Ext Mic"}, + {"Ext Mic", NULL, "Mic Bias 1"}, + {"Ext Mic", NULL, "Mic Bias 2"}, /* External Speakers: HFL, HFR */ {"Ext Spk", NULL, "HFL"}, {"Ext Spk", NULL, "HFR"}, /* Headset Mic: HSMIC with bias */ - {"HSMIC", NULL, "Headset Mic Bias"}, - {"Headset Mic Bias", NULL, "Headset Mic"}, + {"HSMIC", NULL, "Headset Mic"}, + {"Headset Mic", NULL, "Headset Mic Bias"}, /* Headset Stereophone (Headphone): HSOL, HSOR */ {"Headset Stereophone", NULL, "HSOL"}, diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index 5845d487d27..62a6b02d9b3 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c @@ -69,11 +69,11 @@ static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = { }; static const struct snd_soc_dapm_route audio_map[] = { - /* External Mics: MAINMIC, SUBMIC with bias*/ - {"MAINMIC", NULL, "Mic Bias 1"}, - {"SUBMIC", NULL, "Mic Bias 2"}, - {"Mic Bias 1", NULL, "Ext Mic"}, - {"Mic Bias 2", NULL, "Ext Mic"}, + /* External Mics: MAINMIC, SUBMIC with bias */ + {"MAINMIC", NULL, "Ext Mic"}, + {"SUBMIC", NULL, "Ext Mic"}, + {"Ext Mic", NULL, "Mic Bias 1"}, + {"Ext Mic", NULL, "Mic Bias 2"}, /* External Speakers: HFL, HFR */ {"Ext Spk", NULL, "HFL"}, @@ -84,8 +84,8 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Headset Stereophone", NULL, "HSOR"}, /* Headset Mic: HSMIC with bias */ - {"HSMIC", NULL, "Headset Mic Bias"}, - {"Headset Mic Bias", NULL, "Headset Mic"}, + {"HSMIC", NULL, "Headset Mic"}, + {"Headset Mic", NULL, "Headset Mic Bias"}, /* Aux In: AUXL, AUXR */ {"Aux In", NULL, "AUXL"}, -- cgit v1.2.3-70-g09d2 From 5712ded9cf0b6981825af3c86e0059be93e5e17c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 31 Dec 2012 11:51:46 +0100 Subject: ASoC: twl4030: Configure extmute pinmux when the dedicated pin is in use When HS extmute is enabled without custom GPIO we should configure the mux to allow the pin to be used as extmute signal. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 5dd7c81623a..7bfabe5750e 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -41,6 +41,11 @@ /* Register descriptions are here */ #include +/* TWL4030 PMBR1 Register */ +#define TWL4030_PMBR1_REG 0x0D +/* TWL4030 PMBR1 Register GPIO6 mux bits */ +#define TWL4030_GPIO6_PWM0_MUTE(value) ((value & 0x03) << 2) + /* Shadow register used by the audio driver */ #define TWL4030_REG_SW_SHADOW 0x4A #define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1) @@ -348,19 +353,32 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) pdata = twl4030_get_pdata(codec); - if (pdata && pdata->hs_extmute && - gpio_is_valid(pdata->hs_extmute_gpio)) { - int ret; - - if (!pdata->hs_extmute_gpio) - dev_warn(codec->dev, - "Extmute GPIO is 0 is this correct?\n"); - - ret = gpio_request_one(pdata->hs_extmute_gpio, - GPIOF_OUT_INIT_LOW, "hs_extmute"); - if (ret) { - dev_err(codec->dev, "Failed to get hs_extmute GPIO\n"); - pdata->hs_extmute_gpio = -1; + if (pdata && pdata->hs_extmute) { + if (gpio_is_valid(pdata->hs_extmute_gpio)) { + int ret; + + if (!pdata->hs_extmute_gpio) + dev_warn(codec->dev, + "Extmute GPIO is 0 is this correct?\n"); + + ret = gpio_request_one(pdata->hs_extmute_gpio, + GPIOF_OUT_INIT_LOW, + "hs_extmute"); + if (ret) { + dev_err(codec->dev, + "Failed to get hs_extmute GPIO\n"); + pdata->hs_extmute_gpio = -1; + } + } else { + u8 pin_mux; + + /* Set TWL4030 GPIO6 as EXTMUTE signal */ + twl_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux, + TWL4030_PMBR1_REG); + pin_mux &= ~TWL4030_GPIO6_PWM0_MUTE(0x03); + pin_mux |= TWL4030_GPIO6_PWM0_MUTE(0x02); + twl_i2c_write_u8(TWL4030_MODULE_INTBR, pin_mux, + TWL4030_PMBR1_REG); } } -- cgit v1.2.3-70-g09d2 From fff3dd40132d6106d4d2a61e70e782f82394fd17 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 31 Dec 2012 11:51:47 +0100 Subject: ASoC: sdp3430: No need to configure pin mux for extmute The codec driver takes care of this. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/sdp3430.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'sound') diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c index f2e26512d2a..216cbdd569e 100644 --- a/sound/soc/omap/sdp3430.c +++ b/sound/soc/omap/sdp3430.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -32,20 +31,12 @@ #include #include -#include -/* Register descriptions for twl4030 codec part */ -#include #include #include "omap-mcbsp.h" #include "omap-pcm.h" -/* TWL4030 PMBR1 Register */ -#define TWL4030_INTBR_PMBR1 0x0D -/* TWL4030 PMBR1 Register GPIO6 mux bit */ -#define TWL4030_GPIO6_PWM0_MUTE(value) (value << 2) - static struct snd_soc_card snd_soc_sdp3430; static int sdp3430_hw_params(struct snd_pcm_substream *substream, @@ -212,7 +203,6 @@ static struct platform_device *sdp3430_snd_device; static int __init sdp3430_soc_init(void) { int ret; - u8 pin_mux; if (!machine_is_omap_3430sdp()) return -ENODEV; @@ -226,14 +216,6 @@ static int __init sdp3430_soc_init(void) platform_set_drvdata(sdp3430_snd_device, &snd_soc_sdp3430); - /* Set TWL4030 GPIO6 as EXTMUTE signal */ - twl_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux, - TWL4030_INTBR_PMBR1); - pin_mux &= ~TWL4030_GPIO6_PWM0_MUTE(0x03); - pin_mux |= TWL4030_GPIO6_PWM0_MUTE(0x02); - twl_i2c_write_u8(TWL4030_MODULE_INTBR, pin_mux, - TWL4030_INTBR_PMBR1); - ret = platform_device_add(sdp3430_snd_device); if (ret) goto err1; -- cgit v1.2.3-70-g09d2 From bd0b286e838ef1ca19bbe1cb55f0ec7e0135de1f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 31 Dec 2012 11:51:48 +0100 Subject: ASoC: omap-twl4030: Add support for routing, voice port and jack detect Update the common machine driver to support more boards including Zoom2 and SDP3430. - Support for voice port of twl4030 - HS jack plug detection support - The audio routing can be fine tuned via pdata or via provided routing table from DT. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/omap-twl4030.txt | 46 +++++ sound/soc/omap/Kconfig | 2 + sound/soc/omap/omap-twl4030.c | 204 ++++++++++++++++++++- 3 files changed, 250 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/Documentation/devicetree/bindings/sound/omap-twl4030.txt b/Documentation/devicetree/bindings/sound/omap-twl4030.txt index 6fae51c7f76..1ab6bc8404d 100644 --- a/Documentation/devicetree/bindings/sound/omap-twl4030.txt +++ b/Documentation/devicetree/bindings/sound/omap-twl4030.txt @@ -6,6 +6,52 @@ Required properties: - ti,mcbsp: phandle for the McBSP node - ti,codec: phandle for the twl4030 audio node +Optional properties: +- ti,mcbsp-voice: phandle for the McBSP node connected to the voice port of twl +- ti, jack-det-gpio: Jack detect GPIO +- ti,audio-routing: List of connections between audio components. + Each entry is a pair of strings, the first being the connection's sink, + the second being the connection's source. + If the routing is not provided all possible connection will be available + +Available audio endpoints for the audio-routing table: + +Board connectors: + * Headset Stereophone + * Earpiece Spk + * Handsfree Spk + * Ext Spk + * Main Mic + * Sub Mic + * Headset Mic + * Carkit Mic + * Digital0 Mic + * Digital1 Mic + * Line In + +twl4030 pins: + * HSOL + * HSOR + * EARPIECE + * HFL + * HFR + * PREDRIVEL + * PREDRIVER + * CARKITL + * CARKITR + * MAINMIC + * SUBMIC + * HSMIC + * DIGIMIC0 + * DIGIMIC1 + * CARKITMIC + * AUXL + * AUXR + + * Headset Mic Bias + * Mic Bias 1 /* Used for Main Mic or Digimic0 */ + * Mic Bias 2 /* Used for Sub Mic or Digimic1 */ + Example: sound { diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 7048137f9a3..e8d2a2f983b 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -91,6 +91,8 @@ config SND_OMAP_SOC_OMAP_TWL4030 - Gumstix Overo or CompuLab CM-T35/CM-T3730 - IGEP v2 - OMAP3EVM + - SDP3430 + - Zoom2 config SND_OMAP_SOC_OMAP_ABE_TWL6040 tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c index 4541d28b531..fd98509d0f4 100644 --- a/sound/soc/omap/omap-twl4030.c +++ b/sound/soc/omap/omap-twl4030.c @@ -11,6 +11,8 @@ * omap3evm (Author: Anuj Aggarwal ) * overo (Author: Steve Sakoman ) * igep0020 (Author: Enric Balletbo i Serra ) + * zoom2 (Author: Misael Lopez Cruz ) + * sdp3430 (Author: Misael Lopez Cruz ) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -32,14 +34,22 @@ #include #include #include +#include +#include #include #include #include +#include #include "omap-mcbsp.h" #include "omap-pcm.h" +struct omap_twl4030 { + int jack_detect; /* board can detect jack events */ + struct snd_soc_jack hs_jack; +}; + static int omap_twl4030_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -87,17 +97,164 @@ static struct snd_soc_ops omap_twl4030_ops = { .hw_params = omap_twl4030_hw_params, }; +static const struct snd_soc_dapm_widget dapm_widgets[] = { + SND_SOC_DAPM_SPK("Earpiece Spk", NULL), + SND_SOC_DAPM_SPK("Handsfree Spk", NULL), + SND_SOC_DAPM_HP("Headset Stereophone", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_SPK("Carkit Spk", NULL), + + SND_SOC_DAPM_MIC("Main Mic", NULL), + SND_SOC_DAPM_MIC("Sub Mic", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Carkit Mic", NULL), + SND_SOC_DAPM_MIC("Digital0 Mic", NULL), + SND_SOC_DAPM_MIC("Digital1 Mic", NULL), + SND_SOC_DAPM_LINE("Line In", NULL), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + /* Headset Stereophone: HSOL, HSOR */ + {"Headset Stereophone", NULL, "HSOL"}, + {"Headset Stereophone", NULL, "HSOR"}, + /* External Speakers: HFL, HFR */ + {"Handsfree Spk", NULL, "HFL"}, + {"Handsfree Spk", NULL, "HFR"}, + /* External Speakers: PredrivL, PredrivR */ + {"Ext Spk", NULL, "PREDRIVEL"}, + {"Ext Spk", NULL, "PREDRIVER"}, + /* Carkit speakers: CARKITL, CARKITR */ + {"Carkit Spk", NULL, "CARKITL"}, + {"Carkit Spk", NULL, "CARKITR"}, + /* Earpiece */ + {"Earpiece Spk", NULL, "EARPIECE"}, + + /* External Mics: MAINMIC, SUBMIC with bias */ + {"MAINMIC", NULL, "Main Mic"}, + {"Main Mic", NULL, "Mic Bias 1"}, + {"SUBMIC", NULL, "Sub Mic"}, + {"Sub Mic", NULL, "Mic Bias 2"}, + /* Headset Mic: HSMIC with bias */ + {"HSMIC", NULL, "Headset Mic"}, + {"Headset Mic", NULL, "Headset Mic Bias"}, + /* Digital Mics: DIGIMIC0, DIGIMIC1 with bias */ + {"DIGIMIC0", NULL, "Digital0 Mic"}, + {"Digital0 Mic", NULL, "Mic Bias 1"}, + {"DIGIMIC1", NULL, "Digital1 Mic"}, + {"Digital1 Mic", NULL, "Mic Bias 2"}, + /* Carkit In: CARKITMIC */ + {"CARKITMIC", NULL, "Carkit Mic"}, + /* Aux In: AUXL, AUXR */ + {"AUXL", NULL, "Line In"}, + {"AUXR", NULL, "Line In"}, +}; + +/* Headset jack detection DAPM pins */ +static struct snd_soc_jack_pin hs_jack_pins[] = { + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, + { + .pin = "Headset Stereophone", + .mask = SND_JACK_HEADPHONE, + }, +}; + +/* Headset jack detection gpios */ +static struct snd_soc_jack_gpio hs_jack_gpios[] = { + { + .name = "hsdet-gpio", + .report = SND_JACK_HEADSET, + .debounce_time = 200, + }, +}; + +static inline void twl4030_disconnect_pin(struct snd_soc_dapm_context *dapm, + int connected, char *pin) +{ + if (!connected) + snd_soc_dapm_disable_pin(dapm, pin); +} + +static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_card *card = codec->card; + struct snd_soc_dapm_context *dapm = &codec->dapm; + struct omap_tw4030_pdata *pdata = dev_get_platdata(card->dev); + struct omap_twl4030 *priv = snd_soc_card_get_drvdata(card); + int ret = 0; + + /* Headset jack detection only if it is supported */ + if (priv->jack_detect > 0) { + hs_jack_gpios[0].gpio = priv->jack_detect; + + ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, + &priv->hs_jack); + if (ret) + return ret; + + ret = snd_soc_jack_add_pins(&priv->hs_jack, + ARRAY_SIZE(hs_jack_pins), + hs_jack_pins); + if (ret) + return ret; + + ret = snd_soc_jack_add_gpios(&priv->hs_jack, + ARRAY_SIZE(hs_jack_gpios), + hs_jack_gpios); + if (ret) + return ret; + } + + /* + * NULL pdata means we booted with DT. In this case the routing is + * provided and the card is fully routed, no need to mark pins. + */ + if (!pdata || !pdata->custom_routing) + return ret; + + /* Disable not connected paths if not used */ + twl4030_disconnect_pin(dapm, pdata->has_ear, "Earpiece Spk"); + twl4030_disconnect_pin(dapm, pdata->has_hf, "Handsfree Spk"); + twl4030_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); + twl4030_disconnect_pin(dapm, pdata->has_predriv, "Ext Spk"); + twl4030_disconnect_pin(dapm, pdata->has_carkit, "Carkit Spk"); + + twl4030_disconnect_pin(dapm, pdata->has_mainmic, "Main Mic"); + twl4030_disconnect_pin(dapm, pdata->has_submic, "Sub Mic"); + twl4030_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); + twl4030_disconnect_pin(dapm, pdata->has_carkitmic, "Carkit Mic"); + twl4030_disconnect_pin(dapm, pdata->has_digimic0, "Digital0 Mic"); + twl4030_disconnect_pin(dapm, pdata->has_digimic1, "Digital1 Mic"); + twl4030_disconnect_pin(dapm, pdata->has_linein, "Line In"); + + return ret; +} + /* Digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link omap_twl4030_dai_links[] = { { - .name = "TWL4030", - .stream_name = "TWL4030", + .name = "TWL4030 HiFi", + .stream_name = "TWL4030 HiFi", .cpu_dai_name = "omap-mcbsp.2", .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", + .init = omap_twl4030_init, .ops = &omap_twl4030_ops, }, + { + .name = "TWL4030 Voice", + .stream_name = "TWL4030 Voice", + .cpu_dai_name = "omap-mcbsp.3", + .codec_dai_name = "twl4030-voice", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", + .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | + SND_SOC_DAIFMT_CBM_CFM, + }, }; /* Audio machine driver */ @@ -105,6 +262,11 @@ static struct snd_soc_card omap_twl4030_card = { .owner = THIS_MODULE, .dai_link = omap_twl4030_dai_links, .num_links = ARRAY_SIZE(omap_twl4030_dai_links), + + .dapm_widgets = dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static int omap_twl4030_probe(struct platform_device *pdev) @@ -112,12 +274,18 @@ static int omap_twl4030_probe(struct platform_device *pdev) struct omap_tw4030_pdata *pdata = dev_get_platdata(&pdev->dev); struct device_node *node = pdev->dev.of_node; struct snd_soc_card *card = &omap_twl4030_card; + struct omap_twl4030 *priv; int ret = 0; card->dev = &pdev->dev; + priv = devm_kzalloc(&pdev->dev, sizeof(struct omap_twl4030), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + if (node) { struct device_node *dai_node; + struct property *prop; if (snd_soc_of_parse_card_name(card, "ti,model")) { dev_err(&pdev->dev, "Card name is not provided\n"); @@ -132,6 +300,27 @@ static int omap_twl4030_probe(struct platform_device *pdev) omap_twl4030_dai_links[0].cpu_dai_name = NULL; omap_twl4030_dai_links[0].cpu_of_node = dai_node; + dai_node = of_parse_phandle(node, "ti,mcbsp-voice", 0); + if (!dai_node) { + card->num_links = 1; + } else { + omap_twl4030_dai_links[1].cpu_dai_name = NULL; + omap_twl4030_dai_links[1].cpu_of_node = dai_node; + } + + priv->jack_detect = of_get_named_gpio(node, + "ti,jack-det-gpio", 0); + + /* Optional: audio routing can be provided */ + prop = of_find_property(node, "ti,audio-routing", NULL); + if (prop) { + ret = snd_soc_of_parse_audio_routing(card, + "ti,audio-routing"); + if (ret) + return ret; + + card->fully_routed = 1; + } } else if (pdata) { if (pdata->card_name) { card->name = pdata->card_name; @@ -139,11 +328,17 @@ static int omap_twl4030_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Card name is not provided\n"); return -ENODEV; } + + if (!pdata->voice_connected) + card->num_links = 1; + + priv->jack_detect = pdata->jack_detect; } else { dev_err(&pdev->dev, "Missing pdata\n"); return -ENODEV; } + snd_soc_card_set_drvdata(card, priv); ret = snd_soc_register_card(card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", @@ -157,7 +352,12 @@ static int omap_twl4030_probe(struct platform_device *pdev) static int omap_twl4030_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); + struct omap_twl4030 *priv = snd_soc_card_get_drvdata(card); + if (priv->jack_detect > 0) + snd_soc_jack_free_gpios(&priv->hs_jack, + ARRAY_SIZE(hs_jack_gpios), + hs_jack_gpios); snd_soc_unregister_card(card); return 0; -- cgit v1.2.3-70-g09d2 From 57d61b9d2d7bc618b7b28a46310d9c2f086f8f51 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 31 Dec 2012 11:51:49 +0100 Subject: ASoC: OMAP: Remove obsolete machine drivers for Zoom2 and SDP3430 These boards are using the common omap-twl4030 machine driver, no need for separate machine drivers anymore. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/Kconfig | 17 ---- sound/soc/omap/Makefile | 4 - sound/soc/omap/sdp3430.c | 245 ----------------------------------------------- sound/soc/omap/zoom2.c | 193 ------------------------------------- 4 files changed, 459 deletions(-) delete mode 100644 sound/soc/omap/sdp3430.c delete mode 100644 sound/soc/omap/zoom2.c (limited to 'sound') diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index e8d2a2f983b..60259f2f3f2 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -70,15 +70,6 @@ config SND_OMAP_SOC_AM3517EVM Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517 EVM. -config SND_OMAP_SOC_SDP3430 - tristate "SoC Audio support for Texas Instruments SDP3430" - depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for SoC audio on Texas Instruments - SDP3430. - config SND_OMAP_SOC_OMAP_TWL4030 tristate "SoC Audio support for TI SoC based boards with twl4030 codec" depends on TWL4030_CORE && SND_OMAP_SOC @@ -125,11 +116,3 @@ config SND_OMAP_SOC_OMAP3_PANDORA select SND_SOC_TWL4030 help Say Y if you want to add support for SoC audio on the OMAP3 Pandora. - -config SND_OMAP_SOC_ZOOM2 - tristate "SoC Audio support for Zoom2" - depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2 - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for Soc audio on Zoom2 board. diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 19637e55ea4..2b225945359 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -17,11 +17,9 @@ snd-soc-rx51-objs := rx51.o snd-soc-ams-delta-objs := ams-delta.o snd-soc-osk5912-objs := osk5912.o snd-soc-am3517evm-objs := am3517evm.o -snd-soc-sdp3430-objs := sdp3430.o snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o snd-soc-omap-twl4030-objs := omap-twl4030.o snd-soc-omap3pandora-objs := omap3pandora.o -snd-soc-zoom2-objs := zoom2.o snd-soc-omap-hdmi-card-objs := omap-hdmi-card.o obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o @@ -30,9 +28,7 @@ obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o -obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o -obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI) += snd-soc-omap-hdmi-card.o diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c deleted file mode 100644 index 216cbdd569e..00000000000 --- a/sound/soc/omap/sdp3430.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * sdp3430.c -- SoC audio for TI OMAP3430 SDP - * - * Author: Misael Lopez Cruz - * - * Based on: - * Author: Steve Sakoman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -static struct snd_soc_card snd_soc_sdp3430; - -static int sdp3430_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int ret; - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops sdp3430_ops = { - .hw_params = sdp3430_hw_params, -}; - -/* Headset jack */ -static struct snd_soc_jack hs_jack; - -/* Headset jack detection DAPM pins */ -static struct snd_soc_jack_pin hs_jack_pins[] = { - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, - { - .pin = "Headset Stereophone", - .mask = SND_JACK_HEADPHONE, - }, -}; - -/* Headset jack detection gpios */ -static struct snd_soc_jack_gpio hs_jack_gpios[] = { - { - .gpio = (OMAP_MAX_GPIO_LINES + 2), - .name = "hsdet-gpio", - .report = SND_JACK_HEADSET, - .debounce_time = 200, - }, -}; - -/* SDP3430 machine DAPM */ -static const struct snd_soc_dapm_widget sdp3430_twl4030_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Ext Mic", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_HP("Headset Stereophone", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* External Mics: MAINMIC, SUBMIC with bias */ - {"MAINMIC", NULL, "Ext Mic"}, - {"SUBMIC", NULL, "Ext Mic"}, - {"Ext Mic", NULL, "Mic Bias 1"}, - {"Ext Mic", NULL, "Mic Bias 2"}, - - /* External Speakers: HFL, HFR */ - {"Ext Spk", NULL, "HFL"}, - {"Ext Spk", NULL, "HFR"}, - - /* Headset Mic: HSMIC with bias */ - {"HSMIC", NULL, "Headset Mic"}, - {"Headset Mic", NULL, "Headset Mic Bias"}, - - /* Headset Stereophone (Headphone): HSOL, HSOR */ - {"Headset Stereophone", NULL, "HSOL"}, - {"Headset Stereophone", NULL, "HSOR"}, -}; - -static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - /* SDP3430 connected pins */ - snd_soc_dapm_enable_pin(dapm, "Ext Mic"); - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - snd_soc_dapm_disable_pin(dapm, "Headset Mic"); - snd_soc_dapm_disable_pin(dapm, "Headset Stereophone"); - - /* TWL4030 not connected pins */ - snd_soc_dapm_nc_pin(dapm, "AUXL"); - snd_soc_dapm_nc_pin(dapm, "AUXR"); - snd_soc_dapm_nc_pin(dapm, "CARKITMIC"); - snd_soc_dapm_nc_pin(dapm, "DIGIMIC0"); - snd_soc_dapm_nc_pin(dapm, "DIGIMIC1"); - - snd_soc_dapm_nc_pin(dapm, "OUTL"); - snd_soc_dapm_nc_pin(dapm, "OUTR"); - snd_soc_dapm_nc_pin(dapm, "EARPIECE"); - snd_soc_dapm_nc_pin(dapm, "PREDRIVEL"); - snd_soc_dapm_nc_pin(dapm, "PREDRIVER"); - snd_soc_dapm_nc_pin(dapm, "CARKITL"); - snd_soc_dapm_nc_pin(dapm, "CARKITR"); - - /* Headset jack detection */ - ret = snd_soc_jack_new(codec, "Headset Jack", - SND_JACK_HEADSET, &hs_jack); - if (ret) - return ret; - - ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), - hs_jack_pins); - if (ret) - return ret; - - ret = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), - hs_jack_gpios); - - return ret; -} - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link sdp3430_dai[] = { - { - .name = "TWL4030 I2S", - .stream_name = "TWL4030 Audio", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .init = sdp3430_twl4030_init, - .ops = &sdp3430_ops, - }, - { - .name = "TWL4030 PCM", - .stream_name = "TWL4030 Voice", - .cpu_dai_name = "omap-mcbsp.3", - .codec_dai_name = "twl4030-voice", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .ops = &sdp3430_ops, - }, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_sdp3430 = { - .name = "SDP3430", - .owner = THIS_MODULE, - .dai_link = sdp3430_dai, - .num_links = ARRAY_SIZE(sdp3430_dai), - - .dapm_widgets = sdp3430_twl4030_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sdp3430_twl4030_dapm_widgets), - .dapm_routes = audio_map, - .num_dapm_routes = ARRAY_SIZE(audio_map), -}; - -static struct platform_device *sdp3430_snd_device; - -static int __init sdp3430_soc_init(void) -{ - int ret; - - if (!machine_is_omap_3430sdp()) - return -ENODEV; - printk(KERN_INFO "SDP3430 SoC init\n"); - - sdp3430_snd_device = platform_device_alloc("soc-audio", -1); - if (!sdp3430_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(sdp3430_snd_device, &snd_soc_sdp3430); - - ret = platform_device_add(sdp3430_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(sdp3430_snd_device); - - return ret; -} -module_init(sdp3430_soc_init); - -static void __exit sdp3430_soc_exit(void) -{ - snd_soc_jack_free_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), - hs_jack_gpios); - - platform_device_unregister(sdp3430_snd_device); -} -module_exit(sdp3430_soc_exit); - -MODULE_AUTHOR("Misael Lopez Cruz "); -MODULE_DESCRIPTION("ALSA SoC SDP3430"); -MODULE_LICENSE("GPL"); - diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c deleted file mode 100644 index 62a6b02d9b3..00000000000 --- a/sound/soc/omap/zoom2.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * zoom2.c -- SoC audio for Zoom2 - * - * Author: Misael Lopez Cruz - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* Register descriptions for twl4030 codec part */ -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -static int zoom2_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int ret; - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops zoom2_ops = { - .hw_params = zoom2_hw_params, -}; - -/* Zoom2 machine DAPM */ -static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Ext Mic", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_HP("Headset Stereophone", NULL), - SND_SOC_DAPM_LINE("Aux In", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* External Mics: MAINMIC, SUBMIC with bias */ - {"MAINMIC", NULL, "Ext Mic"}, - {"SUBMIC", NULL, "Ext Mic"}, - {"Ext Mic", NULL, "Mic Bias 1"}, - {"Ext Mic", NULL, "Mic Bias 2"}, - - /* External Speakers: HFL, HFR */ - {"Ext Spk", NULL, "HFL"}, - {"Ext Spk", NULL, "HFR"}, - - /* Headset Stereophone: HSOL, HSOR */ - {"Headset Stereophone", NULL, "HSOL"}, - {"Headset Stereophone", NULL, "HSOR"}, - - /* Headset Mic: HSMIC with bias */ - {"HSMIC", NULL, "Headset Mic"}, - {"Headset Mic", NULL, "Headset Mic Bias"}, - - /* Aux In: AUXL, AUXR */ - {"Aux In", NULL, "AUXL"}, - {"Aux In", NULL, "AUXR"}, -}; - -static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - /* TWL4030 not connected pins */ - snd_soc_dapm_nc_pin(dapm, "CARKITMIC"); - snd_soc_dapm_nc_pin(dapm, "DIGIMIC0"); - snd_soc_dapm_nc_pin(dapm, "DIGIMIC1"); - snd_soc_dapm_nc_pin(dapm, "EARPIECE"); - snd_soc_dapm_nc_pin(dapm, "PREDRIVEL"); - snd_soc_dapm_nc_pin(dapm, "PREDRIVER"); - snd_soc_dapm_nc_pin(dapm, "CARKITL"); - snd_soc_dapm_nc_pin(dapm, "CARKITR"); - - return 0; -} - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link zoom2_dai[] = { - { - .name = "TWL4030 I2S", - .stream_name = "TWL4030 Audio", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .init = zoom2_twl4030_init, - .ops = &zoom2_ops, - }, - { - .name = "TWL4030 PCM", - .stream_name = "TWL4030 Voice", - .cpu_dai_name = "omap-mcbsp.3", - .codec_dai_name = "twl4030-voice", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .ops = &zoom2_ops, - }, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_zoom2 = { - .name = "Zoom2", - .owner = THIS_MODULE, - .dai_link = zoom2_dai, - .num_links = ARRAY_SIZE(zoom2_dai), - - .dapm_widgets = zoom2_twl4030_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(zoom2_twl4030_dapm_widgets), - .dapm_routes = audio_map, - .num_dapm_routes = ARRAY_SIZE(audio_map), -}; - -static struct platform_device *zoom2_snd_device; - -static int __init zoom2_soc_init(void) -{ - int ret; - - if (!machine_is_omap_zoom2()) - return -ENODEV; - printk(KERN_INFO "Zoom2 SoC init\n"); - - zoom2_snd_device = platform_device_alloc("soc-audio", -1); - if (!zoom2_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(zoom2_snd_device, &snd_soc_zoom2); - ret = platform_device_add(zoom2_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(zoom2_snd_device); - - return ret; -} -module_init(zoom2_soc_init); - -static void __exit zoom2_soc_exit(void) -{ - platform_device_unregister(zoom2_snd_device); -} -module_exit(zoom2_soc_exit); - -MODULE_AUTHOR("Misael Lopez Cruz "); -MODULE_DESCRIPTION("ALSA SoC Zoom2"); -MODULE_LICENSE("GPL"); - -- cgit v1.2.3-70-g09d2 From 8d61f4901f83461e1f04df7743777e9db5f541aa Mon Sep 17 00:00:00 2001 From: Misael Lopez Cruz Date: Fri, 11 Jan 2013 17:00:59 +0100 Subject: ASoC: twl6040: Convert PLUGINT to no-suspend irq Convert headset PLUGINT interrupt to NO_SUSPEND type in order to allow handling of insertion/removal events while device is suspended. Signed-off-by: Misael Lopez Cruz Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl6040.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 3fc3fc64dd8..ef31ace41d5 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -1174,7 +1174,7 @@ static int twl6040_probe(struct snd_soc_codec *codec) mutex_init(&priv->mutex); ret = request_threaded_irq(priv->plug_irq, NULL, twl6040_audio_handler, - 0, "twl6040_irq_plug", codec); + IRQF_NO_SUSPEND, "twl6040_irq_plug", codec); if (ret) { dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret); goto plugirq_err; -- cgit v1.2.3-70-g09d2 From 09a8b6719caecff6c08d505c1f7126b7be68663a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 11 Jan 2013 17:01:41 +0100 Subject: ASoC: twl4030: Remove suspend/resume soc driver operations With idle_bias_off these are no longer needed. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 7bfabe5750e..8e6e5b01602 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -2296,18 +2296,6 @@ static struct snd_soc_dai_driver twl4030_dai[] = { }, }; -static int twl4030_soc_suspend(struct snd_soc_codec *codec) -{ - twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int twl4030_soc_resume(struct snd_soc_codec *codec) -{ - twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - static int twl4030_soc_probe(struct snd_soc_codec *codec) { struct twl4030_priv *twl4030; @@ -2345,8 +2333,6 @@ static int twl4030_soc_remove(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { .probe = twl4030_soc_probe, .remove = twl4030_soc_remove, - .suspend = twl4030_soc_suspend, - .resume = twl4030_soc_resume, .read = twl4030_read_reg_cache, .write = twl4030_write, .set_bias_level = twl4030_set_bias_level, -- cgit v1.2.3-70-g09d2 From 156db9f3bb3c210cdf905172f6063c90c4a62c3c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 11 Jan 2013 17:01:00 +0100 Subject: ASoC: twl6040: Only set the bias_level once in twl6040_resume() No need to set the bias_level twice to _STANDBY - since this is the only state the device could be at suspend time. The driver do not support idle_bias_off yet. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl6040.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index ef31ace41d5..86f12a498f3 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -1115,7 +1115,6 @@ static int twl6040_suspend(struct snd_soc_codec *codec) static int twl6040_resume(struct snd_soc_codec *codec) { twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - twl6040_set_bias_level(codec, codec->dapm.suspend_bias_level); return 0; } -- cgit v1.2.3-70-g09d2 From 9523fcdcc02e812f3a0f4849b3af1b295ad50470 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 11 Jan 2013 17:01:01 +0100 Subject: ASoC: twl6040: Convert to use devm_* when possible In this way we can clean up the probe and remove paths Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl6040.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 86f12a498f3..90b721e437a 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -1131,9 +1131,10 @@ static int twl6040_probe(struct snd_soc_codec *codec) struct platform_device, dev); int ret = 0; - priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); + priv = devm_kzalloc(codec->dev, sizeof(*priv), GFP_KERNEL); if (priv == NULL) return -ENOMEM; + snd_soc_codec_set_drvdata(codec, priv); priv->codec = codec; @@ -1158,25 +1159,23 @@ static int twl6040_probe(struct snd_soc_codec *codec) priv->plug_irq = platform_get_irq(pdev, 0); if (priv->plug_irq < 0) { dev_err(codec->dev, "invalid irq\n"); - ret = -EINVAL; - goto work_err; + return -EINVAL; } priv->workqueue = alloc_workqueue("twl6040-codec", 0, 0); - if (!priv->workqueue) { - ret = -ENOMEM; - goto work_err; - } + if (!priv->workqueue) + return -ENOMEM; INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work); mutex_init(&priv->mutex); - ret = request_threaded_irq(priv->plug_irq, NULL, twl6040_audio_handler, - IRQF_NO_SUSPEND, "twl6040_irq_plug", codec); + ret = devm_request_threaded_irq(codec->dev, priv->plug_irq, NULL, + twl6040_audio_handler, IRQF_NO_SUSPEND, + "twl6040_irq_plug", codec); if (ret) { dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret); - goto plugirq_err; + goto err; } twl6040_init_chip(codec); @@ -1186,12 +1185,8 @@ static int twl6040_probe(struct snd_soc_codec *codec) if (!ret) return 0; - /* Error path */ - free_irq(priv->plug_irq, codec); -plugirq_err: +err: destroy_workqueue(priv->workqueue); -work_err: - kfree(priv); return ret; } @@ -1200,9 +1195,7 @@ static int twl6040_remove(struct snd_soc_codec *codec) struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); - free_irq(priv->plug_irq, codec); destroy_workqueue(priv->workqueue); - kfree(priv); return 0; } -- cgit v1.2.3-70-g09d2 From da2107d1e464811407675880e9ab78f057b7c9d6 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 11 Jan 2013 17:01:02 +0100 Subject: ASoC: twl6040: Switch to use system workqueue for jack reporting There's no need to create a queue for this anymore Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl6040.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 90b721e437a..984911ba580 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -75,7 +75,6 @@ struct twl6040_data { u16 hf_right_step; struct twl6040_jack_data hs_jack; struct snd_soc_codec *codec; - struct workqueue_struct *workqueue; struct mutex mutex; }; @@ -404,8 +403,7 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data) struct snd_soc_codec *codec = data; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - queue_delayed_work(priv->workqueue, &priv->hs_jack.work, - msecs_to_jiffies(200)); + schedule_delayed_work(&priv->hs_jack.work, msecs_to_jiffies(200)); return IRQ_HANDLED; } @@ -1162,10 +1160,6 @@ static int twl6040_probe(struct snd_soc_codec *codec) return -EINVAL; } - priv->workqueue = alloc_workqueue("twl6040-codec", 0, 0); - if (!priv->workqueue) - return -ENOMEM; - INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work); mutex_init(&priv->mutex); @@ -1175,27 +1169,18 @@ static int twl6040_probe(struct snd_soc_codec *codec) "twl6040_irq_plug", codec); if (ret) { dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret); - goto err; + return ret; } twl6040_init_chip(codec); /* power on device */ - ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - if (!ret) - return 0; - -err: - destroy_workqueue(priv->workqueue); - return ret; + return twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); } static int twl6040_remove(struct snd_soc_codec *codec) { - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); - destroy_workqueue(priv->workqueue); return 0; } -- cgit v1.2.3-70-g09d2 From 85becda62c77d0951a1079bb45d0b5cbe6012252 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 11 Jan 2013 17:01:03 +0100 Subject: ASoC: twl6040: Remove leftover code from hs/hf ramp implementation The code to do the ramp has been removed a long time ago. Remove the remaining code as well since this is not needed. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl6040.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 984911ba580..9b9a6e58761 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -69,10 +69,6 @@ struct twl6040_data { int hs_power_mode_locked; unsigned int clk_in; unsigned int sysclk; - u16 hs_left_step; - u16 hs_right_step; - u16 hf_left_step; - u16 hf_right_step; struct twl6040_jack_data hs_jack; struct snd_soc_codec *codec; struct mutex mutex; @@ -1124,7 +1120,6 @@ static int twl6040_resume(struct snd_soc_codec *codec) static int twl6040_probe(struct snd_soc_codec *codec) { struct twl6040_data *priv; - struct twl6040_codec_data *pdata = dev_get_platdata(codec->dev); struct platform_device *pdev = container_of(codec->dev, struct platform_device, dev); int ret = 0; @@ -1138,22 +1133,6 @@ static int twl6040_probe(struct snd_soc_codec *codec) priv->codec = codec; codec->control_data = dev_get_drvdata(codec->dev->parent); - if (pdata && pdata->hs_left_step && pdata->hs_right_step) { - priv->hs_left_step = pdata->hs_left_step; - priv->hs_right_step = pdata->hs_right_step; - } else { - priv->hs_left_step = 1; - priv->hs_right_step = 1; - } - - if (pdata && pdata->hf_left_step && pdata->hf_right_step) { - priv->hf_left_step = pdata->hf_left_step; - priv->hf_right_step = pdata->hf_right_step; - } else { - priv->hf_left_step = 1; - priv->hf_right_step = 1; - } - priv->plug_irq = platform_get_irq(pdev, 0); if (priv->plug_irq < 0) { dev_err(codec->dev, "invalid irq\n"); -- cgit v1.2.3-70-g09d2