diff options
Diffstat (limited to 'sound/soc/omap')
| -rw-r--r-- | sound/soc/omap/Kconfig | 36 | ||||
| -rw-r--r-- | sound/soc/omap/Makefile | 5 | ||||
| -rw-r--r-- | sound/soc/omap/am3517evm.c | 3 | ||||
| -rw-r--r-- | sound/soc/omap/ams-delta.c | 136 | ||||
| -rw-r--r-- | sound/soc/omap/mcbsp.c | 55 | ||||
| -rw-r--r-- | sound/soc/omap/mcbsp.h | 7 | ||||
| -rw-r--r-- | sound/soc/omap/n810.c | 44 | ||||
| -rw-r--r-- | sound/soc/omap/omap-abe-twl6040.c | 146 | ||||
| -rw-r--r-- | sound/soc/omap/omap-dmic.c | 60 | ||||
| -rw-r--r-- | sound/soc/omap/omap-hdmi-card.c | 4 | ||||
| -rw-r--r-- | sound/soc/omap/omap-hdmi.c | 41 | ||||
| -rw-r--r-- | sound/soc/omap/omap-mcbsp.c | 55 | ||||
| -rw-r--r-- | sound/soc/omap/omap-mcbsp.h | 2 | ||||
| -rw-r--r-- | sound/soc/omap/omap-mcpdm.c | 151 | ||||
| -rw-r--r-- | sound/soc/omap/omap-pcm.c | 141 | ||||
| -rw-r--r-- | sound/soc/omap/omap-pcm.h | 40 | ||||
| -rw-r--r-- | sound/soc/omap/omap-twl4030.c | 238 | ||||
| -rw-r--r-- | sound/soc/omap/omap3pandora.c | 52 | ||||
| -rw-r--r-- | sound/soc/omap/osk5912.c | 3 | ||||
| -rw-r--r-- | sound/soc/omap/rx51.c | 308 | ||||
| -rw-r--r-- | sound/soc/omap/sdp3430.c | 278 | ||||
| -rw-r--r-- | sound/soc/omap/zoom2.c | 207 |
22 files changed, 807 insertions, 1205 deletions
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 7048137f9a3..d44463a7b0f 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -1,7 +1,7 @@ config SND_OMAP_SOC tristate "SoC Audio for the Texas Instruments OMAP chips" - depends on ARCH_OMAP && DMA_OMAP - select SND_SOC_DMAENGINE_PCM + depends on (ARCH_OMAP && DMA_OMAP) || (ARM && COMPILE_TEST) + select SND_DMAENGINE_PCM config SND_OMAP_SOC_DMIC tristate @@ -26,17 +26,18 @@ config SND_OMAP_SOC_N810 config SND_OMAP_SOC_RX51 tristate "SoC Audio support for Nokia RX-51" - depends on SND_OMAP_SOC && MACH_NOKIA_RX51 + depends on SND_OMAP_SOC && ARM && (MACH_NOKIA_RX51 || COMPILE_TEST) && I2C select SND_OMAP_SOC_MCBSP select SND_SOC_TLV320AIC3X select SND_SOC_TPA6130A2 + depends on GPIOLIB help Say Y if you want to add support for SoC audio on Nokia RX-51 hardware. This is also known as Nokia N900 product. config SND_OMAP_SOC_AMS_DELTA tristate "SoC Audio support for Amstrad E3 (Delta) videophone" - depends on SND_OMAP_SOC && MACH_AMS_DELTA + depends on SND_OMAP_SOC && MACH_AMS_DELTA && TTY select SND_OMAP_SOC_MCBSP select SND_SOC_CX20442 help @@ -57,7 +58,7 @@ config SND_OMAP_SOC_OSK5912 tristate "SoC Audio support for omap osk5912" depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y if you want to add support for SoC audio on osk5912. @@ -65,20 +66,11 @@ config SND_OMAP_SOC_AM3517EVM tristate "SoC Audio support for OMAP3517 / AM3517 EVM" depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help 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 @@ -91,10 +83,12 @@ 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" - depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4 + depends on TWL6040_CORE && SND_OMAP_SOC && (ARCH_OMAP4 || COMPILE_TEST) select SND_OMAP_SOC_DMIC select SND_OMAP_SOC_MCPDM select SND_SOC_TWL6040 @@ -110,7 +104,7 @@ config SND_OMAP_SOC_OMAP_HDMI tristate "SoC Audio support for Texas Instruments OMAP HDMI" depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS select SND_OMAP_SOC_HDMI - select SND_SOC_OMAP_HDMI_CODEC + select SND_SOC_HDMI_CODEC select OMAP4_DSS_HDMI_AUDIO help Say Y if you want to add support for SoC HDMI audio on Texas Instruments @@ -123,11 +117,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..a725905b2c6 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -17,22 +17,17 @@ 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 obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o 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/am3517evm.c b/sound/soc/omap/am3517evm.c index c1900b2a6f2..25a33e9d417 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c @@ -28,7 +28,6 @@ #include <linux/platform_data/asoc-ti-mcbsp.h> #include "omap-mcbsp.h" -#include "omap-pcm.h" #include "../codecs/tlv320aic23.h" @@ -78,7 +77,7 @@ static struct snd_soc_dai_link am3517evm_dai = { .stream_name = "AIC23", .cpu_dai_name = "omap-mcbsp.1", .codec_dai_name = "tlv320aic23-hifi", - .platform_name = "omap-pcm-audio", + .platform_name = "omap-mcbsp.1", .codec_name = "tlv320aic23-codec.2-001a", .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 2600447fa74..0cc41f94de4 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -36,10 +36,8 @@ #include <linux/platform_data/asoc-ti-mcbsp.h> #include "omap-mcbsp.h" -#include "omap-pcm.h" #include "../codecs/cx20442.h" - /* Board specific DAPM widgets */ static const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = { /* Handset */ @@ -91,73 +89,81 @@ static const unsigned short ams_delta_audio_mode_pins[] = { static unsigned short ams_delta_audio_agc; +/* + * Used for passing a codec structure pointer + * from the board initialization code to the tty line discipline. + */ +static struct snd_soc_codec *cx20442_codec; + static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = &card->dapm; struct soc_enum *control = (struct soc_enum *)kcontrol->private_value; unsigned short pins; int pin, changed = 0; /* Refuse any mode changes if we are not able to control the codec. */ - if (!codec->hw_write) + if (!cx20442_codec->hw_write) return -EUNATCH; - if (ucontrol->value.enumerated.item[0] >= control->max) + if (ucontrol->value.enumerated.item[0] >= control->items) return -EINVAL; - mutex_lock(&codec->mutex); + snd_soc_dapm_mutex_lock(dapm); /* Translate selection to bitmap */ pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]]; /* Setup pins after corresponding bits if changed */ pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE)); + if (pin != snd_soc_dapm_get_pin_status(dapm, "Mouthpiece")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Mouthpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mouthpiece"); else - snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mouthpiece"); } pin = !!(pins & (1 << AMS_DELTA_EARPIECE)); if (pin != snd_soc_dapm_get_pin_status(dapm, "Earpiece")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Earpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Earpiece"); else - snd_soc_dapm_disable_pin(dapm, "Earpiece"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Earpiece"); } pin = !!(pins & (1 << AMS_DELTA_MICROPHONE)); if (pin != snd_soc_dapm_get_pin_status(dapm, "Microphone")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Microphone"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Microphone"); else - snd_soc_dapm_disable_pin(dapm, "Microphone"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Microphone"); } pin = !!(pins & (1 << AMS_DELTA_SPEAKER)); if (pin != snd_soc_dapm_get_pin_status(dapm, "Speaker")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Speaker"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); else - snd_soc_dapm_disable_pin(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); } pin = !!(pins & (1 << AMS_DELTA_AGC)); if (pin != ams_delta_audio_agc) { ams_delta_audio_agc = pin; changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "AGCIN"); + snd_soc_dapm_enable_pin_unlocked(dapm, "AGCIN"); else - snd_soc_dapm_disable_pin(dapm, "AGCIN"); + snd_soc_dapm_disable_pin_unlocked(dapm, "AGCIN"); } + if (changed) - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync_unlocked(dapm); - mutex_unlock(&codec->mutex); + snd_soc_dapm_mutex_unlock(dapm); return changed; } @@ -165,8 +171,8 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = &card->dapm; unsigned short pins, mode; pins = ((snd_soc_dapm_get_pin_status(dapm, "Mouthpiece") << @@ -195,13 +201,11 @@ static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol, return 0; } -static const struct soc_enum ams_delta_audio_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ams_delta_audio_mode), - ams_delta_audio_mode), -}; +static const SOC_ENUM_SINGLE_EXT_DECL(ams_delta_audio_enum, + ams_delta_audio_mode); static const struct snd_kcontrol_new ams_delta_audio_controls[] = { - SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum[0], + SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum, ams_delta_get_audio_mode, ams_delta_set_audio_mode), }; @@ -271,12 +275,6 @@ static void cx81801_timeout(unsigned long data) ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0); } -/* - * Used for passing a codec structure pointer - * from the board initialization code to the tty line discipline. - */ -static struct snd_soc_codec *cx20442_codec; - /* Line discipline .open() */ static int cx81801_open(struct tty_struct *tty) { @@ -303,7 +301,7 @@ static int cx81801_open(struct tty_struct *tty) static void cx81801_close(struct tty_struct *tty) { struct snd_soc_codec *codec = tty->disc_data; - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_dapm_context *dapm = &codec->card->dapm; del_timer_sync(&cx81801_timer); @@ -316,12 +314,17 @@ static void cx81801_close(struct tty_struct *tty) v253_ops.close(tty); /* Revert back to default audio input/output constellation */ - snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); - snd_soc_dapm_enable_pin(dapm, "Earpiece"); - snd_soc_dapm_enable_pin(dapm, "Microphone"); - snd_soc_dapm_disable_pin(dapm, "Speaker"); - snd_soc_dapm_disable_pin(dapm, "AGCIN"); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_mutex_lock(dapm); + + snd_soc_dapm_disable_pin_unlocked(dapm, "Mouthpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Earpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Microphone"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "AGCIN"); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } /* Line discipline .hangup() */ @@ -471,15 +474,14 @@ static void ams_delta_shutdown(struct snd_pcm_substream *substream) static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = &card->dapm; int ret; /* Codec is ready, now add/activate board specific controls */ /* Store a pointer to the codec structure for tty ldisc use */ - cx20442_codec = codec; + cx20442_codec = rtd->codec; /* Set up digital mute if not provided by the codec */ if (!codec_dai->driver->ops) { @@ -516,40 +518,20 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) return 0; } - /* Add board specific DAPM widgets and routes */ - ret = snd_soc_dapm_new_controls(dapm, ams_delta_dapm_widgets, - ARRAY_SIZE(ams_delta_dapm_widgets)); - if (ret) { - dev_warn(card->dev, - "Failed to register DAPM controls, " - "will continue without any.\n"); - return 0; - } - - ret = snd_soc_dapm_add_routes(dapm, ams_delta_audio_map, - ARRAY_SIZE(ams_delta_audio_map)); - if (ret) { - dev_warn(card->dev, - "Failed to set up DAPM routes, " - "will continue with codec default map.\n"); - return 0; - } - /* Set up initial pin constellation */ snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); - snd_soc_dapm_enable_pin(dapm, "Earpiece"); - snd_soc_dapm_enable_pin(dapm, "Microphone"); snd_soc_dapm_disable_pin(dapm, "Speaker"); snd_soc_dapm_disable_pin(dapm, "AGCIN"); snd_soc_dapm_disable_pin(dapm, "AGCOUT"); - /* Add virtual switch */ - ret = snd_soc_add_codec_controls(codec, ams_delta_audio_controls, - ARRAY_SIZE(ams_delta_audio_controls)); - if (ret) - dev_warn(card->dev, - "Failed to register audio mode control, " - "will continue without it.\n"); + return 0; +} + +static int ams_delta_card_remove(struct snd_soc_card *card) +{ + snd_soc_jack_free_gpios(&ams_delta_hook_switch, + ARRAY_SIZE(ams_delta_hook_switch_gpios), + ams_delta_hook_switch_gpios); return 0; } @@ -561,7 +543,7 @@ static struct snd_soc_dai_link ams_delta_dai_link = { .cpu_dai_name = "omap-mcbsp.1", .codec_dai_name = "cx20442-voice", .init = ams_delta_cx20442_init, - .platform_name = "omap-pcm-audio", + .platform_name = "omap-mcbsp.1", .codec_name = "cx20442-codec", .ops = &ams_delta_ops, }; @@ -570,8 +552,16 @@ static struct snd_soc_dai_link ams_delta_dai_link = { static struct snd_soc_card ams_delta_audio_card = { .name = "AMS_DELTA", .owner = THIS_MODULE, + .remove = ams_delta_card_remove, .dai_link = &ams_delta_dai_link, .num_links = 1, + + .controls = ams_delta_audio_controls, + .num_controls = ARRAY_SIZE(ams_delta_audio_controls), + .dapm_widgets = ams_delta_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ams_delta_dapm_widgets), + .dapm_routes = ams_delta_audio_map, + .num_dapm_routes = ARRAY_SIZE(ams_delta_audio_map), }; /* Module init/exit */ @@ -599,10 +589,6 @@ static int ams_delta_remove(struct platform_device *pdev) dev_warn(&pdev->dev, "failed to unregister V253 line discipline\n"); - snd_soc_jack_free_gpios(&ams_delta_hook_switch, - ARRAY_SIZE(ams_delta_hook_switch_gpios), - ams_delta_hook_switch_gpios); - snd_soc_unregister_card(card); card->dev = NULL; return 0; diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index 285c8368cb4..86c75384c3c 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -36,10 +36,10 @@ static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) if (mcbsp->pdata->reg_size == 2) { ((u16 *)mcbsp->reg_cache)[reg] = (u16)val; - __raw_writew((u16)val, addr); + writew_relaxed((u16)val, addr); } else { ((u32 *)mcbsp->reg_cache)[reg] = val; - __raw_writel(val, addr); + writel_relaxed(val, addr); } } @@ -48,22 +48,22 @@ static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache) void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step; if (mcbsp->pdata->reg_size == 2) { - return !from_cache ? __raw_readw(addr) : + return !from_cache ? readw_relaxed(addr) : ((u16 *)mcbsp->reg_cache)[reg]; } else { - return !from_cache ? __raw_readl(addr) : + return !from_cache ? readl_relaxed(addr) : ((u32 *)mcbsp->reg_cache)[reg]; } } static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) { - __raw_writel(val, mcbsp->st_data->io_base_st + reg); + writel_relaxed(val, mcbsp->st_data->io_base_st + reg); } static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg) { - return __raw_readl(mcbsp->st_data->io_base_st + reg); + return readl_relaxed(mcbsp->st_data->io_base_st + reg); } #define MCBSP_READ(mcbsp, reg) \ @@ -781,7 +781,7 @@ static ssize_t prop##_store(struct device *dev, \ unsigned long val; \ int status; \ \ - status = strict_strtoul(buf, 0, &val); \ + status = kstrtoul(buf, 0, &val); \ if (status) \ return status; \ \ @@ -1012,25 +1012,32 @@ int omap_mcbsp_init(struct platform_device *pdev) } } - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); - if (!res) { - dev_err(&pdev->dev, "invalid rx DMA channel\n"); - return -ENODEV; - } - /* RX DMA request number, and port address configuration */ - mcbsp->dma_data[1].name = "Audio Capture"; - mcbsp->dma_data[1].dma_req = res->start; - mcbsp->dma_data[1].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 1); + if (!pdev->dev.of_node) { + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); + if (!res) { + dev_err(&pdev->dev, "invalid tx DMA channel\n"); + return -ENODEV; + } + mcbsp->dma_req[0] = res->start; + mcbsp->dma_data[0].filter_data = &mcbsp->dma_req[0]; - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); - if (!res) { - dev_err(&pdev->dev, "invalid tx DMA channel\n"); - return -ENODEV; + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); + if (!res) { + dev_err(&pdev->dev, "invalid rx DMA channel\n"); + return -ENODEV; + } + mcbsp->dma_req[1] = res->start; + mcbsp->dma_data[1].filter_data = &mcbsp->dma_req[1]; + } else { + mcbsp->dma_data[0].filter_data = "tx"; + mcbsp->dma_data[1].filter_data = "rx"; } - /* TX DMA request number, and port address configuration */ - mcbsp->dma_data[0].name = "Audio Playback"; - mcbsp->dma_data[0].dma_req = res->start; - mcbsp->dma_data[0].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 0); + + mcbsp->dma_data[0].addr = omap_mcbsp_dma_reg_params(mcbsp, 0); + mcbsp->dma_data[0].maxburst = 4; + + mcbsp->dma_data[1].addr = omap_mcbsp_dma_reg_params(mcbsp, 1); + mcbsp->dma_data[1].maxburst = 4; mcbsp->fclk = clk_get(&pdev->dev, "fck"); if (IS_ERR(mcbsp->fclk)) { diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h index f93e0b0af30..96d1b086bcf 100644 --- a/sound/soc/omap/mcbsp.h +++ b/sound/soc/omap/mcbsp.h @@ -24,14 +24,14 @@ #ifndef __ASOC_MCBSP_H #define __ASOC_MCBSP_H -#include "omap-pcm.h" - #ifdef CONFIG_ARCH_OMAP1 #define mcbsp_omap1() 1 #else #define mcbsp_omap1() 0 #endif +#include <sound/dmaengine_pcm.h> + /* McBSP register numbers. Register address offset = num * reg_step */ enum { /* Common registers */ @@ -312,7 +312,8 @@ struct omap_mcbsp { struct omap_mcbsp_platform_data *pdata; struct omap_mcbsp_st_data *st_data; struct omap_mcbsp_reg_cfg cfg_regs; - struct omap_pcm_dma_data dma_data[2]; + struct snd_dmaengine_dai_dma_data dma_data[2]; + unsigned int dma_req[2]; int dma_op_mode; u16 max_tx_thres; u16 max_rx_thres; diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 230b8c14484..5d7f9cebe04 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c @@ -34,7 +34,6 @@ #include <linux/platform_data/asoc-ti-mcbsp.h> #include "omap-mcbsp.h" -#include "omap-pcm.h" #define N810_HEADSET_AMP_GPIO 10 #define N810_SPEAKER_AMP_GPIO 101 @@ -69,26 +68,30 @@ static void n810_ext_control(struct snd_soc_dapm_context *dapm) break; } + snd_soc_dapm_mutex_lock(dapm); + if (n810_spk_func) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); if (hp) - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); else - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); if (line1l) - snd_soc_dapm_enable_pin(dapm, "LINE1L"); + snd_soc_dapm_enable_pin_unlocked(dapm, "LINE1L"); else - snd_soc_dapm_disable_pin(dapm, "LINE1L"); + snd_soc_dapm_disable_pin_unlocked(dapm, "LINE1L"); if (n810_dmic_func) - snd_soc_dapm_enable_pin(dapm, "DMic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "DMic"); else - snd_soc_dapm_disable_pin(dapm, "DMic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "DMic"); + + snd_soc_dapm_sync_unlocked(dapm); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_mutex_unlock(dapm); } static int n810_startup(struct snd_pcm_substream *substream) @@ -101,12 +104,12 @@ static int n810_startup(struct snd_pcm_substream *substream) SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); n810_ext_control(&codec->dapm); - return clk_enable(sys_clkout2); + return clk_prepare_enable(sys_clkout2); } static void n810_shutdown(struct snd_pcm_substream *substream) { - clk_disable(sys_clkout2); + clk_disable_unprepare(sys_clkout2); } static int n810_hw_params(struct snd_pcm_substream *substream, @@ -230,8 +233,8 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Ext Spk", NULL, "LLOUT"}, {"Ext Spk", NULL, "RLOUT"}, - {"DMic Rate 64", NULL, "Mic Bias 2V"}, - {"Mic Bias 2V", NULL, "DMic"}, + {"DMic Rate 64", NULL, "Mic Bias"}, + {"Mic Bias", NULL, "DMic"}, }; static const char *spk_function[] = {"Off", "On"}; @@ -275,7 +278,7 @@ static struct snd_soc_dai_link n810_dai = { .name = "TLV320AIC33", .stream_name = "AIC33", .cpu_dai_name = "omap-mcbsp.2", - .platform_name = "omap-pcm-audio", + .platform_name = "omap-mcbsp.2", .codec_name = "tlv320aic3x-codec.2-0018", .codec_dai_name = "tlv320aic3x-hifi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | @@ -306,7 +309,9 @@ static int __init n810_soc_init(void) int err; struct device *dev; - if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax())) + if (!of_have_populated_dt() || + (!of_machine_is_compatible("nokia,n810") && + !of_machine_is_compatible("nokia,n810-wimax"))) return -ENODEV; n810_snd_device = platform_device_alloc("soc-audio", -1); @@ -345,8 +350,11 @@ static int __init n810_soc_init(void) clk_set_parent(sys_clkout2_src, func96m_clk); clk_set_rate(sys_clkout2, 12000000); - BUG_ON((gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) || - (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0)); + if (WARN_ON((gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) || + (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0))) { + err = -EINVAL; + goto err4; + } gpio_direction_output(N810_HEADSET_AMP_GPIO, 0); gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0); diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index e7d93fa412a..cec836ed0c0 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c @@ -23,7 +23,6 @@ #include <linux/clk.h> #include <linux/platform_device.h> #include <linux/mfd/twl6040.h> -#include <linux/platform_data/omap-abe-twl6040.h> #include <linux/module.h> #include <linux/of.h> @@ -34,7 +33,6 @@ #include "omap-dmic.h" #include "omap-mcpdm.h" -#include "omap-pcm.h" #include "../codecs/twl6040.h" struct abe_twl6040 { @@ -49,8 +47,7 @@ static int omap_abe_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_card *card = codec->card; + struct snd_soc_card *card = rtd->card; struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); int clk_id, freq; int ret; @@ -167,19 +164,10 @@ static const struct snd_soc_dapm_route audio_map[] = { {"AFMR", NULL, "Line In"}, }; -static inline void twl6040_disconnect_pin(struct snd_soc_dapm_context *dapm, - int connected, char *pin) -{ - if (!connected) - snd_soc_dapm_disable_pin(dapm, pin); -} - static int omap_abe_twl6040_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_abe_twl6040_data *pdata = dev_get_platdata(card->dev); + struct snd_soc_card *card = rtd->card; struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); int hs_trim; int ret = 0; @@ -204,24 +192,6 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); } - /* - * 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) - return ret; - - /* Disable not connected paths if not used */ - twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); - twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); - twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); - twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); - twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vibrator"); - twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); - twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); - twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); - twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In"); - return ret; } @@ -232,8 +202,7 @@ static const struct snd_soc_dapm_route dmic_audio_map[] = { static int omap_abe_dmic_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_dapm_context *dapm = &rtd->card->dapm; return snd_soc_dapm_add_routes(dapm, dmic_audio_map, ARRAY_SIZE(dmic_audio_map)); @@ -244,9 +213,7 @@ static struct snd_soc_dai_link abe_twl6040_dai_links[] = { { .name = "TWL6040", .stream_name = "TWL6040", - .cpu_dai_name = "omap-mcpdm", .codec_dai_name = "twl6040-legacy", - .platform_name = "omap-pcm-audio", .codec_name = "twl6040-codec", .init = omap_abe_twl6040_init, .ops = &omap_abe_ops, @@ -254,9 +221,7 @@ static struct snd_soc_dai_link abe_twl6040_dai_links[] = { { .name = "DMIC", .stream_name = "DMIC Capture", - .cpu_dai_name = "omap-dmic", .codec_dai_name = "dmic-hifi", - .platform_name = "omap-pcm-audio", .codec_name = "dmic-codec", .init = omap_abe_dmic_init, .ops = &omap_abe_dmic_ops, @@ -275,13 +240,18 @@ static struct snd_soc_card omap_abe_card = { static int omap_abe_probe(struct platform_device *pdev) { - struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev); struct device_node *node = pdev->dev.of_node; struct snd_soc_card *card = &omap_abe_card; + struct device_node *dai_node; struct abe_twl6040 *priv; int num_links = 0; int ret = 0; + if (!node) { + dev_err(&pdev->dev, "of node is missing.\n"); + return -ENODEV; + } + card->dev = &pdev->dev; priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); @@ -290,78 +260,50 @@ static int omap_abe_probe(struct platform_device *pdev) priv->dmic_codec_dev = ERR_PTR(-EINVAL); - if (node) { - struct device_node *dai_node; - - if (snd_soc_of_parse_card_name(card, "ti,model")) { - dev_err(&pdev->dev, "Card name is not provided\n"); - return -ENODEV; - } + if (snd_soc_of_parse_card_name(card, "ti,model")) { + dev_err(&pdev->dev, "Card name is not provided\n"); + return -ENODEV; + } - ret = snd_soc_of_parse_audio_routing(card, - "ti,audio-routing"); - if (ret) { - dev_err(&pdev->dev, - "Error while parsing DAPM routing\n"); - return ret; - } + ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing"); + if (ret) { + dev_err(&pdev->dev, "Error while parsing DAPM routing\n"); + return ret; + } - dai_node = of_parse_phandle(node, "ti,mcpdm", 0); - if (!dai_node) { - dev_err(&pdev->dev, "McPDM node is not provided\n"); - return -EINVAL; - } - abe_twl6040_dai_links[0].cpu_dai_name = NULL; - abe_twl6040_dai_links[0].cpu_of_node = dai_node; + dai_node = of_parse_phandle(node, "ti,mcpdm", 0); + if (!dai_node) { + dev_err(&pdev->dev, "McPDM node is not provided\n"); + return -EINVAL; + } + abe_twl6040_dai_links[0].cpu_of_node = dai_node; + abe_twl6040_dai_links[0].platform_of_node = dai_node; - dai_node = of_parse_phandle(node, "ti,dmic", 0); - if (dai_node) { - num_links = 2; - abe_twl6040_dai_links[1].cpu_dai_name = NULL; - abe_twl6040_dai_links[1].cpu_of_node = dai_node; + dai_node = of_parse_phandle(node, "ti,dmic", 0); + if (dai_node) { + num_links = 2; + abe_twl6040_dai_links[1].cpu_of_node = dai_node; + abe_twl6040_dai_links[1].platform_of_node = dai_node; - priv->dmic_codec_dev = platform_device_register_simple( + priv->dmic_codec_dev = platform_device_register_simple( "dmic-codec", -1, NULL, 0); - if (IS_ERR(priv->dmic_codec_dev)) { - dev_err(&pdev->dev, - "Can't instantiate dmic-codec\n"); - return PTR_ERR(priv->dmic_codec_dev); - } - } else { - num_links = 1; - } - - priv->jack_detection = of_property_read_bool(node, - "ti,jack-detection"); - of_property_read_u32(node, "ti,mclk-freq", - &priv->mclk_freq); - if (!priv->mclk_freq) { - dev_err(&pdev->dev, "MCLK frequency not provided\n"); - ret = -EINVAL; - goto err_unregister; + if (IS_ERR(priv->dmic_codec_dev)) { + dev_err(&pdev->dev, "Can't instantiate dmic-codec\n"); + return PTR_ERR(priv->dmic_codec_dev); } - - omap_abe_card.fully_routed = 1; - } else if (pdata) { - if (pdata->card_name) { - card->name = pdata->card_name; - } else { - dev_err(&pdev->dev, "Card name is not provided\n"); - return -ENODEV; - } - - if (pdata->has_dmic) - num_links = 2; - else - num_links = 1; - - priv->jack_detection = pdata->jack_detection; - priv->mclk_freq = pdata->mclk_freq; } else { - dev_err(&pdev->dev, "Missing pdata\n"); - return -ENODEV; + num_links = 1; + } + + priv->jack_detection = of_property_read_bool(node, "ti,jack-detection"); + of_property_read_u32(node, "ti,mclk-freq", &priv->mclk_freq); + if (!priv->mclk_freq) { + dev_err(&pdev->dev, "MCLK frequency not provided\n"); + ret = -EINVAL; + goto err_unregister; } + card->fully_routed = 1; if (!priv->mclk_freq) { dev_err(&pdev->dev, "MCLK frequency missing\n"); diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index ba49ccd9eed..6925d714121 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c @@ -39,8 +39,9 @@ #include <sound/pcm_params.h> #include <sound/initval.h> #include <sound/soc.h> +#include <sound/dmaengine_pcm.h> +#include <sound/omap-pcm.h> -#include "omap-pcm.h" #include "omap-dmic.h" struct omap_dmic { @@ -55,23 +56,18 @@ struct omap_dmic { u32 ch_enabled; bool active; struct mutex mutex; -}; -/* - * Stream DMA parameters - */ -static struct omap_pcm_dma_data omap_dmic_dai_dma_params = { - .name = "DMIC capture", + struct snd_dmaengine_dai_dma_data dma_data; }; static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) { - __raw_writel(val, dmic->io_base + reg); + writel_relaxed(val, dmic->io_base + reg); } static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg) { - return __raw_readl(dmic->io_base + reg); + return readl_relaxed(dmic->io_base + reg); } static inline void omap_dmic_start(struct omap_dmic *dmic) @@ -118,7 +114,6 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream, mutex_unlock(&dmic->mutex); - snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params); return ret; } @@ -203,7 +198,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); - struct omap_pcm_dma_data *dma_data; + struct snd_dmaengine_dai_dma_data *dma_data; int channels; dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params)); @@ -230,7 +225,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream, /* packet size is threshold * channels */ dma_data = snd_soc_dai_get_dma_data(dai, substream); - dma_data->packet_size = dmic->threshold * channels; + dma_data->maxburst = dmic->threshold * channels; return 0; } @@ -422,6 +417,9 @@ static int omap_dmic_probe(struct snd_soc_dai *dai) /* Configure DMIC threshold value */ dmic->threshold = OMAP_DMIC_THRES_MAX - 3; + + snd_soc_dai_init_dma_data(dai, NULL, &dmic->dma_data); + return 0; } @@ -448,6 +446,10 @@ static struct snd_soc_dai_driver omap_dmic_dai = { .ops = &omap_dmic_dai_ops, }; +static const struct snd_soc_component_driver omap_dmic_component = { + .name = "omap-dmic", +}; + static int asoc_dmic_probe(struct platform_device *pdev) { struct omap_dmic *dmic; @@ -476,38 +478,24 @@ static int asoc_dmic_probe(struct platform_device *pdev) ret = -ENODEV; goto err_put_clk; } - omap_dmic_dai_dma_params.port_addr = res->start + OMAP_DMIC_DATA_REG; + dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG; - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(dmic->dev, "invalid dma resource\n"); - ret = -ENODEV; - goto err_put_clk; - } - omap_dmic_dai_dma_params.dma_req = res->start; + dmic->dma_data.filter_data = "up_link"; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); - if (!res) { - dev_err(dmic->dev, "invalid memory resource\n"); - ret = -ENODEV; + dmic->io_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dmic->io_base)) { + ret = PTR_ERR(dmic->io_base); goto err_put_clk; } - if (!devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), pdev->name)) { - dev_err(dmic->dev, "memory region already claimed\n"); - ret = -ENODEV; - goto err_put_clk; - } - dmic->io_base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!dmic->io_base) { - ret = -ENOMEM; + ret = snd_soc_register_component(&pdev->dev, &omap_dmic_component, + &omap_dmic_dai, 1); + if (ret) goto err_put_clk; - } - ret = snd_soc_register_dai(&pdev->dev, &omap_dmic_dai); + ret = omap_pcm_platform_register(&pdev->dev); if (ret) goto err_put_clk; @@ -522,7 +510,7 @@ static int asoc_dmic_remove(struct platform_device *pdev) { struct omap_dmic *dmic = platform_get_drvdata(pdev); - snd_soc_unregister_dai(&pdev->dev); + snd_soc_unregister_component(&pdev->dev); clk_put(dmic->fclk); return 0; diff --git a/sound/soc/omap/omap-hdmi-card.c b/sound/soc/omap/omap-hdmi-card.c index d4eaa92e518..f649fe84b62 100644 --- a/sound/soc/omap/omap-hdmi-card.c +++ b/sound/soc/omap/omap-hdmi-card.c @@ -33,9 +33,9 @@ static struct snd_soc_dai_link omap_hdmi_dai = { .name = "HDMI", .stream_name = "HDMI", .cpu_dai_name = "omap-hdmi-audio-dai", - .platform_name = "omap-pcm-audio", + .platform_name = "omap-hdmi-audio-dai", .codec_name = "hdmi-audio-codec", - .codec_dai_name = "omap-hdmi-hifi", + .codec_dai_name = "hdmi-hifi", }; static struct snd_soc_card snd_soc_omap_hdmi = { diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c index 7ea24819d57..eb9c39299f8 100644 --- a/sound/soc/omap/omap-hdmi.c +++ b/sound/soc/omap/omap-hdmi.c @@ -32,15 +32,17 @@ #include <sound/soc.h> #include <sound/asound.h> #include <sound/asoundef.h> +#include <sound/dmaengine_pcm.h> #include <video/omapdss.h> +#include <sound/omap-pcm.h> -#include "omap-pcm.h" #include "omap-hdmi.h" #define DRV_NAME "omap-hdmi-audio-dai" struct hdmi_priv { - struct omap_pcm_dma_data dma_params; + struct snd_dmaengine_dai_dma_data dma_data; + unsigned int dma_req; struct omap_dss_audio dss_audio; struct snd_aes_iec958 iec; struct snd_cea_861_aud_if cea; @@ -68,7 +70,7 @@ static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream, return -ENODEV; } - snd_soc_dai_set_dma_data(dai, substream, &priv->dma_params); + snd_soc_dai_set_dma_data(dai, substream, &priv->dma_data); return 0; } @@ -88,28 +90,25 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream, struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai); struct snd_aes_iec958 *iec = &priv->iec; struct snd_cea_861_aud_if *cea = &priv->cea; - struct omap_pcm_dma_data *dma_data; int err = 0; - dma_data = snd_soc_dai_get_dma_data(dai, substream); - switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - dma_data->packet_size = 16; + priv->dma_data.maxburst = 16; break; case SNDRV_PCM_FORMAT_S24_LE: - dma_data->packet_size = 32; + priv->dma_data.maxburst = 32; break; default: dev_err(dai->dev, "format not supported!\n"); return -EINVAL; } - dma_data->data_type = 32; - /* * fill the IEC-60958 channel status word */ + /* initialize the word bytes */ + memset(iec->status, 0, sizeof(iec->status)); /* specify IEC-60958-3 (commercial use) */ iec->status[0] &= ~IEC958_AES0_PROFESSIONAL; @@ -262,6 +261,10 @@ static struct snd_soc_dai_driver omap_hdmi_dai = { .ops = &omap_hdmi_dai_ops, }; +static const struct snd_soc_component_driver omap_hdmi_component = { + .name = DRV_NAME, +}; + static int omap_hdmi_probe(struct platform_device *pdev) { int ret; @@ -281,8 +284,7 @@ static int omap_hdmi_probe(struct platform_device *pdev) return -ENODEV; } - hdmi_data->dma_params.port_addr = hdmi_rsrc->start - + OMAP_HDMI_AUDIO_DMA_PORT; + hdmi_data->dma_data.addr = hdmi_rsrc->start + OMAP_HDMI_AUDIO_DMA_PORT; hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (!hdmi_rsrc) { @@ -290,8 +292,9 @@ static int omap_hdmi_probe(struct platform_device *pdev) return -ENODEV; } - hdmi_data->dma_params.dma_req = hdmi_rsrc->start; - hdmi_data->dma_params.name = "HDMI playback"; + hdmi_data->dma_req = hdmi_rsrc->start; + hdmi_data->dma_data.filter_data = &hdmi_data->dma_req; + hdmi_data->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; /* * TODO: We assume that there is only one DSS HDMI device. Future @@ -319,16 +322,20 @@ static int omap_hdmi_probe(struct platform_device *pdev) } dev_set_drvdata(&pdev->dev, hdmi_data); - ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai); + ret = snd_soc_register_component(&pdev->dev, &omap_hdmi_component, + &omap_hdmi_dai, 1); + + if (ret) + return ret; - return ret; + return omap_pcm_platform_register(&pdev->dev); } static int omap_hdmi_remove(struct platform_device *pdev) { struct hdmi_priv *hdmi_data = dev_get_drvdata(&pdev->dev); - snd_soc_unregister_dai(&pdev->dev); + snd_soc_unregister_component(&pdev->dev); if (hdmi_data == NULL) { dev_err(&pdev->dev, "cannot obtain HDMi data\n"); diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 8d2defd6fdb..efe2cd699b7 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -33,11 +33,12 @@ #include <sound/pcm_params.h> #include <sound/initval.h> #include <sound/soc.h> +#include <sound/dmaengine_pcm.h> +#include <sound/omap-pcm.h> #include <linux/platform_data/asoc-ti-mcbsp.h> #include "mcbsp.h" #include "omap-mcbsp.h" -#include "omap-pcm.h" #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) @@ -62,24 +63,22 @@ enum { * Stream DMA parameters. DMA request line and port address are set runtime * since they are different between OMAP1 and later OMAPs */ -static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) +static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream, + unsigned int packet_size) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - struct omap_pcm_dma_data *dma_data; int words; - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - /* * Configure McBSP threshold based on either: * packet_size, when the sDMA is in packet mode, or based on the * period size in THRESHOLD mode, otherwise use McBSP threshold = 1 * for mono streams. */ - if (dma_data->packet_size) - words = dma_data->packet_size; + if (packet_size) + words = packet_size; else words = 1; @@ -151,9 +150,6 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2); } - snd_soc_dai_set_dma_data(cpu_dai, substream, - &mcbsp->dma_data[substream->stream]); - return err; } @@ -226,7 +222,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, { struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; - struct omap_pcm_dma_data *dma_data; + struct snd_dmaengine_dai_dma_data *dma_data; int wlen, channels, wpf; int pkt_size = 0; unsigned int format, div, framesize, master; @@ -245,7 +241,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } if (mcbsp->pdata->buffer_size) { - dma_data->set_threshold = omap_mcbsp_set_threshold; if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { int period_words, max_thrsh; int divider = 0; @@ -276,9 +271,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, /* Use packet mode for non mono streams */ pkt_size = channels; } + omap_mcbsp_set_threshold(substream, pkt_size); } - dma_data->packet_size = pkt_size; + dma_data->maxburst = pkt_size; if (mcbsp->configured) { /* McBSP already configured by another stream */ @@ -435,6 +431,11 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* Sample rate generator drives the FS */ regs->srgr2 |= FSGM; break; + case SND_SOC_DAIFMT_CBM_CFS: + /* McBSP slave. FS clock as output */ + regs->srgr2 |= FSGM; + regs->pcr0 |= FSXM; + break; case SND_SOC_DAIFMT_CBM_CFM: /* McBSP slave */ break; @@ -556,6 +557,10 @@ static int omap_mcbsp_probe(struct snd_soc_dai *dai) pm_runtime_enable(mcbsp->dev); + snd_soc_dai_init_dma_data(dai, + &mcbsp->dma_data[SNDRV_PCM_STREAM_PLAYBACK], + &mcbsp->dma_data[SNDRV_PCM_STREAM_CAPTURE]); + return 0; } @@ -586,6 +591,10 @@ static struct snd_soc_dai_driver omap_mcbsp_dai = { .ops = &mcbsp_dai_ops, }; +static const struct snd_soc_component_driver omap_mcbsp_component = { + .name = "omap-mcbsp", +}; + static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -684,7 +693,7 @@ OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 1 Volume", \ OMAP_MCBSP_ST_CONTROLS(2); OMAP_MCBSP_ST_CONTROLS(3); -int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) +int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd, int port_id) { struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); @@ -694,7 +703,7 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) return 0; } - switch (mcbsp->id) { + switch (port_id) { case 2: /* McBSP 2 */ return snd_soc_add_dai_controls(cpu_dai, omap_mcbsp2_st_controls, @@ -704,6 +713,7 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) omap_mcbsp3_st_controls, ARRAY_SIZE(omap_mcbsp3_st_controls)); default: + dev_err(mcbsp->dev, "Port %d not supported\n", port_id); break; } @@ -792,17 +802,22 @@ static int asoc_mcbsp_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mcbsp); ret = omap_mcbsp_init(pdev); - if (!ret) - return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai); + if (ret) + return ret; - return ret; + ret = snd_soc_register_component(&pdev->dev, &omap_mcbsp_component, + &omap_mcbsp_dai, 1); + if (ret) + return ret; + + return omap_pcm_platform_register(&pdev->dev); } static int asoc_mcbsp_remove(struct platform_device *pdev) { struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); - snd_soc_unregister_dai(&pdev->dev); + snd_soc_unregister_component(&pdev->dev); if (mcbsp->pdata->ops && mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(mcbsp->id); @@ -811,8 +826,6 @@ static int asoc_mcbsp_remove(struct platform_device *pdev) clk_put(mcbsp->fclk); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index ba8386a0d8d..2e3369c27be 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h @@ -39,6 +39,6 @@ enum omap_mcbsp_div { OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */ }; -int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd); +int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd, int port_id); #endif diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 2fe8be20945..f0e2ebeab02 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -39,11 +39,15 @@ #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> +#include <sound/dmaengine_pcm.h> +#include <sound/omap-pcm.h> #include "omap-mcpdm.h" -#include "omap-pcm.h" -#define OMAP44XX_MCPDM_L3_BASE 0x49032000 +struct mcpdm_link_config { + u32 link_mask; /* channel mask for the direction */ + u32 threshold; /* FIFO threshold */ +}; struct omap_mcpdm { struct device *dev; @@ -53,38 +57,30 @@ struct omap_mcpdm { struct mutex mutex; - /* channel data */ - u32 dn_channels; - u32 up_channels; - - /* McPDM FIFO thresholds */ - u32 dn_threshold; - u32 up_threshold; + /* Playback/Capture configuration */ + struct mcpdm_link_config config[2]; /* McPDM dn offsets for rx1, and 2 channels */ u32 dn_rx_offset; + + /* McPDM needs to be restarted due to runtime reconfiguration */ + bool restart; + + struct snd_dmaengine_dai_dma_data dma_data[2]; }; /* * Stream DMA parameters */ -static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { - { - .name = "Audio playback", - }, - { - .name = "Audio capture", - }, -}; static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val) { - __raw_writel(val, mcpdm->io_base + reg); + writel_relaxed(val, mcpdm->io_base + reg); } static inline int omap_mcpdm_read(struct omap_mcpdm *mcpdm, u16 reg) { - return __raw_readl(mcpdm->io_base + reg); + return readl_relaxed(mcpdm->io_base + reg); } #ifdef DEBUG @@ -130,11 +126,12 @@ static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {} static void omap_mcpdm_start(struct omap_mcpdm *mcpdm) { u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); + u32 link_mask = mcpdm->config[0].link_mask | mcpdm->config[1].link_mask; ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); - ctrl |= mcpdm->dn_channels | mcpdm->up_channels; + ctrl |= link_mask; omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); @@ -148,11 +145,12 @@ static void omap_mcpdm_start(struct omap_mcpdm *mcpdm) static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm) { u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); + u32 link_mask = MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK; ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); - ctrl &= ~(mcpdm->dn_channels | mcpdm->up_channels); + ctrl &= ~(link_mask); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); @@ -188,8 +186,10 @@ static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm) omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset); } - omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, mcpdm->dn_threshold); - omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, mcpdm->up_threshold); + omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, + mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold); + omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, + mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold); omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET, MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE); @@ -266,9 +266,6 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, } mutex_unlock(&mcpdm->mutex); - snd_soc_dai_set_dma_data(dai, substream, - &omap_mcpdm_dai_dma_params[substream->stream]); - return 0; } @@ -283,6 +280,8 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, if (omap_mcpdm_active(mcpdm)) { omap_mcpdm_stop(mcpdm); omap_mcpdm_close_streams(mcpdm); + mcpdm->config[0].link_mask = 0; + mcpdm->config[1].link_mask = 0; } } @@ -295,7 +294,8 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, { struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); int stream = substream->stream; - struct omap_pcm_dma_data *dma_data; + struct snd_dmaengine_dai_dma_data *dma_data; + u32 threshold; int channels; int link_mask = 0; @@ -325,16 +325,32 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, dma_data = snd_soc_dai_get_dma_data(dai, substream); + threshold = mcpdm->config[stream].threshold; /* Configure McPDM channels, and DMA packet size */ if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - mcpdm->dn_channels = link_mask << 3; - dma_data->packet_size = - (MCPDM_DN_THRES_MAX - mcpdm->dn_threshold) * channels; + link_mask <<= 3; + + /* If capture is not running assume a stereo stream to come */ + if (!mcpdm->config[!stream].link_mask) + mcpdm->config[!stream].link_mask = 0x3; + + dma_data->maxburst = + (MCPDM_DN_THRES_MAX - threshold) * channels; } else { - mcpdm->up_channels = link_mask << 0; - dma_data->packet_size = mcpdm->up_threshold * channels; + /* If playback is not running assume a stereo stream to come */ + if (!mcpdm->config[!stream].link_mask) + mcpdm->config[!stream].link_mask = (0x3 << 3); + + dma_data->maxburst = threshold * channels; } + /* Check if we need to restart McPDM with this stream */ + if (mcpdm->config[stream].link_mask && + mcpdm->config[stream].link_mask != link_mask) + mcpdm->restart = true; + + mcpdm->config[stream].link_mask = link_mask; + return 0; } @@ -346,6 +362,11 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream, if (!omap_mcpdm_active(mcpdm)) { omap_mcpdm_start(mcpdm); omap_mcpdm_reg_dump(mcpdm); + } else if (mcpdm->restart) { + omap_mcpdm_stop(mcpdm); + omap_mcpdm_start(mcpdm); + mcpdm->restart = false; + omap_mcpdm_reg_dump(mcpdm); } return 0; @@ -369,7 +390,7 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai) pm_runtime_get_sync(mcpdm->dev); omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00); - ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler, + ret = devm_request_irq(mcpdm->dev, mcpdm->irq, omap_mcpdm_irq_handler, 0, "McPDM", (void *)mcpdm); pm_runtime_put_sync(mcpdm->dev); @@ -380,8 +401,14 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai) } /* Configure McPDM threshold values */ - mcpdm->dn_threshold = 2; - mcpdm->up_threshold = MCPDM_UP_THRES_MAX - 3; + mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold = 2; + mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold = + MCPDM_UP_THRES_MAX - 3; + + snd_soc_dai_init_dma_data(dai, + &mcpdm->dma_data[SNDRV_PCM_STREAM_PLAYBACK], + &mcpdm->dma_data[SNDRV_PCM_STREAM_CAPTURE]); + return ret; } @@ -389,7 +416,6 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai) { struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); - free_irq(mcpdm->irq, (void *)mcpdm); pm_runtime_disable(mcpdm->dev); return 0; @@ -420,6 +446,10 @@ static struct snd_soc_dai_driver omap_mcpdm_dai = { .ops = &omap_mcpdm_dai_ops, }; +static const struct snd_soc_component_driver omap_mcpdm_component = { + .name = "omap-mcpdm", +}; + void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd, u8 rx1, u8 rx2) { @@ -433,6 +463,7 @@ static int asoc_mcpdm_probe(struct platform_device *pdev) { struct omap_mcpdm *mcpdm; struct resource *res; + int ret; mcpdm = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcpdm), GFP_KERNEL); if (!mcpdm) @@ -446,37 +477,16 @@ static int asoc_mcpdm_probe(struct platform_device *pdev) if (res == NULL) return -ENOMEM; - omap_mcpdm_dai_dma_params[0].port_addr = res->start + MCPDM_REG_DN_DATA; - omap_mcpdm_dai_dma_params[1].port_addr = res->start + MCPDM_REG_UP_DATA; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) - return -ENOMEM; - - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link"); - if (!res) - return -ENODEV; - - omap_mcpdm_dai_dma_params[0].dma_req = res->start; - - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link"); - if (!res) - return -ENODEV; + mcpdm->dma_data[0].addr = res->start + MCPDM_REG_DN_DATA; + mcpdm->dma_data[1].addr = res->start + MCPDM_REG_UP_DATA; - omap_mcpdm_dai_dma_params[1].dma_req = res->start; + mcpdm->dma_data[0].filter_data = "dn_link"; + mcpdm->dma_data[1].filter_data = "up_link"; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); - if (res == NULL) - return -ENOMEM; - - if (!devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), "McPDM")) - return -EBUSY; - - mcpdm->io_base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!mcpdm->io_base) - return -ENOMEM; + mcpdm->io_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mcpdm->io_base)) + return PTR_ERR(mcpdm->io_base); mcpdm->irq = platform_get_irq(pdev, 0); if (mcpdm->irq < 0) @@ -484,13 +494,13 @@ static int asoc_mcpdm_probe(struct platform_device *pdev) mcpdm->dev = &pdev->dev; - return snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); -} + ret = devm_snd_soc_register_component(&pdev->dev, + &omap_mcpdm_component, + &omap_mcpdm_dai, 1); + if (ret) + return ret; -static int asoc_mcpdm_remove(struct platform_device *pdev) -{ - snd_soc_unregister_dai(&pdev->dev); - return 0; + return omap_pcm_platform_register(&pdev->dev); } static const struct of_device_id omap_mcpdm_of_match[] = { @@ -507,7 +517,6 @@ static struct platform_driver asoc_mcpdm_driver = { }, .probe = asoc_mcpdm_probe, - .remove = asoc_mcpdm_remove, }; module_platform_driver(asoc_mcpdm_driver); diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 47bdbd415ad..8d809f8509c 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -32,8 +32,6 @@ #include <sound/dmaengine_pcm.h> #include <sound/soc.h> -#include "omap-pcm.h" - #ifdef CONFIG_ARCH_OMAP1 #define pcm_omap1510() cpu_is_omap1510() #else @@ -47,8 +45,6 @@ static const struct snd_pcm_hardware omap_pcm_hardware = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE, .period_bytes_min = 32, .period_bytes_max = 64 * 1024, .periods_min = 2, @@ -56,25 +52,6 @@ static const struct snd_pcm_hardware omap_pcm_hardware = { .buffer_bytes_max = 128 * 1024, }; -static int omap_pcm_get_dma_buswidth(int num_bits) -{ - int buswidth; - - switch (num_bits) { - case 16: - buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; - break; - case 32: - buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; - break; - default: - buswidth = -EINVAL; - break; - } - return buswidth; -} - - /* this may get called several times by oss emulation */ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) @@ -105,20 +82,9 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, if (err) return err; - /* Override the *_dma addr_width if requested by the DAI driver */ - if (dma_data->data_type) { - int buswidth = omap_pcm_get_dma_buswidth(dma_data->data_type); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - config.dst_addr_width = buswidth; - else - config.src_addr_width = buswidth; - } - - config.src_addr = dma_data->port_addr; - config.dst_addr = dma_data->port_addr; - config.src_maxburst = dma_data->packet_size; - config.dst_maxburst = dma_data->packet_size; + snd_dmaengine_pcm_set_config_from_dai_data(substream, + snd_soc_dai_get_dma_data(rtd->cpu_dai, substream), + &config); return dmaengine_slave_config(chan, &config); } @@ -129,37 +95,6 @@ static int omap_pcm_hw_free(struct snd_pcm_substream *substream) return 0; } -static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct omap_pcm_dma_data *dma_data; - int ret = 0; - - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - /* Configure McBSP internal buffer usage */ - if (dma_data->set_threshold) - dma_data->set_threshold(substream); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - break; - default: - ret = -EINVAL; - } - - if (ret == 0) - ret = snd_dmaengine_pcm_trigger(substream, cmd); - - return ret; -} - static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) { snd_pcm_uframes_t offset; @@ -174,29 +109,27 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) static int omap_pcm_open(struct snd_pcm_substream *substream) { - struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct omap_pcm_dma_data *dma_data; + struct snd_dmaengine_dai_dma_data *dma_data; int ret; snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware); - /* Ensure that buffer size is a multiple of period size */ - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - return ret; - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - ret = snd_dmaengine_pcm_open(substream, omap_dma_filter_fn, - &dma_data->dma_req); - return ret; -} -static int omap_pcm_close(struct snd_pcm_substream *substream) -{ - snd_dmaengine_pcm_close(substream); - return 0; + /* DT boot: filter_data is the DMA name */ + if (rtd->cpu_dai->dev->of_node) { + struct dma_chan *chan; + + chan = dma_request_slave_channel(rtd->cpu_dai->dev, + dma_data->filter_data); + ret = snd_dmaengine_pcm_open(substream, chan); + } else { + ret = snd_dmaengine_pcm_open_request_chan(substream, + omap_dma_filter_fn, + dma_data->filter_data); + } + return ret; } static int omap_pcm_mmap(struct snd_pcm_substream *substream, @@ -212,17 +145,15 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream, static struct snd_pcm_ops omap_pcm_ops = { .open = omap_pcm_open, - .close = omap_pcm_close, + .close = snd_dmaengine_pcm_close_release_chan, .ioctl = snd_pcm_lib_ioctl, .hw_params = omap_pcm_hw_params, .hw_free = omap_pcm_hw_free, - .trigger = omap_pcm_trigger, + .trigger = snd_dmaengine_pcm_trigger, .pointer = omap_pcm_pointer, .mmap = omap_pcm_mmap, }; -static u64 omap_pcm_dmamask = DMA_BIT_MASK(64); - static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) { @@ -267,12 +198,11 @@ static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd) { struct snd_card *card = rtd->card->snd_card; struct snd_pcm *pcm = rtd->pcm; - int ret = 0; + int ret; - if (!card->dev->dma_mask) - card->dev->dma_mask = &omap_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(64); + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(64)); + if (ret) + return ret; if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { ret = omap_pcm_preallocate_dma_buffer(pcm, @@ -302,31 +232,12 @@ static struct snd_soc_platform_driver omap_soc_platform = { .pcm_free = omap_pcm_free_dma_buffers, }; -static int omap_pcm_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, - &omap_soc_platform); -} - -static int omap_pcm_remove(struct platform_device *pdev) +int omap_pcm_platform_register(struct device *dev) { - snd_soc_unregister_platform(&pdev->dev); - return 0; + return devm_snd_soc_register_platform(dev, &omap_soc_platform); } - -static struct platform_driver omap_pcm_driver = { - .driver = { - .name = "omap-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = omap_pcm_probe, - .remove = omap_pcm_remove, -}; - -module_platform_driver(omap_pcm_driver); +EXPORT_SYMBOL_GPL(omap_pcm_platform_register); MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>"); MODULE_DESCRIPTION("OMAP PCM DMA module"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:omap-pcm-audio"); diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h deleted file mode 100644 index cabe74c4068..00000000000 --- a/sound/soc/omap/omap-pcm.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * omap-pcm.h - * - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com> - * Peter Ujfalusi <peter.ujfalusi@ti.com> - * - * 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 - * - */ - -#ifndef __OMAP_PCM_H__ -#define __OMAP_PCM_H__ - -struct snd_pcm_substream; - -struct omap_pcm_dma_data { - char *name; /* stream identifier */ - int dma_req; /* DMA request line */ - unsigned long port_addr; /* transmit/receive register */ - void (*set_threshold)(struct snd_pcm_substream *substream); - int data_type; /* 8, 16, 32 (bits) or 0 to let omap-pcm - * to decide the sDMA data type */ - int packet_size; /* packet size only in PACKET mode */ -}; - -#endif diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c index 4541d28b531..f8a6adc2d81 100644 --- a/sound/soc/omap/omap-twl4030.c +++ b/sound/soc/omap/omap-twl4030.c @@ -11,6 +11,8 @@ * omap3evm (Author: Anuj Aggarwal <anuj.aggarwal@ti.com>) * overo (Author: Steve Sakoman <steve@sakoman.com>) * igep0020 (Author: Enric Balletbo i Serra <eballetbo@iseebcn.com>) + * zoom2 (Author: Misael Lopez Cruz <misael.lopez@ti.com>) + * sdp3430 (Author: Misael Lopez Cruz <misael.lopez@ti.com>) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -32,13 +34,20 @@ #include <linux/platform_data/omap-twl4030.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/gpio.h> +#include <linux/of_gpio.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> +#include <sound/jack.h> #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) @@ -46,8 +55,7 @@ static int omap_twl4030_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_card *card = codec->card; + struct snd_soc_card *card = rtd->card; unsigned int fmt; int ret; @@ -87,24 +95,189 @@ 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 = rtd->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; +} + +static int omap_twl4030_card_remove(struct snd_soc_card *card) +{ + 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); + + return 0; +} + /* 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", + .platform_name = "omap-mcbsp.2", .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-mcbsp.2", + .codec_name = "twl4030-codec", + .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | + SND_SOC_DAIFMT_CBM_CFM, + }, }; /* Audio machine driver */ static struct snd_soc_card omap_twl4030_card = { .owner = THIS_MODULE, + .remove = omap_twl4030_card_remove, .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 +285,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 +311,33 @@ 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; + omap_twl4030_dai_links[0].platform_name = NULL; + omap_twl4030_dai_links[0].platform_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; + + omap_twl4030_dai_links[1].platform_name = NULL; + omap_twl4030_dai_links[1].platform_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,14 +345,20 @@ 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; } - ret = snd_soc_register_card(card); + snd_soc_card_set_drvdata(card, priv); + ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + dev_err(&pdev->dev, "devm_snd_soc_register_card() failed: %d\n", ret); return ret; } @@ -154,15 +366,6 @@ static int omap_twl4030_probe(struct platform_device *pdev) return 0; } -static int omap_twl4030_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; -} - static const struct of_device_id omap_twl4030_of_match[] = { {.compatible = "ti,omap-twl4030", }, { }, @@ -177,7 +380,6 @@ static struct platform_driver omap_twl4030_driver = { .of_match_table = omap_twl4030_of_match, }, .probe = omap_twl4030_probe, - .remove = omap_twl4030_remove, }; module_platform_driver(omap_twl4030_driver); diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index 43d950a79ff..076bec606d7 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c @@ -34,7 +34,6 @@ #include <linux/platform_data/asoc-ti-mcbsp.h> #include "omap-mcbsp.h" -#include "omap-pcm.h" #define OMAP3_PANDORA_DAC_POWER_GPIO 118 #define OMAP3_PANDORA_AMP_POWER_GPIO 14 @@ -80,12 +79,18 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream, static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { + int ret; + /* * The PCM1773 DAC datasheet requires 1ms delay between switching * VCC power on/off and /PD pin high/low */ if (SND_SOC_DAPM_EVENT_ON(event)) { - regulator_enable(omap3pandora_dac_reg); + ret = regulator_enable(omap3pandora_dac_reg); + if (ret) { + dev_err(w->dapm->dev, "Failed to power DAC: %d\n", ret); + return ret; + } mdelay(1); gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1); } else { @@ -116,7 +121,7 @@ static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w, * |A| <~~clk~~+ * |P| <--- TWL4030 <--------- Line In and MICs */ -static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = { +static const struct snd_soc_dapm_widget omap3pandora_dapm_widgets[] = { SND_SOC_DAPM_DAC_E("PCM DAC", "HiFi Playback", SND_SOC_NOPM, 0, 0, omap3pandora_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), @@ -125,37 +130,32 @@ static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = { SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_LINE("Line Out", NULL), -}; -static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = { SND_SOC_DAPM_MIC("Mic (internal)", NULL), SND_SOC_DAPM_MIC("Mic (external)", NULL), SND_SOC_DAPM_LINE("Line In", NULL), }; -static const struct snd_soc_dapm_route omap3pandora_out_map[] = { +static const struct snd_soc_dapm_route omap3pandora_map[] = { {"PCM DAC", NULL, "APLL Enable"}, {"Headphone Amplifier", NULL, "PCM DAC"}, {"Line Out", NULL, "PCM DAC"}, {"Headphone Jack", NULL, "Headphone Amplifier"}, -}; -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) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; /* All TWL4030 output pins are floating */ snd_soc_dapm_nc_pin(dapm, "EARPIECE"); @@ -169,20 +169,13 @@ static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "HFR"); snd_soc_dapm_nc_pin(dapm, "VIBRA"); - ret = snd_soc_dapm_new_controls(dapm, omap3pandora_out_dapm_widgets, - ARRAY_SIZE(omap3pandora_out_dapm_widgets)); - if (ret < 0) - return ret; - - return snd_soc_dapm_add_routes(dapm, omap3pandora_out_map, - ARRAY_SIZE(omap3pandora_out_map)); + return 0; } static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; /* Not comnnected */ snd_soc_dapm_nc_pin(dapm, "HSMIC"); @@ -190,13 +183,7 @@ static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "DIGIMIC0"); snd_soc_dapm_nc_pin(dapm, "DIGIMIC1"); - ret = snd_soc_dapm_new_controls(dapm, omap3pandora_in_dapm_widgets, - ARRAY_SIZE(omap3pandora_in_dapm_widgets)); - if (ret < 0) - return ret; - - return snd_soc_dapm_add_routes(dapm, omap3pandora_in_map, - ARRAY_SIZE(omap3pandora_in_map)); + return 0; } static struct snd_soc_ops omap3pandora_ops = { @@ -210,7 +197,7 @@ static struct snd_soc_dai_link omap3pandora_dai[] = { .stream_name = "HiFi Out", .cpu_dai_name = "omap-mcbsp.2", .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", + .platform_name = "omap-mcbsp.2", .codec_name = "twl4030-codec", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -221,7 +208,7 @@ static struct snd_soc_dai_link omap3pandora_dai[] = { .stream_name = "Line/Mic In", .cpu_dai_name = "omap-mcbsp.4", .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", + .platform_name = "omap-mcbsp.4", .codec_name = "twl4030-codec", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -236,6 +223,11 @@ static struct snd_soc_card snd_soc_card_omap3pandora = { .owner = THIS_MODULE, .dai_link = omap3pandora_dai, .num_links = ARRAY_SIZE(omap3pandora_dai), + + .dapm_widgets = omap3pandora_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(omap3pandora_dapm_widgets), + .dapm_routes = omap3pandora_map, + .num_dapm_routes = ARRAY_SIZE(omap3pandora_map), }; static struct platform_device *omap3pandora_snd_device; diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c index 06ef8d67ed1..aa4053bf671 100644 --- a/sound/soc/omap/osk5912.c +++ b/sound/soc/omap/osk5912.c @@ -33,7 +33,6 @@ #include <linux/platform_data/asoc-ti-mcbsp.h> #include "omap-mcbsp.h" -#include "omap-pcm.h" #include "../codecs/tlv320aic23.h" #define CODEC_CLOCK 12000000 @@ -97,7 +96,7 @@ static struct snd_soc_dai_link osk_dai = { .stream_name = "AIC23", .cpu_dai_name = "omap-mcbsp.1", .codec_dai_name = "tlv320aic23-hifi", - .platform_name = "omap-pcm-audio", + .platform_name = "omap-mcbsp.1", .codec_name = "tlv320aic23-codec", .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index d921ddbe3ec..943922c79f7 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -26,6 +26,7 @@ #include <linux/delay.h> #include <linux/gpio.h> #include <linux/platform_device.h> +#include <linux/gpio/consumer.h> #include <linux/module.h> #include <sound/core.h> #include <sound/jack.h> @@ -37,16 +38,6 @@ #include <asm/mach-types.h> #include "omap-mcbsp.h" -#include "omap-pcm.h" - -#define RX51_TVOUT_SEL_GPIO 40 -#define RX51_JACK_DETECT_GPIO 177 -#define RX51_ECI_SW_GPIO 182 -/* - * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This - * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c - */ -#define RX51_SPEAKER_AMP_TWL_GPIO (192 + 7) enum { RX51_JACK_DISABLED, @@ -55,12 +46,21 @@ enum { RX51_JACK_HS, /* headset: stereo output with mic */ }; +struct rx51_audio_pdata { + struct gpio_desc *tvout_selection_gpio; + struct gpio_desc *jack_detection_gpio; + struct gpio_desc *eci_sw_gpio; + struct gpio_desc *speaker_amp_gpio; +}; + static int rx51_spk_func; static int rx51_dmic_func; static int rx51_jack_func; static void rx51_ext_control(struct snd_soc_dapm_context *dapm) { + struct snd_soc_card *card = dapm->card; + struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card); int hp = 0, hs = 0, tvout = 0; switch (rx51_jack_func) { @@ -75,26 +75,30 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm) break; } + snd_soc_dapm_mutex_lock(dapm); + if (rx51_spk_func) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); if (rx51_dmic_func) - snd_soc_dapm_enable_pin(dapm, "DMic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "DMic"); else - snd_soc_dapm_disable_pin(dapm, "DMic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "DMic"); if (hp) - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); else - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); if (hs) - snd_soc_dapm_enable_pin(dapm, "HS Mic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "HS Mic"); else - snd_soc_dapm_disable_pin(dapm, "HS Mic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "HS Mic"); + + gpiod_set_value(pdata->tvout_selection_gpio, tvout); - gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout); + snd_soc_dapm_sync_unlocked(dapm); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_mutex_unlock(dapm); } static int rx51_startup(struct snd_pcm_substream *substream) @@ -151,10 +155,12 @@ static int rx51_set_spk(struct snd_kcontrol *kcontrol, static int rx51_spk_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - if (SND_SOC_DAPM_EVENT_ON(event)) - gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 1); - else - gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 0); + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card); + + gpiod_set_raw_value_cansleep(pdata->speaker_amp_gpio, + !!SND_SOC_DAPM_EVENT_ON(event)); return 0; } @@ -220,7 +226,6 @@ static struct snd_soc_jack rx51_av_jack; static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = { { - .gpio = RX51_JACK_DETECT_GPIO, .name = "avdet-gpio", .report = SND_JACK_HEADSET, .invert = 1, @@ -234,9 +239,6 @@ static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event), SND_SOC_DAPM_MIC("HS Mic", NULL), SND_SOC_DAPM_LINE("FM Transmitter", NULL), -}; - -static const struct snd_soc_dapm_widget aic34_dapm_widgetsb[] = { SND_SOC_DAPM_SPK("Earphone", NULL), }; @@ -248,21 +250,21 @@ static const struct snd_soc_dapm_route audio_map[] = { {"FM Transmitter", NULL, "LLOUT"}, {"FM Transmitter", NULL, "RLOUT"}, - {"DMic Rate 64", NULL, "Mic Bias 2V"}, - {"Mic Bias 2V", NULL, "DMic"}, -}; + {"DMic Rate 64", NULL, "Mic Bias"}, + {"Mic Bias", NULL, "DMic"}, -static const struct snd_soc_dapm_route audio_mapb[] = { {"b LINE2R", NULL, "MONO_LOUT"}, {"Earphone", NULL, "b HPLOUT"}, - {"LINE1L", NULL, "b Mic Bias 2.5V"}, - {"b Mic Bias 2.5V", NULL, "HS Mic"} + {"LINE1L", NULL, "b Mic Bias"}, + {"b Mic Bias", NULL, "HS Mic"} }; -static const char *spk_function[] = {"Off", "On"}; -static const char *input_function[] = {"ADC", "Digital Mic"}; -static const char *jack_function[] = {"Off", "TV-OUT", "Headphone", "Headset"}; +static const char * const spk_function[] = {"Off", "On"}; +static const char * const input_function[] = {"ADC", "Digital Mic"}; +static const char * const jack_function[] = { + "Off", "TV-OUT", "Headphone", "Headset" +}; static const struct soc_enum rx51_enum[] = { SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), @@ -278,15 +280,15 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = { SOC_ENUM_EXT("Jack Function", rx51_enum[2], rx51_get_jack, rx51_set_jack), SOC_DAPM_PIN_SWITCH("FM Transmitter"), -}; - -static const struct snd_kcontrol_new aic34_rx51_controlsb[] = { SOC_DAPM_PIN_SWITCH("Earphone"), }; static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_card *card = rtd->card; + struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card); + struct snd_soc_dapm_context *dapm = &codec->dapm; int err; @@ -295,57 +297,49 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "MIC3R"); snd_soc_dapm_nc_pin(dapm, "LINE1R"); - /* Add RX-51 specific controls */ - err = snd_soc_add_card_controls(rtd->card, aic34_rx51_controls, - ARRAY_SIZE(aic34_rx51_controls)); - if (err < 0) - return err; - - /* Add RX-51 specific widgets */ - snd_soc_dapm_new_controls(dapm, aic34_dapm_widgets, - ARRAY_SIZE(aic34_dapm_widgets)); - - /* Set up RX-51 specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - err = tpa6130a2_add_controls(codec); - if (err < 0) + if (err < 0) { + dev_err(card->dev, "Failed to add TPA6130A2 controls\n"); return err; + } snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42); - err = omap_mcbsp_st_add_controls(rtd); - if (err < 0) + err = omap_mcbsp_st_add_controls(rtd, 2); + if (err < 0) { + dev_err(card->dev, "Failed to add MCBSP controls\n"); return err; + } /* AV jack detection */ err = snd_soc_jack_new(codec, "AV Jack", SND_JACK_HEADSET | SND_JACK_VIDEOOUT, &rx51_av_jack); - if (err) + if (err) { + dev_err(card->dev, "Failed to add AV Jack\n"); return err; + } + + /* prepare gpio for snd_soc_jack_add_gpios */ + rx51_av_jack_gpios[0].gpio = desc_to_gpio(pdata->jack_detection_gpio); + devm_gpiod_put(card->dev, pdata->jack_detection_gpio); + err = snd_soc_jack_add_gpios(&rx51_av_jack, ARRAY_SIZE(rx51_av_jack_gpios), rx51_av_jack_gpios); + if (err) { + dev_err(card->dev, "Failed to add GPIOs\n"); + return err; + } return err; } -static int rx51_aic34b_init(struct snd_soc_dapm_context *dapm) +static int rx51_card_remove(struct snd_soc_card *card) { - int err; - - err = snd_soc_add_card_controls(dapm->card, aic34_rx51_controlsb, - ARRAY_SIZE(aic34_rx51_controlsb)); - if (err < 0) - return err; - - err = snd_soc_dapm_new_controls(dapm, aic34_dapm_widgetsb, - ARRAY_SIZE(aic34_dapm_widgetsb)); - if (err < 0) - return 0; + snd_soc_jack_free_gpios(&rx51_av_jack, ARRAY_SIZE(rx51_av_jack_gpios), + rx51_av_jack_gpios); - return snd_soc_dapm_add_routes(dapm, audio_mapb, - ARRAY_SIZE(audio_mapb)); + return 0; } /* Digital audio interface glue - connects codec <--> CPU */ @@ -355,7 +349,7 @@ static struct snd_soc_dai_link rx51_dai[] = { .stream_name = "AIC34", .cpu_dai_name = "omap-mcbsp.2", .codec_dai_name = "tlv320aic3x-hifi", - .platform_name = "omap-pcm-audio", + .platform_name = "omap-mcbsp.2", .codec_name = "tlv320aic3x-codec.2-0018", .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM, @@ -368,7 +362,6 @@ static struct snd_soc_aux_dev rx51_aux_dev[] = { { .name = "TLV320AIC34b", .codec_name = "tlv320aic3x-codec.2-0019", - .init = rx51_aic34b_init, }, }; @@ -383,69 +376,158 @@ static struct snd_soc_codec_conf rx51_codec_conf[] = { static struct snd_soc_card rx51_sound_card = { .name = "RX-51", .owner = THIS_MODULE, + .remove = rx51_card_remove, .dai_link = rx51_dai, .num_links = ARRAY_SIZE(rx51_dai), .aux_dev = rx51_aux_dev, .num_aux_devs = ARRAY_SIZE(rx51_aux_dev), .codec_conf = rx51_codec_conf, .num_configs = ARRAY_SIZE(rx51_codec_conf), -}; -static struct platform_device *rx51_snd_device; + .controls = aic34_rx51_controls, + .num_controls = ARRAY_SIZE(aic34_rx51_controls), + .dapm_widgets = aic34_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic34_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), +}; -static int __init rx51_soc_init(void) +static int rx51_soc_probe(struct platform_device *pdev) { + struct rx51_audio_pdata *pdata; + struct device_node *np = pdev->dev.of_node; + struct snd_soc_card *card = &rx51_sound_card; int err; - if (!machine_is_nokia_rx51()) + if (!machine_is_nokia_rx51() && !of_machine_is_compatible("nokia,omap3-n900")) return -ENODEV; - err = gpio_request_one(RX51_TVOUT_SEL_GPIO, - GPIOF_DIR_OUT | GPIOF_INIT_LOW, "tvout_sel"); - if (err) - goto err_gpio_tvout_sel; - err = gpio_request_one(RX51_ECI_SW_GPIO, - GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "eci_sw"); - if (err) - goto err_gpio_eci_sw; - - rx51_snd_device = platform_device_alloc("soc-audio", -1); - if (!rx51_snd_device) { - err = -ENOMEM; - goto err1; + card->dev = &pdev->dev; + + if (np) { + struct device_node *dai_node; + + dai_node = of_parse_phandle(np, "nokia,cpu-dai", 0); + if (!dai_node) { + dev_err(&pdev->dev, "McBSP node is not provided\n"); + return -EINVAL; + } + rx51_dai[0].cpu_dai_name = NULL; + rx51_dai[0].platform_name = NULL; + rx51_dai[0].cpu_of_node = dai_node; + rx51_dai[0].platform_of_node = dai_node; + + dai_node = of_parse_phandle(np, "nokia,audio-codec", 0); + if (!dai_node) { + dev_err(&pdev->dev, "Codec node is not provided\n"); + return -EINVAL; + } + rx51_dai[0].codec_name = NULL; + rx51_dai[0].codec_of_node = dai_node; + + dai_node = of_parse_phandle(np, "nokia,audio-codec", 1); + if (!dai_node) { + dev_err(&pdev->dev, "Auxiliary Codec node is not provided\n"); + return -EINVAL; + } + rx51_aux_dev[0].codec_name = NULL; + rx51_aux_dev[0].codec_of_node = dai_node; + rx51_codec_conf[0].dev_name = NULL; + rx51_codec_conf[0].of_node = dai_node; + + dai_node = of_parse_phandle(np, "nokia,headphone-amplifier", 0); + if (!dai_node) { + dev_err(&pdev->dev, "Headphone amplifier node is not provided\n"); + return -EINVAL; + } + + /* TODO: tpa6130a2a driver supports only a single instance, so + * this driver ignores the headphone-amplifier node for now. + * It's already mandatory in the DT binding to be future proof. + */ } - platform_set_drvdata(rx51_snd_device, &rx51_sound_card); + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (pdata == NULL) { + dev_err(card->dev, "failed to create private data\n"); + return -ENOMEM; + } + snd_soc_card_set_drvdata(card, pdata); - err = platform_device_add(rx51_snd_device); - if (err) - goto err2; + pdata->tvout_selection_gpio = devm_gpiod_get(card->dev, + "tvout-selection"); + if (IS_ERR(pdata->tvout_selection_gpio)) { + dev_err(card->dev, "could not get tvout selection gpio\n"); + return PTR_ERR(pdata->tvout_selection_gpio); + } - return 0; -err2: - platform_device_put(rx51_snd_device); -err1: - gpio_free(RX51_ECI_SW_GPIO); -err_gpio_eci_sw: - gpio_free(RX51_TVOUT_SEL_GPIO); -err_gpio_tvout_sel: + err = gpiod_direction_output(pdata->tvout_selection_gpio, 0); + if (err) { + dev_err(card->dev, "could not setup tvout selection gpio\n"); + return err; + } - return err; -} + pdata->jack_detection_gpio = devm_gpiod_get(card->dev, + "jack-detection"); + if (IS_ERR(pdata->jack_detection_gpio)) { + dev_err(card->dev, "could not get jack detection gpio\n"); + return PTR_ERR(pdata->jack_detection_gpio); + } -static void __exit rx51_soc_exit(void) -{ - snd_soc_jack_free_gpios(&rx51_av_jack, ARRAY_SIZE(rx51_av_jack_gpios), - rx51_av_jack_gpios); + pdata->eci_sw_gpio = devm_gpiod_get(card->dev, "eci-switch"); + if (IS_ERR(pdata->eci_sw_gpio)) { + dev_err(card->dev, "could not get eci switch gpio\n"); + return PTR_ERR(pdata->eci_sw_gpio); + } - platform_device_unregister(rx51_snd_device); - gpio_free(RX51_ECI_SW_GPIO); - gpio_free(RX51_TVOUT_SEL_GPIO); + err = gpiod_direction_output(pdata->eci_sw_gpio, 1); + if (err) { + dev_err(card->dev, "could not setup eci switch gpio\n"); + return err; + } + + pdata->speaker_amp_gpio = devm_gpiod_get(card->dev, + "speaker-amplifier"); + if (IS_ERR(pdata->speaker_amp_gpio)) { + dev_err(card->dev, "could not get speaker enable gpio\n"); + return PTR_ERR(pdata->speaker_amp_gpio); + } + + err = gpiod_direction_output(pdata->speaker_amp_gpio, 0); + if (err) { + dev_err(card->dev, "could not setup speaker enable gpio\n"); + return err; + } + + err = devm_snd_soc_register_card(card->dev, card); + if (err) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", err); + return err; + } + + return 0; } -module_init(rx51_soc_init); -module_exit(rx51_soc_exit); +#if defined(CONFIG_OF) +static const struct of_device_id rx51_audio_of_match[] = { + { .compatible = "nokia,n900-audio", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rx51_audio_of_match); +#endif + +static struct platform_driver rx51_soc_driver = { + .driver = { + .name = "rx51-audio", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(rx51_audio_of_match), + }, + .probe = rx51_soc_probe, +}; + +module_platform_driver(rx51_soc_driver); MODULE_AUTHOR("Nokia Corporation"); MODULE_DESCRIPTION("ALSA SoC Nokia RX-51"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rx51-audio"); diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c deleted file mode 100644 index b462a2c9385..00000000000 --- a/sound/soc/omap/sdp3430.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * sdp3430.c -- SoC audio for TI OMAP3430 SDP - * - * Author: Misael Lopez Cruz <x0052729@ti.com> - * - * Based on: - * Author: Steve Sakoman <steve@sakoman.com> - * - * 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 <linux/clk.h> -#include <linux/platform_device.h> -#include <linux/i2c/twl.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/soc.h> -#include <sound/jack.h> - -#include <asm/mach-types.h> -#include <linux/platform_data/gpio-omap.h> -#include <linux/platform_data/asoc-ti-mcbsp.h> - -/* Register descriptions for twl4030 codec part */ -#include <linux/mfd/twl4030-audio.h> -#include <linux/module.h> - -#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, - 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, "Mic Bias 1"}, - {"SUBMIC", NULL, "Mic Bias 2"}, - {"Mic Bias 1", NULL, "Ext Mic"}, - {"Mic Bias 2", NULL, "Ext Mic"}, - - /* 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"}, - - /* 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; -} - -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[] = { - { - .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, - .init = sdp3430_twl4030_voice_init, - .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; - u8 pin_mux; - - 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); - - /* 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; - - 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 <x0052729@ti.com>"); -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 771bff27ac3..00000000000 --- a/sound/soc/omap/zoom2.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * zoom2.c -- SoC audio for Zoom2 - * - * Author: Misael Lopez Cruz <x0052729@ti.com> - * - * 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 <linux/clk.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/soc.h> - -#include <asm/mach-types.h> -#include <linux/platform_data/asoc-ti-mcbsp.h> -#include <linux/platform_data/gpio-omap.h> - -/* Register descriptions for twl4030 codec part */ -#include <linux/mfd/twl4030-audio.h> -#include <linux/module.h> - -#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, "Mic Bias 1"}, - {"SUBMIC", NULL, "Mic Bias 2"}, - {"Mic Bias 1", NULL, "Ext Mic"}, - {"Mic Bias 2", NULL, "Ext Mic"}, - - /* 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 Bias"}, - {"Headset Mic Bias", NULL, "Headset Mic"}, - - /* 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; -} - -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[] = { - { - .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, - .init = zoom2_twl4030_voice_init, - .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 <x0052729@ti.com>"); -MODULE_DESCRIPTION("ALSA SoC Zoom2"); -MODULE_LICENSE("GPL"); - |
