summaryrefslogtreecommitdiffstats
path: root/sound/soc/ti
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2018-12-17 14:21:34 +0200
committerMark Brown <broonie@kernel.org>2018-12-18 12:22:43 +0000
commitf2055e145f2975a75dace8e386fad9364828cdb4 (patch)
tree447c549b6c72d4a8cedd34db1cb7b94691c21a16 /sound/soc/ti
parent0718f87b0df49570cdcb96179997bd372cac1742 (diff)
ASoC: ti: Merge davinci and omap directories
Create new directory to contain all Texas Instruments specific DAI, platform and machine drivers instead of scattering them under davinci and omap directories. There is already inter dependency between the two directories becasue of McASP (on dra7x it is serviced by sDMA, not EDMA). With the upcoming AM654 we will need to introduce new platform driver for UDMA and it does not fit under davinci, nor under omap. With the move I have restructured the Kconfig to be more usable in the era of simple-sound-card: CPU DAIs can be selected individually and they will select the platform driver they can be served with. To avoid breakage, I have moved over deprecated Kconfig options so defconfig builds will work without regression. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> For sound/soc/{omap => ti}: Tested-by: Jarkko Nikula <jarkko.nikula@bitmer.com> Acked-by: Jarkko Nikula <jarkko.nikula@bitmer.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/ti')
-rw-r--r--sound/soc/ti/Kconfig368
-rw-r--r--sound/soc/ti/Makefile44
-rw-r--r--sound/soc/ti/ams-delta.c594
-rw-r--r--sound/soc/ti/davinci-evm.c511
-rw-r--r--sound/soc/ti/davinci-i2s.c782
-rw-r--r--sound/soc/ti/davinci-i2s.h20
-rw-r--r--sound/soc/ti/davinci-mcasp.c2212
-rw-r--r--sound/soc/ti/davinci-mcasp.h306
-rw-r--r--sound/soc/ti/davinci-vcif.c259
-rw-r--r--sound/soc/ti/edma-pcm.c59
-rw-r--r--sound/soc/ti/edma-pcm.h32
-rw-r--r--sound/soc/ti/n810.c378
-rw-r--r--sound/soc/ti/omap-abe-twl6040.c353
-rw-r--r--sound/soc/ti/omap-dmic.c541
-rw-r--r--sound/soc/ti/omap-dmic.h69
-rw-r--r--sound/soc/ti/omap-hdmi.c418
-rw-r--r--sound/soc/ti/omap-mcbsp-priv.h324
-rw-r--r--sound/soc/ti/omap-mcbsp-st.c516
-rw-r--r--sound/soc/ti/omap-mcbsp.c1479
-rw-r--r--sound/soc/ti/omap-mcbsp.h46
-rw-r--r--sound/soc/ti/omap-mcpdm.c619
-rw-r--r--sound/soc/ti/omap-mcpdm.h107
-rw-r--r--sound/soc/ti/omap-twl4030.c353
-rw-r--r--sound/soc/ti/omap3pandora.c315
-rw-r--r--sound/soc/ti/osk5912.c187
-rw-r--r--sound/soc/ti/rx51.c493
-rw-r--r--sound/soc/ti/sdma-pcm.c74
-rw-r--r--sound/soc/ti/sdma-pcm.h21
28 files changed, 11480 insertions, 0 deletions
diff --git a/sound/soc/ti/Kconfig b/sound/soc/ti/Kconfig
new file mode 100644
index 000000000000..698810c770f0
--- /dev/null
+++ b/sound/soc/ti/Kconfig
@@ -0,0 +1,368 @@
+menu "Audio support for Texas Instruments SoCs"
+depends on DMA_OMAP || TI_EDMA || COMPILE_TEST
+
+config SND_SOC_TI_EDMA_PCM
+ tristate
+ select SND_SOC_GENERIC_DMAENGINE_PCM
+
+config SND_SOC_TI_SDMA_PCM
+ tristate
+ select SND_SOC_GENERIC_DMAENGINE_PCM
+
+comment "Texas Instruments DAI support for:"
+config SND_SOC_DAVINCI_ASP
+ tristate "daVinci Audio Serial Port (ASP) or McBSP suport"
+ depends on ARCH_DAVINCI || COMPILE_TEST
+ select SND_SOC_TI_EDMA_PCM
+ help
+ Say Y or M here if you want audio support via daVinci ASP or McBSP.
+ The driver only implements the ASP support which is a subset of
+ daVinci McBSP (w/o the multichannel support).
+
+config SND_SOC_DAVINCI_MCASP
+ tristate "Multichannel Audio Serial Port (McASP) support"
+ select SND_SOC_TI_EDMA_PCM if TI_EDMA
+ select SND_SOC_TI_SDMA_PCM if DMA_OMAP
+ help
+ Say Y or M here if you want to have support for McASP IP found in
+ various Texas Instruments SoCs like:
+ - daVinci devices
+ - Sitara line of SoCs (AM335x, AM438x, etc)
+ - DRA7x devices
+ - Keystone devices
+
+config SND_SOC_DAVINCI_VCIF
+ tristate "daVinci Voice Interface (VCIF) suport"
+ depends on ARCH_DAVINCI || COMPILE_TEST
+ select SND_SOC_TI_EDMA_PCM
+ help
+ Say Y or M here if you want audio support via daVinci VCIF.
+
+config SND_SOC_OMAP_DMIC
+ tristate "Digital Microphone Module (DMIC) support"
+ depends on ARCH_OMAP4 || SOC_OMAP5 || COMPILE_TEST
+ select SND_SOC_TI_SDMA_PCM
+ help
+ Say Y or M here if you want to have support for DMIC IP found in
+ OMAP4 and OMAP5.
+
+config SND_OMAP_SOC_MCBSP
+ tristate
+
+config SND_SOC_OMAP_MCBSP
+ tristate "Multichannel Buffered Serial Port (McBSP) support"
+ depends on ARCH_OMAP || ARCH_OMAP1 || COMPILE_TEST
+ select SND_SOC_TI_SDMA_PCM
+ select SND_OMAP_SOC_MCBSP
+ help
+ Say Y or M here if you want to have support for McBSP IP found in
+ Texas Instruments OMAP1/2/3/4/5 SoCs.
+
+config SND_SOC_OMAP_MCPDM
+ tristate "Multichannel PDM Controller (McPDM) support"
+ depends on ARCH_OMAP4 || SOC_OMAP5 || COMPILE_TEST
+ select SND_SOC_TI_SDMA_PCM
+ help
+ Say Y or M here if you want to have support for McPDM IP found in
+ OMAP4 and OMAP5.
+
+comment "Audio support for boards with Texas Instruments SoCs"
+config SND_SOC_NOKIA_N810
+ tristate "SoC Audio support for Nokia N810"
+ depends on MACH_NOKIA_N810 && I2C
+ select SND_SOC_OMAP_MCBSP
+ select SND_SOC_TLV320AIC3X
+ help
+ Say Y or M if you want to add support for SoC audio on Nokia N810.
+
+config SND_SOC_NOKIA_RX51
+ tristate "SoC Audio support for Nokia RX-51"
+ depends on ARCH_OMAP3 && I2C && GPIOLIB
+ select SND_SOC_OMAP_MCBSP
+ select SND_SOC_TLV320AIC3X
+ select SND_SOC_TPA6130A2
+ help
+ Say Y or M if you want to add support for SoC audio on Nokia RX-51
+ hardware. This is also known as Nokia N900 product.
+
+config SND_SOC_OMAP3_PANDORA
+ tristate "SoC Audio support for OMAP3 Pandora"
+ depends on ARCH_OMAP3
+ depends on TWL4030_CORE
+ select SND_SOC_OMAP_MCBSP
+ select SND_SOC_TWL4030
+ help
+ Say Y or M if you want to add support for SoC audio on the OMAP3 Pandora.
+
+config SND_SOC_OMAP3_TWL4030
+ tristate "SoC Audio support for OMAP3 based boards with twl4030 codec"
+ depends on ARCH_OMAP3 || COMPILE_TEST
+ depends on TWL4030_CORE
+ select SND_SOC_OMAP_MCBSP
+ select SND_SOC_TWL4030
+ help
+ Say Y or M if you want to add support for SoC audio on OMAP3 based
+ boards using twl4030 as codec. This driver currently supports:
+ - Beagleboard or Devkit8000
+ - Gumstix Overo or CompuLab CM-T35/CM-T3730
+ - IGEP v2
+ - OMAP3EVM
+ - SDP3430
+ - Zoom2
+
+config SND_SOC_OMAP_ABE_TWL6040
+ tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
+ depends on TWL6040_CORE && COMMON_CLK
+ depends on ARCH_OMAP4 || (SOC_OMAP5 && MFD_PALMAS) || COMPILE_TEST
+ select SND_SOC_OMAP_DMIC
+ select SND_SOC_OMAP_MCPDM
+ select SND_SOC_TWL6040
+ help
+ Say Y or M if you want to add support for SoC audio on OMAP boards
+ using ABE and twl6040 codec. This driver currently supports:
+ - SDP4430/Blaze boards
+ - PandaBoard (4430)
+ - PandaBoardES (4460)
+ - OMAP5 uEVM
+
+config SND_SOC_OMAP_AMS_DELTA
+ tristate "SoC Audio support for Amstrad E3 (Delta) videophone"
+ depends on MACH_AMS_DELTA && TTY
+ select SND_SOC_OMAP_MCBSP
+ select SND_SOC_CX20442
+ help
+ Say Y or M if you want to add support for SoC audio device
+ connected to a handset and a speakerphone found on Amstrad E3 (Delta)
+ videophone.
+
+ Note that in order to get those devices fully supported, you have to
+ build the kernel with standard serial port driver included and
+ configured for at least 4 ports. Then, from userspace, you must load
+ a line discipline #19 on the modem (ttyS3) serial line. The simplest
+ way to achieve this is to install util-linux-ng and use the included
+ ldattach utility. This can be started automatically from udev,
+ a simple rule like this one should do the trick (it does for me):
+ ACTION=="add", KERNEL=="controlC0", \
+ RUN+="/usr/sbin/ldattach 19 /dev/ttyS3"
+
+config SND_SOC_OMAP_HDMI
+ tristate "OMAP4/5 HDMI audio support"
+ depends on OMAP4_DSS_HDMI || OMAP5_DSS_HDMI || COMPILE_TEST
+ select SND_SOC_TI_SDMA_PCM
+ help
+ For HDMI audio to work OMAPDSS HDMI support should be
+ enabled.
+ The hdmi audio driver implements cpu-dai component using the
+ callbacks provided by OMAPDSS and registers the component
+ under DSS HDMI device. Omap-pcm is registered for platform
+ component also under DSS HDMI device. Dummy codec is used as
+ as codec component. The hdmi audio driver implements also
+ the card and registers it under its own platform device.
+ The device for the driver is registered by OMAPDSS hdmi
+ driver.
+
+config SND_SOC_OMAP_OSK5912
+ tristate "SoC Audio support for omap osk5912"
+ depends on MACH_OMAP_OSK && I2C
+ select SND_SOC_OMAP_MCBSP
+ select SND_SOC_TLV320AIC23_I2C
+ help
+ Say Y or M if you want to add support for SoC audio on osk5912.
+
+config SND_SOC_DAVINCI_EVM
+ tristate "SoC Audio support for DaVinci EVMs"
+ depends on ARCH_DAVINCI && I2C
+ select SND_SOC_DAVINCI_ASP if MACH_DAVINCI_DM355_EVM
+ select SND_SOC_DAVINCI_ASP if SND_SOC_DM365_AIC3X_CODEC
+ select SND_SOC_DAVINCI_VCIF if SND_SOC_DM365_VOICE_CODEC
+ select SND_SOC_DAVINCI_ASP if MACH_DAVINCI_EVM # DM6446
+ select SND_SOC_DAVINCI_MCASP if MACH_DAVINCI_DM6467_EVM
+ select SND_SOC_SPDIF if MACH_DAVINCI_DM6467_EVM
+ select SND_SOC_DAVINCI_MCASP if MACH_DAVINCI_DA830_EVM
+ select SND_SOC_DAVINCI_MCASP if MACH_DAVINCI_DA850_EVM
+ select SND_SOC_TLV320AIC3X
+ help
+ Say Y if you want to add support for SoC audio on the following TI
+ DaVinci EVM platforms:
+ - DM355
+ - DM365
+ - DM6446
+ - DM6447
+ - DM830
+ - DM850
+
+choice
+ prompt "DM365 codec select"
+ depends on SND_SOC_DAVINCI_EVM
+ depends on MACH_DAVINCI_DM365_EVM
+
+config SND_SOC_DM365_AIC3X_CODEC
+ bool "Audio Codec - AIC3101"
+ help
+ Say Y if you want to add support for AIC3101 audio codec
+
+config SND_SOC_DM365_VOICE_CODEC
+ bool "Voice Codec - CQ93VC"
+ select MFD_DAVINCI_VOICECODEC
+ select SND_SOC_CQ0093VC
+ help
+ Say Y if you want to add support for SoC On-chip voice codec
+endchoice
+
+menu "Deprecated kconfig options:"
+
+config SND_AM33XX_SOC_EVM
+ tristate "SoC Audio for the AM33XX chip based boards"
+ depends on SOC_AM33XX && I2C
+ select SND_SOC_TLV320AIC3X
+ select SND_SOC_DAVINCI_MCASP
+ help
+ Say Y or M if you want to add support for SoC audio on AM33XX
+ boards using McASP and TLV320AIC3X codec. For example AM335X-EVM,
+ AM335X-EVMSK, and BeagelBone with AudioCape boards have this
+ setup.
+
+config SND_DAVINCI_SOC_EVM
+ tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
+ depends on ARCH_DAVINCI && I2C
+ depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM
+ select SND_SOC_DAVINCI_EVM
+ help
+ Say Y if you want to add support for SoC audio on TI
+ DaVinci DM6446, DM355 or DM365 EVM platforms.
+
+choice
+ prompt "DM365 codec select"
+ depends on SND_DAVINCI_SOC_EVM
+ depends on MACH_DAVINCI_DM365_EVM
+
+config SND_DM365_AIC3X_CODEC
+ tristate "Audio Codec - AIC3101"
+ select SND_SOC_DM365_AIC3X_CODEC
+ help
+ Say Y if you want to add support for AIC3101 audio codec
+
+config SND_DM365_VOICE_CODEC
+ tristate "Voice Codec - CQ93VC"
+ select SND_SOC_DM365_VOICE_CODEC
+ help
+ Say Y if you want to add support for SoC On-chip voice codec
+endchoice
+
+config SND_DM6467_SOC_EVM
+ tristate "SoC Audio support for DaVinci DM6467 EVM"
+ depends on MACH_DAVINCI_DM6467_EVM && I2C
+ select SND_SOC_DAVINCI_EVM
+
+ help
+ Say Y if you want to add support for SoC audio on TI
+
+config SND_DA830_SOC_EVM
+ tristate "SoC Audio support for DA830/OMAP-L137 EVM"
+ depends on MACH_DAVINCI_DA830_EVM && I2C
+ select SND_SOC_DAVINCI_EVM
+
+ help
+ Say Y if you want to add support for SoC audio on TI
+ DA830/OMAP-L137 EVM
+
+config SND_DA850_SOC_EVM
+ tristate "SoC Audio support for DA850/OMAP-L138 EVM"
+ depends on MACH_DAVINCI_DA850_EVM && I2C
+ select SND_SOC_DAVINCI_EVM
+ help
+ Say Y if you want to add support for SoC audio on TI
+ DA850/OMAP-L138 EVM
+
+config SND_OMAP_SOC_HDMI_AUDIO
+ tristate "HDMI audio support for OMAP4+ based SoCs"
+ select SND_SOC_OMAP_HDMI
+ help
+ For HDMI audio to work OMAPDSS HDMI support should be
+ enabled.
+ The hdmi audio driver implements cpu-dai component using the
+ callbacks provided by OMAPDSS and registers the component
+ under DSS HDMI device. Omap-pcm is registered for platform
+ component also under DSS HDMI device. Dummy codec is used as
+ as codec component. The hdmi audio driver implements also
+ the card and registers it under its own platform device.
+ The device for the driver is registered by OMAPDSS hdmi
+ driver.
+
+config SND_OMAP_SOC_N810
+ tristate "SoC Audio support for Nokia N810"
+ depends on MACH_NOKIA_N810 && I2C
+ select SND_SOC_NOKIA_N810
+ help
+ Say Y if you want to add support for SoC audio on Nokia N810.
+
+config SND_OMAP_SOC_RX51
+ tristate "SoC Audio support for Nokia N900 (RX-51)"
+ depends on ARM && I2C && GPIOLIB && ARCH_OMAP3
+ select SND_SOC_NOKIA_RX51
+ help
+ Say Y if you want to add support for SoC audio on Nokia N900
+ cellphone.
+
+config SND_OMAP_SOC_AMS_DELTA
+ tristate "SoC Audio support for Amstrad E3 (Delta) videophone"
+ depends on MACH_AMS_DELTA && TTY
+ select SND_SOC_OMAP_AMS_DELTA
+ help
+ Say Y if you want to add support for SoC audio device connected to
+ a handset and a speakerphone found on Amstrad E3 (Delta) videophone.
+
+ Note that in order to get those devices fully supported, you have to
+ build the kernel with standard serial port driver included and
+ configured for at least 4 ports. Then, from userspace, you must load
+ a line discipline #19 on the modem (ttyS3) serial line. The simplest
+ way to achieve this is to install util-linux-ng and use the included
+ ldattach utility. This can be started automatically from udev,
+ a simple rule like this one should do the trick (it does for me):
+ ACTION=="add", KERNEL=="controlC0", \
+ RUN+="/usr/sbin/ldattach 19 /dev/ttyS3"
+
+config SND_OMAP_SOC_OSK5912
+ tristate "SoC Audio support for omap osk5912"
+ depends on MACH_OMAP_OSK && I2C
+ select SND_SOC_OMAP_OSK5912
+ help
+ Say Y if you want to add support for SoC audio on osk5912.
+
+config SND_OMAP_SOC_OMAP_TWL4030
+ tristate "SoC Audio support for TI SoC based boards with twl4030 codec"
+ depends on TWL4030_CORE
+ select SND_SOC_OMAP3_TWL4030
+ help
+ Say Y if you want to add support for SoC audio on TI SoC based boards
+ using twl4030 as c codec. This driver currently supports:
+ - Beagleboard or Devkit8000
+ - 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 && COMMON_CLK
+ depends on ARCH_OMAP4 || (SOC_OMAP5 && MFD_PALMAS) || COMPILE_TEST
+ select SND_SOC_OMAP_ABE_TWL6040
+ help
+ Say Y if you want to add support for SoC audio on OMAP boards using
+ ABE and twl6040 codec. This driver currently supports:
+ - SDP4430/Blaze boards
+ - PandaBoard (4430)
+ - PandaBoardES (4460)
+ - omap5-uevm (5432)
+
+config SND_OMAP_SOC_OMAP3_PANDORA
+ tristate "SoC Audio support for OMAP3 Pandora"
+ depends on TWL4030_CORE
+ select SND_SOC_OMAP3_PANDORA
+ help
+ Say Y if you want to add support for SoC audio on the OMAP3 Pandora.
+endmenu
+
+endmenu
+
diff --git a/sound/soc/ti/Makefile b/sound/soc/ti/Makefile
new file mode 100644
index 000000000000..08c44d56ef3e
--- /dev/null
+++ b/sound/soc/ti/Makefile
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# Platform drivers
+snd-soc-ti-edma-objs := edma-pcm.o
+snd-soc-ti-sdma-objs := sdma-pcm.o
+
+obj-$(CONFIG_SND_SOC_TI_EDMA_PCM) += snd-soc-ti-edma.o
+obj-$(CONFIG_SND_SOC_TI_SDMA_PCM) += snd-soc-ti-sdma.o
+
+# CPU DAI drivers
+snd-soc-davinci-asp-objs := davinci-i2s.o
+snd-soc-davinci-mcasp-objs := davinci-mcasp.o
+snd-soc-davinci-vcif-objs := davinci-vcif.o
+snd-soc-omap-dmic-objs := omap-dmic.o
+snd-soc-omap-mcbsp-objs := omap-mcbsp.o omap-mcbsp-st.o
+snd-soc-omap-mcpdm-objs := omap-mcpdm.o
+
+obj-$(CONFIG_SND_SOC_DAVINCI_ASP) += snd-soc-davinci-asp.o
+obj-$(CONFIG_SND_SOC_DAVINCI_MCASP) += snd-soc-davinci-mcasp.o
+obj-$(CONFIG_SND_SOC_DAVINCI_VCIF) += snd-soc-davinci-vcif.o
+obj-$(CONFIG_SND_SOC_OMAP_DMIC) += snd-soc-omap-dmic.o
+obj-$(CONFIG_SND_SOC_OMAP_MCBSP) += snd-soc-omap-mcbsp.o
+obj-$(CONFIG_SND_SOC_OMAP_MCPDM) += snd-soc-omap-mcpdm.o
+
+# Machine drivers
+snd-soc-davinci-evm-objs := davinci-evm.o
+snd-soc-n810-objs := n810.o
+snd-soc-rx51-objs := rx51.o
+snd-soc-omap3pandora-objs := omap3pandora.o
+snd-soc-omap-twl4030-objs := omap-twl4030.o
+snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o
+snd-soc-ams-delta-objs := ams-delta.o
+snd-soc-omap-hdmi-objs := omap-hdmi.o
+snd-soc-osk5912-objs := osk5912.o
+
+obj-$(CONFIG_SND_SOC_DAVINCI_EVM) += snd-soc-davinci-evm.o
+obj-$(CONFIG_SND_SOC_NOKIA_N810) += snd-soc-n810.o
+obj-$(CONFIG_SND_SOC_NOKIA_RX51) += snd-soc-rx51.o
+obj-$(CONFIG_SND_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
+obj-$(CONFIG_SND_SOC_OMAP3_TWL4030) += snd-soc-omap-twl4030.o
+obj-$(CONFIG_SND_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o
+obj-$(CONFIG_SND_SOC_OMAP_AMS_DELTA) += snd-soc-ams-delta.o
+obj-$(CONFIG_SND_SOC_OMAP_HDMI) += snd-soc-omap-hdmi.o
+obj-$(CONFIG_SND_SOC_OMAP_OSK5912) += snd-soc-osk5912.o
diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c
new file mode 100644
index 000000000000..4dce494dfbd3
--- /dev/null
+++ b/sound/soc/ti/ams-delta.c
@@ -0,0 +1,594 @@
+/*
+ * ams-delta.c -- SoC audio for Amstrad E3 (Delta) videophone
+ *
+ * Copyright (C) 2009 Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
+ *
+ * Initially based on sound/soc/omap/osk5912.x
+ * Copyright (C) 2008 Mistral Solutions
+ *
+ * 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/gpio/consumer.h>
+#include <linux/spinlock.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+
+#include <sound/soc.h>
+#include <sound/jack.h>
+
+#include <asm/mach-types.h>
+
+#include <linux/platform_data/asoc-ti-mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "../codecs/cx20442.h"
+
+/* Board specific DAPM widgets */
+static const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = {
+ /* Handset */
+ SND_SOC_DAPM_MIC("Mouthpiece", NULL),
+ SND_SOC_DAPM_HP("Earpiece", NULL),
+ /* Handsfree/Speakerphone */
+ SND_SOC_DAPM_MIC("Microphone", NULL),
+ SND_SOC_DAPM_SPK("Speaker", NULL),
+};
+
+/* How they are connected to codec pins */
+static const struct snd_soc_dapm_route ams_delta_audio_map[] = {
+ {"TELIN", NULL, "Mouthpiece"},
+ {"Earpiece", NULL, "TELOUT"},
+
+ {"MIC", NULL, "Microphone"},
+ {"Speaker", NULL, "SPKOUT"},
+};
+
+/*
+ * Controls, functional after the modem line discipline is activated.
+ */
+
+/* Virtual switch: audio input/output constellations */
+static const char *ams_delta_audio_mode[] =
+ {"Mixed", "Handset", "Handsfree", "Speakerphone"};
+
+/* Selection <-> pin translation */
+#define AMS_DELTA_MOUTHPIECE 0
+#define AMS_DELTA_EARPIECE 1
+#define AMS_DELTA_MICROPHONE 2
+#define AMS_DELTA_SPEAKER 3
+#define AMS_DELTA_AGC 4
+
+#define AMS_DELTA_MIXED ((1 << AMS_DELTA_EARPIECE) | \
+ (1 << AMS_DELTA_MICROPHONE))
+#define AMS_DELTA_HANDSET ((1 << AMS_DELTA_MOUTHPIECE) | \
+ (1 << AMS_DELTA_EARPIECE))
+#define AMS_DELTA_HANDSFREE ((1 << AMS_DELTA_MICROPHONE) | \
+ (1 << AMS_DELTA_SPEAKER))
+#define AMS_DELTA_SPEAKERPHONE (AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC))
+
+static const unsigned short ams_delta_audio_mode_pins[] = {
+ AMS_DELTA_MIXED,
+ AMS_DELTA_HANDSET,
+ AMS_DELTA_HANDSFREE,
+ AMS_DELTA_SPEAKERPHONE,
+};
+
+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_component *cx20442_codec;
+
+static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ 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 (!cx20442_codec->card->pop_time)
+ return -EUNATCH;
+
+ if (ucontrol->value.enumerated.item[0] >= control->items)
+ return -EINVAL;
+
+ 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_unlocked(dapm, "Mouthpiece");
+ else
+ 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_unlocked(dapm, "Earpiece");
+ else
+ 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_unlocked(dapm, "Microphone");
+ else
+ 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_unlocked(dapm, "Speaker");
+ else
+ 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_unlocked(dapm, "AGCIN");
+ else
+ snd_soc_dapm_disable_pin_unlocked(dapm, "AGCIN");
+ }
+
+ if (changed)
+ snd_soc_dapm_sync_unlocked(dapm);
+
+ snd_soc_dapm_mutex_unlock(dapm);
+
+ return changed;
+}
+
+static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ 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") <<
+ AMS_DELTA_MOUTHPIECE) |
+ (snd_soc_dapm_get_pin_status(dapm, "Earpiece") <<
+ AMS_DELTA_EARPIECE));
+ if (pins)
+ pins |= (snd_soc_dapm_get_pin_status(dapm, "Microphone") <<
+ AMS_DELTA_MICROPHONE);
+ else
+ pins = ((snd_soc_dapm_get_pin_status(dapm, "Microphone") <<
+ AMS_DELTA_MICROPHONE) |
+ (snd_soc_dapm_get_pin_status(dapm, "Speaker") <<
+ AMS_DELTA_SPEAKER) |
+ (ams_delta_audio_agc << AMS_DELTA_AGC));
+
+ for (mode = 0; mode < ARRAY_SIZE(ams_delta_audio_mode); mode++)
+ if (pins == ams_delta_audio_mode_pins[mode])
+ break;
+
+ if (mode >= ARRAY_SIZE(ams_delta_audio_mode))
+ return -EINVAL;
+
+ ucontrol->value.enumerated.item[0] = mode;
+
+ return 0;
+}
+
+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,
+ ams_delta_get_audio_mode, ams_delta_set_audio_mode),
+};
+
+/* Hook switch */
+static struct snd_soc_jack ams_delta_hook_switch;
+static struct snd_soc_jack_gpio ams_delta_hook_switch_gpios[] = {
+ {
+ .name = "hook_switch",
+ .report = SND_JACK_HEADSET,
+ .invert = 1,
+ .debounce_time = 150,
+ }
+};
+
+/* After we are able to control the codec over the modem,
+ * the hook switch can be used for dynamic DAPM reconfiguration. */
+static struct snd_soc_jack_pin ams_delta_hook_switch_pins[] = {
+ /* Handset */
+ {
+ .pin = "Mouthpiece",
+ .mask = SND_JACK_MICROPHONE,
+ },
+ {
+ .pin = "Earpiece",
+ .mask = SND_JACK_HEADPHONE,
+ },
+ /* Handsfree */
+ {
+ .pin = "Microphone",
+ .mask = SND_JACK_MICROPHONE,
+ .invert = 1,
+ },
+ {
+ .pin = "Speaker",
+ .mask = SND_JACK_HEADPHONE,
+ .invert = 1,
+ },
+};
+
+
+/*
+ * Modem line discipline, required for making above controls functional.
+ * Activated from userspace with ldattach, possibly invoked from udev rule.
+ */
+
+/* To actually apply any modem controlled configuration changes to the codec,
+ * we must connect codec DAI pins to the modem for a moment. Be careful not
+ * to interfere with our digital mute function that shares the same hardware. */
+static struct timer_list cx81801_timer;
+static bool cx81801_cmd_pending;
+static bool ams_delta_muted;
+static DEFINE_SPINLOCK(ams_delta_lock);
+static struct gpio_desc *gpiod_modem_codec;
+
+static void cx81801_timeout(struct timer_list *unused)
+{
+ int muted;
+
+ spin_lock(&ams_delta_lock);
+ cx81801_cmd_pending = 0;
+ muted = ams_delta_muted;
+ spin_unlock(&ams_delta_lock);
+
+ /* Reconnect the codec DAI back from the modem to the CPU DAI
+ * only if digital mute still off */
+ if (!muted)
+ gpiod_set_value(gpiod_modem_codec, 0);
+}
+
+/* Line discipline .open() */
+static int cx81801_open(struct tty_struct *tty)
+{
+ int ret;
+
+ if (!cx20442_codec)
+ return -ENODEV;
+
+ /*
+ * Pass the codec structure pointer for use by other ldisc callbacks,
+ * both the card and the codec specific parts.
+ */
+ tty->disc_data = cx20442_codec;
+
+ ret = v253_ops.open(tty);
+
+ if (ret < 0)
+ tty->disc_data = NULL;
+
+ return ret;
+}
+
+/* Line discipline .close() */
+static void cx81801_close(struct tty_struct *tty)
+{
+ struct snd_soc_component *component = tty->disc_data;
+ struct snd_soc_dapm_context *dapm = &component->card->dapm;
+
+ del_timer_sync(&cx81801_timer);
+
+ /* Prevent the hook switch from further changing the DAPM pins */
+ INIT_LIST_HEAD(&ams_delta_hook_switch.pins);
+
+ if (!component)
+ return;
+
+ v253_ops.close(tty);
+
+ /* Revert back to default audio input/output constellation */
+ 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() */
+static int cx81801_hangup(struct tty_struct *tty)
+{
+ cx81801_close(tty);
+ return 0;
+}
+
+/* Line discipline .receive_buf() */
+static void cx81801_receive(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count)
+{
+ struct snd_soc_component *component = tty->disc_data;
+ const unsigned char *c;
+ int apply, ret;
+
+ if (!component)
+ return;
+
+ if (!component->card->pop_time) {
+ /* First modem response, complete setup procedure */
+
+ /* Initialize timer used for config pulse generation */
+ timer_setup(&cx81801_timer, cx81801_timeout, 0);
+
+ v253_ops.receive_buf(tty, cp, fp, count);
+
+ /* Link hook switch to DAPM pins */
+ ret = snd_soc_jack_add_pins(&ams_delta_hook_switch,
+ ARRAY_SIZE(ams_delta_hook_switch_pins),
+ ams_delta_hook_switch_pins);
+ if (ret)
+ dev_warn(component->dev,
+ "Failed to link hook switch to DAPM pins, "
+ "will continue with hook switch unlinked.\n");
+
+ return;
+ }
+
+ v253_ops.receive_buf(tty, cp, fp, count);
+
+ for (c = &cp[count - 1]; c >= cp; c--) {
+ if (*c != '\r')
+ continue;
+ /* Complete modem response received, apply config to codec */
+
+ spin_lock_bh(&ams_delta_lock);
+ mod_timer(&cx81801_timer, jiffies + msecs_to_jiffies(150));
+ apply = !ams_delta_muted && !cx81801_cmd_pending;
+ cx81801_cmd_pending = 1;
+ spin_unlock_bh(&ams_delta_lock);
+
+ /* Apply config pulse by connecting the codec to the modem
+ * if not already done */
+ if (apply)
+ gpiod_set_value(gpiod_modem_codec, 1);
+ break;
+ }
+}
+
+/* Line discipline .write_wakeup() */
+static void cx81801_wakeup(struct tty_struct *tty)
+{
+ v253_ops.write_wakeup(tty);
+}
+
+static struct tty_ldisc_ops cx81801_ops = {
+ .magic = TTY_LDISC_MAGIC,
+ .name = "cx81801",
+ .owner = THIS_MODULE,
+ .open = cx81801_open,
+ .close = cx81801_close,
+ .hangup = cx81801_hangup,
+ .receive_buf = cx81801_receive,
+ .write_wakeup = cx81801_wakeup,
+};
+
+
+/*
+ * Even if not very useful, the sound card can still work without any of the
+ * above functonality activated. You can still control its audio input/output
+ * constellation and speakerphone gain from userspace by issuing AT commands
+ * over the modem port.
+ */
+
+static struct snd_soc_ops ams_delta_ops;
+
+
+/* Digital mute implemented using modem/CPU multiplexer.
+ * Shares hardware with codec config pulse generation */
+static bool ams_delta_muted = 1;
+
+static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+ int apply;
+
+ if (ams_delta_muted == mute)
+ return 0;
+
+ spin_lock_bh(&ams_delta_lock);
+ ams_delta_muted = mute;
+ apply = !cx81801_cmd_pending;
+ spin_unlock_bh(&ams_delta_lock);
+
+ if (apply)
+ gpiod_set_value(gpiod_modem_codec, !!mute);
+ return 0;
+}
+
+/* Our codec DAI probably doesn't have its own .ops structure */
+static const struct snd_soc_dai_ops ams_delta_dai_ops = {
+ .digital_mute = ams_delta_digital_mute,
+};