Merge tag 'asoc-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound...
authorTakashi Iwai <tiwai@suse.de>
Tue, 5 Jun 2018 14:51:55 +0000 (16:51 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 5 Jun 2018 14:51:55 +0000 (16:51 +0200)
ASoC: Updates for v4.18

This is a very big update, mainly due to a huge set of new drivers some
of which are individually very large.  We also have a lot of fixes for
the topology stuff, several of the users have stepped up and fixed some
the serious issues there, and continued progress on the transition away
from CODEC specific drivers to generic component drivers.

 - Many fixes for the topology code, including fixes for the half done
   v4 ABI compatibility from Guenter Roeck and other ABI fixes from
   Kirill Marinushkin.
 - Lots of cleanup for Intel platforms based on Realtek CODECs from Hans
   de Goode.
 - More followups on removing legacy CODEC things and transitioning to
   components from Morimoto-san.
 - Conversion of OMAP DMA to the new, more standard SDMA-PCM driver.
 - A series of fixes and updates to the rather elderly Cirrus Logic SoC
   drivers from Alexander Sverdlin.
 - Qualcomm DSP support from Srinivas Kandagatla.
 - New drivers for Analog SSM2305, Atmel I2S controllers, Mediatek
   MT6351, MT6797 and MT7622, Qualcomm DSPs, Realtek RT1305, RT1306 and
   RT5668 and TI TSCS454

257 files changed:
.mailmap
Documentation/devicetree/bindings/soc/qcom/qcom,apr.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/adi,ssm2305.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/atmel-i2s.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/cs42xx8.txt
Documentation/devicetree/bindings/sound/fsl,asrc.txt
Documentation/devicetree/bindings/sound/fsl,esai.txt
Documentation/devicetree/bindings/sound/fsl,spdif.txt
Documentation/devicetree/bindings/sound/fsl-sai.txt
Documentation/devicetree/bindings/sound/mt2701-afe-pcm.txt
Documentation/devicetree/bindings/sound/mt6351.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/mt6797-afe-pcm.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/mt6797-mt6351.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/qcom,apq8096.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/qcom,q6adm.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/qcom,q6afe.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/qcom,q6asm.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/qcom,q6core.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/rt274.txt
Documentation/devicetree/bindings/sound/rt5514.txt
Documentation/devicetree/bindings/sound/rt5616.txt
Documentation/devicetree/bindings/sound/rt5640.txt
Documentation/devicetree/bindings/sound/rt5645.txt
Documentation/devicetree/bindings/sound/rt5651.txt
Documentation/devicetree/bindings/sound/rt5663.txt
Documentation/devicetree/bindings/sound/rt5668.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/sgtl5000.txt
Documentation/devicetree/bindings/sound/simple-card.txt
Documentation/devicetree/bindings/sound/ti,tas6424.txt
Documentation/devicetree/bindings/sound/tscs42xx.txt
Documentation/devicetree/bindings/sound/tscs454.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8510.txt
Documentation/devicetree/bindings/sound/wm8523.txt
Documentation/devicetree/bindings/sound/wm8524.txt
Documentation/devicetree/bindings/sound/wm8580.txt
Documentation/devicetree/bindings/sound/wm8711.txt
Documentation/devicetree/bindings/sound/wm8728.txt
Documentation/devicetree/bindings/sound/wm8731.txt
Documentation/devicetree/bindings/sound/wm8737.txt
Documentation/devicetree/bindings/sound/wm8741.txt
Documentation/devicetree/bindings/sound/wm8750.txt
Documentation/devicetree/bindings/sound/wm8753.txt
Documentation/devicetree/bindings/sound/wm8770.txt
Documentation/devicetree/bindings/sound/wm8776.txt
Documentation/devicetree/bindings/sound/wm8804.txt
Documentation/devicetree/bindings/sound/wm8903.txt
Documentation/devicetree/bindings/sound/wm8960.txt
Documentation/devicetree/bindings/sound/wm8962.txt
Documentation/devicetree/bindings/sound/wm8994.txt
Documentation/sound/soc/codec.rst
Documentation/sound/soc/platform.rst
MAINTAINERS
arch/arm/mach-ep93xx/core.c
drivers/media/i2c/tda1997x.c
drivers/soc/qcom/Kconfig
drivers/soc/qcom/Makefile
drivers/soc/qcom/apr.c [new file with mode: 0644]
include/dt-bindings/soc/qcom,apr.h [new file with mode: 0644]
include/dt-bindings/sound/fsl-imx-audmux.h
include/dt-bindings/sound/qcom,q6afe.h [new file with mode: 0644]
include/dt-bindings/sound/qcom,q6asm.h [new file with mode: 0644]
include/dt-bindings/sound/rt5640.h [new file with mode: 0644]
include/linux/mfd/wm8350/audio.h
include/linux/mod_devicetable.h
include/linux/soc/qcom/apr.h [new file with mode: 0644]
include/sound/omap-pcm.h [deleted file]
include/sound/rt5640.h [deleted file]
include/sound/rt5668.h [new file with mode: 0644]
include/sound/soc-dai.h
include/sound/soc.h
include/trace/events/asoc.h
include/uapi/sound/asoc.h
include/uapi/sound/skl-tplg-interface.h [new file with mode: 0644]
sound/soc/Makefile
sound/soc/amd/acp-da7219-max98357a.c
sound/soc/amd/acp-pcm-dma.c
sound/soc/amd/acp.h
sound/soc/atmel/Kconfig
sound/soc/atmel/Makefile
sound/soc/atmel/atmel-i2s.c [new file with mode: 0644]
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/bcm/Kconfig
sound/soc/cirrus/Kconfig
sound/soc/cirrus/edb93xx.c
sound/soc/cirrus/ep93xx-i2s.c
sound/soc/cirrus/snappercl15.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/adau17x1.c
sound/soc/codecs/cs35l35.c
sound/soc/codecs/max98088.c
sound/soc/codecs/max98095.c
sound/soc/codecs/max9860.c
sound/soc/codecs/max9860.h
sound/soc/codecs/mt6351.c [new file with mode: 0644]
sound/soc/codecs/mt6351.h [new file with mode: 0644]
sound/soc/codecs/nau8810.c
sound/soc/codecs/nau8824.c
sound/soc/codecs/pcm1789.c
sound/soc/codecs/pcm512x-i2c.c
sound/soc/codecs/rt1305.c [new file with mode: 0644]
sound/soc/codecs/rt1305.h [new file with mode: 0644]
sound/soc/codecs/rt5640.c
sound/soc/codecs/rt5640.h
sound/soc/codecs/rt5645.c
sound/soc/codecs/rt5663.c
sound/soc/codecs/rt5663.h
sound/soc/codecs/rt5668.c [new file with mode: 0644]
sound/soc/codecs/rt5668.h [new file with mode: 0644]
sound/soc/codecs/rt5670.c
sound/soc/codecs/rt5677.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/sgtl5000.h
sound/soc/codecs/ssm2305.c [new file with mode: 0644]
sound/soc/codecs/tas6424.c
sound/soc/codecs/tas6424.h
sound/soc/codecs/tfa9879.c
sound/soc/codecs/tfa9879.h
sound/soc/codecs/tscs42xx.c
sound/soc/codecs/tscs42xx.h
sound/soc/codecs/tscs454.c [new file with mode: 0644]
sound/soc/codecs/tscs454.h [new file with mode: 0644]
sound/soc/codecs/wm2200.c
sound/soc/codecs/wm5100.c
sound/soc/codecs/wm8782.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm_adsp.c
sound/soc/davinci/Kconfig
sound/soc/davinci/davinci-mcasp.c
sound/soc/fsl/fsl_esai.c
sound/soc/fsl/fsl_esai.h
sound/soc/fsl/fsl_sai.c
sound/soc/fsl/fsl_sai.h
sound/soc/fsl/fsl_spdif.c
sound/soc/fsl/fsl_spdif.h
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/fsl_ssi.h
sound/soc/fsl/fsl_ssi_dbg.c
sound/soc/generic/simple-card.c
sound/soc/hisilicon/hi6210-i2s.c
sound/soc/intel/Kconfig
sound/soc/intel/boards/bxt_da7219_max98357a.c
sound/soc/intel/boards/bxt_rt298.c
sound/soc/intel/boards/byt-max98090.c
sound/soc/intel/boards/bytcht_es8316.c
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/boards/bytcr_rt5651.c
sound/soc/intel/boards/cht_bsw_max98090_ti.c
sound/soc/intel/boards/cht_bsw_nau8824.c
sound/soc/intel/boards/cht_bsw_rt5645.c
sound/soc/intel/boards/cht_bsw_rt5672.c
sound/soc/intel/boards/kbl_da7219_max98357a.c
sound/soc/intel/boards/kbl_rt5663_max98927.c
sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
sound/soc/intel/boards/skl_nau88l25_max98357a.c
sound/soc/intel/boards/skl_nau88l25_ssm4567.c
sound/soc/intel/boards/skl_rt286.c
sound/soc/intel/skylake/skl-debug.c
sound/soc/intel/skylake/skl-messages.c
sound/soc/intel/skylake/skl-pcm.c
sound/soc/intel/skylake/skl-sst-dsp.h
sound/soc/intel/skylake/skl-sst.c
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl-topology.h
sound/soc/intel/skylake/skl-tplg-interface.h [deleted file]
sound/soc/intel/skylake/skl.c
sound/soc/kirkwood/Kconfig
sound/soc/mediatek/Kconfig
sound/soc/mediatek/Makefile
sound/soc/mediatek/common/Makefile
sound/soc/mediatek/common/mtk-afe-fe-dai.c
sound/soc/mediatek/common/mtk-afe-fe-dai.h
sound/soc/mediatek/common/mtk-afe-platform-driver.c
sound/soc/mediatek/common/mtk-afe-platform-driver.h
sound/soc/mediatek/common/mtk-base-afe.h
sound/soc/mediatek/mt2701/Makefile
sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h
sound/soc/mediatek/mt2701/mt2701-afe-common.h
sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
sound/soc/mediatek/mt2701/mt2701-cs42448.c
sound/soc/mediatek/mt2701/mt2701-reg.h
sound/soc/mediatek/mt2701/mt2701-wm8960.c
sound/soc/mediatek/mt6797/Makefile [new file with mode: 0644]
sound/soc/mediatek/mt6797/mt6797-afe-clk.c [new file with mode: 0644]
sound/soc/mediatek/mt6797/mt6797-afe-clk.h [new file with mode: 0644]
sound/soc/mediatek/mt6797/mt6797-afe-common.h [new file with mode: 0644]
sound/soc/mediatek/mt6797/mt6797-afe-pcm.c [new file with mode: 0644]
sound/soc/mediatek/mt6797/mt6797-dai-adda.c [new file with mode: 0644]
sound/soc/mediatek/mt6797/mt6797-dai-hostless.c [new file with mode: 0644]
sound/soc/mediatek/mt6797/mt6797-dai-pcm.c [new file with mode: 0644]
sound/soc/mediatek/mt6797/mt6797-interconnection.h [new file with mode: 0644]
sound/soc/mediatek/mt6797/mt6797-mt6351.c [new file with mode: 0644]
sound/soc/mediatek/mt6797/mt6797-reg.h [new file with mode: 0644]
sound/soc/mediatek/mt8173/mt8173-afe-common.h
sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
sound/soc/mediatek/mt8173/mt8173-max98090.c
sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c
sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c
sound/soc/mediatek/mt8173/mt8173-rt5650.c
sound/soc/omap/Kconfig
sound/soc/omap/Makefile
sound/soc/omap/n810.c
sound/soc/omap/omap-dmic.c
sound/soc/omap/omap-hdmi-audio.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/omap-pcm.c [deleted file]
sound/soc/omap/sdma-pcm.c [new file with mode: 0644]
sound/soc/omap/sdma-pcm.h [new file with mode: 0644]
sound/soc/pxa/Kconfig
sound/soc/pxa/pxa-ssp.c
sound/soc/qcom/Kconfig
sound/soc/qcom/Makefile
sound/soc/qcom/apq8096.c [new file with mode: 0644]
sound/soc/qcom/qdsp6/Makefile [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6adm.c [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6adm.h [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6afe-dai.c [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6afe.c [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6afe.h [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6asm-dai.c [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6asm.c [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6asm.h [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6core.c [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6core.h [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6dsp-common.c [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6dsp-common.h [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6dsp-errno.h [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6routing.c [new file with mode: 0644]
sound/soc/qcom/qdsp6/q6routing.h [new file with mode: 0644]
sound/soc/rockchip/rk3399_gru_sound.c
sound/soc/sh/Kconfig
sound/soc/sh/rcar/cmd.c
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/dma.c
sound/soc/sh/rcar/gen.c
sound/soc/sh/rcar/rsnd.h
sound/soc/sh/rcar/ssi.c
sound/soc/soc-cache.c [deleted file]
sound/soc/soc-compress.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-devres.c
sound/soc/soc-io.c
sound/soc/soc-jack.c
sound/soc/soc-pcm.c
sound/soc/soc-topology.c
sound/soc/uniphier/aio-compress.c
sound/soc/uniphier/aio-core.c
sound/soc/uniphier/aio-cpu.c
sound/soc/uniphier/aio-dma.c
sound/soc/uniphier/aio-ld11.c
sound/soc/uniphier/aio-reg.h
sound/soc/uniphier/aio.h
sound/soc/uniphier/evea.c
sound/soc/zte/zx-i2s.c

index 7fa9d41fbdaf945c807700300c1b3eb4289eb218..29ddeb1bf015c46f6316b6d4a436c94bdb9b3ae9 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -186,6 +186,9 @@ Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
 Uwe Kleine-König <ukl@pengutronix.de>
 Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
 Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
+Vinod Koul <vkoul@kernel.org> <vinod.koul@intel.com>
+Vinod Koul <vkoul@kernel.org> <vinod.koul@linux.intel.com>
+Vinod Koul <vkoul@kernel.org> <vkoul@infradead.org>
 Viresh Kumar <vireshk@kernel.org> <viresh.kumar@st.com>
 Viresh Kumar <vireshk@kernel.org> <viresh.linux@gmail.com>
 Viresh Kumar <vireshk@kernel.org> <viresh.kumar2@arm.com>
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,apr.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,apr.txt
new file mode 100644 (file)
index 0000000..bcc612c
--- /dev/null
@@ -0,0 +1,84 @@
+Qualcomm APR (Asynchronous Packet Router) binding
+
+This binding describes the Qualcomm APR. APR is a IPC protocol for
+communication between Application processor and QDSP. APR is mainly
+used for audio/voice services on the QDSP.
+
+- compatible:
+       Usage: required
+       Value type: <stringlist>
+       Definition: must be "qcom,apr-v<VERSION-NUMBER>", example "qcom,apr-v2"
+
+- reg
+       Usage: required
+       Value type: <u32>
+       Definition: Destination processor ID.
+       Possible values are :
+                       1 - APR simulator
+                       2 - PC
+                       3 - MODEM
+                       4 - ADSP
+                       5 - APPS
+                       6 - MODEM2
+                       7 - APPS2
+
+= APR SERVICES
+Each subnode of the APR node represents service tied to this apr. The name
+of the nodes are not important. The properties of these nodes are defined
+by the individual bindings for the specific service
+- All APR services MUST contain the following property:
+
+- reg
+       Usage: required
+       Value type: <u32>
+       Definition: APR Service ID
+       Possible values are :
+                       3 - DSP Core Service
+                       4 - Audio Front End Service.
+                       5 - Voice Stream Manager Service.
+                       6 - Voice processing manager.
+                       7 - Audio Stream Manager Service.
+                       8 - Audio Device Manager Service.
+                       9 - Multimode voice manager.
+                       10 - Core voice stream.
+                       11 - Core voice processor.
+                       12 - Ultrasound stream manager.
+                       13 - Listen stream manager.
+
+= EXAMPLE
+The following example represents a QDSP based sound card on a MSM8996 device
+which uses apr as communication between Apps and QDSP.
+
+       apr@4 {
+               compatible = "qcom,apr-v2";
+               reg = <APR_DOMAIN_ADSP>;
+
+               q6core@3 {
+                       compatible = "qcom,q6core";
+                       reg = <APR_SVC_ADSP_CORE>;
+               };
+
+               q6afe@4 {
+                       compatible = "qcom,q6afe";
+                       reg = <APR_SVC_AFE>;
+
+                       dais {
+                               #sound-dai-cells = <1>;
+                               hdmi@1 {
+                                       reg = <1>;
+                               };
+                       };
+               };
+
+               q6asm@7 {
+                       compatible = "qcom,q6asm";
+                       reg = <APR_SVC_ASM>;
+                       ...
+               };
+
+               q6adm@8 {
+                       compatible = "qcom,q6adm";
+                       reg = <APR_SVC_ADM>;
+                       ...
+               };
+       };
diff --git a/Documentation/devicetree/bindings/sound/adi,ssm2305.txt b/Documentation/devicetree/bindings/sound/adi,ssm2305.txt
new file mode 100644 (file)
index 0000000..a9c9d83
--- /dev/null
@@ -0,0 +1,14 @@
+Analog Devices SSM2305 Speaker Amplifier
+========================================
+
+Required properties:
+  - compatible : "adi,ssm2305"
+  - shutdown-gpios : The gpio connected to the shutdown pin.
+                     The gpio signal is ACTIVE_LOW.
+
+Example:
+
+ssm2305: analog-amplifier {
+       compatible = "adi,ssm2305";
+       shutdown-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>;
+};
diff --git a/Documentation/devicetree/bindings/sound/atmel-i2s.txt b/Documentation/devicetree/bindings/sound/atmel-i2s.txt
new file mode 100644 (file)
index 0000000..735368b
--- /dev/null
@@ -0,0 +1,47 @@
+* Atmel I2S controller
+
+Required properties:
+- compatible:     Should be "atmel,sama5d2-i2s".
+- reg:            Should be the physical base address of the controller and the
+                  length of memory mapped region.
+- interrupts:     Should contain the interrupt for the controller.
+- dmas:           Should be one per channel name listed in the dma-names property,
+                  as described in atmel-dma.txt and dma.txt files.
+- dma-names:      Two dmas have to be defined, "tx" and "rx".
+                  This IP also supports one shared channel for both rx and tx;
+                  if this mode is used, one "rx-tx" name must be used.
+- clocks:         Must contain an entry for each entry in clock-names.
+                  Please refer to clock-bindings.txt.
+- clock-names:    Should be one of each entry matching the clocks phandles list:
+                  - "pclk" (peripheral clock) Required.
+                  - "gclk" (generated clock) Optional (1).
+                  - "aclk" (Audio PLL clock) Optional (1).
+                  - "muxclk" (I2S mux clock) Optional (1).
+
+Optional properties:
+- pinctrl-0:      Should specify pin control groups used for this controller.
+- princtrl-names: Should contain only one value - "default".
+
+
+(1) : Only the peripheral clock is required. The generated clock, the Audio
+      PLL clock adn the I2S mux clock are optional and should only be set
+      together, when Master Mode is required.
+
+Example:
+
+       i2s@f8050000 {
+               compatible = "atmel,sama5d2-i2s";
+               reg = <0xf8050000 0x300>;
+               interrupts = <54 IRQ_TYPE_LEVEL_HIGH 7>;
+               dmas = <&dma0
+                       (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+                        AT91_XDMAC_DT_PERID(31))>,
+                      <&dma0
+                       (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+                        AT91_XDMAC_DT_PERID(32))>;
+               dma-names = "tx", "rx";
+               clocks = <&i2s0_clk>, <&i2s0_gclk>, <&audio_pll_pmc>, <&i2s0muxck>;
+               clock-names = "pclk", "gclk", "aclk", "muxclk";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_i2s0_default>;
+       };
index f631fbca6284325378e959683d737fc787035a17..8619a156d038bdd76e342351fe83af63b4105746 100644 (file)
@@ -16,7 +16,7 @@ Required properties:
 
 Example:
 
-codec: cs42888@48 {
+cs42888: codec@48 {
        compatible = "cirrus,cs42888";
        reg = <0x48>;
        clocks = <&codec_mclk 0>;
index f5a14115b459482ea7ffa2ce43c9b84096cdb3df..1d4d9f938689f39b5214a730991ac068aec02f35 100644 (file)
@@ -31,14 +31,16 @@ Required properties:
                          it. This property is optional depending on the SoC
                          design.
 
-   - big-endian                : If this property is absent, the little endian mode
-                         will be in use as default. Otherwise, the big endian
-                         mode will be in use for all the device registers.
-
    - fsl,asrc-rate     : Defines a mutual sample rate used by DPCM Back Ends.
 
    - fsl,asrc-width    : Defines a mutual sample width used by DPCM Back Ends.
 
+Optional properties:
+
+   - big-endian                : If this property is absent, the little endian mode
+                         will be in use as default. Otherwise, the big endian
+                         mode will be in use for all the device registers.
+
 Example:
 
 asrc: asrc@2034000 {
index cacd18bb9ba63978a73d569a00db21d6389b9b21..5b9914367610315d8aaab3a614dd318de9408c6d 100644 (file)
@@ -42,6 +42,8 @@ Required properties:
                          means all the settings for Receiving would be
                          duplicated from Transmition related registers.
 
+Optional properties:
+
   - big-endian         : If this property is absent, the native endian mode
                          will be in use as default, or the big endian mode
                          will be in use for all the device registers.
index 38cfa75734415e018107c6a0a2cc128497cc059f..8b324f82a7828013c06a1688c80c7316558c47ce 100644 (file)
@@ -33,6 +33,8 @@ Required properties:
                          it. This property is optional depending on the SoC
                          design.
 
+Optional properties:
+
    - big-endian                : If this property is absent, the native endian mode
                          will be in use as default, or the big endian mode
                          will be in use for all the device registers.
index 740b467adf7d1d46f318d5a2a6bf74f35cfa80bc..dd9e59738e0820b4db57b737e34a37c11c90fd55 100644 (file)
@@ -28,9 +28,6 @@ Required properties:
                          pinctrl-names. See ../pinctrl/pinctrl-bindings.txt
                          for details of the property values.
 
-  - big-endian         : Boolean property, required if all the FTM_PWM
-                         registers are big-endian rather than little-endian.
-
   - lsb-first          : Configures whether the LSB or the MSB is transmitted
                          first for the fifo data. If this property is absent,
                          the MSB is transmitted first as default, or the LSB
@@ -48,6 +45,11 @@ Required properties:
                          receive data by following their own bit clocks and
                          frame sync clocks separately.
 
+Optional properties:
+
+  - big-endian         : Boolean property, required if all the SAI
+                         registers are big-endian rather than little-endian.
+
 Optional properties (for mx6ul):
 
   - fsl,sai-mclk-direction-output: This is a boolean property. If present,
index e2f7f49512155e1084c85ce9e3dd6b9770285a97..560762e0a1681b37ef1a66750e14474868a137c8 100644 (file)
@@ -1,7 +1,9 @@
 Mediatek AFE PCM controller for mt2701
 
 Required properties:
-- compatible = "mediatek,mt2701-audio";
+- compatible: should be one of the followings.
+             - "mediatek,mt2701-audio"
+             - "mediatek,mt7622-audio"
 - interrupts: should contain AFE and ASYS interrupts
 - interrupt-names: should be "afe" and "asys"
 - power-domains: should define the power domain
diff --git a/Documentation/devicetree/bindings/sound/mt6351.txt b/Documentation/devicetree/bindings/sound/mt6351.txt
new file mode 100644 (file)
index 0000000..7fb2cb9
--- /dev/null
@@ -0,0 +1,16 @@
+Mediatek MT6351 Audio Codec
+
+The communication between MT6351 and SoC is through Mediatek PMIC wrapper.
+For more detail, please visit Mediatek PMIC wrapper documentation.
+
+Must be a child node of PMIC wrapper.
+
+Required properties:
+
+- compatible : "mediatek,mt6351-sound".
+
+Example:
+
+mt6351_snd {
+       compatible = "mediatek,mt6351-sound";
+};
diff --git a/Documentation/devicetree/bindings/sound/mt6797-afe-pcm.txt b/Documentation/devicetree/bindings/sound/mt6797-afe-pcm.txt
new file mode 100644 (file)
index 0000000..0ae29de
--- /dev/null
@@ -0,0 +1,42 @@
+Mediatek AFE PCM controller for mt6797
+
+Required properties:
+- compatible = "mediatek,mt6797-audio";
+- reg: register location and size
+- interrupts: should contain AFE interrupt
+- power-domains: should define the power domain
+- clocks: Must contain an entry for each entry in clock-names
+- clock-names: should have these clock names:
+               "infra_sys_audio_clk",
+               "infra_sys_audio_26m",
+               "mtkaif_26m_clk",
+               "top_mux_audio",
+               "top_mux_aud_intbus",
+               "top_sys_pll3_d4",
+               "top_sys_pll1_d4",
+               "top_clk26m_clk";
+
+Example:
+
+       afe: mt6797-afe-pcm@11220000  {
+               compatible = "mediatek,mt6797-audio";
+               reg = <0 0x11220000 0 0x1000>;
+               interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_LOW>;
+               power-domains = <&scpsys MT6797_POWER_DOMAIN_AUDIO>;
+               clocks = <&infrasys CLK_INFRA_AUDIO>,
+                        <&infrasys CLK_INFRA_AUDIO_26M>,
+                        <&infrasys CLK_INFRA_AUDIO_26M_PAD_TOP>,
+                        <&topckgen CLK_TOP_MUX_AUDIO>,
+                        <&topckgen CLK_TOP_MUX_AUD_INTBUS>,
+                        <&topckgen CLK_TOP_SYSPLL3_D4>,
+                        <&topckgen CLK_TOP_SYSPLL1_D4>,
+                        <&clk26m>;
+               clock-names = "infra_sys_audio_clk",
+                             "infra_sys_audio_26m",
+                             "mtkaif_26m_clk",
+                             "top_mux_audio",
+                             "top_mux_aud_intbus",
+                             "top_sys_pll3_d4",
+                             "top_sys_pll1_d4",
+                             "top_clk26m_clk";
+       };
diff --git a/Documentation/devicetree/bindings/sound/mt6797-mt6351.txt b/Documentation/devicetree/bindings/sound/mt6797-mt6351.txt
new file mode 100644 (file)
index 0000000..1d95a88
--- /dev/null
@@ -0,0 +1,14 @@
+MT6797 with MT6351 CODEC
+
+Required properties:
+- compatible: "mediatek,mt6797-mt6351-sound"
+- mediatek,platform: the phandle of MT6797 ASoC platform
+- mediatek,audio-codec: the phandles of MT6351 codec
+
+Example:
+
+       sound {
+               compatible = "mediatek,mt6797-mt6351-sound";
+               mediatek,audio-codec = <&mt6351_snd>;
+               mediatek,platform = <&afe>;
+       };
diff --git a/Documentation/devicetree/bindings/sound/qcom,apq8096.txt b/Documentation/devicetree/bindings/sound/qcom,apq8096.txt
new file mode 100644 (file)
index 0000000..aa54e49
--- /dev/null
@@ -0,0 +1,109 @@
+* Qualcomm Technologies APQ8096 ASoC sound card driver
+
+This binding describes the APQ8096 sound card, which uses qdsp for audio.
+
+- compatible:
+       Usage: required
+       Value type: <stringlist>
+       Definition: must be "qcom,apq8096-sndcard"
+
+- qcom,audio-routing:
+       Usage: Optional
+       Value type: <stringlist>
+       Definition:  A list of the connections between audio components.
+                 Each entry is a pair of strings, the first being the
+                 connection's sink, the second being the connection's
+                 source. Valid names could be power supplies, MicBias
+                 of codec and the jacks on the board:
+                 Valid names include:
+
+               Board Connectors:
+                       "Headphone Left"
+                       "Headphone Right"
+                       "Earphone"
+                       "Line Out1"
+                       "Line Out2"
+                       "Line Out3"
+                       "Line Out4"
+                       "Analog Mic1"
+                       "Analog Mic2"
+                       "Analog Mic3"
+                       "Analog Mic4"
+                       "Analog Mic5"
+                       "Analog Mic6"
+                       "Digital Mic2"
+                       "Digital Mic3"
+
+               Audio pins and MicBias on WCD9335 Codec:
+                       "MIC_BIAS1
+                       "MIC_BIAS2"
+                       "MIC_BIAS3"
+                       "MIC_BIAS4"
+                       "AMIC1"
+                       "AMIC2"
+                       "AMIC3"
+                       "AMIC4"
+                       "AMIC5"
+                       "AMIC6"
+                       "AMIC6"
+                       "DMIC1"
+                       "DMIC2"
+                       "DMIC3"
+= dailinks
+Each subnode of sndcard represents either a dailink, and subnodes of each
+dailinks would be cpu/codec/platform dais.
+
+- link-name:
+       Usage: required
+       Value type: <string>
+       Definition: User friendly name for dai link
+
+= CPU, PLATFORM, CODEC dais subnodes
+- cpu:
+       Usage: required
+       Value type: <subnode>
+       Definition: cpu dai sub-node
+
+- codec:
+       Usage: Optional
+       Value type: <subnode>
+       Definition: codec dai sub-node
+
+- platform:
+       Usage: Optional
+       Value type: <subnode>
+       Definition: platform dai sub-node
+
+- sound-dai:
+       Usage: required
+       Value type: <phandle with arguments>
+       Definition: dai phandle/s and port of CPU/CODEC/PLATFORM node.
+
+Example:
+
+audio {
+       compatible = "qcom,apq8096-sndcard";
+       qcom,model = "DB820c";
+
+       mm1-dai-link {
+               link-name = "MultiMedia1";
+               cpu {
+                       sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
+               };
+       };
+
+       hdmi-dai-link {
+               link-name = "HDMI Playback";
+               cpu {
+                       sound-dai = <&q6afe HDMI_RX>;
+               };
+
+               platform {
+                       sound-dai = <&q6adm>;
+               };
+
+               codec {
+                       sound-dai = <&hdmi 0>;
+               };
+       };
+};
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6adm.txt b/Documentation/devicetree/bindings/sound/qcom,q6adm.txt
new file mode 100644 (file)
index 0000000..cb709e5
--- /dev/null
@@ -0,0 +1,33 @@
+Qualcomm Audio Device Manager (Q6ADM) binding
+
+Q6ADM is one of the APR audio service on Q6DSP.
+Please refer to qcom,apr.txt for details of the coommon apr service bindings
+used by the apr service device.
+
+- but must contain the following property:
+
+- compatible:
+       Usage: required
+       Value type: <stringlist>
+       Definition: must be "qcom,q6adm-v<MAJOR-NUMBER>.<MINOR-NUMBER>".
+                  Or "qcom,q6adm" where the version number can be queried
+                  from DSP.
+                  example "qcom,q6adm-v2.0"
+
+
+= ADM routing
+"routing" subnode of the ADM node represents adm routing specific configuration
+
+- #sound-dai-cells
+       Usage: required
+       Value type: <u32>
+       Definition: Must be 0
+
+= EXAMPLE
+q6adm@8 {
+       compatible = "qcom,q6adm";
+       reg = <APR_SVC_ADM>;
+       q6routing: routing {
+               #sound-dai-cells = <0>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6afe.txt b/Documentation/devicetree/bindings/sound/qcom,q6afe.txt
new file mode 100644 (file)
index 0000000..bdbf87d
--- /dev/null
@@ -0,0 +1,172 @@
+Qualcomm Audio Front End (Q6AFE) binding
+
+AFE is one of the APR audio service on Q6DSP
+Please refer to qcom,apr.txt for details of the common apr service bindings
+used by all apr services. Must contain the following properties.
+
+- compatible:
+       Usage: required
+       Value type: <stringlist>
+       Definition: must be "qcom,q6afe-v<MAJOR-NUMBER>.<MINOR-NUMBER>"
+                 Or "qcom,q6afe" where the version number can be queried
+                 from DSP.
+                 example "qcom,q6afe"
+
+= AFE DAIs (Digial Audio Interface)
+"dais" subnode of the AFE node. It represents afe dais, each afe dai is a
+subnode of "dais" representing board specific dai setup.
+"dais" node should have following properties followed by dai children.
+
+- #sound-dai-cells
+       Usage: required
+       Value type: <u32>
+       Definition: Must be 1
+
+- #address-cells
+       Usage: required
+       Value type: <u32>
+       Definition: Must be 1
+
+- #size-cells
+       Usage: required
+       Value type: <u32>
+       Definition: Must be 0
+
+== AFE DAI is subnode of "dais" and represent a dai, it includes board specific
+configuration of each dai. Must contain the following properties.
+
+- reg
+       Usage: required
+       Value type: <u32>
+       Definition: Must be dai id
+
+- qcom,sd-lines
+       Usage: required for mi2s interface
+       Value type: <prop-encoded-array>
+       Definition: Must be list of serial data lines used by this dai.
+       should be one or more of the 1-4 sd lines.
+
+ - qcom,tdm-sync-mode:
+       Usage: required for tdm interface
+       Value type: <prop-encoded-array>
+       Definition: Synchronization mode.
+               0 - Short sync bit mode
+               1 - Long sync mode
+               2 - Short sync slot mode
+
+ - qcom,tdm-sync-src:
+       Usage: required for tdm interface
+       Value type: <prop-encoded-array>
+       Definition: Synchronization source.
+               0 - External source
+               1 - Internal source
+
+ - qcom,tdm-data-out:
+       Usage: required for tdm interface
+       Value type: <prop-encoded-array>
+       Definition: Data out signal to drive with other masters.
+               0 - Disable
+               1 - Enable
+
+ - qcom,tdm-invert-sync:
+       Usage: required for tdm interface
+       Value type: <prop-encoded-array>
+       Definition: Invert the sync.
+               0 - Normal
+               1 - Invert
+
+ - qcom,tdm-data-delay:
+       Usage: required for tdm interface
+       Value type: <prop-encoded-array>
+       Definition: Number of bit clock to delay data
+               with respect to sync edge.
+               0 - 0 bit clock cycle
+               1 - 1 bit clock cycle
+               2 - 2 bit clock cycle
+
+ - qcom,tdm-data-align:
+       Usage: required for tdm interface
+       Value type: <prop-encoded-array>
+       Definition: Indicate how data is packed
+               within the slot. For example, 32 slot width in case of
+               sample bit width is 24.
+               0 - MSB
+               1 - LSB
+
+= EXAMPLE
+
+q6afe@4 {
+       compatible = "qcom,q6afe";
+       reg = <APR_SVC_AFE>;
+
+       dais {
+               #sound-dai-cells = <1>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               hdmi@1 {
+                       reg = <1>;
+               };
+
+               tdm@24 {
+                       reg = <24>;
+                       qcom,tdm-sync-mode = <1>:
+                       qcom,tdm-sync-src = <1>;
+                       qcom,tdm-data-out = <0>;
+                       qcom,tdm-invert-sync = <1>;
+                       qcom,tdm-data-delay = <1>;
+                       qcom,tdm-data-align = <0>;
+
+               };
+
+               tdm@25 {
+                       reg = <25>;
+                       qcom,tdm-sync-mode = <1>:
+                       qcom,tdm-sync-src = <1>;
+                       qcom,tdm-data-out = <0>;
+                       qcom,tdm-invert-sync = <1>;
+                       qcom,tdm-data-delay <1>:
+                       qcom,tdm-data-align = <0>;
+               };
+
+               prim-mi2s-rx@16 {
+                       reg = <16>;
+                       qcom,sd-lines = <1 3>;
+               };
+
+               prim-mi2s-tx@17 {
+                       reg = <17>;
+                       qcom,sd-lines = <2>;
+               };
+
+               sec-mi2s-rx@18 {
+                       reg = <18>;
+                       qcom,sd-lines = <1 4>;
+               };
+
+               sec-mi2s-tx@19 {
+                       reg = <19>;
+                       qcom,sd-lines = <2>;
+               };
+
+               tert-mi2s-rx@20 {
+                       reg = <20>;
+                       qcom,sd-lines = <2 4>;
+               };
+
+               tert-mi2s-tx@21 {
+                       reg = <21>;
+                       qcom,sd-lines = <1>;
+               };
+
+               quat-mi2s-rx@22 {
+                       reg = <22>;
+                       qcom,sd-lines = <1>;
+               };
+
+               quat-mi2s-tx@23 {
+                       reg = <23>;
+                       qcom,sd-lines = <2>;
+               };
+       };
+};
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6asm.txt b/Documentation/devicetree/bindings/sound/qcom,q6asm.txt
new file mode 100644 (file)
index 0000000..2178eb9
--- /dev/null
@@ -0,0 +1,33 @@
+Qualcomm Audio Stream Manager (Q6ASM) binding
+
+Q6ASM is one of the APR audio service on Q6DSP.
+Please refer to qcom,apr.txt for details of the common apr service bindings
+used by the apr service device.
+
+- but must contain the following property:
+
+- compatible:
+       Usage: required
+       Value type: <stringlist>
+       Definition: must be "qcom,q6asm-v<MAJOR-NUMBER>.<MINOR-NUMBER>".
+                   Or "qcom,q6asm" where the version number can be queried
+                   from DSP.
+                   example "qcom,q6asm-v2.0"
+
+= ASM DAIs (Digial Audio Interface)
+"dais" subnode of the ASM node represents dai specific configuration
+
+- #sound-dai-cells
+       Usage: required
+       Value type: <u32>
+       Definition: Must be 1
+
+= EXAMPLE
+
+q6asm@7 {
+       compatible = "qcom,q6asm";
+       reg = <APR_SVC_ASM>;
+       q6asmdai: dais {
+               #sound-dai-cells = <1>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6core.txt b/Documentation/devicetree/bindings/sound/qcom,q6core.txt
new file mode 100644 (file)
index 0000000..7f36ff8
--- /dev/null
@@ -0,0 +1,21 @@
+Qualcomm ADSP Core service binding
+
+Q6CORE is one of the APR audio service on Q6DSP.
+Please refer to qcom,apr.txt for details of the common apr service bindings
+used by the apr service device.
+
+- but must contain the following property:
+
+- compatible:
+       Usage: required
+       Value type: <stringlist>
+       Definition: must be "qcom,q6core-v<MAJOR-NUMBER>.<MINOR-NUMBER>".
+                  Or "qcom,q6core" where the version number can be queried
+                  from DSP.
+                  example "qcom,q6core-v2.0"
+
+= EXAMPLE
+q6core@3 {
+       compatible = "qcom,q6core";
+       reg = <APR_SVC_ADSP_CORE>;
+};
index e9a6178c78cfe09c56a303495ec4d207ed53b11b..791a1bd767b9166e9330bf9a0fc4f90dfcfc62b2 100644 (file)
@@ -26,7 +26,7 @@ Pins on the device (for linking into audio routes) for RT274:
 
 Example:
 
-codec: rt274@1c {
+rt274: codec@1c {
        compatible = "realtek,rt274";
        reg = <0x1c>;
        interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
index 4f33b0d96afeb106bb457ed071ab3f4779d80ec5..b25ed08c7a5a0113761c18a17d3ceef50d0d6d96 100644 (file)
@@ -32,7 +32,7 @@ Pins on the device (for linking into audio routes) for I2C:
 
 Example:
 
-codec: rt5514@57 {
+rt5514: codec@57 {
        compatible = "realtek,rt5514";
        reg = <0x57>;
 };
index e410858185596a0fb74ec5812cef3dd3e6282762..540a4bf252e48eb4dcce34061b0b9ee537ab0d23 100644 (file)
@@ -26,7 +26,7 @@ Pins on the device (for linking into audio routes) for RT5616:
 
 Example:
 
-codec: rt5616@1b {
+rt5616: codec@1b {
        compatible = "realtek,rt5616";
        reg = <0x1b>;
 };
index 57fe64643050a5e9f41072dd0d4ae0376f5d6958..e40e4893eed8014352cb81ab86c42f21da38e123 100644 (file)
@@ -22,6 +22,41 @@ Optional properties:
 
 - realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
 
+- realtek,dmic1-data-pin
+  0: dmic1 is not used
+  1: using IN1P pin as dmic1 data pin
+  2: using GPIO3 pin as dmic1 data pin
+
+- realtek,dmic2-data-pin
+  0: dmic2 is not used
+  1: using IN1N pin as dmic2 data pin
+  2: using GPIO4 pin as dmic2 data pin
+
+- realtek,jack-detect-source
+  u32. Valid values:
+  0: jack-detect is not used
+  1: Use GPIO1 for jack-detect
+  2: Use JD1_IN4P for jack-detect
+  3: Use JD2_IN4N for jack-detect
+  4: Use GPIO2 for jack-detect
+  5: Use GPIO3 for jack-detect
+  6: Use GPIO4 for jack-detect
+
+- realtek,jack-detect-not-inverted
+  bool. Normal jack-detect switches give an inverted signal, set this bool
+  in the rare case you've a jack-detect switch which is not inverted.
+
+- realtek,over-current-threshold-microamp
+  u32, micbias over-current detection threshold in µA, valid values are
+  600, 1500 and 2000µA.
+
+- realtek,over-current-scale-factor
+  u32, micbias over-current detection scale-factor, valid values are:
+  0: Scale current by 0.5
+  1: Scale current by 0.75
+  2: Scale current by 1.0
+  3: Scale current by 1.5
+
 Pins on the device (for linking into audio routes) for RT5639/RT5640:
 
   * DMIC1
index 7cee1f518f59fc7ec2fccc1882a939b2a2589a37..a03f9a872a71667ddc2ab9197ece633ee337af96 100644 (file)
@@ -69,4 +69,4 @@ codec: rt5650@1a {
        realtek,dmic-en = "true";
        realtek,en-jd-func = "true";
        realtek,jd-mode = <3>;
-};
\ No newline at end of file
+};
index b85221864cec8a607f62dc27c41f4f37e05b941e..a41199a5cd79b5225b2b732bacfef782d9286d54 100644 (file)
@@ -50,7 +50,7 @@ Pins on the device (for linking into audio routes) for RT5651:
 
 Example:
 
-codec: rt5651@1a {
+rt5651: codec@1a {
        compatible = "realtek,rt5651";
        reg = <0x1a>;
        realtek,dmic-en = "true";
index 497bcfc58b712173b05ce876600f1595a3d20125..23386446c63d6fde5b63c35b8badd989a8ada56b 100644 (file)
@@ -47,7 +47,7 @@ Pins on the device (for linking into audio routes) for RT5663:
 
 Example:
 
-codec: rt5663@12 {
+rt5663: codec@12 {
        compatible = "realtek,rt5663";
        reg = <0x12>;
        interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
diff --git a/Documentation/devicetree/bindings/sound/rt5668.txt b/Documentation/devicetree/bindings/sound/rt5668.txt
new file mode 100644 (file)
index 0000000..c88b96e
--- /dev/null
@@ -0,0 +1,50 @@
+RT5668B audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+- compatible : "realtek,rt5668b"
+
+- reg : The I2C address of the device.
+
+Optional properties:
+
+- interrupts : The CODEC's interrupt output.
+
+- realtek,dmic1-data-pin
+  0: dmic1 is not used
+  1: using GPIO2 pin as dmic1 data pin
+  2: using GPIO5 pin as dmic1 data pin
+
+- realtek,dmic1-clk-pin
+  0: using GPIO1 pin as dmic1 clock pin
+  1: using GPIO3 pin as dmic1 clock pin
+
+- realtek,jd-src
+  0: No JD is used
+  1: using JD1 as JD source
+
+- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
+
+Pins on the device (for linking into audio routes) for RT5668B:
+
+  * DMIC L1
+  * DMIC R1
+  * IN1P
+  * HPOL
+  * HPOR
+
+Example:
+
+rt5668 {
+       compatible = "realtek,rt5668b";
+       reg = <0x1a>;
+       interrupt-parent = <&gpio>;
+       interrupts = <TEGRA_GPIO(U, 6) GPIO_ACTIVE_HIGH>;
+       realtek,ldo1-en-gpios =
+               <&gpio TEGRA_GPIO(R, 2) GPIO_ACTIVE_HIGH>;
+       realtek,dmic1-data-pin = <1>;
+       realtek,dmic1-clk-pin = <1>;
+       realtek,jd-src = <1>;
+};
index 9a36c7e2a1434ad60bb61436d5da9df29d05f8f3..0f214457476f2aa399925720ee8b42c934b89568 100644 (file)
@@ -39,7 +39,7 @@ VDDIO         1.8V            2.5V            3.3V
 
 Example:
 
-codec: sgtl5000@a {
+sgtl5000: codec@a {
        compatible = "fsl,sgtl5000";
        reg = <0x0a>;
        #sound-dai-cells = <0>;
index 17c13e74667da8d2135fa3360926909b6dbc569b..a4c72d09cd45718e6ce5197d6f8fce1e782deeac 100644 (file)
@@ -86,6 +86,11 @@ Optional CPU/CODEC subnodes properties:
                                          in dai startup() and disabled with
                                          clk_disable_unprepare() in dai
                                          shutdown().
+                                         If a clock is specified and a
+                                         multiplication factor is given with
+                                         mclk-fs, the clock will be set to the
+                                         calculated mclk frequency when the
+                                         stream starts.
 - system-clock-direction-out           : specifies clock direction as 'out' on
                                          initialization. It is useful for some aCPUs with
                                          fixed clocks.
index 1c4ada0eef4e1613d2a88f79e3d572c65e64b1e9..eacb54f34188fa6cf10f3ad101b1c70bf590a488 100644 (file)
@@ -6,6 +6,8 @@ Required properties:
        - compatible: "ti,tas6424" - TAS6424
        - reg: I2C slave address
        - sound-dai-cells: must be equal to 0
+       - standby-gpios: GPIO used to shut the TAS6424 down.
+       - mute-gpios: GPIO used to mute all the outputs
 
 Example:
 
index 2ac2f099669761354469f9550700c00b61e7c91e..7eea32e9d07838aec8d7f30b4e88b39c69da24d3 100644 (file)
@@ -8,9 +8,15 @@ Required Properties:
        - reg :         <0x71> for analog mic
                        <0x69> for digital mic
 
+       - clock-names:  Must one of  the following "mclk1", "xtal", "mclk2"
+
+       - clocks:       phandle of the clock that provides the codec sysclk
+
 Example:
 
 wookie: codec@69 {
        compatible = "tempo,tscs42A2";
        reg = <0x69>;
+       clock-names = "xtal";
+       clocks = <&audio_xtal>;
 };
diff --git a/Documentation/devicetree/bindings/sound/tscs454.txt b/Documentation/devicetree/bindings/sound/tscs454.txt
new file mode 100644 (file)
index 0000000..3ba3e2d
--- /dev/null
@@ -0,0 +1,23 @@
+TSCS454 Audio CODEC
+
+Required Properties:
+
+       - compatible :  "tempo,tscs454"
+
+       - reg :         <0x69>
+
+       - clock-names:  Must one of  the following "xtal", "mclk1", "mclk2"
+
+       - clocks:       phandle of the clock that provides the codec sysclk
+
+       Note: If clock is not provided then bit clock is assumed
+
+Example:
+
+redwood: codec@69 {
+       #sound-dai-cells = <1>;
+       compatible = "tempo,tscs454";
+       reg = <0x69>;
+       clock-names = "mclk1";
+       clocks = <&audio_mclk>;
+};
index fa1a32b85577db40322c4ee9655a9da77d983261..e6b6cc041f895b21d22cfc8a7e73277d2716fff1 100644 (file)
@@ -12,7 +12,7 @@ Required properties:
 
 Example:
 
-codec: wm8510@1a {
+wm8510: codec@1a {
        compatible = "wlf,wm8510";
        reg = <0x1a>;
 };
index 04746186b2831558c7e9f3b27589cbf4d13475da..f3a6485f4b8abf1b149c944d1f3486936f6529e0 100644 (file)
@@ -10,7 +10,7 @@ Required properties:
 
 Example:
 
-codec: wm8523@1a {
+wm8523: codec@1a {
        compatible = "wlf,wm8523";
        reg = <0x1a>;
 };
index 0f0553563fc1c265ea759d1c7348ad1c71f97c57..f6c0c263b135add1539054bb3beee8414da11c63 100644 (file)
@@ -10,7 +10,7 @@ Required properties:
 
 Example:
 
-codec: wm8524 {
+wm8524: codec {
        compatible = "wlf,wm8524";
        wlf,mute-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
 };
index 78fce9b14954ef76f9726b98486674d35b4ae934..ff3f9f5f2111f7afc832fcf6b280468dad843eb1 100644 (file)
@@ -10,7 +10,7 @@ Required properties:
 
 Example:
 
-codec: wm8580@1a {
+wm8580: codec@1a {
        compatible = "wlf,wm8580";
        reg = <0x1a>;
 };
index 8ed9998cd23c0ad1f0357152f09b4360d52ec74a..c30a1387c4bff4f08a081d1a711b43d6f8e2a53e 100644 (file)
@@ -12,7 +12,7 @@ Required properties:
 
 Example:
 
-codec: wm8711@1a {
+wm8711: codec@1a {
        compatible = "wlf,wm8711";
        reg = <0x1a>;
 };
index a8b5c3668e602537faf0bf1189fcd006286af3a4..a3608b4c78b95ce2a3998de2df43e6a3d8fbc4d5 100644 (file)
@@ -12,7 +12,7 @@ Required properties:
 
 Example:
 
-codec: wm8728@1a {
+wm8728: codec@1a {
        compatible = "wlf,wm8728";
        reg = <0x1a>;
 };
index 236690e99b87fbc81c0cb5b1823981cf1e87ff4d..f660d9bb0e698eb0a9d141541709071ff745b418 100644 (file)
@@ -12,7 +12,7 @@ Required properties:
 
 Example:
 
-codec: wm8731@1a {
+wm8731: codec@1a {
        compatible = "wlf,wm8731";
        reg = <0x1a>;
 };
index 4bc2cea3b14085cf4b95c62065db7bcdce4e771c..eda1ec6a7563a04a4b83bc3fafea57d91b4ec9a4 100644 (file)
@@ -12,7 +12,7 @@ Required properties:
 
 Example:
 
-codec: wm8737@1a {
+wm8737: codec@1a {
        compatible = "wlf,wm8737";
        reg = <0x1a>;
 };
index a133154087194cb90a2056ba6f927d67b6e49ba4..b69e196c741c4f8d13b051e16b06c904e64c25f1 100644 (file)
@@ -21,7 +21,7 @@ Optional properties:
 
 Example:
 
-codec: wm8741@1a {
+wm8741: codec@1a {
        compatible = "wlf,wm8741";
        reg = <0x1a>;
 
index 8db239fd5ecde354e559e56ef8f32194336a1586..682f221f6f38e3615d043070a26585916e096dc7 100644 (file)
@@ -12,7 +12,7 @@ Required properties:
 
 Example:
 
-codec: wm8750@1a {
+wm8750: codec@1a {
        compatible = "wlf,wm8750";
        reg = <0x1a>;
 };
index 8eee6128210552e0d8decfedeffbc0b216a9ec21..eca9e5a825a96e5ff17f682a83ffeef7f33a896b 100644 (file)
@@ -34,7 +34,7 @@ Pins on the device (for linking into audio routes):
 
 Example:
 
-codec: wm8753@1a {
+wm8753: codec@1a {
        compatible = "wlf,wm8753";
        reg = <0x1a>;
 };
index 866e00ca150b4b04e573e204a3ad39a0c057a58a..cac762a1105ded99ebe0966d2c4f0c67bbba7dc6 100644 (file)
@@ -10,7 +10,7 @@ Required properties:
 
 Example:
 
-codec: wm8770@1 {
+wm8770: codec@1 {
        compatible = "wlf,wm8770";
        reg = <1>;
 };
index 3b9ca49abc2b146a8bacafb0e182b8773b6cb4c3..01173369c3ed300a89dd86c288757ddfae0e37b7 100644 (file)
@@ -12,7 +12,7 @@ Required properties:
 
 Example:
 
-codec: wm8776@1a {
+wm8776: codec@1a {
        compatible = "wlf,wm8776";
        reg = <0x1a>;
 };
index 6fd124b1649652dfaac67bf0efbf35f0bade58e4..2c1641c17a91efc97c0a6194724da559849721cb 100644 (file)
@@ -19,7 +19,7 @@ Optional properties:
 
 Example:
 
-codec: wm8804@1a {
+wm8804: codec@1a {
        compatible = "wlf,wm8804";
        reg = <0x1a>;
 };
index afc51caf113705e4da112635385c205f290442ac..6371c2434afe75f0dbfd7228f1b905879fc0288d 100644 (file)
@@ -57,7 +57,7 @@ Pins on the device (for linking into audio routes):
 
 Example:
 
-codec: wm8903@1a {
+wm8903: codec@1a {
        compatible = "wlf,wm8903";
        reg = <0x1a>;
        interrupts = < 347 >;
index 2deb8a3da9c55662882f55abdd5da719ca5c5f6a..6d29ac3750eeea29da05a361b527580e65d6f76f 100644 (file)
@@ -23,7 +23,7 @@ Optional properties:
 
 Example:
 
-codec: wm8960@1a {
+wm8960: codec@1a {
        compatible = "wlf,wm8960";
        reg = <0x1a>;
 
index 7f82b59ec8f947f336ec6515d88839cbe7c3bb54..dcfa9a3369fde640da518de0f61466a1a54235c4 100644 (file)
@@ -24,7 +24,7 @@ Optional properties:
 
 Example:
 
-codec: wm8962@1a {
+wm8962: codec@1a {
        compatible = "wlf,wm8962";
        reg = <0x1a>;
 
index 68c4e8d96bed68c4c3d0ea09b10cbe8cb8170515..4a9dead1b7d32e67b6dd51c081574c4f59b3bb86 100644 (file)
@@ -59,7 +59,7 @@ Optional properties:
 
 Example:
 
-codec: wm8994@1a {
+wm8994: codec@1a {
        compatible = "wlf,wm8994";
        reg = <0x1a>;
 
index f87612b948120870869314d1bdfa924520c3ca9c..58f625fe3d39720a87dea848c5ce5c965d688c18 100644 (file)
@@ -179,12 +179,12 @@ i.e.
 
   static int wm8974_mute(struct snd_soc_dai *dai, int mute)
   {
-       struct snd_soc_codec *codec = dai->codec;
-       u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf;
+       struct snd_soc_component *component = dai->component;
+       u16 mute_reg = snd_soc_component_read32(component, WM8974_DAC) & 0xffbf;
 
        if (mute)
-               snd_soc_write(codec, WM8974_DAC, mute_reg | 0x40);
+               snd_soc_component_write(component, WM8974_DAC, mute_reg | 0x40);
        else
-               snd_soc_write(codec, WM8974_DAC, mute_reg);
+               snd_soc_component_write(component, WM8974_DAC, mute_reg);
        return 0;
   }
index d5574904d981d59e1b2a23afbfcc71262f50edbe..cc817078daa65d0ef19d5f8daa5e9656d988bc08 100644 (file)
@@ -23,30 +23,26 @@ The platform DMA driver optionally supports the following ALSA operations:-
   };
 
 The platform driver exports its DMA functionality via struct
-snd_soc_platform_driver:-
+snd_soc_component_driver:-
 ::
 
-  struct snd_soc_platform_driver {
-       char *name;
+  struct snd_soc_component_driver {
+       const char *name;
 
-       int (*probe)(struct platform_device *pdev);
-       int (*remove)(struct platform_device *pdev);
-       int (*suspend)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
-       int (*resume)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
+       ...
+       int (*probe)(struct snd_soc_component *);
+       void (*remove)(struct snd_soc_component *);
+       int (*suspend)(struct snd_soc_component *);
+       int (*resume)(struct snd_soc_component *);
 
        /* pcm creation and destruction */
-       int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *, struct snd_pcm *);
+       int (*pcm_new)(struct snd_soc_pcm_runtime *);
        void (*pcm_free)(struct snd_pcm *);
 
-       /*
-        * For platform caused delay reporting.
-        * Optional.
-        */
-       snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
-               struct snd_soc_dai *);
-
-       /* platform stream ops */
-       struct snd_pcm_ops *pcm_ops;
+       ...
+       const struct snd_pcm_ops *ops;
+       const struct snd_compr_ops *compr_ops;
+       ...
   };
 
 Please refer to the ALSA driver documentation for details of audio DMA.
index bd214e061359e5512a3cd87c0fcc4887c351ac69..488b88071c13a12f9070984a7fbdc87ecbb6b424 100644 (file)
@@ -7038,14 +7038,13 @@ L:      linux-fbdev@vger.kernel.org
 S:     Maintained
 F:     drivers/video/fbdev/i810/
 
-INTEL ASoC BDW/HSW DRIVERS
+INTEL ASoC DRIVERS
+M:     Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+M:     Liam Girdwood <liam.r.girdwood@linux.intel.com>
 M:     Jie Yang <yang.jie@linux.intel.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
-F:     sound/soc/intel/common/sst-dsp*
-F:     sound/soc/intel/common/sst-firmware.c
-F:     sound/soc/intel/boards/broadwell.c
-F:     sound/soc/intel/haswell/
+F:     sound/soc/intel/
 
 INTEL C600 SERIES SAS CONTROLLER DRIVER
 M:     Intel SCU Linux support <intel-linux-scu@intel.com>
@@ -13124,7 +13123,7 @@ F:      include/uapi/sound/
 F:     sound/
 
 SOUND - COMPRESSED AUDIO
-M:     Vinod Koul <vinod.koul@intel.com>
+M:     Vinod Koul <vkoul@kernel.org>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
 S:     Supported
index e70feec6fad5e296b869d76e90d31bf5b71d1334..48d6a9e01dc8aef472645bcf28906508e73ca2e8 100644 (file)
@@ -635,6 +635,7 @@ EXPORT_SYMBOL(ep93xx_keypad_release_gpio);
  *************************************************************************/
 static struct resource ep93xx_i2s_resource[] = {
        DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100),
+       DEFINE_RES_IRQ(IRQ_EP93XX_SAI),
 };
 
 static struct platform_device ep93xx_i2s_device = {
index 3021913c28fa3ca3001820f176adcd003b1864c8..33d7fcf541fc0867a8317b90f1700868f0313b42 100644 (file)
@@ -2444,7 +2444,7 @@ static int tda1997x_pcm_startup(struct snd_pcm_substream *substream,
                                struct snd_soc_dai *dai)
 {
        struct tda1997x_state *state = snd_soc_dai_get_drvdata(dai);
-       struct snd_soc_codec *codec = dai->codec;
+       struct snd_soc_component *component = dai->component;
        struct snd_pcm_runtime *rtd = substream->runtime;
        int rate, err;
 
@@ -2452,11 +2452,11 @@ static int tda1997x_pcm_startup(struct snd_pcm_substream *substream,
        err = snd_pcm_hw_constraint_minmax(rtd, SNDRV_PCM_HW_PARAM_RATE,
                                           rate, rate);
        if (err < 0) {
-               dev_err(codec->dev, "failed to constrain samplerate to %dHz\n",
+               dev_err(component->dev, "failed to constrain samplerate to %dHz\n",
                        rate);
                return err;
        }
-       dev_info(codec->dev, "set samplerate constraint to %dHz\n", rate);
+       dev_info(component->dev, "set samplerate constraint to %dHz\n", rate);
 
        return 0;
 }
@@ -2479,20 +2479,22 @@ static struct snd_soc_dai_driver tda1997x_audio_dai = {
        .ops = &tda1997x_dai_ops,
 };
 
-static int tda1997x_codec_probe(struct snd_soc_codec *codec)
+static int tda1997x_codec_probe(struct snd_soc_component *component)
 {
        return 0;
 }
 
-static int tda1997x_codec_remove(struct snd_soc_codec *codec)
+static void tda1997x_codec_remove(struct snd_soc_component *component)
 {
-       return 0;
 }
 
-static struct snd_soc_codec_driver tda1997x_codec_driver = {
-       .probe = tda1997x_codec_probe,
-       .remove = tda1997x_codec_remove,
-       .reg_word_size = sizeof(u16),
+static struct snd_soc_component_driver tda1997x_codec_driver = {
+       .probe                  = tda1997x_codec_probe,
+       .remove                 = tda1997x_codec_remove,
+       .idle_bias_on           = 1,
+       .use_pmdown_time        = 1,
+       .endianness             = 1,
+       .non_legacy_dai_naming  = 1,
 };
 
 static int tda1997x_probe(struct i2c_client *client,
@@ -2737,7 +2739,7 @@ static int tda1997x_probe(struct i2c_client *client,
                else
                        formats = SNDRV_PCM_FMTBIT_S16_LE;
                tda1997x_audio_dai.capture.formats = formats;
-               ret = snd_soc_register_codec(&state->client->dev,
+               ret = devm_snd_soc_register_component(&state->client->dev,
                                             &tda1997x_codec_driver,
                                             &tda1997x_audio_dai, 1);
                if (ret) {
@@ -2782,7 +2784,6 @@ static int tda1997x_remove(struct i2c_client *client)
        struct tda1997x_platform_data *pdata = &state->pdata;
 
        if (pdata->audout_format) {
-               snd_soc_unregister_codec(&client->dev);
                mutex_destroy(&state->audio_lock);
        }
 
index 5c4535b545cc9564529b2c76877a24ce8cff8aff..d053f2634c67a30da9c04a9b0f484c2d6683c59e 100644 (file)
@@ -108,4 +108,13 @@ config QCOM_WCNSS_CTRL
          Client driver for the WCNSS_CTRL SMD channel, used to download nv
          firmware to a newly booted WCNSS chip.
 
+config QCOM_APR
+       tristate "Qualcomm APR Bus (Asynchronous Packet Router)"
+       depends on ARCH_QCOM
+       depends on RPMSG
+       help
+          Enable APR IPC protocol support between
+          application processor and QDSP6. APR is
+          used by audio driver to configure QDSP6
+          ASM, ADM and AFE modules.
 endmenu
index dcebf2814e6d299ce87e0d137cfc2b1af61afbc9..39de5dee55d9d3835b6c1f91d227ef2abae26fde 100644 (file)
@@ -12,3 +12,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
 obj-$(CONFIG_QCOM_SMP2P)       += smp2p.o
 obj-$(CONFIG_QCOM_SMSM)        += smsm.o
 obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
+obj-$(CONFIG_QCOM_APR) += apr.o
diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c
new file mode 100644 (file)
index 0000000..57af8a5
--- /dev/null
@@ -0,0 +1,378 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+// Copyright (c) 2018, Linaro Limited
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/idr.h>
+#include <linux/slab.h>
+#include <linux/of_device.h>
+#include <linux/soc/qcom/apr.h>
+#include <linux/rpmsg.h>
+#include <linux/of.h>
+
+struct apr {
+       struct rpmsg_endpoint *ch;
+       struct device *dev;
+       spinlock_t svcs_lock;
+       struct idr svcs_idr;
+       int dest_domain_id;
+};
+
+/**
+ * apr_send_pkt() - Send a apr message from apr device
+ *
+ * @adev: Pointer to previously registered apr device.
+ * @pkt: Pointer to apr packet to send
+ *
+ * Return: Will be an negative on packet size on success.
+ */
+int apr_send_pkt(struct apr_device *adev, struct apr_pkt *pkt)
+{
+       struct apr *apr = dev_get_drvdata(adev->dev.parent);
+       struct apr_hdr *hdr;
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&adev->lock, flags);
+
+       hdr = &pkt->hdr;
+       hdr->src_domain = APR_DOMAIN_APPS;
+       hdr->src_svc = adev->svc_id;
+       hdr->dest_domain = adev->domain_id;
+       hdr->dest_svc = adev->svc_id;
+
+       ret = rpmsg_trysend(apr->ch, pkt, hdr->pkt_size);
+       spin_unlock_irqrestore(&adev->lock, flags);
+
+       return ret ? ret : hdr->pkt_size;
+}
+EXPORT_SYMBOL_GPL(apr_send_pkt);
+
+static void apr_dev_release(struct device *dev)
+{
+       struct apr_device *adev = to_apr_device(dev);
+
+       kfree(adev);
+}
+
+static int apr_callback(struct rpmsg_device *rpdev, void *buf,
+                                 int len, void *priv, u32 addr)
+{
+       struct apr *apr = dev_get_drvdata(&rpdev->dev);
+       uint16_t hdr_size, msg_type, ver, svc_id;
+       struct apr_device *svc = NULL;
+       struct apr_driver *adrv = NULL;
+       struct apr_resp_pkt resp;
+       struct apr_hdr *hdr;
+       unsigned long flags;
+
+       if (len <= APR_HDR_SIZE) {
+               dev_err(apr->dev, "APR: Improper apr pkt received:%p %d\n",
+                       buf, len);
+               return -EINVAL;
+       }
+
+       hdr = buf;
+       ver = APR_HDR_FIELD_VER(hdr->hdr_field);
+       if (ver > APR_PKT_VER + 1)
+               return -EINVAL;
+
+       hdr_size = APR_HDR_FIELD_SIZE_BYTES(hdr->hdr_field);
+       if (hdr_size < APR_HDR_SIZE) {
+               dev_err(apr->dev, "APR: Wrong hdr size:%d\n", hdr_size);
+               return -EINVAL;
+       }
+
+       if (hdr->pkt_size < APR_HDR_SIZE || hdr->pkt_size != len) {
+               dev_err(apr->dev, "APR: Wrong paket size\n");
+               return -EINVAL;
+       }
+
+       msg_type = APR_HDR_FIELD_MT(hdr->hdr_field);
+       if (msg_type >= APR_MSG_TYPE_MAX) {
+               dev_err(apr->dev, "APR: Wrong message type: %d\n", msg_type);
+               return -EINVAL;
+       }
+
+       if (hdr->src_domain >= APR_DOMAIN_MAX ||
+                       hdr->dest_domain >= APR_DOMAIN_MAX ||
+                       hdr->src_svc >= APR_SVC_MAX ||
+                       hdr->dest_svc >= APR_SVC_MAX) {
+               dev_err(apr->dev, "APR: Wrong APR header\n");
+               return -EINVAL;
+       }
+
+       svc_id = hdr->dest_svc;
+       spin_lock_irqsave(&apr->svcs_lock, flags);
+       svc = idr_find(&apr->svcs_idr, svc_id);
+       if (svc && svc->dev.driver)
+               adrv = to_apr_driver(svc->dev.driver);
+       spin_unlock_irqrestore(&apr->svcs_lock, flags);
+
+       if (!adrv) {
+               dev_err(apr->dev, "APR: service is not registered\n");
+               return -EINVAL;
+       }
+
+       resp.hdr = *hdr;
+       resp.payload_size = hdr->pkt_size - hdr_size;
+
+       /*
+        * NOTE: hdr_size is not same as APR_HDR_SIZE as remote can include
+        * optional headers in to apr_hdr which should be ignored
+        */
+       if (resp.payload_size > 0)
+               resp.payload = buf + hdr_size;
+
+       adrv->callback(svc, &resp);
+
+       return 0;
+}
+
+static int apr_device_match(struct device *dev, struct device_driver *drv)
+{
+       struct apr_device *adev = to_apr_device(dev);
+       struct apr_driver *adrv = to_apr_driver(drv);
+       const struct apr_device_id *id = adrv->id_table;
+
+       /* Attempt an OF style match first */
+       if (of_driver_match_device(dev, drv))
+               return 1;
+
+       if (!id)
+               return 0;
+
+       while (id->domain_id != 0 || id->svc_id != 0) {
+               if (id->domain_id == adev->domain_id &&
+                   id->svc_id == adev->svc_id)
+                       return 1;
+               id++;
+       }
+
+       return 0;
+}
+
+static int apr_device_probe(struct device *dev)
+{
+       struct apr_device *adev = to_apr_device(dev);
+       struct apr_driver *adrv = to_apr_driver(dev->driver);
+
+       return adrv->probe(adev);
+}
+
+static int apr_device_remove(struct device *dev)
+{
+       struct apr_device *adev = to_apr_device(dev);
+       struct apr_driver *adrv;
+       struct apr *apr = dev_get_drvdata(adev->dev.parent);
+
+       if (dev->driver) {
+               adrv = to_apr_driver(dev->driver);
+               if (adrv->remove)
+                       adrv->remove(adev);
+               spin_lock(&apr->svcs_lock);
+               idr_remove(&apr->svcs_idr, adev->svc_id);
+               spin_unlock(&apr->svcs_lock);
+       }
+
+       return 0;
+}
+
+static int apr_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       struct apr_device *adev = to_apr_device(dev);
+       int ret;
+
+       ret = of_device_uevent_modalias(dev, env);
+       if (ret != -ENODEV)
+               return ret;
+
+       return add_uevent_var(env, "MODALIAS=apr:%s", adev->name);
+}
+
+struct bus_type aprbus = {
+       .name           = "aprbus",
+       .match          = apr_device_match,
+       .probe          = apr_device_probe,
+       .uevent         = apr_uevent,
+       .remove         = apr_device_remove,
+};
+EXPORT_SYMBOL_GPL(aprbus);
+
+static int apr_add_device(struct device *dev, struct device_node *np,
+                         const struct apr_device_id *id)
+{
+       struct apr *apr = dev_get_drvdata(dev);
+       struct apr_device *adev = NULL;
+       int ret;
+
+       adev = kzalloc(sizeof(*adev), GFP_KERNEL);
+       if (!adev)
+               return -ENOMEM;
+
+       spin_lock_init(&adev->lock);
+
+       adev->svc_id = id->svc_id;
+       adev->domain_id = id->domain_id;
+       adev->version = id->svc_version;
+       if (np)
+               strncpy(adev->name, np->name, APR_NAME_SIZE);
+       else
+               strncpy(adev->name, id->name, APR_NAME_SIZE);
+
+       dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name,
+                    id->domain_id, id->svc_id);
+
+       adev->dev.bus = &aprbus;
+       adev->dev.parent = dev;
+       adev->dev.of_node = np;
+       adev->dev.release = apr_dev_release;
+       adev->dev.driver = NULL;
+
+       spin_lock(&apr->svcs_lock);
+       idr_alloc(&apr->svcs_idr, adev, id->svc_id,
+                 id->svc_id + 1, GFP_ATOMIC);
+       spin_unlock(&apr->svcs_lock);
+
+       dev_info(dev, "Adding APR dev: %s\n", dev_name(&adev->dev));
+
+       ret = device_register(&adev->dev);
+       if (ret) {
+               dev_err(dev, "device_register failed: %d\n", ret);
+               put_device(&adev->dev);
+       }
+
+       return ret;
+}
+
+static void of_register_apr_devices(struct device *dev)
+{
+       struct apr *apr = dev_get_drvdata(dev);
+       struct device_node *node;
+
+       for_each_child_of_node(dev->of_node, node) {
+               struct apr_device_id id = { {0} };
+
+               if (of_property_read_u32(node, "reg", &id.svc_id))
+                       continue;
+
+               id.domain_id = apr->dest_domain_id;
+
+               if (apr_add_device(dev, node, &id))
+                       dev_err(dev, "Failed to add apr %d svc\n", id.svc_id);
+       }
+}
+
+static int apr_probe(struct rpmsg_device *rpdev)
+{
+       struct device *dev = &rpdev->dev;
+       struct apr *apr;
+       int ret;
+
+       apr = devm_kzalloc(dev, sizeof(*apr), GFP_KERNEL);
+       if (!apr)
+               return -ENOMEM;
+
+       ret = of_property_read_u32(dev->of_node, "reg", &apr->dest_domain_id);
+       if (ret) {
+               dev_err(dev, "APR Domain ID not specified in DT\n");
+               return ret;
+       }
+
+       dev_set_drvdata(dev, apr);
+       apr->ch = rpdev->ept;
+       apr->dev = dev;
+       spin_lock_init(&apr->svcs_lock);
+       idr_init(&apr->svcs_idr);
+       of_register_apr_devices(dev);
+
+       return 0;
+}
+
+static int apr_remove_device(struct device *dev, void *null)
+{
+       struct apr_device *adev = to_apr_device(dev);
+
+       device_unregister(&adev->dev);
+
+       return 0;
+}
+
+static void apr_remove(struct rpmsg_device *rpdev)
+{
+       device_for_each_child(&rpdev->dev, NULL, apr_remove_device);
+}
+
+/*
+ * __apr_driver_register() - Client driver registration with aprbus
+ *
+ * @drv:Client driver to be associated with client-device.
+ * @owner: owning module/driver
+ *
+ * This API will register the client driver with the aprbus
+ * It is called from the driver's module-init function.
+ */
+int __apr_driver_register(struct apr_driver *drv, struct module *owner)
+{
+       drv->driver.bus = &aprbus;
+       drv->driver.owner = owner;
+
+       return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(__apr_driver_register);
+
+/*
+ * apr_driver_unregister() - Undo effect of apr_driver_register
+ *
+ * @drv: Client driver to be unregistered
+ */
+void apr_driver_unregister(struct apr_driver *drv)
+{
+       driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(apr_driver_unregister);
+
+static const struct of_device_id apr_of_match[] = {
+       { .compatible = "qcom,apr"},
+       { .compatible = "qcom,apr-v2"},
+       {}
+};
+MODULE_DEVICE_TABLE(of, apr_of_match);
+
+static struct rpmsg_driver apr_driver = {
+       .probe = apr_probe,
+       .remove = apr_remove,
+       .callback = apr_callback,
+       .drv = {
+               .name = "qcom,apr",
+               .of_match_table = apr_of_match,
+       },
+};
+
+static int __init apr_init(void)
+{
+       int ret;
+
+       ret = bus_register(&aprbus);
+       if (!ret)
+               ret = register_rpmsg_driver(&apr_driver);
+       else
+               bus_unregister(&aprbus);
+
+       return ret;
+}
+
+static void __exit apr_exit(void)
+{
+       bus_unregister(&aprbus);
+       unregister_rpmsg_driver(&apr_driver);
+}
+
+subsys_initcall(apr_init);
+module_exit(apr_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Qualcomm APR Bus");
diff --git a/include/dt-bindings/soc/qcom,apr.h b/include/dt-bindings/soc/qcom,apr.h
new file mode 100644 (file)
index 0000000..0063624
--- /dev/null
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DT_BINDINGS_QCOM_APR_H
+#define __DT_BINDINGS_QCOM_APR_H
+
+/* Domain IDs */
+#define APR_DOMAIN_SIM         0x1
+#define APR_DOMAIN_PC          0x2
+#define APR_DOMAIN_MODEM       0x3
+#define APR_DOMAIN_ADSP                0x4
+#define APR_DOMAIN_APPS                0x5
+#define APR_DOMAIN_MAX         0x6
+
+/* ADSP service IDs */
+#define APR_SVC_ADSP_CORE      0x3
+#define APR_SVC_AFE            0x4
+#define APR_SVC_VSM            0x5
+#define APR_SVC_VPM            0x6
+#define APR_SVC_ASM            0x7
+#define APR_SVC_ADM            0x8
+#define APR_SVC_ADSP_MVM       0x09
+#define APR_SVC_ADSP_CVS       0x0A
+#define APR_SVC_ADSP_CVP       0x0B
+#define APR_SVC_USM            0x0C
+#define APR_SVC_LSM            0x0D
+#define APR_SVC_VIDC           0x16
+#define APR_SVC_MAX            0x17
+
+#endif /* __DT_BINDINGS_QCOM_APR_H */
index 751fe1416f958ea0f3f5ae56309fe7992f2134eb..15f138bebe16b229ed00230d4c3d0221475c2408 100644 (file)
 #define MX51_AUDMUX_PORT6              5
 #define MX51_AUDMUX_PORT7              6
 
+/*
+ * TFCSEL/RFCSEL (i.MX27) or TFSEL/TCSEL/RFSEL/RCSEL (i.MX31/51/53/6Q)
+ * can be sourced from Rx/Tx.
+ */
+#define IMX_AUDMUX_RXFS                        0x8
+#define IMX_AUDMUX_RXCLK               0x8
+
 /* Register definitions for the i.MX21/27 Digital Audio Multiplexer */
 #define IMX_AUDMUX_V1_PCR_INMMASK(x)   ((x) & 0xff)
 #define IMX_AUDMUX_V1_PCR_INMEN                (1 << 8)
diff --git a/include/dt-bindings/sound/qcom,q6afe.h b/include/dt-bindings/sound/qcom,q6afe.h
new file mode 100644 (file)
index 0000000..e2d3892
--- /dev/null
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DT_BINDINGS_Q6_AFE_H__
+#define __DT_BINDINGS_Q6_AFE_H__
+
+/* Audio Front End (AFE) virtual ports IDs */
+#define HDMI_RX                1
+#define SLIMBUS_0_RX    2
+#define SLIMBUS_0_TX    3
+#define SLIMBUS_1_RX    4
+#define SLIMBUS_1_TX    5
+#define SLIMBUS_2_RX    6
+#define SLIMBUS_2_TX    7
+#define SLIMBUS_3_RX    8
+#define SLIMBUS_3_TX    9
+#define SLIMBUS_4_RX    10
+#define SLIMBUS_4_TX    11
+#define SLIMBUS_5_RX    12
+#define SLIMBUS_5_TX    13
+#define SLIMBUS_6_RX    14
+#define SLIMBUS_6_TX    15
+#define PRIMARY_MI2S_RX                16
+#define PRIMARY_MI2S_TX                17
+#define SECONDARY_MI2S_RX      18
+#define SECONDARY_MI2S_TX      19
+#define TERTIARY_MI2S_RX       20
+#define TERTIARY_MI2S_TX       21
+#define QUATERNARY_MI2S_RX     22
+#define QUATERNARY_MI2S_TX     23
+#define PRIMARY_TDM_RX_0       24
+#define PRIMARY_TDM_TX_0       25
+#define PRIMARY_TDM_RX_1       26
+#define PRIMARY_TDM_TX_1       27
+#define PRIMARY_TDM_RX_2       28
+#define PRIMARY_TDM_TX_2       29
+#define PRIMARY_TDM_RX_3       30
+#define PRIMARY_TDM_TX_3       31
+#define PRIMARY_TDM_RX_4       32
+#define PRIMARY_TDM_TX_4       33
+#define PRIMARY_TDM_RX_5       34
+#define PRIMARY_TDM_TX_5       35
+#define PRIMARY_TDM_RX_6       36
+#define PRIMARY_TDM_TX_6       37
+#define PRIMARY_TDM_RX_7       38
+#define PRIMARY_TDM_TX_7       39
+#define SECONDARY_TDM_RX_0     40
+#define SECONDARY_TDM_TX_0     41
+#define SECONDARY_TDM_RX_1     42
+#define SECONDARY_TDM_TX_1     43
+#define SECONDARY_TDM_RX_2     44
+#define SECONDARY_TDM_TX_2     45
+#define SECONDARY_TDM_RX_3     46
+#define SECONDARY_TDM_TX_3     47
+#define SECONDARY_TDM_RX_4     48
+#define SECONDARY_TDM_TX_4     49
+#define SECONDARY_TDM_RX_5     50
+#define SECONDARY_TDM_TX_5     51
+#define SECONDARY_TDM_RX_6     52
+#define SECONDARY_TDM_TX_6     53
+#define SECONDARY_TDM_RX_7     54
+#define SECONDARY_TDM_TX_7     55
+#define TERTIARY_TDM_RX_0      56
+#define TERTIARY_TDM_TX_0      57
+#define TERTIARY_TDM_RX_1      58
+#define TERTIARY_TDM_TX_1      59
+#define TERTIARY_TDM_RX_2      60
+#define TERTIARY_TDM_TX_2      61
+#define TERTIARY_TDM_RX_3      62
+#define TERTIARY_TDM_TX_3      63
+#define TERTIARY_TDM_RX_4      64
+#define TERTIARY_TDM_TX_4      65
+#define TERTIARY_TDM_RX_5      66
+#define TERTIARY_TDM_TX_5      67
+#define TERTIARY_TDM_RX_6      68
+#define TERTIARY_TDM_TX_6      69
+#define TERTIARY_TDM_RX_7      70
+#define TERTIARY_TDM_TX_7      71
+#define QUATERNARY_TDM_RX_0    72
+#define QUATERNARY_TDM_TX_0    73
+#define QUATERNARY_TDM_RX_1    74
+#define QUATERNARY_TDM_TX_1    75
+#define QUATERNARY_TDM_RX_2    76
+#define QUATERNARY_TDM_TX_2    77
+#define QUATERNARY_TDM_RX_3    78
+#define QUATERNARY_TDM_TX_3    79
+#define QUATERNARY_TDM_RX_4    80
+#define QUATERNARY_TDM_TX_4    81
+#define QUATERNARY_TDM_RX_5    82
+#define QUATERNARY_TDM_TX_5    83
+#define QUATERNARY_TDM_RX_6    84
+#define QUATERNARY_TDM_TX_6    85
+#define QUATERNARY_TDM_RX_7    86
+#define QUATERNARY_TDM_TX_7    87
+#define QUINARY_TDM_RX_0       88
+#define QUINARY_TDM_TX_0       89
+#define QUINARY_TDM_RX_1       90
+#define QUINARY_TDM_TX_1       91
+#define QUINARY_TDM_RX_2       92
+#define QUINARY_TDM_TX_2       93
+#define QUINARY_TDM_RX_3       94
+#define QUINARY_TDM_TX_3       95
+#define QUINARY_TDM_RX_4       96
+#define QUINARY_TDM_TX_4       97
+#define QUINARY_TDM_RX_5       98
+#define QUINARY_TDM_TX_5       99
+#define QUINARY_TDM_RX_6       100
+#define QUINARY_TDM_TX_6       101
+#define QUINARY_TDM_RX_7       102
+#define QUINARY_TDM_TX_7       103
+
+#endif /* __DT_BINDINGS_Q6_AFE_H__ */
+
diff --git a/include/dt-bindings/sound/qcom,q6asm.h b/include/dt-bindings/sound/qcom,q6asm.h
new file mode 100644 (file)
index 0000000..1eb77d8
--- /dev/null
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DT_BINDINGS_Q6_ASM_H__
+#define __DT_BINDINGS_Q6_ASM_H__
+
+#define        MSM_FRONTEND_DAI_MULTIMEDIA1    0
+#define        MSM_FRONTEND_DAI_MULTIMEDIA2    1
+#define        MSM_FRONTEND_DAI_MULTIMEDIA3    2
+#define        MSM_FRONTEND_DAI_MULTIMEDIA4    3
+#define        MSM_FRONTEND_DAI_MULTIMEDIA5    4
+#define        MSM_FRONTEND_DAI_MULTIMEDIA6    5
+#define        MSM_FRONTEND_DAI_MULTIMEDIA7    6
+#define        MSM_FRONTEND_DAI_MULTIMEDIA8    7
+#define        MSM_FRONTEND_DAI_MULTIMEDIA9    8
+#define        MSM_FRONTEND_DAI_MULTIMEDIA10   9
+#define        MSM_FRONTEND_DAI_MULTIMEDIA11   10
+#define        MSM_FRONTEND_DAI_MULTIMEDIA12   11
+#define        MSM_FRONTEND_DAI_MULTIMEDIA13   12
+#define        MSM_FRONTEND_DAI_MULTIMEDIA14   13
+#define        MSM_FRONTEND_DAI_MULTIMEDIA15   14
+#define        MSM_FRONTEND_DAI_MULTIMEDIA16   15
+
+#endif /* __DT_BINDINGS_Q6_ASM_H__ */
diff --git a/include/dt-bindings/sound/rt5640.h b/include/dt-bindings/sound/rt5640.h
new file mode 100644 (file)
index 0000000..154c9b4
--- /dev/null
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DT_RT5640_H
+#define __DT_RT5640_H
+
+#define RT5640_DMIC1_DATA_PIN_NONE     0
+#define RT5640_DMIC1_DATA_PIN_IN1P     1
+#define RT5640_DMIC1_DATA_PIN_GPIO3    2
+
+#define RT5640_DMIC2_DATA_PIN_NONE     0
+#define RT5640_DMIC2_DATA_PIN_IN1N     1
+#define RT5640_DMIC2_DATA_PIN_GPIO4    2
+
+#define RT5640_JD_SRC_GPIO1            1
+#define RT5640_JD_SRC_JD1_IN4P         2
+#define RT5640_JD_SRC_JD2_IN4N         3
+#define RT5640_JD_SRC_GPIO2            4
+#define RT5640_JD_SRC_GPIO3            5
+#define RT5640_JD_SRC_GPIO4            6
+
+#define RT5640_OVCD_SF_0P5             0
+#define RT5640_OVCD_SF_0P75            1
+#define RT5640_OVCD_SF_1P0             2
+#define RT5640_OVCD_SF_1P5             3
+
+#endif /* __DT_RT5640_H */
index bd581c6fa0855bf9014a5cb061d5dc78df204e21..0bc41c4c0429a5bb8937aece23a0843f82a7b9b1 100644 (file)
@@ -617,11 +617,8 @@ struct wm8350_audio_platform_data {
        u32 codec_current_charge:2;     /* codec current @ vmid charge */
 };
 
-struct snd_soc_codec;
-
 struct wm8350_codec {
        struct platform_device *pdev;
-       struct snd_soc_codec *codec;
        struct wm8350_audio_platform_data *platform_data;
 };
 
index 7d361be2e24f4f428a1167efe04f79ebe0a3fde5..2014bd19f28eff41ae37b80eba324644c537e291 100644 (file)
@@ -471,6 +471,17 @@ struct slim_device_id {
        kernel_ulong_t driver_data;
 };
 
+#define APR_NAME_SIZE  32
+#define APR_MODULE_PREFIX "apr:"
+
+struct apr_device_id {
+       char name[APR_NAME_SIZE];
+       __u32 domain_id;
+       __u32 svc_id;
+       __u32 svc_version;
+       kernel_ulong_t driver_data;     /* Data private to the driver */
+};
+
 #define SPMI_NAME_SIZE 32
 #define SPMI_MODULE_PREFIX "spmi:"
 
diff --git a/include/linux/soc/qcom/apr.h b/include/linux/soc/qcom/apr.h
new file mode 100644 (file)
index 0000000..c5d52e2
--- /dev/null
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __QCOM_APR_H_
+#define __QCOM_APR_H_
+
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <dt-bindings/soc/qcom,apr.h>
+
+extern struct bus_type aprbus;
+
+#define APR_HDR_LEN(hdr_len) ((hdr_len)/4)
+
+/*
+ * HEADER field
+ * version:0:3
+ * header_size : 4:7
+ * message_type : 8:9
+ * reserved: 10:15
+ */
+#define APR_HDR_FIELD(msg_type, hdr_len, ver)\
+       (((msg_type & 0x3) << 8) | ((hdr_len & 0xF) << 4) | (ver & 0xF))
+
+#define APR_HDR_SIZE sizeof(struct apr_hdr)
+#define APR_SEQ_CMD_HDR_FIELD APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
+                                           APR_HDR_LEN(APR_HDR_SIZE), \
+                                           APR_PKT_VER)
+/* Version */
+#define APR_PKT_VER            0x0
+
+/* Command and Response Types */
+#define APR_MSG_TYPE_EVENT     0x0
+#define APR_MSG_TYPE_CMD_RSP   0x1
+#define APR_MSG_TYPE_SEQ_CMD   0x2
+#define APR_MSG_TYPE_NSEQ_CMD  0x3
+#define APR_MSG_TYPE_MAX       0x04
+
+/* APR Basic Response Message */
+#define APR_BASIC_RSP_RESULT 0x000110E8
+#define APR_RSP_ACCEPTED     0x000100BE
+
+struct aprv2_ibasic_rsp_result_t {
+       uint32_t opcode;
+       uint32_t status;
+};
+
+/* hdr field Ver [0:3], Size [4:7], Message type [8:10] */
+#define APR_HDR_FIELD_VER(h)           (h & 0x000F)
+#define APR_HDR_FIELD_SIZE(h)          ((h & 0x00F0) >> 4)
+#define APR_HDR_FIELD_SIZE_BYTES(h)    (((h & 0x00F0) >> 4) * 4)
+#define APR_HDR_FIELD_MT(h)            ((h & 0x0300) >> 8)
+
+struct apr_hdr {
+       uint16_t hdr_field;
+       uint16_t pkt_size;
+       uint8_t src_svc;
+       uint8_t src_domain;
+       uint16_t src_port;
+       uint8_t dest_svc;
+       uint8_t dest_domain;
+       uint16_t dest_port;
+       uint32_t token;
+       uint32_t opcode;
+} __packed;
+
+struct apr_pkt {
+       struct apr_hdr hdr;
+       uint8_t payload[];
+};
+
+struct apr_resp_pkt {
+       struct apr_hdr hdr;
+       void *payload;
+       int payload_size;
+};
+
+/* Bits 0 to 15 -- Minor version,  Bits 16 to 31 -- Major version */
+#define APR_SVC_MAJOR_VERSION(v)       ((v >> 16) & 0xFF)
+#define APR_SVC_MINOR_VERSION(v)       (v & 0xFF)
+
+struct apr_device {
+       struct device   dev;
+       uint16_t        svc_id;
+       uint16_t        domain_id;
+       uint32_t        version;
+       char name[APR_NAME_SIZE];
+       spinlock_t      lock;
+       struct list_head node;
+};
+
+#define to_apr_device(d) container_of(d, struct apr_device, dev)
+
+struct apr_driver {
+       int     (*probe)(struct apr_device *sl);
+       int     (*remove)(struct apr_device *sl);
+       int     (*callback)(struct apr_device *a,
+                           struct apr_resp_pkt *d);
+       struct device_driver            driver;
+       const struct apr_device_id      *id_table;
+};
+
+#define to_apr_driver(d) container_of(d, struct apr_driver, driver)
+
+/*
+ * use a macro to avoid include chaining to get THIS_MODULE
+ */
+#define apr_driver_register(drv) __apr_driver_register(drv, THIS_MODULE)
+
+int __apr_driver_register(struct apr_driver *drv, struct module *owner);
+void apr_driver_unregister(struct apr_driver *drv);
+
+/**
+ * module_apr_driver() - Helper macro for registering a aprbus driver
+ * @__aprbus_driver: aprbus_driver struct
+ *
+ * Helper macro for aprbus drivers which do not do anything special in
+ * module init/exit. This eliminates a lot of boilerplate. Each module
+ * may only use this macro once, and calling it replaces module_init()
+ * and module_exit()
+ */
+#define module_apr_driver(__apr_driver) \
+       module_driver(__apr_driver, apr_driver_register, \
+                       apr_driver_unregister)
+
+int apr_send_pkt(struct apr_device *adev, struct apr_pkt *pkt);
+
+#endif /* __QCOM_APR_H_ */
diff --git a/include/sound/omap-pcm.h b/include/sound/omap-pcm.h
deleted file mode 100644 (file)
index c1d2f31..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * omap-pcm.h - OMAP PCM driver
- *
- * Copyright (C) 2014 Texas Instruments, Inc.
- *
- * Author: 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.
- */
-
-#ifndef __OMAP_PCM_H__
-#define __OMAP_PCM_H__
-
-#if IS_ENABLED(CONFIG_SND_OMAP_SOC)
-int omap_pcm_platform_register(struct device *dev);
-#else
-static inline int omap_pcm_platform_register(struct device *dev)
-{
-       return 0;
-}
-#endif /* CONFIG_SND_OMAP_SOC */
-
-#endif /* __OMAP_PCM_H__ */
diff --git a/include/sound/rt5640.h b/include/sound/rt5640.h
deleted file mode 100644 (file)
index e3c84b9..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * linux/sound/rt5640.h -- Platform data for RT5640
- *
- * Copyright 2011 Realtek Microelectronics
- *
- * 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.
- */
-
-#ifndef __LINUX_SND_RT5640_H
-#define __LINUX_SND_RT5640_H
-
-struct rt5640_platform_data {
-       /* IN1 & IN2 & IN3 can optionally be differential */
-       bool in1_diff;
-       bool in2_diff;
-       bool in3_diff;
-
-       bool dmic_en;
-       bool dmic1_data_pin; /* 0 = IN1P; 1 = GPIO3 */
-       bool dmic2_data_pin; /* 0 = IN1N; 1 = GPIO4 */
-
-       int ldo1_en; /* GPIO for LDO1_EN */
-};
-
-#endif
diff --git a/include/sound/rt5668.h b/include/sound/rt5668.h
new file mode 100644 (file)
index 0000000..f907b78
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * linux/sound/rt5668.h -- Platform data for RT5668
+ *
+ * Copyright 2018 Realtek Microelectronics
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_SND_RT5668_H
+#define __LINUX_SND_RT5668_H
+
+enum rt5668_dmic1_data_pin {
+       RT5668_DMIC1_NULL,
+       RT5668_DMIC1_DATA_GPIO2,
+       RT5668_DMIC1_DATA_GPIO5,
+};
+
+enum rt5668_dmic1_clk_pin {
+       RT5668_DMIC1_CLK_GPIO1,
+       RT5668_DMIC1_CLK_GPIO3,
+};
+
+enum rt5668_jd_src {
+       RT5668_JD_NULL,
+       RT5668_JD1,
+};
+
+struct rt5668_platform_data {
+
+       int ldo1_en; /* GPIO for LDO1_EN */
+
+       enum rt5668_dmic1_data_pin dmic1_data_pin;
+       enum rt5668_dmic1_clk_pin dmic1_clk_pin;
+       enum rt5668_jd_src jd_src;
+};
+
+#endif
+
index 8ad11669e4d8f346ae3e654587386af88d08281e..568f6a72c974d13c6012e64828b92eb6d5ac6889 100644 (file)
@@ -294,8 +294,8 @@ struct snd_soc_dai {
        struct snd_soc_dai_driver *driver;
 
        /* DAI runtime info */
-       unsigned int capture_active:1;          /* stream is in use */
-       unsigned int playback_active:1;         /* stream is in use */
+       unsigned int capture_active;            /* stream usage count */
+       unsigned int playback_active;           /* stream usage count */
        unsigned int probed:1;
 
        unsigned int active;
@@ -313,7 +313,6 @@ struct snd_soc_dai {
        unsigned int sample_bits;
 
        /* parent platform/codec */
-       struct snd_soc_codec *codec;
        struct snd_soc_component *component;
 
        /* CODEC TDM slot masks and params (for fixup) */
index ad266d7e95537c470837cdeae1a7afcad639d75c..1378dcd2128aa34f9fdbf9197817760bb98e96df 100644 (file)
@@ -401,11 +401,7 @@ struct snd_soc_ops;
 struct snd_soc_pcm_runtime;
 struct snd_soc_dai;
 struct snd_soc_dai_driver;
-struct snd_soc_platform;
 struct snd_soc_dai_link;
-struct snd_soc_platform_driver;
-struct snd_soc_codec;
-struct snd_soc_codec_driver;
 struct snd_soc_component;
 struct snd_soc_component_driver;
 struct soc_enum;
@@ -430,13 +426,6 @@ enum snd_soc_card_subclass {
        SND_SOC_CARD_CLASS_RUNTIME      = 1,
 };
 
-int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
-                            int source, unsigned int freq, int dir);
-int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
-                         unsigned int freq_in, unsigned int freq_out);
-int snd_soc_codec_set_jack(struct snd_soc_codec *codec,
-                          struct snd_soc_jack *jack, void *data);
-
 int snd_soc_register_card(struct snd_soc_card *card);
 int snd_soc_unregister_card(struct snd_soc_card *card);
 int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card);
@@ -455,19 +444,6 @@ static inline int snd_soc_resume(struct device *dev)
 }
 #endif
 int snd_soc_poweroff(struct device *dev);
-int snd_soc_register_platform(struct device *dev,
-               const struct snd_soc_platform_driver *platform_drv);
-int devm_snd_soc_register_platform(struct device *dev,
-               const struct snd_soc_platform_driver *platform_drv);
-void snd_soc_unregister_platform(struct device *dev);
-int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
-               const struct snd_soc_platform_driver *platform_drv);
-void snd_soc_remove_platform(struct snd_soc_platform *platform);
-struct snd_soc_platform *snd_soc_lookup_platform(struct device *dev);
-int snd_soc_register_codec(struct device *dev,
-               const struct snd_soc_codec_driver *codec_drv,
-               struct snd_soc_dai_driver *dai_drv, int num_dai);
-void snd_soc_unregister_codec(struct device *dev);
 int snd_soc_add_component(struct device *dev,
                struct snd_soc_component *component,
                const struct snd_soc_component_driver *component_driver,
@@ -482,16 +458,15 @@ int devm_snd_soc_register_component(struct device *dev,
 void snd_soc_unregister_component(struct device *dev);
 struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
                                                   const char *driver_name);
-int snd_soc_cache_init(struct snd_soc_codec *codec);
-int snd_soc_cache_exit(struct snd_soc_codec *codec);
 
-int snd_soc_platform_read(struct snd_soc_platform *platform,
-                                       unsigned int reg);
-int snd_soc_platform_write(struct snd_soc_platform *platform,
-                                       unsigned int reg, unsigned int val);
 int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
 #ifdef CONFIG_SND_SOC_COMPRESS
 int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num);
+#else
+static inline int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
+{
+       return 0;
+}
 #endif
 
 void snd_soc_disconnect_sync(struct device *dev);
@@ -576,23 +551,7 @@ static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
 }
 #endif
 
-/* codec register bit access */
-int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg,
-                               unsigned int mask, unsigned int value);
-int snd_soc_update_bits_locked(struct snd_soc_codec *codec,
-                              unsigned int reg, unsigned int mask,
-                              unsigned int value);
-int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
-                               unsigned int mask, unsigned int value);
-
 #ifdef CONFIG_SND_SOC_AC97_BUS
-#define snd_soc_alloc_ac97_codec(codec) \
-       snd_soc_alloc_ac97_component(&codec->component)
-#define snd_soc_new_ac97_codec(codec, id, id_mask) \
-       snd_soc_new_ac97_component(&codec->component, id, id_mask)
-#define snd_soc_free_ac97_codec(ac97) \
-       snd_soc_free_ac97_component(ac97)
-
 struct snd_ac97 *snd_soc_alloc_ac97_component(struct snd_soc_component *component);
 struct snd_ac97 *snd_soc_new_ac97_component(struct snd_soc_component *component,
        unsigned int id, unsigned int id_mask);
@@ -626,10 +585,6 @@ struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
                                               const char *name);
 int snd_soc_add_component_controls(struct snd_soc_component *component,
        const struct snd_kcontrol_new *controls, unsigned int num_controls);
-int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
-       const struct snd_kcontrol_new *controls, unsigned int num_controls);
-int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
-       const struct snd_kcontrol_new *controls, unsigned int num_controls);
 int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
        const struct snd_kcontrol_new *controls, int num_controls);
 int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
@@ -862,8 +817,6 @@ struct snd_soc_component {
 
        unsigned int active;
 
-       unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
-       unsigned int registered_as_component:1;
        unsigned int suspended:1; /* is in suspend PM state */
 
        struct list_head list;
@@ -875,9 +828,6 @@ struct snd_soc_component {
        struct list_head dai_list;
        int num_dai;
 
-       int (*read)(struct snd_soc_component *, unsigned int, unsigned int *);
-       int (*write)(struct snd_soc_component *, unsigned int, unsigned int);
-
        struct regmap *regmap;
        int val_bytes;
 
@@ -886,10 +836,6 @@ struct snd_soc_component {
        /* attached dynamic objects */
        struct list_head dobj_list;
 
-#ifdef CONFIG_DEBUG_FS
-       struct dentry *debugfs_root;
-#endif
-
        /*
        * DO NOT use any of the fields below in drivers, they are temporary and
        * are going to be removed again soon. If you use them in driver code the
@@ -899,29 +845,11 @@ struct snd_soc_component {
        /* Don't use these, use snd_soc_component_get_dapm() */
        struct snd_soc_dapm_context dapm;
 
-       struct snd_soc_codec *codec;
-
-       int (*probe)(struct snd_soc_component *);
-       void (*remove)(struct snd_soc_component *);
-       int (*suspend)(struct snd_soc_component *);
-       int (*resume)(struct snd_soc_component *);
-       int (*pcm_new)(struct snd_soc_component *, struct snd_soc_pcm_runtime *);
-       void (*pcm_free)(struct snd_soc_component *, struct snd_pcm *);
-
-       int (*set_sysclk)(struct snd_soc_component *component,
-                         int clk_id, int source, unsigned int freq, int dir);
-       int (*set_pll)(struct snd_soc_component *component, int pll_id,
-                      int source, unsigned int freq_in, unsigned int freq_out);
-       int (*set_jack)(struct snd_soc_component *component,
-                       struct snd_soc_jack *jack,  void *data);
-       int (*set_bias_level)(struct snd_soc_component *component,
-                             enum snd_soc_bias_level level);
-
        /* machine specific init */
        int (*init)(struct snd_soc_component *component);
 
 #ifdef CONFIG_DEBUG_FS
-       void (*init_debugfs)(struct snd_soc_component *component);
+       struct dentry *debugfs_root;
        const char *debugfs_prefix;
 #endif
 };
@@ -938,97 +866,12 @@ snd_soc_rtdcom_lookup(struct snd_soc_pcm_runtime *rtd,
 #define for_each_rtdcom_safe(rtd, rtdcom1, rtdcom2) \
        list_for_each_entry_safe(rtdcom1, rtdcom2, &(rtd)->component_list, list)
 
-/* SoC Audio Codec device */
-struct snd_soc_codec {
-       struct device *dev;
-       const struct snd_soc_codec_driver *driver;
-
-       struct list_head list;
-
-       /* runtime */
-       unsigned int cache_init:1; /* codec cache has been initialized */
-
-       /* codec IO */
-       void *control_data; /* codec control (i2c/3wire) data */
-       hw_write_t hw_write;
-       void *reg_cache;
-
-       /* component */
-       struct snd_soc_component component;
-};
-
-/* codec driver */
-struct snd_soc_codec_driver {
-
-       /* driver ops */
-       int (*probe)(struct snd_soc_codec *);
-       int (*remove)(struct snd_soc_codec *);
-       int (*suspend)(struct snd_soc_codec *);
-       int (*resume)(struct snd_soc_codec *);
-       struct snd_soc_component_driver component_driver;
-
-       /* codec wide operations */
-       int (*set_sysclk)(struct snd_soc_codec *codec,
-                         int clk_id, int source, unsigned int freq, int dir);
-       int (*set_pll)(struct snd_soc_codec *codec, int pll_id, int source,
-               unsigned int freq_in, unsigned int freq_out);
-       int (*set_jack)(struct snd_soc_codec *codec,
-                       struct snd_soc_jack *jack,  void *data);
-
-       /* codec IO */
-       struct regmap *(*get_regmap)(struct device *);
-       unsigned int (*read)(struct snd_soc_codec *, unsigned int);
-       int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
-       unsigned int reg_cache_size;
-       short reg_cache_step;
-       short reg_word_size;
-       const void *reg_cache_default;
-
-       /* codec bias level */
-       int (*set_bias_level)(struct snd_soc_codec *,
-                             enum snd_soc_bias_level level);
-       bool idle_bias_off;
-       bool suspend_bias_off;
-
-       void (*seq_notifier)(struct snd_soc_dapm_context *,
-                            enum snd_soc_dapm_type, int);
-
-       bool ignore_pmdown_time;  /* Doesn't benefit from pmdown delay */
-};
-
-/* SoC platform interface */
-struct snd_soc_platform_driver {
-
-       int (*probe)(struct snd_soc_platform *);
-       int (*remove)(struct snd_soc_platform *);
-       struct snd_soc_component_driver component_driver;
-
-       /* pcm creation and destruction */
-       int (*pcm_new)(struct snd_soc_pcm_runtime *);
-       void (*pcm_free)(struct snd_pcm *);
-
-       /* platform stream pcm ops */
-       const struct snd_pcm_ops *ops;
-
-       /* platform stream compress ops */
-       const struct snd_compr_ops *compr_ops;
-};
-
 struct snd_soc_dai_link_component {
        const char *name;
        struct device_node *of_node;
        const char *dai_name;
 };
 
-struct snd_soc_platform {
-       struct device *dev;
-       const struct snd_soc_platform_driver *driver;
-
-       struct list_head list;
-
-       struct snd_soc_component component;
-};
-
 struct snd_soc_dai_link {
        /* config - must be set by machine driver */
        const char *name;                       /* Codec name */
@@ -1276,8 +1119,6 @@ struct snd_soc_pcm_runtime {
        /* runtime devices */
        struct snd_pcm *pcm;
        struct snd_compr *compr;
-       struct snd_soc_codec *codec;
-       struct snd_soc_platform *platform; /* will be removed */
        struct snd_soc_dai *codec_dai;
        struct snd_soc_dai *cpu_dai;
 
@@ -1345,32 +1186,6 @@ struct soc_enum {
        struct snd_soc_dobj dobj;
 };
 
-/**
- * snd_soc_component_to_codec() - Casts a component to the CODEC it is embedded in
- * @component: The component to cast to a CODEC
- *
- * This function must only be used on components that are known to be CODECs.
- * Otherwise the behavior is undefined.
- */
-static inline struct snd_soc_codec *snd_soc_component_to_codec(
-       struct snd_soc_component *component)
-{
-       return container_of(component, struct snd_soc_codec, component);
-}
-
-/**
- * snd_soc_component_to_platform() - Casts a component to the platform it is embedded in
- * @component: The component to cast to a platform
- *
- * This function must only be used on components that are known to be platforms.
- * Otherwise the behavior is undefined.
- */
-static inline struct snd_soc_platform *snd_soc_component_to_platform(
-       struct snd_soc_component *component)
-{
-       return container_of(component, struct snd_soc_platform, component);
-}
-
 /**
  * snd_soc_dapm_to_component() - Casts a DAPM context to the component it is
  *  embedded in
@@ -1386,33 +1201,6 @@ static inline struct snd_soc_component *snd_soc_dapm_to_component(
        return container_of(dapm, struct snd_soc_component, dapm);
 }
 
-/**
- * snd_soc_dapm_to_codec() - Casts a DAPM context to the CODEC it is embedded in
- * @dapm: The DAPM context to cast to the CODEC
- *
- * This function must only be used on DAPM contexts that are known to be part of
- * a CODEC (e.g. in a CODEC driver). Otherwise the behavior is undefined.
- */
-static inline struct snd_soc_codec *snd_soc_dapm_to_codec(
-       struct snd_soc_dapm_context *dapm)
-{
-       return snd_soc_component_to_codec(snd_soc_dapm_to_component(dapm));
-}
-
-/**
- * snd_soc_dapm_to_platform() - Casts a DAPM context to the platform it is
- *  embedded in
- * @dapm: The DAPM context to cast to the platform.
- *
- * This function must only be used on DAPM contexts that are known to be part of
- * a platform (e.g. in a platform driver). Otherwise the behavior is undefined.
- */
-static inline struct snd_soc_platform *snd_soc_dapm_to_platform(
-       struct snd_soc_dapm_context *dapm)
-{
-       return snd_soc_component_to_platform(snd_soc_dapm_to_component(dapm));
-}
-
 /**
  * snd_soc_component_get_dapm() - Returns the DAPM context associated with a
  *  component
@@ -1424,31 +1212,6 @@ static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm(
        return &component->dapm;
 }
 
-/**
- * snd_soc_codec_get_dapm() - Returns the DAPM context for the CODEC
- * @codec: The CODEC for which to get the DAPM context
- *
- * Note: Use this function instead of directly accessing the CODEC's dapm field
- */
-static inline struct snd_soc_dapm_context *snd_soc_codec_get_dapm(
-       struct snd_soc_codec *codec)
-{
-       return snd_soc_component_get_dapm(&codec->component);
-}
-
-/**
- * snd_soc_dapm_init_bias_level() - Initialize CODEC DAPM bias level
- * @codec: The CODEC for which to initialize the DAPM bias level
- * @level: The DAPM level to initialize to
- *
- * Initializes the CODEC DAPM bias level. See snd_soc_dapm_init_bias_level().
- */
-static inline void snd_soc_codec_init_bias_level(struct snd_soc_codec *codec,
-       enum snd_soc_bias_level level)
-{
-       snd_soc_dapm_init_bias_level(snd_soc_codec_get_dapm(codec), level);
-}
-
 /**
  * snd_soc_component_init_bias_level() - Initialize COMPONENT DAPM bias level
  * @component: The COMPONENT for which to initialize the DAPM bias level
@@ -1464,18 +1227,6 @@ snd_soc_component_init_bias_level(struct snd_soc_component *component,
                snd_soc_component_get_dapm(component), level);
 }
 
-/**
- * snd_soc_dapm_get_bias_level() - Get current CODEC DAPM bias level
- * @codec: The CODEC for which to get the DAPM bias level
- *
- * Returns: The current DAPM bias level of the CODEC.
- */
-static inline enum snd_soc_bias_level snd_soc_codec_get_bias_level(
-       struct snd_soc_codec *codec)
-{
-       return snd_soc_dapm_get_bias_level(snd_soc_codec_get_dapm(codec));
-}
-
 /**
  * snd_soc_component_get_bias_level() - Get current COMPONENT DAPM bias level
  * @component: The COMPONENT for which to get the DAPM bias level
@@ -1489,21 +1240,6 @@ snd_soc_component_get_bias_level(struct snd_soc_component *component)
                snd_soc_component_get_dapm(component));
 }
 
-/**
- * snd_soc_codec_force_bias_level() - Set the CODEC DAPM bias level
- * @codec: The CODEC for which to set the level
- * @level: The level to set to
- *
- * Forces the CODEC bias level to a specific state. See
- * snd_soc_dapm_force_bias_level().
- */
-static inline int snd_soc_codec_force_bias_level(struct snd_soc_codec *codec,
-       enum snd_soc_bias_level level)
-{
-       return snd_soc_dapm_force_bias_level(snd_soc_codec_get_dapm(codec),
-               level);
-}
-
 /**
  * snd_soc_component_force_bias_level() - Set the COMPONENT DAPM bias level
  * @component: The COMPONENT for which to set the level
@@ -1521,19 +1257,6 @@ snd_soc_component_force_bias_level(struct snd_soc_component *component,
                level);
 }
 
-/**
- * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol
- * @kcontrol: The kcontrol
- *
- * This function must only be used on DAPM contexts that are known to be part of
- * a CODEC (e.g. in a CODEC driver). Otherwise the behavior is undefined.
- */
-static inline struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(
-       struct snd_kcontrol *kcontrol)
-{
-       return snd_soc_dapm_to_codec(snd_soc_dapm_kcontrol_dapm(kcontrol));
-}
-
 /**
  * snd_soc_dapm_kcontrol_component() - Returns the component associated to a kcontrol
  * @kcontrol: The kcontrol
@@ -1547,22 +1270,6 @@ static inline struct snd_soc_component *snd_soc_dapm_kcontrol_component(
        return snd_soc_dapm_to_component(snd_soc_dapm_kcontrol_dapm(kcontrol));
 }
 
-/* codec IO */
-unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg);
-int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int val);
-
-/**
- * snd_soc_cache_sync() - Sync the register cache with the hardware
- * @codec: CODEC to sync
- *
- * Note: This function will call regcache_sync()
- */
-static inline int snd_soc_cache_sync(struct snd_soc_codec *codec)
-{
-       return regcache_sync(codec->component.regmap);
-}
-
 /**
  * snd_soc_component_cache_sync() - Sync the register cache with the hardware
  * @component: COMPONENT to sync
@@ -1605,37 +1312,6 @@ void snd_soc_component_init_regmap(struct snd_soc_component *component,
        struct regmap *regmap);
 void snd_soc_component_exit_regmap(struct snd_soc_component *component);
 
-/**
- * snd_soc_codec_init_regmap() - Initialize regmap instance for the CODEC
- * @codec: The CODEC for which to initialize the regmap instance
- * @regmap: The regmap instance that should be used by the CODEC
- *
- * This function allows deferred assignment of the regmap instance that is
- * associated with the CODEC. Only use this if the regmap instance is not yet
- * ready when the CODEC is registered. The function must also be called before
- * the first IO attempt of the CODEC.
- */
-static inline void snd_soc_codec_init_regmap(struct snd_soc_codec *codec,
-       struct regmap *regmap)
-{
-       snd_soc_component_init_regmap(&codec->component, regmap);
-}
-
-/**
- * snd_soc_codec_exit_regmap() - De-initialize regmap instance for the CODEC
- * @codec: The CODEC for which to de-initialize the regmap instance
- *
- * Calls regmap_exit() on the regmap instance associated to the CODEC and
- * removes the regmap instance from the CODEC.
- *
- * This function should only be used if snd_soc_codec_init_regmap() was used to
- * initialize the regmap instance.
- */
-static inline void snd_soc_codec_exit_regmap(struct snd_soc_codec *codec)
-{
-       snd_soc_component_exit_regmap(&codec->component);
-}
-
 #endif
 
 /* device driver data */
@@ -1662,28 +1338,6 @@ static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c)
        return dev_get_drvdata(c->dev);
 }
 
-static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec,
-               void *data)
-{
-       snd_soc_component_set_drvdata(&codec->component, data);
-}
-
-static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec)
-{
-       return snd_soc_component_get_drvdata(&codec->component);
-}
-
-static inline void snd_soc_platform_set_drvdata(struct snd_soc_platform *platform,
-               void *data)
-{
-       snd_soc_component_set_drvdata(&platform->component, data);
-}
-
-static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platform)
-{
-       return snd_soc_component_get_drvdata(&platform->component);
-}
-
 static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
 {
        INIT_LIST_HEAD(&card->widgets);
@@ -1735,20 +1389,15 @@ static inline bool snd_soc_component_is_active(
        return component->active != 0;
 }
 
-static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec)
-{
-       return snd_soc_component_is_active(&codec->component);
-}
-
 /**
  * snd_soc_kcontrol_component() - Returns the component that registered the
  *  control
  * @kcontrol: The control for which to get the component
  *
  * Note: This function will work correctly if the control has been registered
- * for a component. Either with snd_soc_add_codec_controls() or
- * snd_soc_add_platform_controls() or via  table based setup for either a
- * CODEC, a platform or component driver. Otherwise the behavior is undefined.
+ * for a component. With snd_soc_add_codec_controls() or via table based
+ * setup for either a CODEC or component driver. Otherwise the behavior is
+ * undefined.
  */
 static inline struct snd_soc_component *snd_soc_kcontrol_component(
        struct snd_kcontrol *kcontrol)
@@ -1756,34 +1405,6 @@ static inline struct snd_soc_component *snd_soc_kcontrol_component(
        return snd_kcontrol_chip(kcontrol);
 }
 
-/**
- * snd_soc_kcontrol_codec() - Returns the CODEC that registered the control
- * @kcontrol: The control for which to get the CODEC
- *
- * Note: This function will only work correctly if the control has been
- * registered with snd_soc_add_codec_controls() or via table based setup of
- * snd_soc_codec_driver. Otherwise the behavior is undefined.
- */
-static inline struct snd_soc_codec *snd_soc_kcontrol_codec(
-       struct snd_kcontrol *kcontrol)
-{
-       return snd_soc_component_to_codec(snd_soc_kcontrol_component(kcontrol));
-}
-
-/**
- * snd_soc_kcontrol_platform() - Returns the platform that registered the control
- * @kcontrol: The control for which to get the platform
- *
- * Note: This function will only work correctly if the control has been
- * registered with snd_soc_add_platform_controls() or via table based setup of
- * a snd_soc_platform_driver. Otherwise the behavior is undefined.
- */
-static inline struct snd_soc_platform *snd_soc_kcontrol_platform(
-       struct snd_kcontrol *kcontrol)
-{
-       return snd_soc_component_to_platform(snd_soc_kcontrol_component(kcontrol));
-}
-
 int snd_soc_util_init(void);
 void snd_soc_util_exit(void);
 
index ccd1a3bdff46e28bdd363822141d55522ca55543..40c300fe704dadbe2974593e19cf9c29b062792b 100644 (file)
@@ -12,7 +12,6 @@
 #define DAPM_ARROW(dir) (((dir) == SND_SOC_DAPM_DIR_OUT) ? "->" : "<-")
 
 struct snd_soc_jack;
-struct snd_soc_codec;
 struct snd_soc_card;
 struct snd_soc_dapm_widget;
 struct snd_soc_dapm_path;
index 69c37ecbff7ee389cb31b7dc49be4021e9a6fd14..a74ca232f1fc1ff69bc6b7e9e6a3d17feae0108f 100644 (file)
 #define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS      (1 << 1)
 #define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS    (1 << 2)
 
+/* DAI clock gating */
+#define SND_SOC_TPLG_DAI_CLK_GATE_UNDEFINED    0
+#define SND_SOC_TPLG_DAI_CLK_GATE_GATED        1
+#define SND_SOC_TPLG_DAI_CLK_GATE_CONT         2
+
+/* DAI mclk_direction */
+#define SND_SOC_TPLG_MCLK_CO            0 /* for codec, mclk is output */
+#define SND_SOC_TPLG_MCLK_CI            1 /* for codec, mclk is input */
+
 /* DAI physical PCM data formats.
  * Add new formats to the end of the list.
  */
 #define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS    (1 << 2)
 #define SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP            (1 << 3)
 
+/* DAI topology BCLK parameter
+ * For the backwards capability, by default codec is bclk master
+ */
+#define SND_SOC_TPLG_BCLK_CM         0 /* codec is bclk master */
+#define SND_SOC_TPLG_BCLK_CS         1 /* codec is bclk slave */
+
+/* DAI topology FSYNC parameter
+ * For the backwards capability, by default codec is fsync master
+ */
+#define SND_SOC_TPLG_FSYNC_CM         0 /* codec is fsync master */
+#define SND_SOC_TPLG_FSYNC_CS         1 /* codec is fsync slave */
+
 /*
  * Block Header.
  * This header precedes all object and object arrays below.
@@ -312,12 +333,12 @@ struct snd_soc_tplg_hw_config {
        __le32 size;            /* in bytes of this structure */
        __le32 id;              /* unique ID - - used to match */
        __le32 fmt;             /* SND_SOC_DAI_FORMAT_ format value */
-       __u8 clock_gated;       /* 1 if clock can be gated to save power */
+       __u8 clock_gated;       /* SND_SOC_TPLG_DAI_CLK_GATE_ value */
        __u8 invert_bclk;       /* 1 for inverted BCLK, 0 for normal */
        __u8 invert_fsync;      /* 1 for inverted frame clock, 0 for normal */
-       __u8 bclk_master;       /* 1 for master of BCLK, 0 for slave */
-       __u8 fsync_master;      /* 1 for master of FSYNC, 0 for slave */
-       __u8 mclk_direction;    /* 0 for input, 1 for output */
+       __u8 bclk_master;       /* SND_SOC_TPLG_BCLK_ value */
+       __u8 fsync_master;      /* SND_SOC_TPLG_FSYNC_ value */
+       __u8 mclk_direction;    /* SND_SOC_TPLG_MCLK_ value */
        __le16 reserved;        /* for 32bit alignment */
        __le32 mclk_rate;       /* MCLK or SYSCLK freqency in Hz */
        __le32 bclk_rate;       /* BCLK freqency in Hz */
@@ -552,4 +573,61 @@ struct snd_soc_tplg_dai {
        __le32 flags;           /* SND_SOC_TPLG_DAI_FLGBIT_* */
        struct snd_soc_tplg_private priv;
 } __attribute__((packed));
+
+/*
+ * Old version of ABI structs, supported for backward compatibility.
+ */
+
+/* Manifest v4 */
+struct snd_soc_tplg_manifest_v4 {
+       __le32 size;            /* in bytes of this structure */
+       __le32 control_elems;   /* number of control elements */
+       __le32 widget_elems;    /* number of widget elements */
+       __le32 graph_elems;     /* number of graph elements */
+       __le32 pcm_elems;       /* number of PCM elements */
+       __le32 dai_link_elems;  /* number of DAI link elements */
+       struct snd_soc_tplg_private priv;
+} __packed;
+
+/* Stream Capabilities v4 */
+struct snd_soc_tplg_stream_caps_v4 {
+       __le32 size;            /* in bytes of this structure */
+       char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+       __le64 formats; /* supported formats SNDRV_PCM_FMTBIT_* */
+       __le32 rates;           /* supported rates SNDRV_PCM_RATE_* */
+       __le32 rate_min;        /* min rate */
+       __le32 rate_max;        /* max rate */
+       __le32 channels_min;    /* min channels */
+       __le32 channels_max;    /* max channels */
+       __le32 periods_min;     /* min number of periods */
+       __le32 periods_max;     /* max number of periods */
+       __le32 period_size_min; /* min period size bytes */
+       __le32 period_size_max; /* max period size bytes */
+       __le32 buffer_size_min; /* min buffer size bytes */
+       __le32 buffer_size_max; /* max buffer size bytes */
+} __packed;
+
+/* PCM v4 */
+struct snd_soc_tplg_pcm_v4 {
+       __le32 size;            /* in bytes of this structure */
+       char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+       char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+       __le32 pcm_id;          /* unique ID - used to match with DAI link */
+       __le32 dai_id;          /* unique ID - used to match */
+       __le32 playback;        /* supports playback mode */
+       __le32 capture;         /* supports capture mode */
+       __le32 compress;        /* 1 = compressed; 0 = PCM */
+       struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* for DAI link */
+       __le32 num_streams;     /* number of streams */
+       struct snd_soc_tplg_stream_caps_v4 caps[2]; /* playback and capture for DAI */
+} __packed;
+
+/* Physical link config v4 */
+struct snd_soc_tplg_link_config_v4 {
+       __le32 size;            /* in bytes of this structure */
+       __le32 id;              /* unique ID - used to match */
+       struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */
+       __le32 num_streams;     /* number of streams */
+} __packed;
+
 #endif
diff --git a/include/uapi/sound/skl-tplg-interface.h b/include/uapi/sound/skl-tplg-interface.h
new file mode 100644 (file)
index 0000000..f58cafa
--- /dev/null
@@ -0,0 +1,237 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * skl-tplg-interface.h - Intel DSP FW private data interface
+ *
+ * Copyright (C) 2015 Intel Corp
+ * Author: Jeeja KP <jeeja.kp@intel.com>
+ *         Nilofer, Samreen <samreen.nilofer@intel.com>
+ */
+
+#ifndef __HDA_TPLG_INTERFACE_H__
+#define __HDA_TPLG_INTERFACE_H__
+
+/*
+ * Default types range from 0~12. type can range from 0 to 0xff
+ * SST types start at higher to avoid any overlapping in future
+ */
+#define SKL_CONTROL_TYPE_BYTE_TLV      0x100
+#define SKL_CONTROL_TYPE_MIC_SELECT    0x102
+
+#define HDA_SST_CFG_MAX        900 /* size of copier cfg*/
+#define MAX_IN_QUEUE 8
+#define MAX_OUT_QUEUE 8
+
+#define SKL_UUID_STR_SZ 40
+/* Event types goes here */
+/* Reserve event type 0 for no event handlers */
+enum skl_event_types {
+       SKL_EVENT_NONE = 0,
+       SKL_MIXER_EVENT,
+       SKL_MUX_EVENT,
+       SKL_VMIXER_EVENT,
+       SKL_PGA_EVENT
+};
+
+/**
+ * enum skl_ch_cfg - channel configuration
+ *
+ * @SKL_CH_CFG_MONO:   One channel only
+ * @SKL_CH_CFG_STEREO: L & R
+ * @SKL_CH_CFG_2_1:    L, R & LFE
+ * @SKL_CH_CFG_3_0:    L, C & R
+ * @SKL_CH_CFG_3_1:    L, C, R & LFE
+ * @SKL_CH_CFG_QUATRO: L, R, Ls & Rs
+ * @SKL_CH_CFG_4_0:    L, C, R & Cs
+ * @SKL_CH_CFG_5_0:    L, C, R, Ls & Rs
+ * @SKL_CH_CFG_5_1:    L, C, R, Ls, Rs & LFE
+ * @SKL_CH_CFG_DUAL_MONO: One channel replicated in two
+ * @SKL_CH_CFG_I2S_DUAL_STEREO_0: Stereo(L,R) in 4 slots, 1st stream:[ L, R, -, - ]
+ * @SKL_CH_CFG_I2S_DUAL_STEREO_1: Stereo(L,R) in 4 slots, 2nd stream:[ -, -, L, R ]
+ * @SKL_CH_CFG_INVALID:        Invalid
+ */
+enum skl_ch_cfg {
+       SKL_CH_CFG_MONO = 0,
+       SKL_CH_CFG_STEREO = 1,
+       SKL_CH_CFG_2_1 = 2,
+       SKL_CH_CFG_3_0 = 3,
+       SKL_CH_CFG_3_1 = 4,
+       SKL_CH_CFG_QUATRO = 5,
+       SKL_CH_CFG_4_0 = 6,
+       SKL_CH_CFG_5_0 = 7,
+       SKL_CH_CFG_5_1 = 8,
+       SKL_CH_CFG_DUAL_MONO = 9,
+       SKL_CH_CFG_I2S_DUAL_STEREO_0 = 10,
+       SKL_CH_CFG_I2S_DUAL_STEREO_1 = 11,
+       SKL_CH_CFG_4_CHANNEL = 12,
+       SKL_CH_CFG_INVALID
+};
+
+enum skl_module_type {
+       SKL_MODULE_TYPE_MIXER = 0,
+       SKL_MODULE_TYPE_COPIER,
+       SKL_MODULE_TYPE_UPDWMIX,
+       SKL_MODULE_TYPE_SRCINT,
+       SKL_MODULE_TYPE_ALGO,
+       SKL_MODULE_TYPE_BASE_OUTFMT,
+       SKL_MODULE_TYPE_KPB,
+       SKL_MODULE_TYPE_MIC_SELECT,
+};
+
+enum skl_core_affinity {
+       SKL_AFFINITY_CORE_0 = 0,
+       SKL_AFFINITY_CORE_1,
+       SKL_AFFINITY_CORE_MAX
+};
+
+enum skl_pipe_conn_type {
+       SKL_PIPE_CONN_TYPE_NONE = 0,
+       SKL_PIPE_CONN_TYPE_FE,
+       SKL_PIPE_CONN_TYPE_BE
+};
+
+enum skl_hw_conn_type {
+       SKL_CONN_NONE = 0,
+       SKL_CONN_SOURCE = 1,
+       SKL_CONN_SINK = 2
+};
+
+enum skl_dev_type {
+       SKL_DEVICE_BT = 0x0,
+       SKL_DEVICE_DMIC = 0x1,
+       SKL_DEVICE_I2S = 0x2,
+       SKL_DEVICE_SLIMBUS = 0x3,
+       SKL_DEVICE_HDALINK = 0x4,
+       SKL_DEVICE_HDAHOST = 0x5,
+       SKL_DEVICE_NONE
+};
+
+/**
+ * enum skl_interleaving - interleaving style
+ *
+ * @SKL_INTERLEAVING_PER_CHANNEL: [s1_ch1...s1_chN,...,sM_ch1...sM_chN]
+ * @SKL_INTERLEAVING_PER_SAMPLE: [s1_ch1...sM_ch1,...,s1_chN...sM_chN]
+ */
+enum skl_interleaving {
+       SKL_INTERLEAVING_PER_CHANNEL = 0,
+       SKL_INTERLEAVING_PER_SAMPLE = 1,
+};
+
+enum skl_sample_type {
+       SKL_SAMPLE_TYPE_INT_MSB = 0,
+       SKL_SAMPLE_TYPE_INT_LSB = 1,
+       SKL_SAMPLE_TYPE_INT_SIGNED = 2,
+       SKL_SAMPLE_TYPE_INT_UNSIGNED = 3,
+       SKL_SAMPLE_TYPE_FLOAT = 4
+};
+
+enum module_pin_type {
+       /* All pins of the module takes same PCM inputs or outputs
+       * e.g. mixout
+       */
+       SKL_PIN_TYPE_HOMOGENEOUS,
+       /* All pins of the module takes different PCM inputs or outputs
+       * e.g mux
+       */
+       SKL_PIN_TYPE_HETEROGENEOUS,
+};
+
+enum skl_module_param_type {
+       SKL_PARAM_DEFAULT = 0,
+       SKL_PARAM_INIT,
+       SKL_PARAM_SET,
+       SKL_PARAM_BIND
+};
+
+struct skl_dfw_algo_data {
+       u32 set_params:2;
+       u32 rsvd:30;
+       u32 param_id;
+       u32 max;
+       char params[0];
+} __packed;
+
+enum skl_tkn_dir {
+       SKL_DIR_IN,
+       SKL_DIR_OUT
+};
+
+enum skl_tuple_type {
+       SKL_TYPE_TUPLE,
+       SKL_TYPE_DATA
+};
+
+/* v4 configuration data */
+
+struct skl_dfw_v4_module_pin {
+       u16 module_id;
+       u16 instance_id;
+} __packed;
+
+struct skl_dfw_v4_module_fmt {
+       u32 channels;
+       u32 freq;
+       u32 bit_depth;
+       u32 valid_bit_depth;
+       u32 ch_cfg;
+       u32 interleaving_style;
+       u32 sample_type;
+       u32 ch_map;
+} __packed;
+
+struct skl_dfw_v4_module_caps {
+       u32 set_params:2;
+       u32 rsvd:30;
+       u32 param_id;
+       u32 caps_size;
+       u32 caps[HDA_SST_CFG_MAX];
+} __packed;
+
+struct skl_dfw_v4_pipe {
+       u8 pipe_id;
+       u8 pipe_priority;
+       u16 conn_type:4;
+       u16 rsvd:4;
+       u16 memory_pages:8;
+} __packed;
+
+struct skl_dfw_v4_module {
+       char uuid[SKL_UUID_STR_SZ];
+
+       u16 module_id;
+       u16 instance_id;
+       u32 max_mcps;
+       u32 mem_pages;
+       u32 obs;
+       u32 ibs;
+       u32 vbus_id;
+
+       u32 max_in_queue:8;
+       u32 max_out_queue:8;
+       u32 time_slot:8;
+       u32 core_id:4;
+       u32 rsvd1:4;
+
+       u32 module_type:8;
+       u32 conn_type:4;
+       u32 dev_type:4;
+       u32 hw_conn_type:4;
+       u32 rsvd2:12;
+
+       u32 params_fixup:8;
+       u32 converter:8;
+       u32 input_pin_type:1;
+       u32 output_pin_type:1;
+       u32 is_dynamic_in_pin:1;
+       u32 is_dynamic_out_pin:1;
+       u32 is_loadable:1;
+       u32 rsvd3:11;
+
+       struct skl_dfw_v4_pipe pipe;
+       struct skl_dfw_v4_module_fmt in_fmt[MAX_IN_QUEUE];
+       struct skl_dfw_v4_module_fmt out_fmt[MAX_OUT_QUEUE];
+       struct skl_dfw_v4_module_pin in_pin[MAX_IN_QUEUE];
+       struct skl_dfw_v4_module_pin out_pin[MAX_OUT_QUEUE];
+       struct skl_dfw_v4_module_caps caps;
+} __packed;
+
+#endif
index 8d92492183d28ca4cafd2021a0edf885853112ce..06389a5385d71ac05806a9d1db7eab1678b2dc2a 100644 (file)
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
-snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
+snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o
 snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o
 snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o
 
index f41560ecbcd18024f2f1354cd741115fcbd69739..ccddc6650b9c79a112791e3d5ecd2e11d77e8494 100644 (file)
 #include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/i2c.h>
+#include <linux/input.h>
 #include <linux/acpi.h>
 
+#include "acp.h"
 #include "../codecs/da7219.h"
 #include "../codecs/da7219-aad.h"
 
-#define CZ_PLAT_CLK 24000000
-#define MCLK_RATE 24576000
+#define CZ_PLAT_CLK 25000000
 #define DUAL_CHANNEL           2
 
 static struct snd_soc_jack cz_jack;
 static struct clk *da7219_dai_clk;
+extern int bt_uart_enable;
 
 static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
 {
@@ -62,7 +64,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
        }
 
        ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL,
-                                 CZ_PLAT_CLK, MCLK_RATE);
+                                 CZ_PLAT_CLK, DA7219_PLL_FREQ_OUT_98304);
        if (ret < 0) {
                dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
                return ret;
@@ -80,13 +82,17 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
                return ret;
        }
 
+       snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+       snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
+       snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
+       snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
+
        da7219_aad_jack_det(component, &cz_jack);
 
        return 0;
 }
 
-static int cz_da7219_hw_params(struct snd_pcm_substream *substream,
-                            struct snd_pcm_hw_params *params)
+static int da7219_clk_enable(struct snd_pcm_substream *substream)
 {
        int ret = 0;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -100,11 +106,9 @@ static int cz_da7219_hw_params(struct snd_pcm_substream *substream,
        return ret;
 }
 
-static int cz_da7219_hw_free(struct snd_pcm_substream *substream)
+static void da7219_clk_disable(void)
 {
        clk_disable_unprepare(da7219_dai_clk);
-
-       return 0;
 }
 
 static const unsigned int channels[] = {
@@ -127,9 +131,12 @@ static const struct snd_pcm_hw_constraint_list constraints_channels = {
        .mask = 0,
 };
 
-static int cz_fe_startup(struct snd_pcm_substream *substream)
+static int cz_da7219_startup(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_card *card = rtd->card;
+       struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
 
        /*
         * On this platform for PCM device we support stereo
@@ -141,23 +148,58 @@ static int cz_fe_startup(struct snd_pcm_substream *substream)
        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                   &constraints_rates);
 
-       return 0;
+       machine->i2s_instance = I2S_BT_INSTANCE;
+       return da7219_clk_enable(substream);
+}
+
+static void cz_da7219_shutdown(struct snd_pcm_substream *substream)
+{
+       da7219_clk_disable();
+}
+
+static int cz_max_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_card *card = rtd->card;
+       struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
+
+       machine->i2s_instance = I2S_SP_INSTANCE;
+       return da7219_clk_enable(substream);
+}
+
+static void cz_max_shutdown(struct snd_pcm_substream *substream)
+{
+       da7219_clk_disable();
+}
+
+static int cz_dmic_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_card *card = rtd->card;
+       struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
+
+       machine->i2s_instance = I2S_SP_INSTANCE;
+       return da7219_clk_enable(substream);
+}
+
+static void cz_dmic_shutdown(struct snd_pcm_substream *substream)
+{
+       da7219_clk_disable();
 }
 
-static struct snd_soc_ops cz_da7219_cap_ops = {
-       .hw_params = cz_da7219_hw_params,
-       .hw_free = cz_da7219_hw_free,
-       .startup = cz_fe_startup,
+static const struct snd_soc_ops cz_da7219_cap_ops = {
+       .startup = cz_da7219_startup,
+       .shutdown = cz_da7219_shutdown,
 };
 
-static struct snd_soc_ops cz_max_play_ops = {
-       .hw_params = cz_da7219_hw_params,
-       .hw_free = cz_da7219_hw_free,
+static const struct snd_soc_ops cz_max_play_ops = {
+       .startup = cz_max_startup,
+       .shutdown = cz_max_shutdown,
 };
 
-static struct snd_soc_ops cz_dmic_cap_ops = {
-       .hw_params = cz_da7219_hw_params,
-       .hw_free = cz_da7219_hw_free,
+static const struct snd_soc_ops cz_dmic_cap_ops = {
+       .startup = cz_dmic_startup,
+       .shutdown = cz_dmic_shutdown,
 };
 
 static struct snd_soc_dai_link cz_dai_7219_98357[] = {
@@ -240,10 +282,16 @@ static int cz_probe(struct platform_device *pdev)
 {
        int ret;
        struct snd_soc_card *card;
+       struct acp_platform_info *machine;
 
+       machine = devm_kzalloc(&pdev->dev, sizeof(struct acp_platform_info),
+                              GFP_KERNEL);
+       if (!machine)
+               return -ENOMEM;
        card = &cz_card;
        cz_card.dev = &pdev->dev;
        platform_set_drvdata(pdev, card);
+       snd_soc_card_set_drvdata(card, machine);
        ret = devm_snd_soc_register_card(&pdev->dev, &cz_card);
        if (ret) {
                dev_err(&pdev->dev,
@@ -251,6 +299,8 @@ static int cz_probe(struct platform_device *pdev)
                                cz_card.name, ret);
                return ret;
        }
+       bt_uart_enable = !device_property_read_bool(&pdev->dev,
+                                                   "bt-pad-enable");
        return 0;
 }
 
index 540088d317f2e0fe55d8a7ae4f6f4c1a12a04432..77203841c535017bd0fea9c0cd20c5722e5d0ead 100644 (file)
 #define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS)
 #define MIN_BUFFER MAX_BUFFER
 
-#define ST_PLAYBACK_MAX_PERIOD_SIZE 8192
+#define ST_PLAYBACK_MAX_PERIOD_SIZE 4096
 #define ST_CAPTURE_MAX_PERIOD_SIZE  ST_PLAYBACK_MAX_PERIOD_SIZE
 #define ST_MAX_BUFFER (ST_PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS)
 #define ST_MIN_BUFFER ST_MAX_BUFFER
 
 #define DRV_NAME "acp_audio_dma"
+bool bt_uart_enable = true;
+EXPORT_SYMBOL(bt_uart_enable);
 
 static const struct snd_pcm_hardware acp_pcm_hardware_playback = {
        .info = SNDRV_PCM_INFO_INTERLEAVED |
@@ -130,7 +132,8 @@ static void acp_reg_write(u32 val, void __iomem *acp_mmio, u32 reg)
        writel(val, acp_mmio + (reg * 4));
 }
 
-/* Configure a given dma channel parameters - enable/disable,
+/*
+ * Configure a given dma channel parameters - enable/disable,
  * number of descriptors, priority
  */
 static void config_acp_dma_channel(void __iomem *acp_mmio, u8 ch_num,
@@ -149,11 +152,12 @@ static void config_acp_dma_channel(void __iomem *acp_mmio, u8 ch_num,
                        & dscr_strt_idx),
                        acp_mmio, mmACP_DMA_DSCR_STRT_IDX_0 + ch_num);
 
-       /* program a DMA channel with the number of descriptors to be
+       /*
+        * program a DMA channel with the number of descriptors to be
         * processed in the transfer
-       */
+        */
        acp_reg_write(ACP_DMA_DSCR_CNT_0__DMAChDscrCnt_MASK & num_dscrs,
-               acp_mmio, mmACP_DMA_DSCR_CNT_0 + ch_num);
+                     acp_mmio, mmACP_DMA_DSCR_CNT_0 + ch_num);
 
        /* set DMA channel priority */
        acp_reg_write(priority_level, acp_mmio, mmACP_DMA_PRIO_0 + ch_num);
@@ -180,13 +184,15 @@ static void config_dma_descriptor_in_sram(void __iomem *acp_mmio,
        acp_reg_write(descr_info->xfer_val, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
 }
 
-/* Initialize the DMA descriptor information for transfer between
+/*
+ * Initialize the DMA descriptor information for transfer between
  * system memory <-> ACP SRAM
  */
 static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio,
-                                       u32 size, int direction, u32 pte_offset,
-                                       u16 ch, u32 sram_bank,
-                                       u16 dma_dscr_idx, u32 asic_type)
+                                          u32 size, int direction,
+                                          u32 pte_offset, u16 ch,
+                                          u32 sram_bank, u16 dma_dscr_idx,
+                                          u32 asic_type)
 {
        u16 i;
        acp_dma_dscr_transfer_t dmadscr[NUM_DSCRS_PER_CHANNEL];
@@ -195,58 +201,58 @@ static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio,
                dmadscr[i].xfer_val = 0;
                if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
                        dma_dscr_idx = dma_dscr_idx + i;
-                       dmadscr[i].dest = sram_bank + (i * (size/2));
+                       dmadscr[i].dest = sram_bank + (i * (size / 2));
                        dmadscr[i].src = ACP_INTERNAL_APERTURE_WINDOW_0_ADDRESS
-                               + (pte_offset * SZ_4K) + (i * (size/2));
+                               + (pte_offset * SZ_4K) + (i * (size / 2));
                        switch (asic_type) {
                        case CHIP_STONEY:
                                dmadscr[i].xfer_val |=
-                               (ACP_DMA_ATTRIBUTES_DAGB_GARLIC_TO_SHAREDMEM  << 16) |
+                               (ACP_DMA_ATTR_DAGB_GARLIC_TO_SHAREDMEM  << 16) |
                                (size / 2);
                                break;
                        default:
                                dmadscr[i].xfer_val |=
-                               (ACP_DMA_ATTRIBUTES_DAGB_ONION_TO_SHAREDMEM  << 16) |
+                               (ACP_DMA_ATTR_DAGB_ONION_TO_SHAREDMEM  << 16) |
                                (size / 2);
                        }
                } else {
                        dma_dscr_idx = dma_dscr_idx + i;
-                       dmadscr[i].src = sram_bank + (i * (size/2));
+                       dmadscr[i].src = sram_bank + (i * (size / 2));
                        dmadscr[i].dest =
                        ACP_INTERNAL_APERTURE_WINDOW_0_ADDRESS +
-                       (pte_offset * SZ_4K) + (i * (size/2));
+                       (pte_offset * SZ_4K) + (i * (size / 2));
                        switch (asic_type) {
                        case CHIP_STONEY:
                                dmadscr[i].xfer_val |=
                                BIT(22) |
-                               (ACP_DMA_ATTRIBUTES_SHARED_MEM_TO_DAGB_GARLIC << 16) |
+                               (ACP_DMA_ATTR_SHARED_MEM_TO_DAGB_GARLIC << 16) |
                                (size / 2);
                                break;
                        default:
                                dmadscr[i].xfer_val |=
                                BIT(22) |
-                               (ACP_DMA_ATTRIBUTES_SHAREDMEM_TO_DAGB_ONION << 16) |
+                               (ACP_DMA_ATTR_SHAREDMEM_TO_DAGB_ONION << 16) |
                                (size / 2);
                        }
                }
                config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
-                                               &dmadscr[i]);
+                                             &dmadscr[i]);
        }
        config_acp_dma_channel(acp_mmio, ch,
-                               dma_dscr_idx - 1,
-                               NUM_DSCRS_PER_CHANNEL,
-                               ACP_DMA_PRIORITY_LEVEL_NORMAL);
+                              dma_dscr_idx - 1,
+                              NUM_DSCRS_PER_CHANNEL,
+                              ACP_DMA_PRIORITY_LEVEL_NORMAL);
 }
 
-/* Initialize the DMA descriptor information for transfer between
+/*
+ * Initialize the DMA descriptor information for transfer between
  * ACP SRAM <-> I2S
  */
 static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size,
-                                               int direction, u32 sram_bank,
-                                               u16 destination, u16 ch,
-                                               u16 dma_dscr_idx, u32 asic_type)
+                                          int direction, u32 sram_bank,
+                                          u16 destination, u16 ch,
+                                          u16 dma_dscr_idx, u32 asic_type)
 {
-
        u16 i;
        acp_dma_dscr_transfer_t dmadscr[NUM_DSCRS_PER_CHANNEL];
 
@@ -254,7 +260,7 @@ static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size,
                dmadscr[i].xfer_val = 0;
                if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
                        dma_dscr_idx = dma_dscr_idx + i;
-                       dmadscr[i].src = sram_bank  + (i * (size/2));
+                       dmadscr[i].src = sram_bank  + (i * (size / 2));
                        /* dmadscr[i].dest is unused by hardware. */
                        dmadscr[i].dest = 0;
                        dmadscr[i].xfer_val |= BIT(22) | (destination << 16) |
@@ -269,12 +275,12 @@ static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size,
                                (destination << 16) | (size / 2);
                }
                config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
-                                               &dmadscr[i]);
+                                             &dmadscr[i]);
        }
        /* Configure the DMA channel with the above descriptore */
        config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1,
-                               NUM_DSCRS_PER_CHANNEL,
-                               ACP_DMA_PRIORITY_LEVEL_NORMAL);
+                              NUM_DSCRS_PER_CHANNEL,
+                              ACP_DMA_PRIORITY_LEVEL_NORMAL);
 }
 
 /* Create page table entries in ACP SRAM for the allocated memory */
@@ -291,7 +297,7 @@ static void acp_pte_config(void __iomem *acp_mmio, struct page *pg,
        for (page_idx = 0; page_idx < (num_of_pages); page_idx++) {
                /* Load the low address of page int ACP SRAM through SRBM */
                acp_reg_write((offset + (page_idx * 8)),
-                       acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
+                             acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
                addr = page_to_phys(pg);
 
                low = lower_32_bits(addr);
@@ -301,7 +307,7 @@ static void acp_pte_config(void __iomem *acp_mmio, struct page *pg,
 
                /* Load the High address of page int ACP SRAM through SRBM */
                acp_reg_write((offset + (page_idx * 8) + 4),
-                       acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
+                             acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
 
                /* page enable in ACP */
                high |= BIT(31);
@@ -313,59 +319,25 @@ static void acp_pte_config(void __iomem *acp_mmio, struct page *pg,
 }
 
 static void config_acp_dma(void __iomem *acp_mmio,
-                       struct audio_substream_data *audio_config,
-                       u32 asic_type)
+                          struct audio_substream_data *rtd,
+                          u32 asic_type)
 {
-       u32 pte_offset, sram_bank;
-       u16 ch1, ch2, destination, dma_dscr_idx;
-
-       if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK) {
-               pte_offset = ACP_PLAYBACK_PTE_OFFSET;
-               ch1 = SYSRAM_TO_ACP_CH_NUM;
-               ch2 = ACP_TO_I2S_DMA_CH_NUM;
-               sram_bank = ACP_SHARED_RAM_BANK_1_ADDRESS;
-               destination = TO_ACP_I2S_1;
-
-       } else {
-               pte_offset = ACP_CAPTURE_PTE_OFFSET;
-               ch1 = SYSRAM_TO_ACP_CH_NUM;
-               ch2 = ACP_TO_I2S_DMA_CH_NUM;
-               switch (asic_type) {
-               case CHIP_STONEY:
-                       sram_bank = ACP_SHARED_RAM_BANK_3_ADDRESS;
-                       break;
-               default:
-                       sram_bank = ACP_SHARED_RAM_BANK_5_ADDRESS;
-               }
-               destination = FROM_ACP_I2S_1;
-       }
-
-       acp_pte_config(acp_mmio, audio_config->pg, audio_config->num_of_pages,
-                       pte_offset);
-       if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK)
-               dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
-       else
-               dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
-
+       acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages,
+                      rtd->pte_offset);
        /* Configure System memory <-> ACP SRAM DMA descriptors */
-       set_acp_sysmem_dma_descriptors(acp_mmio, audio_config->size,
-                                      audio_config->direction, pte_offset,
-                                       ch1, sram_bank, dma_dscr_idx, asic_type);
-
-       if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK)
-               dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH13;
-       else
-               dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH15;
+       set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size,
+                                      rtd->direction, rtd->pte_offset,
+                                      rtd->ch1, rtd->sram_bank,
+                                      rtd->dma_dscr_idx_1, asic_type);
        /* Configure ACP SRAM <-> I2S DMA descriptors */
-       set_acp_to_i2s_dma_descriptors(acp_mmio, audio_config->size,
-                                       audio_config->direction, sram_bank,
-                                       destination, ch2, dma_dscr_idx,
-                                       asic_type);
+       set_acp_to_i2s_dma_descriptors(acp_mmio, rtd->size,
+                                      rtd->direction, rtd->sram_bank,
+                                      rtd->destination, rtd->ch2,
+                                      rtd->dma_dscr_idx_2, asic_type);
 }
 
 /* Start a given DMA channel transfer */
-static void acp_dma_start(void __iomem *acp_mmio,
-                        u16 ch_num, bool is_circular)
+static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
 {
        u32 dma_ctrl;
 
@@ -375,7 +347,8 @@ static void acp_dma_start(void __iomem *acp_mmio,
        /* Invalidating the DAGB cache */
        acp_reg_write(1, acp_mmio, mmACP_DAGB_ATU_CTRL);
 
-       /* configure the DMA channel and start the DMA transfer
+       /*
+        * configure the DMA channel and start the DMA transfer
         * set dmachrun bit to start the transfer and enable the
         * interrupt on completion of the dma transfer
         */
@@ -385,6 +358,9 @@ static void acp_dma_start(void __iomem *acp_mmio,
        case ACP_TO_I2S_DMA_CH_NUM:
        case ACP_TO_SYSRAM_CH_NUM:
        case I2S_TO_ACP_DMA_CH_NUM:
+       case ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM:
+       case ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM:
+       case I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM:
                dma_ctrl |= ACP_DMA_CNTL_0__DMAChIOCEn_MASK;
                break;
        default:
@@ -392,11 +368,8 @@ static void acp_dma_start(void __iomem *acp_mmio,
                break;
        }
 
-       /* enable  for ACP SRAM to/from I2S DMA channel */
-       if (is_circular == true)
-               dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
-       else
-               dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+       /* circular for both DMA channel */
+       dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
 
        acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
 }
@@ -410,9 +383,10 @@ static int acp_dma_stop(void __iomem *acp_mmio, u8 ch_num)
 
        dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
 
-       /* clear the dma control register fields before writing zero
+       /*
+        * clear the dma control register fields before writing zero
         * in reset bit
-       */
+        */
        dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRun_MASK;
        dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChIOCEn_MASK;
 
@@ -420,9 +394,10 @@ static int acp_dma_stop(void __iomem *acp_mmio, u8 ch_num)
        dma_ch_sts = acp_reg_read(acp_mmio, mmACP_DMA_CH_STS);
 
        if (dma_ch_sts & BIT(ch_num)) {
-               /* set the reset bit for this channel to stop the dma
-               *  transfer
-               */
+               /*
+                * set the reset bit for this channel to stop the dma
+                *  transfer
+                */
                dma_ctrl |= ACP_DMA_CNTL_0__DMAChRst_MASK;
                acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
        }
@@ -431,13 +406,14 @@ static int acp_dma_stop(void __iomem *acp_mmio, u8 ch_num)
        while (true) {
                dma_ch_sts = acp_reg_read(acp_mmio, mmACP_DMA_CH_STS);
                if (!(dma_ch_sts & BIT(ch_num))) {
-                       /* clear the reset flag after successfully stopping
-                       * the dma transfer and break from the loop
-                       */
+                       /*
+                        * clear the reset flag after successfully stopping
+                        * the dma transfer and break from the loop
+                        */
                        dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRst_MASK;
 
                        acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0
-                                                               + ch_num);
+                                     + ch_num);
                        break;
                }
                if (--count == 0) {
@@ -450,7 +426,7 @@ static int acp_dma_stop(void __iomem *acp_mmio, u8 ch_num)
 }
 
 static void acp_set_sram_bank_state(void __iomem *acp_mmio, u16 bank,
-                                       bool power_on)
+                                   bool power_on)
 {
        u32 val, req_reg, sts_reg, sts_reg_mask;
        u32 loops = 1000;
@@ -530,7 +506,7 @@ static int acp_init(void __iomem *acp_mmio, u32 asic_type)
 
        while (true) {
                val = acp_reg_read(acp_mmio, mmACP_STATUS);
-               if (val & (u32) 0x1)
+               if (val & (u32)0x1)
                        break;
                if (--count == 0) {
                        pr_err("Failed to reset ACP\n");
@@ -544,13 +520,20 @@ static int acp_init(void __iomem *acp_mmio, u32 asic_type)
        val &= ~ACP_SOFT_RESET__SoftResetAud_MASK;
        acp_reg_write(val, acp_mmio, mmACP_SOFT_RESET);
 
+       /* For BT instance change pins from UART to BT */
+       if (!bt_uart_enable) {
+               val = acp_reg_read(acp_mmio, mmACP_BT_UART_PAD_SEL);
+               val |= ACP_BT_UART_PAD_SELECT_MASK;
+               acp_reg_write(val, acp_mmio, mmACP_BT_UART_PAD_SEL);
+       }
+
        /* initiailize Onion control DAGB register */
        acp_reg_write(ACP_ONION_CNTL_DEFAULT, acp_mmio,
-                       mmACP_AXI2DAGB_ONION_CNTL);
+                     mmACP_AXI2DAGB_ONION_CNTL);
 
        /* initiailize Garlic control DAGB registers */
        acp_reg_write(ACP_GARLIC_CNTL_DEFAULT, acp_mmio,
-                       mmACP_AXI2DAGB_GARLIC_CNTL);
+                     mmACP_AXI2DAGB_GARLIC_CNTL);
 
        sram_pte_offset = ACP_DAGB_GRP_SRAM_BASE_ADDRESS |
                        ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBSnoopSel_MASK |
@@ -558,17 +541,18 @@ static int acp_init(void __iomem *acp_mmio, u32 asic_type)
                        ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBGrpEnable_MASK;
        acp_reg_write(sram_pte_offset,  acp_mmio, mmACP_DAGB_BASE_ADDR_GRP_1);
        acp_reg_write(ACP_PAGE_SIZE_4K_ENABLE, acp_mmio,
-                       mmACP_DAGB_PAGE_SIZE_GRP_1);
+                     mmACP_DAGB_PAGE_SIZE_GRP_1);
 
        acp_reg_write(ACP_SRAM_BASE_ADDRESS, acp_mmio,
-                       mmACP_DMA_DESC_BASE_ADDR);
+                     mmACP_DMA_DESC_BASE_ADDR);
 
        /* Num of descriptiors in SRAM 0x4, means 256 descriptors;(64 * 4) */
        acp_reg_write(0x4, acp_mmio, mmACP_DMA_DESC_MAX_NUM_DSCR);
        acp_reg_write(ACP_EXTERNAL_INTR_CNTL__DMAIOCMask_MASK,
-               acp_mmio, mmACP_EXTERNAL_INTR_CNTL);
+                     acp_mmio, mmACP_EXTERNAL_INTR_CNTL);
 
-       /* When ACP_TILE_P1 is turned on, all SRAM banks get turned on.
+       /*
+       * When ACP_TILE_P1 is turned on, all SRAM banks get turned on.
        * Now, turn off all of them. This can't be done in 'poweron' of
        * ACP pm domain, as this requires ACP to be initialized.
        * For Stoney, Memory gating is disabled,i.e SRAM Banks
@@ -606,7 +590,7 @@ static int acp_deinit(void __iomem *acp_mmio)
                }
                udelay(100);
        }
-       /** Disable ACP clock */
+       /* Disable ACP clock */
        val = acp_reg_read(acp_mmio, mmACP_CONTROL);
        val &= ~ACP_CONTROL__ClkEn_MASK;
        acp_reg_write(val, acp_mmio, mmACP_CONTROL);
@@ -615,7 +599,7 @@ static int acp_deinit(void __iomem *acp_mmio)
 
        while (true) {
                val = acp_reg_read(acp_mmio, mmACP_STATUS);
-               if (!(val & (u32) 0x1))
+               if (!(val & (u32)0x1))
                        break;
                if (--count == 0) {
                        pr_err("Failed to reset ACP\n");
@@ -629,7 +613,6 @@ static int acp_deinit(void __iomem *acp_mmio)
 /* ACP DMA irq handler routine for playback, capture usecases */
 static irqreturn_t dma_irq_handler(int irq, void *arg)
 {
-       u16 dscr_idx;
        u32 intr_flag, ext_intr_status;
        struct audio_drv_data *irq_data;
        void __iomem *acp_mmio;
@@ -646,41 +629,45 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
        if ((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) != 0) {
                valid_irq = true;
-               if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_13) ==
-                               PLAYBACK_START_DMA_DESCR_CH13)
-                       dscr_idx = PLAYBACK_END_DMA_DESCR_CH12;
-               else
-                       dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
-               config_acp_dma_channel(acp_mmio, SYSRAM_TO_ACP_CH_NUM, dscr_idx,
-                                      1, 0);
-               acp_dma_start(acp_mmio, SYSRAM_TO_ACP_CH_NUM, false);
-
                snd_pcm_period_elapsed(irq_data->play_i2ssp_stream);
-
                acp_reg_write((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) << 16,
-                               acp_mmio, mmACP_EXTERNAL_INTR_STAT);
+                             acp_mmio, mmACP_EXTERNAL_INTR_STAT);
        }
 
-       if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
+       if ((intr_flag & BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) != 0) {
                valid_irq = true;
-               if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_15) ==
-                               CAPTURE_START_DMA_DESCR_CH15)
-                       dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
-               else
-                       dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
-               config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx,
-                                      1, 0);
-               acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
+               snd_pcm_period_elapsed(irq_data->play_i2sbt_stream);
+               acp_reg_write((intr_flag &
+                             BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) << 16,
+                             acp_mmio, mmACP_EXTERNAL_INTR_STAT);
+       }
 
+       if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
+               valid_irq = true;
+               snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
                acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
-                               acp_mmio, mmACP_EXTERNAL_INTR_STAT);
+                             acp_mmio, mmACP_EXTERNAL_INTR_STAT);
        }
 
        if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
                valid_irq = true;
-               snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
                acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
-                               acp_mmio, mmACP_EXTERNAL_INTR_STAT);
+                             acp_mmio, mmACP_EXTERNAL_INTR_STAT);
+       }
+
+       if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
+               valid_irq = true;
+               snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream);
+               acp_reg_write((intr_flag &
+                             BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
+                             acp_mmio, mmACP_EXTERNAL_INTR_STAT);
+       }
+
+       if ((intr_flag & BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) != 0) {
+               valid_irq = true;
+               acp_reg_write((intr_flag &
+                             BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) << 16,
+                             acp_mmio, mmACP_EXTERNAL_INTR_STAT);
        }
 
        if (valid_irq)
@@ -695,11 +682,12 @@ static int acp_dma_open(struct snd_pcm_substream *substream)
        int ret = 0;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *prtd = substream->private_data;
-       struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
+       struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
+                                                                   DRV_NAME);
        struct audio_drv_data *intr_data = dev_get_drvdata(component->dev);
        struct audio_substream_data *adata =
                kzalloc(sizeof(struct audio_substream_data), GFP_KERNEL);
-       if (adata == NULL)
+       if (!adata)
                return -ENOMEM;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -731,17 +719,19 @@ static int acp_dma_open(struct snd_pcm_substream *substream)
        adata->acp_mmio = intr_data->acp_mmio;
        runtime->private_data = adata;
 
-       /* Enable ACP irq, when neither playback or capture streams are
+       /*
+        * Enable ACP irq, when neither playback or capture streams are
         * active by the time when a new stream is being opened.
         * This enablement is not required for another stream, if current
         * stream is not closed
-       */
-       if (!intr_data->play_i2ssp_stream && !intr_data->capture_i2ssp_stream)
+        */
+       if (!intr_data->play_i2ssp_stream && !intr_data->capture_i2ssp_stream &&
+           !intr_data->play_i2sbt_stream && !intr_data->capture_i2sbt_stream)
                acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               intr_data->play_i2ssp_stream = substream;
-               /* For Stoney, Memory gating is disabled,i.e SRAM Banks
+               /*
+                * For Stoney, Memory gating is disabled,i.e SRAM Banks
                 * won't be turned off. The default state for SRAM banks is ON.
                 * Setting SRAM bank state code skipped for STONEY platform.
                 */
@@ -751,7 +741,6 @@ static int acp_dma_open(struct snd_pcm_substream *substream)
                                                        bank, true);
                }
        } else {
-               intr_data->capture_i2ssp_stream = substream;
                if (intr_data->asic_type != CHIP_STONEY) {
                        for (bank = 5; bank <= 8; bank++)
                                acp_set_sram_bank_state(intr_data->acp_mmio,
@@ -772,8 +761,11 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_runtime *runtime;
        struct audio_substream_data *rtd;
        struct snd_soc_pcm_runtime *prtd = substream->private_data;
-       struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
+       struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
+                                                                   DRV_NAME);
        struct audio_drv_data *adata = dev_get_drvdata(component->dev);
+       struct snd_soc_card *card = prtd->card;
+       struct acp_platform_info *pinfo = snd_soc_card_get_drvdata(card);
 
        runtime = substream->runtime;
        rtd = runtime->private_data;
@@ -781,14 +773,111 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
        if (WARN_ON(!rtd))
                return -EINVAL;
 
+       rtd->i2s_instance = pinfo->i2s_instance;
        if (adata->asic_type == CHIP_STONEY) {
-               val = acp_reg_read(adata->acp_mmio, mmACP_I2S_16BIT_RESOLUTION_EN);
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-                       val |= ACP_I2S_SP_16BIT_RESOLUTION_EN;
-               else
-                       val |= ACP_I2S_MIC_16BIT_RESOLUTION_EN;
-               acp_reg_write(val, adata->acp_mmio, mmACP_I2S_16BIT_RESOLUTION_EN);
+               val = acp_reg_read(adata->acp_mmio,
+                                  mmACP_I2S_16BIT_RESOLUTION_EN);
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       switch (rtd->i2s_instance) {
+                       case I2S_BT_INSTANCE:
+                               val |= ACP_I2S_BT_16BIT_RESOLUTION_EN;
+                               break;
+                       case I2S_SP_INSTANCE:
+                       default:
+                               val |= ACP_I2S_SP_16BIT_RESOLUTION_EN;
+                       }
+               } else {
+                       switch (rtd->i2s_instance) {
+                       case I2S_BT_INSTANCE:
+                               val |= ACP_I2S_BT_16BIT_RESOLUTION_EN;
+                               break;
+                       case I2S_SP_INSTANCE:
+                       default:
+                               val |= ACP_I2S_MIC_16BIT_RESOLUTION_EN;
+                       }
+               }
+               acp_reg_write(val, adata->acp_mmio,
+                             mmACP_I2S_16BIT_RESOLUTION_EN);
+       }
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               switch (rtd->i2s_instance) {
+               case I2S_BT_INSTANCE:
+                       rtd->pte_offset = ACP_ST_BT_PLAYBACK_PTE_OFFSET;
+                       rtd->ch1 = SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM;
+                       rtd->ch2 = ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM;
+                       rtd->sram_bank = ACP_SRAM_BANK_3_ADDRESS;
+                       rtd->destination = TO_BLUETOOTH;
+                       rtd->dma_dscr_idx_1 = PLAYBACK_START_DMA_DESCR_CH8;
+                       rtd->dma_dscr_idx_2 = PLAYBACK_START_DMA_DESCR_CH9;
+                       rtd->byte_cnt_high_reg_offset =
+                                       mmACP_I2S_BT_TRANSMIT_BYTE_CNT_HIGH;
+                       rtd->byte_cnt_low_reg_offset =
+                                       mmACP_I2S_BT_TRANSMIT_BYTE_CNT_LOW;
+                       adata->play_i2sbt_stream = substream;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       switch (adata->asic_type) {
+                       case CHIP_STONEY:
+                               rtd->pte_offset = ACP_ST_PLAYBACK_PTE_OFFSET;
+                               break;
+                       default:
+                               rtd->pte_offset = ACP_PLAYBACK_PTE_OFFSET;
+                       }
+                       rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
+                       rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
+                       rtd->sram_bank = ACP_SRAM_BANK_1_ADDRESS;
+                       rtd->destination = TO_ACP_I2S_1;
+                       rtd->dma_dscr_idx_1 = PLAYBACK_START_DMA_DESCR_CH12;
+                       rtd->dma_dscr_idx_2 = PLAYBACK_START_DMA_DESCR_CH13;
+                       rtd->byte_cnt_high_reg_offset =
+                                       mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH;
+                       rtd->byte_cnt_low_reg_offset =
+                                       mmACP_I2S_TRANSMIT_BYTE_CNT_LOW;
+                       adata->play_i2ssp_stream = substream;
+               }
+       } else {
+               switch (rtd->i2s_instance) {
+               case I2S_BT_INSTANCE:
+                       rtd->pte_offset = ACP_ST_BT_CAPTURE_PTE_OFFSET;
+                       rtd->ch1 = ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM;
+                       rtd->ch2 = I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM;
+                       rtd->sram_bank = ACP_SRAM_BANK_4_ADDRESS;
+                       rtd->destination = FROM_BLUETOOTH;
+                       rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10;
+                       rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH11;
+                       rtd->byte_cnt_high_reg_offset =
+                                       mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH;
+                       rtd->byte_cnt_low_reg_offset =
+                                       mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW;
+                       adata->capture_i2sbt_stream = substream;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET;
+                       rtd->ch1 = ACP_TO_SYSRAM_CH_NUM;
+                       rtd->ch2 = I2S_TO_ACP_DMA_CH_NUM;
+                       switch (adata->asic_type) {
+                       case CHIP_STONEY:
+                               rtd->pte_offset = ACP_ST_CAPTURE_PTE_OFFSET;
+                               rtd->sram_bank = ACP_SRAM_BANK_2_ADDRESS;
+                               break;
+                       default:
+                               rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET;
+                               rtd->sram_bank = ACP_SRAM_BANK_5_ADDRESS;
+                       }
+                       rtd->destination = FROM_ACP_I2S_1;
+                       rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14;
+                       rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15;
+                       rtd->byte_cnt_high_reg_offset =
+                                       mmACP_I2S_RECEIVED_BYTE_CNT_HIGH;
+                       rtd->byte_cnt_low_reg_offset =
+                                       mmACP_I2S_RECEIVED_BYTE_CNT_LOW;
+                       adata->capture_i2ssp_stream = substream;
+               }
        }
+
        size = params_buffer_bytes(params);
        status = snd_pcm_lib_malloc_pages(substream, size);
        if (status < 0)
@@ -797,7 +886,7 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
        memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
        pg = virt_to_page(substream->dma_buffer.area);
 
-       if (pg != NULL) {
+       if (pg) {
                acp_set_sram_bank_state(rtd->acp_mmio, 0, true);
                /* Save for runtime private data */
                rtd->pg = pg;
@@ -822,26 +911,15 @@ static int acp_dma_hw_free(struct snd_pcm_substream *substream)
        return snd_pcm_lib_free_pages(substream);
 }
 
-static u64 acp_get_byte_count(void __iomem *acp_mmio, int stream)
+static u64 acp_get_byte_count(struct audio_substream_data *rtd)
 {
-       union acp_dma_count playback_dma_count;
-       union acp_dma_count capture_dma_count;
-       u64 bytescount = 0;
+       union acp_dma_count byte_count;
 
-       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               playback_dma_count.bcount.high = acp_reg_read(acp_mmio,
-                                       mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH);
-               playback_dma_count.bcount.low  = acp_reg_read(acp_mmio,
-                                       mmACP_I2S_TRANSMIT_BYTE_CNT_LOW);
-               bytescount = playback_dma_count.bytescount;
-       } else {
-               capture_dma_count.bcount.high = acp_reg_read(acp_mmio,
-                                       mmACP_I2S_RECEIVED_BYTE_CNT_HIGH);
-               capture_dma_count.bcount.low  = acp_reg_read(acp_mmio,
-                                       mmACP_I2S_RECEIVED_BYTE_CNT_LOW);
-               bytescount = capture_dma_count.bytescount;
-       }
-       return bytescount;
+       byte_count.bcount.high = acp_reg_read(rtd->acp_mmio,
+                                             rtd->byte_cnt_high_reg_offset);
+       byte_count.bcount.low  = acp_reg_read(rtd->acp_mmio,
+                                             rtd->byte_cnt_low_reg_offset);
+       return byte_count.bytescount;
 }
 
 static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream)
@@ -857,15 +935,10 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream)
                return -EINVAL;
 
        buffersize = frames_to_bytes(runtime, runtime->buffer_size);
-       bytescount = acp_get_byte_count(rtd->acp_mmio, substream->stream);
+       bytescount = acp_get_byte_count(rtd);
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               if (bytescount > rtd->i2ssp_renderbytescount)
-                       bytescount = bytescount - rtd->i2ssp_renderbytescount;
-       } else {
-               if (bytescount > rtd->i2ssp_capturebytescount)
-                       bytescount = bytescount - rtd->i2ssp_capturebytescount;
-       }
+       if (bytescount > rtd->bytescount)
+               bytescount -= rtd->bytescount;
        pos = do_div(bytescount, buffersize);
        return bytes_to_frames(runtime, pos);
 }
@@ -883,34 +956,25 @@ static int acp_dma_prepare(struct snd_pcm_substream *substream)
 
        if (!rtd)
                return -EINVAL;
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               config_acp_dma_channel(rtd->acp_mmio, SYSRAM_TO_ACP_CH_NUM,
-                                       PLAYBACK_START_DMA_DESCR_CH12,
-                                       NUM_DSCRS_PER_CHANNEL, 0);
-               config_acp_dma_channel(rtd->acp_mmio, ACP_TO_I2S_DMA_CH_NUM,
-                                       PLAYBACK_START_DMA_DESCR_CH13,
-                                       NUM_DSCRS_PER_CHANNEL, 0);
-       } else {
-               config_acp_dma_channel(rtd->acp_mmio, ACP_TO_SYSRAM_CH_NUM,
-                                       CAPTURE_START_DMA_DESCR_CH14,
-                                       NUM_DSCRS_PER_CHANNEL, 0);
-               config_acp_dma_channel(rtd->acp_mmio, I2S_TO_ACP_DMA_CH_NUM,
-                                       CAPTURE_START_DMA_DESCR_CH15,
-                                       NUM_DSCRS_PER_CHANNEL, 0);
-       }
+
+       config_acp_dma_channel(rtd->acp_mmio,
+                              rtd->ch1,
+                              rtd->dma_dscr_idx_1,
+                              NUM_DSCRS_PER_CHANNEL, 0);
+       config_acp_dma_channel(rtd->acp_mmio,
+                              rtd->ch2,
+                              rtd->dma_dscr_idx_2,
+                              NUM_DSCRS_PER_CHANNEL, 0);
        return 0;
 }
 
 static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        int ret;
-       u32 loops = 4000;
        u64 bytescount = 0;
 
        struct snd_pcm_runtime *runtime = substream->runtime;
-       struct snd_soc_pcm_runtime *prtd = substream->private_data;
        struct audio_substream_data *rtd = runtime->private_data;
-       struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
 
        if (!rtd)
                return -EINVAL;
@@ -918,59 +982,40 @@ static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
        case SNDRV_PCM_TRIGGER_RESUME:
-               bytescount = acp_get_byte_count(rtd->acp_mmio,
-                                               substream->stream);
+               bytescount = acp_get_byte_count(rtd);
+               if (rtd->bytescount == 0)
+                       rtd->bytescount = bytescount;
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                       if (rtd->i2ssp_renderbytescount == 0)
-                               rtd->i2ssp_renderbytescount = bytescount;
-                       acp_dma_start(rtd->acp_mmio,
-                                               SYSRAM_TO_ACP_CH_NUM, false);
-                       while (acp_reg_read(rtd->acp_mmio, mmACP_DMA_CH_STS) &
-                                               BIT(SYSRAM_TO_ACP_CH_NUM)) {
-                               if (!loops--) {
-                                       dev_err(component->dev,
-                                               "acp dma start timeout\n");
-                                       return -ETIMEDOUT;
-                               }
-                               cpu_relax();
-                       }
-
-                       acp_dma_start(rtd->acp_mmio,
-                                       ACP_TO_I2S_DMA_CH_NUM, true);
-
+                       acp_dma_start(rtd->acp_mmio, rtd->ch1);
+                       acp_dma_start(rtd->acp_mmio, rtd->ch2);
                } else {
-                       if (rtd->i2ssp_capturebytescount == 0)
-                               rtd->i2ssp_capturebytescount = bytescount;
-                       acp_dma_start(rtd->acp_mmio,
-                                           I2S_TO_ACP_DMA_CH_NUM, true);
+                       acp_dma_start(rtd->acp_mmio, rtd->ch2);
+                       acp_dma_start(rtd->acp_mmio, rtd->ch1);
                }
                ret = 0;
                break;
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               /* Need to stop only circular DMA channels :
-                * ACP_TO_I2S_DMA_CH_NUM / I2S_TO_ACP_DMA_CH_NUM. Non-circular
-                * channels will stopped automatically after its transfer
-                * completes : SYSRAM_TO_ACP_CH_NUM / ACP_TO_SYSRAM_CH_NUM
+               /* For playback, non circular dma should be stopped first
+                * i.e Sysram to acp dma transfer channel(rtd->ch1) should be
+                * stopped before stopping cirular dma which is acp sram to i2s
+                * fifo dma transfer channel(rtd->ch2). Where as in Capture
+                * scenario, i2s fifo to acp sram dma channel(rtd->ch2) stopped
+                * first before stopping acp sram to sysram which is circular
+                * dma(rtd->ch1).
                 */
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                       ret = acp_dma_stop(rtd->acp_mmio,
-                                               SYSRAM_TO_ACP_CH_NUM);
-                       ret = acp_dma_stop(rtd->acp_mmio,
-                                       ACP_TO_I2S_DMA_CH_NUM);
-                       rtd->i2ssp_renderbytescount = 0;
+                       acp_dma_stop(rtd->acp_mmio, rtd->ch1);
+                       ret =  acp_dma_stop(rtd->acp_mmio, rtd->ch2);
                } else {
-                       ret = acp_dma_stop(rtd->acp_mmio,
-                                       I2S_TO_ACP_DMA_CH_NUM);
-                       ret = acp_dma_stop(rtd->acp_mmio,
-                                               ACP_TO_SYSRAM_CH_NUM);
-                       rtd->i2ssp_capturebytescount = 0;
+                       acp_dma_stop(rtd->acp_mmio, rtd->ch2);
+                       ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1);
                }
+               rtd->bytescount = 0;
                break;
        default:
                ret = -EINVAL;
-
        }
        return ret;
 }
@@ -978,26 +1023,27 @@ static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
 static int acp_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
        int ret;
-       struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
+       struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd,
+                                                                   DRV_NAME);
        struct audio_drv_data *adata = dev_get_drvdata(component->dev);
 
        switch (adata->asic_type) {
        case CHIP_STONEY:
                ret = snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
-                                                       SNDRV_DMA_TYPE_DEV,
-                                                       NULL, ST_MIN_BUFFER,
-                                                       ST_MAX_BUFFER);
+                                                           SNDRV_DMA_TYPE_DEV,
+                                                           NULL, ST_MIN_BUFFER,
+                                                           ST_MAX_BUFFER);
                break;
        default:
                ret = snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
-                                                       SNDRV_DMA_TYPE_DEV,
-                                                       NULL, MIN_BUFFER,
-                                                       MAX_BUFFER);
+                                                           SNDRV_DMA_TYPE_DEV,
+                                                           NULL, MIN_BUFFER,
+                                                           MAX_BUFFER);
                break;
        }
        if (ret < 0)
                dev_err(component->dev,
-                               "buffer preallocation failer error:%d\n", ret);
+                       "buffer preallocation failure error:%d\n", ret);
        return ret;
 }
 
@@ -1007,38 +1053,55 @@ static int acp_dma_close(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct audio_substream_data *rtd = runtime->private_data;
        struct snd_soc_pcm_runtime *prtd = substream->private_data;
-       struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
+       struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
+                                                                   DRV_NAME);
        struct audio_drv_data *adata = dev_get_drvdata(component->dev);
 
-       kfree(rtd);
-
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               adata->play_i2ssp_stream = NULL;
-               /* For Stoney, Memory gating is disabled,i.e SRAM Banks
-                * won't be turned off. The default state for SRAM banks is ON.
-                * Setting SRAM bank state code skipped for STONEY platform.
-                * added condition checks for Carrizo platform only
-                */
-               if (adata->asic_type != CHIP_STONEY) {
-                       for (bank = 1; bank <= 4; bank++)
-                               acp_set_sram_bank_state(adata->acp_mmio, bank,
-                               false);
+               switch (rtd->i2s_instance) {
+               case I2S_BT_INSTANCE:
+                       adata->play_i2sbt_stream = NULL;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       adata->play_i2ssp_stream = NULL;
+                       /*
+                        * For Stoney, Memory gating is disabled,i.e SRAM Banks
+                        * won't be turned off. The default state for SRAM banks
+                        * is ON.Setting SRAM bank state code skipped for STONEY
+                        * platform. Added condition checks for Carrizo platform
+                        * only.
+                        */
+                       if (adata->asic_type != CHIP_STONEY) {
+                               for (bank = 1; bank <= 4; bank++)
+                                       acp_set_sram_bank_state(adata->acp_mmio,
+                                                               bank, false);
+                       }
                }
        } else  {
-               adata->capture_i2ssp_stream = NULL;
-               if (adata->asic_type != CHIP_STONEY) {
-                       for (bank = 5; bank <= 8; bank++)
-                               acp_set_sram_bank_state(adata->acp_mmio, bank,
-                                                    false);
+               switch (rtd->i2s_instance) {
+               case I2S_BT_INSTANCE:
+                       adata->capture_i2sbt_stream = NULL;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       adata->capture_i2ssp_stream = NULL;
+                       if (adata->asic_type != CHIP_STONEY) {
+                               for (bank = 5; bank <= 8; bank++)
+                                       acp_set_sram_bank_state(adata->acp_mmio,
+                                                               bank, false);
+                       }
                }
        }
 
-       /* Disable ACP irq, when the current stream is being closed and
+       /*
+        * Disable ACP irq, when the current stream is being closed and
         * another stream is also not active.
-       */
-       if (!adata->play_i2ssp_stream && !adata->capture_i2ssp_stream)
+        */
+       if (!adata->play_i2ssp_stream && !adata->capture_i2ssp_stream &&
+           !adata->play_i2sbt_stream && !adata->capture_i2sbt_stream)
                acp_reg_write(0, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB);
-
+       kfree(rtd);
        return 0;
 }
 
@@ -1054,7 +1117,7 @@ static const struct snd_pcm_ops acp_dma_ops = {
        .prepare = acp_dma_prepare,
 };
 
-static struct snd_soc_component_driver acp_asoc_platform = {
+static const struct snd_soc_component_driver acp_asoc_platform = {
        .name = DRV_NAME,
        .ops = &acp_dma_ops,
        .pcm_new = acp_dma_new,
@@ -1073,8 +1136,8 @@ static int acp_audio_probe(struct platform_device *pdev)
        }
 
        audio_drv_data = devm_kzalloc(&pdev->dev, sizeof(struct audio_drv_data),
-                                       GFP_KERNEL);
-       if (audio_drv_data == NULL)
+                                     GFP_KERNEL);
+       if (!audio_drv_data)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1082,13 +1145,16 @@ static int acp_audio_probe(struct platform_device *pdev)
        if (IS_ERR(audio_drv_data->acp_mmio))
                return PTR_ERR(audio_drv_data->acp_mmio);
 
-       /* The following members gets populated in device 'open'
+       /*
+        * The following members gets populated in device 'open'
         * function. Till then interrupts are disabled in 'acp_init'
         * and device doesn't generate any interrupts.
         */
 
        audio_drv_data->play_i2ssp_stream = NULL;
        audio_drv_data->capture_i2ssp_stream = NULL;
+       audio_drv_data->play_i2sbt_stream = NULL;
+       audio_drv_data->capture_i2sbt_stream = NULL;
 
        audio_drv_data->asic_type =  *pdata;
 
@@ -1099,7 +1165,7 @@ static int acp_audio_probe(struct platform_device *pdev)
        }
 
        status = devm_request_irq(&pdev->dev, res->start, dma_irq_handler,
-                                       0, "ACP_IRQ", &pdev->dev);
+                                 0, "ACP_IRQ", &pdev->dev);
        if (status) {
                dev_err(&pdev->dev, "ACP IRQ request failed\n");
                return status;
@@ -1115,7 +1181,7 @@ static int acp_audio_probe(struct platform_device *pdev)
        }
 
        status = devm_snd_soc_register_component(&pdev->dev,
-                                               &acp_asoc_platform, NULL, 0);
+                                                &acp_asoc_platform, NULL, 0);
        if (status != 0) {
                dev_err(&pdev->dev, "Fail to register ALSA platform device\n");
                return status;
@@ -1145,6 +1211,7 @@ static int acp_pcm_resume(struct device *dev)
 {
        u16 bank;
        int status;
+       struct audio_substream_data *rtd;
        struct audio_drv_data *adata = dev_get_drvdata(dev);
 
        status = acp_init(adata->acp_mmio, adata->asic_type);
@@ -1154,28 +1221,40 @@ static int acp_pcm_resume(struct device *dev)
        }
 
        if (adata->play_i2ssp_stream && adata->play_i2ssp_stream->runtime) {
-               /* For Stoney, Memory gating is disabled,i.e SRAM Banks
+               /*
+                * For Stoney, Memory gating is disabled,i.e SRAM Banks
                 * won't be turned off. The default state for SRAM banks is ON.
                 * Setting SRAM bank state code skipped for STONEY platform.
                 */
                if (adata->asic_type != CHIP_STONEY) {
                        for (bank = 1; bank <= 4; bank++)
                                acp_set_sram_bank_state(adata->acp_mmio, bank,
-                                               true);
+                                                       true);
                }
-               config_acp_dma(adata->acp_mmio,
-                       adata->play_i2ssp_stream->runtime->private_data,
-                       adata->asic_type);
+               rtd = adata->play_i2ssp_stream->runtime->private_data;
+               config_acp_dma(adata->acp_mmio, rtd, adata->asic_type);
        }
-       if (adata->capture_i2ssp_stream && adata->capture_i2ssp_stream->runtime) {
+       if (adata->capture_i2ssp_stream &&
+           adata->capture_i2ssp_stream->runtime) {
                if (adata->asic_type != CHIP_STONEY) {
                        for (bank = 5; bank <= 8; bank++)
                                acp_set_sram_bank_state(adata->acp_mmio, bank,
-                                               true);
+                                                       true);
+               }
+               rtd =  adata->capture_i2ssp_stream->runtime->private_data;
+               config_acp_dma(adata->acp_mmio, rtd, adata->asic_type);
+       }
+       if (adata->asic_type != CHIP_CARRIZO) {
+               if (adata->play_i2sbt_stream &&
+                   adata->play_i2sbt_stream->runtime) {
+                       rtd = adata->play_i2sbt_stream->runtime->private_data;
+                       config_acp_dma(adata->acp_mmio, rtd, adata->asic_type);
+               }
+               if (adata->capture_i2sbt_stream &&
+                   adata->capture_i2sbt_stream->runtime) {
+                       rtd = adata->capture_i2sbt_stream->runtime->private_data;
+                       config_acp_dma(adata->acp_mmio, rtd, adata->asic_type);
                }
-               config_acp_dma(adata->acp_mmio,
-                       adata->capture_i2ssp_stream->runtime->private_data,
-                       adata->asic_type);
        }
        acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB);
        return 0;
index ba01510eb818b7079fc633d575199daf436fb449..9cd3e96c84d473ef39bef686ecf16cd9411c18f1 100644 (file)
 #define ACP_PLAYBACK_PTE_OFFSET                        10
 #define ACP_CAPTURE_PTE_OFFSET                 0
 
+/* Playback and Capture Offset for Stoney */
+#define ACP_ST_PLAYBACK_PTE_OFFSET     0x04
+#define ACP_ST_CAPTURE_PTE_OFFSET      0x00
+#define ACP_ST_BT_PLAYBACK_PTE_OFFSET  0x08
+#define ACP_ST_BT_CAPTURE_PTE_OFFSET   0x0c
+
 #define ACP_GARLIC_CNTL_DEFAULT                        0x00000FB4
 #define ACP_ONION_CNTL_DEFAULT                 0x00000FB4
 
 #define ACP_PHYSICAL_BASE                      0x14000
 
-/* Playback SRAM address (as a destination in dma descriptor) */
-#define ACP_SHARED_RAM_BANK_1_ADDRESS          0x4002000
-
-/* Capture SRAM address (as a source in dma descriptor) */
-#define ACP_SHARED_RAM_BANK_5_ADDRESS          0x400A000
-#define ACP_SHARED_RAM_BANK_3_ADDRESS          0x4006000
+/*
+ * In case of I2S SP controller instance, Stoney uses SRAM bank 1 for
+ * playback and SRAM Bank 2 for capture where as in case of BT I2S
+ * Instance, Stoney uses SRAM Bank 3 for playback & SRAM Bank 4 will
+ * be used for capture. Carrizo uses I2S SP controller instance. SRAM Banks
+ * 1, 2, 3, 4 will be used for playback & SRAM Banks 5, 6, 7, 8 will be used
+ * for capture scenario.
+ */
+#define ACP_SRAM_BANK_1_ADDRESS                0x4002000
+#define ACP_SRAM_BANK_2_ADDRESS                0x4004000
+#define ACP_SRAM_BANK_3_ADDRESS                0x4006000
+#define ACP_SRAM_BANK_4_ADDRESS                0x4008000
+#define ACP_SRAM_BANK_5_ADDRESS                0x400A000
 
 #define ACP_DMA_RESET_TIME                     10000
 #define ACP_CLOCK_EN_TIME_OUT_VALUE            0x000000FF
 
 #define TO_ACP_I2S_1   0x2
 #define TO_ACP_I2S_2   0x4
+#define TO_BLUETOOTH   0x3
 #define FROM_ACP_I2S_1 0xa
 #define FROM_ACP_I2S_2 0xb
+#define FROM_BLUETOOTH 0xb
+
+#define I2S_SP_INSTANCE                 0x01
+#define I2S_BT_INSTANCE                 0x02
 
 #define ACP_TILE_ON_MASK                0x03
 #define ACP_TILE_OFF_MASK               0x02
 #define ACP_TO_SYSRAM_CH_NUM 14
 #define I2S_TO_ACP_DMA_CH_NUM 15
 
+/* Playback DMA Channels for I2S BT instance */
+#define SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM  8
+#define ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM 9
+
+/* Capture DMA Channels for I2S BT Instance */
+#define ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM 10
+#define I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM 11
+
 #define NUM_DSCRS_PER_CHANNEL 2
 
 #define PLAYBACK_START_DMA_DESCR_CH12 0
 #define CAPTURE_START_DMA_DESCR_CH15 6
 #define CAPTURE_END_DMA_DESCR_CH15 7
 
+/* I2S BT Instance DMA Descriptors */
+#define PLAYBACK_START_DMA_DESCR_CH8 8
+#define PLAYBACK_END_DMA_DESCR_CH8 9
+#define PLAYBACK_START_DMA_DESCR_CH9 10
+#define PLAYBACK_END_DMA_DESCR_CH9 11
+
+#define CAPTURE_START_DMA_DESCR_CH10 12
+#define CAPTURE_END_DMA_DESCR_CH10 13
+#define CAPTURE_START_DMA_DESCR_CH11 14
+#define CAPTURE_END_DMA_DESCR_CH11 15
+
 #define mmACP_I2S_16BIT_RESOLUTION_EN       0x5209
 #define ACP_I2S_MIC_16BIT_RESOLUTION_EN 0x01
 #define ACP_I2S_SP_16BIT_RESOLUTION_EN 0x02
+#define ACP_I2S_BT_16BIT_RESOLUTION_EN 0x04
+#define ACP_BT_UART_PAD_SELECT_MASK    0x1
+
 enum acp_dma_priority_level {
        /* 0x0 Specifies the DMA channel is given normal priority */
        ACP_DMA_PRIORITY_LEVEL_NORMAL = 0x0,
@@ -84,20 +124,39 @@ struct audio_substream_data {
        struct page *pg;
        unsigned int order;
        u16 num_of_pages;
+       u16 i2s_instance;
        u16 direction;
+       u16 ch1;
+       u16 ch2;
+       u16 destination;
+       u16 dma_dscr_idx_1;
+       u16 dma_dscr_idx_2;
+       u32 pte_offset;
+       u32 sram_bank;
+       u32 byte_cnt_high_reg_offset;
+       u32 byte_cnt_low_reg_offset;
        uint64_t size;
-       u64 i2ssp_renderbytescount;
-       u64 i2ssp_capturebytescount;
+       u64 bytescount;
        void __iomem *acp_mmio;
 };
 
 struct audio_drv_data {
        struct snd_pcm_substream *play_i2ssp_stream;
        struct snd_pcm_substream *capture_i2ssp_stream;
+       struct snd_pcm_substream *play_i2sbt_stream;
+       struct snd_pcm_substream *capture_i2sbt_stream;
        void __iomem *acp_mmio;
        u32 asic_type;
 };
 
+/*
+ * this structure used for platform data transfer between machine driver
+ * and dma driver
+ */
+struct acp_platform_info {
+       u16 i2s_instance;
+};
+
 union acp_dma_count {
        struct {
        u32 low;
@@ -115,23 +174,25 @@ enum {
 };
 
 enum {
-       ACP_DMA_ATTRIBUTES_SHAREDMEM_TO_DAGB_ONION = 0x0,
-       ACP_DMA_ATTRIBUTES_SHARED_MEM_TO_DAGB_GARLIC = 0x1,
-       ACP_DMA_ATTRIBUTES_DAGB_ONION_TO_SHAREDMEM = 0x8,
-       ACP_DMA_ATTRIBUTES_DAGB_GARLIC_TO_SHAREDMEM = 0x9,
-       ACP_DMA_ATTRIBUTES_FORCE_SIZE = 0xF
+       ACP_DMA_ATTR_SHAREDMEM_TO_DAGB_ONION = 0x0,
+       ACP_DMA_ATTR_SHARED_MEM_TO_DAGB_GARLIC = 0x1,
+       ACP_DMA_ATTR_DAGB_ONION_TO_SHAREDMEM = 0x8,
+       ACP_DMA_ATTR_DAGB_GARLIC_TO_SHAREDMEM = 0x9,
+       ACP_DMA_ATTR_FORCE_SIZE = 0xF
 };
 
 typedef struct acp_dma_dscr_transfer {
        /* Specifies the source memory location for the DMA data transfer. */
        u32 src;
-       /* Specifies the destination memory location to where the data will
+       /*
+        * Specifies the destination memory location to where the data will
         * be transferred.
-       */
+        */
        u32 dest;
-       /* Specifies the number of bytes need to be transferred
-       * from source to destination memory.Transfer direction & IOC enable
-       */
+       /*
+        * Specifies the number of bytes need to be transferred
+        * from source to destination memory.Transfer direction & IOC enable
+        */
        u32 xfer_val;
        /* Reserved for future use */
        u32 reserved;
index dcee145dd17922ac2f81b2fb92a4085d3754e78d..64b784e96f844d3c77efe4eb8623dc3a23de2d20 100644 (file)
@@ -88,4 +88,13 @@ config SND_ATMEL_SOC_TSE850_PCM5142
        help
          Say Y if you want to add support for the ASoC driver for the
          Axentia TSE-850 with a PCM5142 codec.
+
+config SND_ATMEL_SOC_I2S
+       tristate "Atmel ASoC driver for boards using I2S"
+       depends on OF && (ARCH_AT91 || COMPILE_TEST)
+       select SND_SOC_GENERIC_DMAENGINE_PCM
+       select REGMAP_MMIO
+       help
+         Say Y or M if you want to add support for Atmel ASoc driver for boards
+         using I2S.
 endif
index 4440646416e8754271f25d365ea9f43cc4e9c17c..cd87cb4bcff51841a899cc583a6387e1cbf9a416 100644 (file)
@@ -3,10 +3,12 @@
 snd-soc-atmel-pcm-pdc-objs := atmel-pcm-pdc.o
 snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
 snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
+snd-soc-atmel-i2s-objs := atmel-i2s.o
 
 obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o
 obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o
 obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
+obj-$(CONFIG_SND_ATMEL_SOC_I2S) += snd-soc-atmel-i2s.o
 
 # AT91 Machine Support
 snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c
new file mode 100644 (file)
index 0000000..5d3b5af
--- /dev/null
@@ -0,0 +1,765 @@
+/*
+ * Driver for Atmel I2S controller
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen <cyrille.pitchen@atmel.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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
+
+#define ATMEL_I2SC_MAX_TDM_CHANNELS    8
+
+/*
+ * ---- I2S Controller Register map ----
+ */
+#define ATMEL_I2SC_CR          0x0000  /* Control Register */
+#define ATMEL_I2SC_MR          0x0004  /* Mode Register */
+#define ATMEL_I2SC_SR          0x0008  /* Status Register */
+#define ATMEL_I2SC_SCR         0x000c  /* Status Clear Register */
+#define ATMEL_I2SC_SSR         0x0010  /* Status Set Register */
+#define ATMEL_I2SC_IER         0x0014  /* Interrupt Enable Register */
+#define ATMEL_I2SC_IDR         0x0018  /* Interrupt Disable Register */
+#define ATMEL_I2SC_IMR         0x001c  /* Interrupt Mask Register */
+#define ATMEL_I2SC_RHR         0x0020  /* Receiver Holding Register */
+#define ATMEL_I2SC_THR         0x0024  /* Transmitter Holding Register */
+#define ATMEL_I2SC_VERSION     0x0028  /* Version Register */
+
+/*
+ * ---- Control Register (Write-only) ----
+ */
+#define ATMEL_I2SC_CR_RXEN     BIT(0)  /* Receiver Enable */
+#define ATMEL_I2SC_CR_RXDIS    BIT(1)  /* Receiver Disable */
+#define ATMEL_I2SC_CR_CKEN     BIT(2)  /* Clock Enable */
+#define ATMEL_I2SC_CR_CKDIS    BIT(3)  /* Clock Disable */
+#define ATMEL_I2SC_CR_TXEN     BIT(4)  /* Transmitter Enable */
+#define ATMEL_I2SC_CR_TXDIS    BIT(5)  /* Transmitter Disable */
+#define ATMEL_I2SC_CR_SWRST    BIT(7)  /* Software Reset */
+
+/*
+ * ---- Mode Register (Read/Write) ----
+ */
+#define ATMEL_I2SC_MR_MODE_MASK                GENMASK(0, 0)
+#define ATMEL_I2SC_MR_MODE_SLAVE       (0 << 0)
+#define ATMEL_I2SC_MR_MODE_MASTER      (1 << 0)
+
+#define ATMEL_I2SC_MR_DATALENGTH_MASK          GENMASK(4, 2)
+#define ATMEL_I2SC_MR_DATALENGTH_32_BITS       (0 << 2)
+#define ATMEL_I2SC_MR_DATALENGTH_24_BITS       (1 << 2)
+#define ATMEL_I2SC_MR_DATALENGTH_20_BITS       (2 << 2)
+#define ATMEL_I2SC_MR_DATALENGTH_18_BITS       (3 << 2)
+#define ATMEL_I2SC_MR_DATALENGTH_16_BITS       (4 << 2)
+#define ATMEL_I2SC_MR_DATALENGTH_16_BITS_COMPACT       (5 << 2)
+#define ATMEL_I2SC_MR_DATALENGTH_8_BITS                (6 << 2)
+#define ATMEL_I2SC_MR_DATALENGTH_8_BITS_COMPACT        (7 << 2)
+
+#define ATMEL_I2SC_MR_FORMAT_MASK      GENMASK(7, 6)
+#define ATMEL_I2SC_MR_FORMAT_I2S       (0 << 6)
+#define ATMEL_I2SC_MR_FORMAT_LJ                (1 << 6)  /* Left Justified */
+#define ATMEL_I2SC_MR_FORMAT_TDM       (2 << 6)
+#define ATMEL_I2SC_MR_FORMAT_TDMLJ     (3 << 6)
+
+/* Left audio samples duplicated to right audio channel */
+#define ATMEL_I2SC_MR_RXMONO           BIT(8)
+
+/* Receiver uses one DMA channel ... */
+#define ATMEL_I2SC_MR_RXDMA_MASK       GENMASK(9, 9)
+#define ATMEL_I2SC_MR_RXDMA_SINGLE     (0 << 9)  /* for all audio channels */
+#define ATMEL_I2SC_MR_RXDMA_MULTIPLE   (1 << 9)  /* per audio channel */
+
+/* I2SDO output of I2SC is internally connected to I2SDI input */
+#define ATMEL_I2SC_MR_RXLOOP           BIT(10)
+
+/* Left audio samples duplicated to right audio channel */
+#define ATMEL_I2SC_MR_TXMONO           BIT(12)
+
+/* Transmitter uses one DMA channel ... */
+#define ATMEL_I2SC_MR_TXDMA_MASK       GENMASK(13, 13)
+#define ATMEL_I2SC_MR_TXDMA_SINGLE     (0 << 13)  /* for all audio channels */
+#define ATMEL_I2SC_MR_TXDME_MULTIPLE   (1 << 13)  /* per audio channel */
+
+/* x sample transmitted when underrun */
+#define ATMEL_I2SC_MR_TXSAME_MASK      GENMASK(14, 14)
+#define ATMEL_I2SC_MR_TXSAME_ZERO      (0 << 14)  /* Zero sample */
+#define ATMEL_I2SC_MR_TXSAME_PREVIOUS  (1 << 14)  /* Previous sample */
+
+/* Audio Clock to I2SC Master Clock ratio */
+#define ATMEL_I2SC_MR_IMCKDIV_MASK     GENMASK(21, 16)
+#define ATMEL_I2SC_MR_IMCKDIV(div) \
+       (((div) << 16) & ATMEL_I2SC_MR_IMCKDIV_MASK)
+
+/* Master Clock to fs ratio */
+#define ATMEL_I2SC_MR_IMCKFS_MASK      GENMASK(29, 24)
+#define ATMEL_I2SC_MR_IMCKFS(fs) \
+       (((fs) << 24) & ATMEL_I2SC_MR_IMCKFS_MASK)
+
+/* Master Clock mode */
+#define ATMEL_I2SC_MR_IMCKMODE_MASK    GENMASK(30, 30)
+/* 0: No master clock generated (selected clock drives I2SCK pin) */
+#define ATMEL_I2SC_MR_IMCKMODE_I2SCK   (0 << 30)
+/* 1: master clock generated (internally generated clock drives I2SMCK pin) */
+#define ATMEL_I2SC_MR_IMCKMODE_I2SMCK  (1 << 30)
+
+/* Slot Width */
+/* 0: slot is 32 bits wide for DATALENGTH = 18/20/24 bits. */
+/* 1: slot is 24 bits wide for DATALENGTH = 18/20/24 bits. */
+#define ATMEL_I2SC_MR_IWS              BIT(31)
+
+/*
+ * ---- Status Registers ----
+ */
+#define ATMEL_I2SC_SR_RXEN     BIT(0)  /* Receiver Enabled */
+#define ATMEL_I2SC_SR_RXRDY    BIT(1)  /* Receive Ready */
+#define ATMEL_I2SC_SR_RXOR     BIT(2)  /* Receive Overrun */
+
+#define ATMEL_I2SC_SR_TXEN     BIT(4)  /* Transmitter Enabled */
+#define ATMEL_I2SC_SR_TXRDY    BIT(5)  /* Transmit Ready */
+#define ATMEL_I2SC_SR_TXUR     BIT(6)  /* Transmit Underrun */
+
+/* Receive Overrun Channel */
+#define ATMEL_I2SC_SR_RXORCH_MASK      GENMASK(15, 8)
+#define ATMEL_I2SC_SR_RXORCH(ch)       (1 << (((ch) & 0x7) + 8))
+
+/* Transmit Underrun Channel */
+#define ATMEL_I2SC_SR_TXURCH_MASK      GENMASK(27, 20)
+#define ATMEL_I2SC_SR_TXURCH(ch)       (1 << (((ch) & 0x7) + 20))
+
+/*
+ * ---- Interrupt Enable/Disable/Mask Registers ----
+ */
+#define ATMEL_I2SC_INT_RXRDY   ATMEL_I2SC_SR_RXRDY
+#define ATMEL_I2SC_INT_RXOR    ATMEL_I2SC_SR_RXOR
+#define ATMEL_I2SC_INT_TXRDY   ATMEL_I2SC_SR_TXRDY
+#define ATMEL_I2SC_INT_TXUR    ATMEL_I2SC_SR_TXUR
+
+static const struct regmap_config atmel_i2s_regmap_config = {
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .max_register = ATMEL_I2SC_VERSION,
+};
+
+struct atmel_i2s_gck_param {
+       int             fs;
+       unsigned long   mck;
+       int             imckdiv;
+       int             imckfs;
+};
+
+#define I2S_MCK_12M288         12288000UL
+#define I2S_MCK_11M2896                11289600UL
+
+/* mck = (32 * (imckfs+1) / (imckdiv+1)) * fs */
+static const struct atmel_i2s_gck_param gck_params[] = {
+       /* mck = 12.288MHz */
+       {  8000, I2S_MCK_12M288, 0, 47},        /* mck = 1536 fs */
+       { 16000, I2S_MCK_12M288, 1, 47},        /* mck =  768 fs */
+       { 24000, I2S_MCK_12M288, 3, 63},        /* mck =  512 fs */
+       { 32000, I2S_MCK_12M288, 3, 47},        /* mck =  384 fs */
+       { 48000, I2S_MCK_12M288, 7, 63},        /* mck =  256 fs */
+       { 64000, I2S_MCK_12M288, 7, 47},        /* mck =  192 fs */
+       { 96000, I2S_MCK_12M288, 7, 31},        /* mck =  128 fs */
+       {192000, I2S_MCK_12M288, 7, 15},        /* mck =   64 fs */
+
+       /* mck = 11.2896MHz */
+       { 11025, I2S_MCK_11M2896, 1, 63},       /* mck = 1024 fs */
+       { 22050, I2S_MCK_11M2896, 3, 63},       /* mck =  512 fs */
+       { 44100, I2S_MCK_11M2896, 7, 63},       /* mck =  256 fs */
+       { 88200, I2S_MCK_11M2896, 7, 31},       /* mck =  128 fs */
+       {176400, I2S_MCK_11M2896, 7, 15},       /* mck =   64 fs */
+};
+
+struct atmel_i2s_dev;
+
+struct atmel_i2s_caps {
+       int     (*mck_init)(struct atmel_i2s_dev *, struct device_node *np);
+};
+
+struct atmel_i2s_dev {
+       struct device                           *dev;
+       struct regmap                           *regmap;
+       struct clk                              *pclk;
+       struct clk                              *gclk;
+       struct clk                              *aclk;
+       struct snd_dmaengine_dai_dma_data       playback;
+       struct snd_dmaengine_dai_dma_data       capture;
+       unsigned int                            fmt;
+       const struct atmel_i2s_gck_param        *gck_param;
+       const struct atmel_i2s_caps             *caps;
+};
+
+static irqreturn_t atmel_i2s_interrupt(int irq, void *dev_id)
+{
+       struct atmel_i2s_dev *dev = dev_id;
+       unsigned int sr, imr, pending, ch, mask;
+       irqreturn_t ret = IRQ_NONE;
+
+       regmap_read(dev->regmap, ATMEL_I2SC_SR, &sr);
+       regmap_read(dev->regmap, ATMEL_I2SC_IMR, &imr);
+       pending = sr & imr;
+
+       if (!pending)
+               return IRQ_NONE;
+
+       if (pending & ATMEL_I2SC_INT_RXOR) {
+               mask = ATMEL_I2SC_SR_RXOR;
+
+               for (ch = 0; ch < ATMEL_I2SC_MAX_TDM_CHANNELS; ++ch) {
+                       if (sr & ATMEL_I2SC_SR_RXORCH(ch)) {
+                               mask |= ATMEL_I2SC_SR_RXORCH(ch);
+                               dev_err(dev->dev,
+                                       "RX overrun on channel %d\n", ch);
+                       }
+               }
+               regmap_write(dev->regmap, ATMEL_I2SC_SCR, mask);
+               ret = IRQ_HANDLED;
+       }
+
+       if (pending & ATMEL_I2SC_INT_TXUR) {
+               mask = ATMEL_I2SC_SR_TXUR;
+
+               for (ch = 0; ch < ATMEL_I2SC_MAX_TDM_CHANNELS; ++ch) {
+                       if (sr & ATMEL_I2SC_SR_TXURCH(ch)) {
+                               mask |= ATMEL_I2SC_SR_TXURCH(ch);
+                               dev_err(dev->dev,
+                                       "TX underrun on channel %d\n", ch);
+                       }
+               }
+               regmap_write(dev->regmap, ATMEL_I2SC_SCR, mask);
+               ret = IRQ_HANDLED;
+       }
+
+       return ret;
+}
+
+#define ATMEL_I2S_RATES                SNDRV_PCM_RATE_8000_192000
+
+#define ATMEL_I2S_FORMATS      (SNDRV_PCM_FMTBIT_S8 |          \
+                                SNDRV_PCM_FMTBIT_S16_LE |      \
+                                SNDRV_PCM_FMTBIT_S18_3LE |     \
+                                SNDRV_PCM_FMTBIT_S20_3LE |     \
+                                SNDRV_PCM_FMTBIT_S24_3LE |     \
+                                SNDRV_PCM_FMTBIT_S24_LE |      \
+                                SNDRV_PCM_FMTBIT_S32_LE)
+
+static int atmel_i2s_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       dev->fmt = fmt;
+       return 0;
+}
+
+static int atmel_i2s_prepare(struct snd_pcm_substream *substream,
+                            struct snd_soc_dai *dai)
+{
+       struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+       bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       unsigned int rhr, sr = 0;
+
+       if (is_playback) {
+               regmap_read(dev->regmap, ATMEL_I2SC_SR, &sr);
+               if (sr & ATMEL_I2SC_SR_RXRDY) {
+                       /*
+                        * The RX Ready flag should not be set. However if here,
+                        * we flush (read) the Receive Holding Register to start
+                        * from a clean state.
+                        */
+                       dev_dbg(dev->dev, "RXRDY is set\n");
+                       regmap_read(dev->regmap, ATMEL_I2SC_RHR, &rhr);
+               }
+       }
+
+       return 0;
+}
+
+static int atmel_i2s_get_gck_param(struct atmel_i2s_dev *dev, int fs)
+{
+       int i, best;
+
+       if (!dev->gclk || !dev->aclk) {
+               dev_err(dev->dev, "cannot generate the I2S Master Clock\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Find the best possible settings to generate the I2S Master Clock
+        * from the PLL Audio.
+        */
+       dev->gck_param = NULL;
+       best = INT_MAX;
+       for (i = 0; i < ARRAY_SIZE(gck_params); ++i) {
+               const struct atmel_i2s_gck_param *gck_param = &gck_params[i];
+               int val = abs(fs - gck_param->fs);
+
+               if (val < best) {
+                       best = val;
+                       dev->gck_param = gck_param;
+               }
+       }
+
+       return 0;
+}
+
+static int atmel_i2s_hw_params(struct snd_pcm_substream *substream,
+                              struct snd_pcm_hw_params *params,
+                              struct snd_soc_dai *dai)
+{
+       struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+       bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       unsigned int mr = 0;
+       int ret;
+
+       switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               mr |= ATMEL_I2SC_MR_FORMAT_I2S;
+               break;
+
+       default:
+               dev_err(dev->dev, "unsupported bus format\n");
+               return -EINVAL;
+       }
+
+       switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               /* codec is slave, so cpu is master */
+               mr |= ATMEL_I2SC_MR_MODE_MASTER;
+               ret = atmel_i2s_get_gck_param(dev, params_rate(params));
+               if (ret)
+                       return ret;
+               break;
+
+       case SND_SOC_DAIFMT_CBM_CFM:
+               /* codec is master, so cpu is slave */
+               mr |= ATMEL_I2SC_MR_MODE_SLAVE;
+               dev->gck_param = NULL;
+               break;
+
+       default:
+               dev_err(dev->dev, "unsupported master/slave mode\n");
+               return -EINVAL;
+       }
+
+       switch (params_channels(params)) {
+       case 1:
+               if (is_playback)
+                       mr |= ATMEL_I2SC_MR_TXMONO;
+               else
+                       mr |= ATMEL_I2SC_MR_RXMONO;
+               break;
+       case 2:
+               break;
+       default:
+               dev_err(dev->dev, "unsupported number of audio channels\n");
+               return -EINVAL;
+       }
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S8:
+               mr |= ATMEL_I2SC_MR_DATALENGTH_8_BITS;
+               break;
+
+       case SNDRV_PCM_FORMAT_S16_LE:
+               mr |= ATMEL_I2SC_MR_DATALENGTH_16_BITS;
+               break;
+
+       case SNDRV_PCM_FORMAT_S18_3LE:
+               mr |= ATMEL_I2SC_MR_DATALENGTH_18_BITS | ATMEL_I2SC_MR_IWS;
+               break;
+
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               mr |= ATMEL_I2SC_MR_DATALENGTH_20_BITS | ATMEL_I2SC_MR_IWS;
+               break;
+
+       case SNDRV_PCM_FORMAT_S24_3LE:
+               mr |= ATMEL_I2SC_MR_DATALENGTH_24_BITS | ATMEL_I2SC_MR_IWS;
+               break;
+
+       case SNDRV_PCM_FORMAT_S24_LE:
+               mr |= ATMEL_I2SC_MR_DATALENGTH_24_BITS;
+               break;
+
+       case SNDRV_PCM_FORMAT_S32_LE:
+               mr |= ATMEL_I2SC_MR_DATALENGTH_32_BITS;
+               break;
+
+       default:
+               dev_err(dev->dev, "unsupported size/endianness for audio samples\n");
+               return -EINVAL;
+       }
+
+       return regmap_write(dev->regmap, ATMEL_I2SC_MR, mr);
+}
+
+static int atmel_i2s_switch_mck_generator(struct atmel_i2s_dev *dev,
+                                         bool enabled)
+{
+       unsigned int mr, mr_mask;
+       unsigned long aclk_rate;
+       int ret;
+
+       mr = 0;
+       mr_mask = (ATMEL_I2SC_MR_IMCKDIV_MASK |
+                  ATMEL_I2SC_MR_IMCKFS_MASK |
+                  ATMEL_I2SC_MR_IMCKMODE_MASK);
+
+       if (!enabled) {
+               /* Disable the I2S Master Clock generator. */
+               ret = regmap_write(dev->regmap, ATMEL_I2SC_CR,
+                                  ATMEL_I2SC_CR_CKDIS);
+               if (ret)
+                       return ret;
+
+               /* Reset the I2S Master Clock generator settings. */
+               ret = regmap_update_bits(dev->regmap, ATMEL_I2SC_MR,
+                                        mr_mask, mr);
+               if (ret)
+                       return ret;
+
+               /* Disable/unprepare the PMC generated clock. */
+               clk_disable_unprepare(dev->gclk);
+
+               /* Disable/unprepare the PLL audio clock. */
+               clk_disable_unprepare(dev->aclk);
+               return 0;
+       }
+
+       if (!dev->gck_param)
+               return -EINVAL;
+
+       aclk_rate = dev->gck_param->mck * (dev->gck_param->imckdiv + 1);
+
+       /* Fist change the PLL audio clock frequency ... */
+       ret = clk_set_rate(dev->aclk, aclk_rate);
+       if (ret)
+               return ret;
+
+       /*
+        * ... then set the PMC generated clock rate to the very same frequency
+        * to set the gclk parent to aclk.
+        */
+       ret = clk_set_rate(dev->gclk, aclk_rate);
+       if (ret)
+               return ret;
+
+       /* Prepare and enable the PLL audio clock first ... */
+       ret = clk_prepare_enable(dev->aclk);
+       if (ret)
+               return ret;
+
+       /* ... then prepare and enable the PMC generated clock. */
+       ret = clk_prepare_enable(dev->gclk);
+       if (ret)
+               return ret;
+
+       /* Update the Mode Register to generate the I2S Master Clock. */
+       mr |= ATMEL_I2SC_MR_IMCKDIV(dev->gck_param->imckdiv);
+       mr |= ATMEL_I2SC_MR_IMCKFS(dev->gck_param->imckfs);
+       mr |= ATMEL_I2SC_MR_IMCKMODE_I2SMCK;
+       ret = regmap_update_bits(dev->regmap, ATMEL_I2SC_MR, mr_mask, mr);
+       if (ret)
+               return ret;
+
+       /* Finally enable the I2S Master Clock generator. */
+       return regmap_write(dev->regmap, ATMEL_I2SC_CR,
+                           ATMEL_I2SC_CR_CKEN);
+}
+
+static int atmel_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+                            struct snd_soc_dai *dai)
+{
+       struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+       bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       bool is_master, mck_enabled;
+       unsigned int cr, mr;
+       int err;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               cr = is_playback ? ATMEL_I2SC_CR_TXEN : ATMEL_I2SC_CR_RXEN;
+               mck_enabled = true;
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               cr = is_playback ? ATMEL_I2SC_CR_TXDIS : ATMEL_I2SC_CR_RXDIS;
+               mck_enabled = false;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Read the Mode Register to retrieve the master/slave state. */
+       err = regmap_read(dev->regmap, ATMEL_I2SC_MR, &mr);
+       if (err)
+               return err;
+       is_master = (mr & ATMEL_I2SC_MR_MODE_MASK) == ATMEL_I2SC_MR_MODE_MASTER;
+
+       /* If master starts, enable the audio clock. */
+       if (is_master && mck_enabled)
+               err = atmel_i2s_switch_mck_generator(dev, true);
+       if (err)
+               return err;
+
+       err = regmap_write(dev->regmap, ATMEL_I2SC_CR, cr);
+       if (err)
+               return err;
+
+       /* If master stops, disable the audio clock. */
+       if (is_master && !mck_enabled)
+               err = atmel_i2s_switch_mck_generator(dev, false);
+
+       return err;
+}
+
+static const struct snd_soc_dai_ops atmel_i2s_dai_ops = {
+       .prepare        = atmel_i2s_prepare,
+       .trigger        = atmel_i2s_trigger,
+       .hw_params      = atmel_i2s_hw_params,
+       .set_fmt        = atmel_i2s_set_dai_fmt,
+};
+
+static int atmel_i2s_dai_probe(struct snd_soc_dai *dai)
+{
+       struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_init_dma_data(dai, &dev->playback, &dev->capture);
+       return 0;
+}
+
+static struct snd_soc_dai_driver atmel_i2s_dai = {
+       .probe  = atmel_i2s_dai_probe,
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = ATMEL_I2S_RATES,
+               .formats = ATMEL_I2S_FORMATS,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = ATMEL_I2S_RATES,
+               .formats = ATMEL_I2S_FORMATS,
+       },
+       .ops = &atmel_i2s_dai_ops,
+       .symmetric_rates = 1,
+};
+
+static const struct snd_soc_component_driver atmel_i2s_component = {
+       .name   = "atmel-i2s",
+};
+
+static int atmel_i2s_sama5d2_mck_init(struct atmel_i2s_dev *dev,
+                                     struct device_node *np)
+{
+       struct clk *muxclk;
+       int err;
+
+       if (!dev->gclk)
+               return 0;
+
+       /* muxclk is optional, so we return error for probe defer only */
+       muxclk = devm_clk_get(dev->dev, "muxclk");
+       if (IS_ERR(muxclk)) {
+               err = PTR_ERR(muxclk);
+               if (err == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+               dev_warn(dev->dev,
+                        "failed to get the I2S clock control: %d\n", err);
+               return 0;
+       }
+
+       return clk_set_parent(muxclk, dev->gclk);
+}
+
+static const struct atmel_i2s_caps atmel_i2s_sama5d2_caps = {
+       .mck_init = atmel_i2s_sama5d2_mck_init,
+};
+
+static const struct of_device_id atmel_i2s_dt_ids[] = {
+       {
+               .compatible = "atmel,sama5d2-i2s",
+               .data = (void *)&atmel_i2s_sama5d2_caps,
+       },
+
+       { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, atmel_i2s_dt_ids);
+
+static int atmel_i2s_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       const struct of_device_id *match;
+       struct atmel_i2s_dev *dev;
+       struct resource *mem;
+       struct regmap *regmap;
+       void __iomem *base;
+       int irq;
+       int err = -ENXIO;
+       unsigned int pcm_flags = 0;
+       unsigned int version;
+
+       /* Get memory for driver data. */
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       /* Get hardware capabilities. */
+       match = of_match_node(atmel_i2s_dt_ids, np);
+       if (match)
+               dev->caps = match->data;
+
+       /* Map I/O registers. */
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(&pdev->dev, mem);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap = devm_regmap_init_mmio(&pdev->dev, base,
+                                      &atmel_i2s_regmap_config);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
+       /* Request IRQ. */
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+
+       err = devm_request_irq(&pdev->dev, irq, atmel_i2s_interrupt, 0,
+                              dev_name(&pdev->dev), dev);
+       if (err)
+               return err;
+
+       /* Get the peripheral clock. */
+       dev->pclk = devm_clk_get(&pdev->dev, "pclk");
+       if (IS_ERR(dev->pclk)) {
+               err = PTR_ERR(dev->pclk);
+               dev_err(&pdev->dev,
+                       "failed to get the peripheral clock: %d\n", err);
+               return err;
+       }
+
+       /* Get audio clocks to generate the I2S Master Clock (I2S_MCK) */
+       dev->aclk = devm_clk_get(&pdev->dev, "aclk");
+       dev->gclk = devm_clk_get(&pdev->dev, "gclk");
+       if (IS_ERR(dev->aclk) && IS_ERR(dev->gclk)) {
+               if (PTR_ERR(dev->aclk) == -EPROBE_DEFER ||
+                   PTR_ERR(dev->gclk) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+               /* Master Mode not supported */
+               dev->aclk = NULL;
+               dev->gclk = NULL;
+       } else if (IS_ERR(dev->gclk)) {
+               err = PTR_ERR(dev->gclk);
+               dev_err(&pdev->dev,
+                       "failed to get the PMC generated clock: %d\n", err);
+               return err;
+       } else if (IS_ERR(dev->aclk)) {
+               err = PTR_ERR(dev->aclk);
+               dev_err(&pdev->dev,
+                       "failed to get the PLL audio clock: %d\n", err);
+               return err;
+       }
+
+       dev->dev = &pdev->dev;
+       dev->regmap = regmap;
+       platform_set_drvdata(pdev, dev);
+
+       /* Do hardware specific settings to initialize I2S_MCK generator */
+       if (dev->caps && dev->caps->mck_init) {
+               err = dev->caps->mck_init(dev, np);
+               if (err)
+                       return err;
+       }
+
+       /* Enable the peripheral clock. */
+       err = clk_prepare_enable(dev->pclk);
+       if (err)
+               return err;
+
+       /* Get IP version. */
+       regmap_read(dev->regmap, ATMEL_I2SC_VERSION, &version);
+       dev_info(&pdev->dev, "hw version: %#x\n", version);
+
+       /* Enable error interrupts. */
+       regmap_write(dev->regmap, ATMEL_I2SC_IER,
+                    ATMEL_I2SC_INT_RXOR | ATMEL_I2SC_INT_TXUR);
+
+       err = devm_snd_soc_register_component(&pdev->dev,
+                                             &atmel_i2s_component,
+                                             &atmel_i2s_dai, 1);
+       if (err) {
+               dev_err(&pdev->dev, "failed to register DAI: %d\n", err);
+               clk_disable_unprepare(dev->pclk);
+               return err;
+       }
+
+       /* Prepare DMA config. */
+       dev->playback.addr      = (dma_addr_t)mem->start + ATMEL_I2SC_THR;
+       dev->playback.maxburst  = 1;
+       dev->capture.addr       = (dma_addr_t)mem->start + ATMEL_I2SC_RHR;
+       dev->capture.maxburst   = 1;
+
+       if (of_property_match_string(np, "dma-names", "rx-tx") == 0)
+               pcm_flags |= SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX;
+       err = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, pcm_flags);
+       if (err) {
+               dev_err(&pdev->dev, "failed to register PCM: %d\n", err);
+               clk_disable_unprepare(dev->pclk);
+               return err;
+       }
+
+       return 0;
+}
+
+static int atmel_i2s_remove(struct platform_device *pdev)
+{
+       struct atmel_i2s_dev *dev = platform_get_drvdata(pdev);
+
+       clk_disable_unprepare(dev->pclk);
+
+       return 0;
+}
+
+static struct platform_driver atmel_i2s_driver = {
+       .driver         = {
+               .name   = "atmel_i2s",
+               .of_match_table = of_match_ptr(atmel_i2s_dt_ids),
+       },
+       .probe          = atmel_i2s_probe,
+       .remove         = atmel_i2s_remove,
+};
+module_platform_driver(atmel_i2s_driver);
+
+MODULE_DESCRIPTION("Atmel I2S Controller driver");
+MODULE_AUTHOR("Cyrille Pitchen <cyrille.pitchen@atmel.com>");
+MODULE_LICENSE("GPL v2");
index a1e2c5682dcda82b5c04566f6d773659dcc4bb47..d3b69682d9c2244ac9699361fa1e887e346e33e9 100644 (file)
@@ -820,7 +820,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
                if (ret < 0) {
                        printk(KERN_WARNING
                                        "atmel_ssc_dai: request_irq failure\n");
-                       pr_debug("Atmel_ssc_dai: Stoping clock\n");
+                       pr_debug("Atmel_ssc_dai: Stopping clock\n");
                        clk_disable(ssc_p->ssc->clk);
                        return ret;
                }
@@ -1002,8 +1002,7 @@ static const struct snd_soc_component_driver atmel_ssc_component = {
 
 static int asoc_ssc_init(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct ssc_device *ssc = platform_get_drvdata(pdev);
+       struct ssc_device *ssc = dev_get_drvdata(dev);
        int ret;
 
        ret = snd_soc_register_component(dev, &atmel_ssc_component,
@@ -1033,8 +1032,7 @@ err:
 
 static void asoc_ssc_exit(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct ssc_device *ssc = platform_get_drvdata(pdev);
+       struct ssc_device *ssc = dev_get_drvdata(dev);
 
        if (ssc->pdata->use_dma)
                atmel_pcm_dma_platform_unregister(dev);
index edf367100ebd2f1701f4a32b2bfcc14b6cf978d3..02f50b7a966ff262b5318d96887376aab0fa01e8 100644 (file)
@@ -11,9 +11,8 @@ config SND_BCM2835_SOC_I2S
 config SND_SOC_CYGNUS
        tristate "SoC platform audio for Broadcom Cygnus chips"
        depends on ARCH_BCM_CYGNUS || COMPILE_TEST
-       depends on HAS_DMA
        help
          Say Y if you want to add support for ASoC audio on Broadcom
          Cygnus chips (bcm958300, bcm958305, bcm911360)
 
-         If you don't know what to do here, say N.
\ No newline at end of file
+         If you don't know what to do here, say N.
index c7cd60f009e93e69ef2220eec3eb6ec97a9e6500..e09199124c36f208894e8b4a90d38ed82d2f4025 100644 (file)
@@ -9,6 +9,23 @@ config SND_EP93XX_SOC
 config SND_EP93XX_SOC_I2S
        tristate
 
+if SND_EP93XX_SOC_I2S
+
+config SND_EP93XX_SOC_I2S_WATCHDOG
+       bool "IRQ based underflow watchdog workaround"
+       default y
+       help
+         I2S controller on EP93xx seems to have undocumented HW issue.
+         Underflow of internal I2S controller FIFO could confuse the
+         state machine and the whole stream can be shifted by one byte
+         until I2S is disabled. This option enables IRQ based watchdog
+         which disables and re-enables I2S in case of underflow and
+         fills FIFO with zeroes.
+
+         If you are unsure how to answer this question, answer Y.
+
+endif # if SND_EP93XX_SOC_I2S
+
 config SND_EP93XX_SOC_AC97
        tristate
        select AC97_BUS
index c53bd6f2c2d7f6179420c0f6db37b8d1b41c1838..3d011abaa2660a7cc92b4690006c107352862007 100644 (file)
@@ -67,7 +67,7 @@ static struct snd_soc_dai_link edb93xx_dai = {
        .cpu_dai_name   = "ep93xx-i2s",
        .codec_name     = "spi0.0",
        .codec_dai_name = "cs4271-hifi",
-       .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
+       .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
                          SND_SOC_DAIFMT_CBS_CFS,
        .ops            = &edb93xx_ops,
 };
index 934f8aefdd90b8f94beda83dc82393d4091e4aec..0918c5da575aba1feedb4cf73f23cbdc7d380940 100644 (file)
 
 #define EP93XX_I2S_TXCLKCFG            0x00
 #define EP93XX_I2S_RXCLKCFG            0x04
+#define EP93XX_I2S_GLSTS               0x08
 #define EP93XX_I2S_GLCTRL              0x0C
 
+#define EP93XX_I2S_I2STX0LFT           0x10
+#define EP93XX_I2S_I2STX0RT            0x14
+
 #define EP93XX_I2S_TXLINCTRLDATA       0x28
 #define EP93XX_I2S_TXCTRL              0x2C
 #define EP93XX_I2S_TXWRDLEN            0x30
 #define EP93XX_I2S_WRDLEN_24           (1 << 0)
 #define EP93XX_I2S_WRDLEN_32           (2 << 0)
 
-#define EP93XX_I2S_LINCTRLDATA_R_JUST  (1 << 2) /* Right justify */
+#define EP93XX_I2S_RXLINCTRLDATA_R_JUST        BIT(1) /* Right justify */
+
+#define EP93XX_I2S_TXLINCTRLDATA_R_JUST        BIT(2) /* Right justify */
+
+/*
+ * Transmit empty interrupt level select:
+ * 0 - Generate interrupt when FIFO is half empty
+ * 1 - Generate interrupt when FIFO is empty
+ */
+#define EP93XX_I2S_TXCTRL_TXEMPTY_LVL  BIT(0)
+#define EP93XX_I2S_TXCTRL_TXUFIE       BIT(1) /* Transmit interrupt enable */
 
 #define EP93XX_I2S_CLKCFG_LRS          (1 << 0) /* lrclk polarity */
 #define EP93XX_I2S_CLKCFG_CKP          (1 << 1) /* Bit clock polarity */
@@ -59,6 +73,8 @@
 #define EP93XX_I2S_CLKCFG_MASTER       (1 << 3) /* Master mode */
 #define EP93XX_I2S_CLKCFG_NBCG         (1 << 4) /* Not bit clock gating */
 
+#define EP93XX_I2S_GLSTS_TX0_FIFO_FULL BIT(12)
+
 struct ep93xx_i2s_info {
        struct clk                      *mclk;
        struct clk                      *sclk;
@@ -96,7 +112,6 @@ static inline unsigned ep93xx_i2s_read_reg(struct ep93xx_i2s_info *info,
 static void ep93xx_i2s_enable(struct ep93xx_i2s_info *info, int stream)
 {
        unsigned base_reg;
-       int i;
 
        if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 &&
            (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) {
@@ -109,27 +124,36 @@ static void ep93xx_i2s_enable(struct ep93xx_i2s_info *info, int stream)
                ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 1);
        }
 
-       /* Enable fifos */
+       /* Enable fifo */
        if (stream == SNDRV_PCM_STREAM_PLAYBACK)
                base_reg = EP93XX_I2S_TX0EN;
        else
                base_reg = EP93XX_I2S_RX0EN;
-       for (i = 0; i < 3; i++)
-               ep93xx_i2s_write_reg(info, base_reg + (i * 4), 1);
+       ep93xx_i2s_write_reg(info, base_reg, 1);
+
+       /* Enable TX IRQs (FIFO empty or underflow) */
+       if (IS_ENABLED(CONFIG_SND_EP93XX_SOC_I2S_WATCHDOG) &&
+           stream == SNDRV_PCM_STREAM_PLAYBACK)
+               ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCTRL,
+                                    EP93XX_I2S_TXCTRL_TXEMPTY_LVL |
+                                    EP93XX_I2S_TXCTRL_TXUFIE);
 }
 
 static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream)
 {
        unsigned base_reg;
-       int i;
 
-       /* Disable fifos */
+       /* Disable IRQs */
+       if (IS_ENABLED(CONFIG_SND_EP93XX_SOC_I2S_WATCHDOG) &&
+           stream == SNDRV_PCM_STREAM_PLAYBACK)
+               ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCTRL, 0);
+
+       /* Disable fifo */
        if (stream == SNDRV_PCM_STREAM_PLAYBACK)
                base_reg = EP93XX_I2S_TX0EN;
        else
                base_reg = EP93XX_I2S_RX0EN;
-       for (i = 0; i < 3; i++)
-               ep93xx_i2s_write_reg(info, base_reg + (i * 4), 0);
+       ep93xx_i2s_write_reg(info, base_reg, 0);
 
        if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 &&
            (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) {
@@ -143,6 +167,37 @@ static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream)
        }
 }
 
+/*
+ * According to documentation I2S controller can handle underflow conditions
+ * just fine, but in reality the state machine is sometimes confused so that
+ * the whole stream is shifted by one byte. The watchdog below disables the TX
+ * FIFO, fills the buffer with zeroes and re-enables the FIFO. State machine
+ * is being reset and by filling the buffer we get some time before next
+ * underflow happens.
+ */
+static irqreturn_t ep93xx_i2s_interrupt(int irq, void *dev_id)
+{
+       struct ep93xx_i2s_info *info = dev_id;
+
+       /* Disable FIFO */
+       ep93xx_i2s_write_reg(info, EP93XX_I2S_TX0EN, 0);
+       /*
+        * Fill TX FIFO with zeroes, this way we can defer next IRQs as much as
+        * possible and get more time for DMA to catch up. Actually there are
+        * only 8 samples in this FIFO, so even on 8kHz maximum deferral here is
+        * 1ms.
+        */
+       while (!(ep93xx_i2s_read_reg(info, EP93XX_I2S_GLSTS) &
+                EP93XX_I2S_GLSTS_TX0_FIFO_FULL)) {
+               ep93xx_i2s_write_reg(info, EP93XX_I2S_I2STX0LFT, 0);
+               ep93xx_i2s_write_reg(info, EP93XX_I2S_I2STX0RT, 0);
+       }
+       /* Re-enable FIFO */
+       ep93xx_i2s_write_reg(info, EP93XX_I2S_TX0EN, 1);
+
+       return IRQ_HANDLED;
+}
+
 static int ep93xx_i2s_dai_probe(struct snd_soc_dai *dai)
 {
        struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
@@ -170,25 +225,25 @@ static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                                  unsigned int fmt)
 {
        struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
-       unsigned int clk_cfg, lin_ctrl;
+       unsigned int clk_cfg;
+       unsigned int txlin_ctrl = 0;
+       unsigned int rxlin_ctrl = 0;
 
        clk_cfg  = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG);
-       lin_ctrl = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXLINCTRLDATA);
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
                clk_cfg |= EP93XX_I2S_CLKCFG_REL;
-               lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST;
                break;
 
        case SND_SOC_DAIFMT_LEFT_J:
                clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
-               lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST;
                break;
 
        case SND_SOC_DAIFMT_RIGHT_J:
                clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
-               lin_ctrl |= EP93XX_I2S_LINCTRLDATA_R_JUST;
+               rxlin_ctrl |= EP93XX_I2S_RXLINCTRLDATA_R_JUST;
+               txlin_ctrl |= EP93XX_I2S_TXLINCTRLDATA_R_JUST;
                break;
 
        default:
@@ -213,32 +268,32 @@ static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
                /* Negative bit clock, lrclk low on left word */
-               clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL);
+               clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_LRS);
                break;
 
        case SND_SOC_DAIFMT_NB_IF:
                /* Negative bit clock, lrclk low on right word */
                clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP;
-               clk_cfg |= EP93XX_I2S_CLKCFG_REL;
+               clk_cfg |= EP93XX_I2S_CLKCFG_LRS;
                break;
 
        case SND_SOC_DAIFMT_IB_NF:
                /* Positive bit clock, lrclk low on left word */
                clk_cfg |= EP93XX_I2S_CLKCFG_CKP;
-               clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
+               clk_cfg &= ~EP93XX_I2S_CLKCFG_LRS;
                break;
 
        case SND_SOC_DAIFMT_IB_IF:
                /* Positive bit clock, lrclk low on right word */
-               clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL;
+               clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_LRS;
                break;
        }
 
        /* Write new register values */
        ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg);
        ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg);
-       ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, lin_ctrl);
-       ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, lin_ctrl);
+       ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, rxlin_ctrl);
+       ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, txlin_ctrl);
        return 0;
 }
 
@@ -392,6 +447,17 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
        if (IS_ERR(info->regs))
                return PTR_ERR(info->regs);
 
+       if (IS_ENABLED(CONFIG_SND_EP93XX_SOC_I2S_WATCHDOG)) {
+               int irq = platform_get_irq(pdev, 0);
+               if (irq <= 0)
+                       return irq < 0 ? irq : -ENODEV;
+
+               err = devm_request_irq(&pdev->dev, irq, ep93xx_i2s_interrupt, 0,
+                                      pdev->name, info);
+               if (err)
+                       return err;
+       }
+
        info->mclk = clk_get(&pdev->dev, "mclk");
        if (IS_ERR(info->mclk)) {
                err = PTR_ERR(info->mclk);
index 2334ec19e7ebb74d4e9b60db5fe37bb4abf6a10f..11ff7b2672b2250318ea17652054619bb7fb897f 100644 (file)
@@ -72,7 +72,7 @@ static struct snd_soc_dai_link snappercl15_dai = {
        .codec_dai_name = "tlv320aic23-hifi",
        .codec_name     = "tlv320aic23-codec.0-001a",
        .platform_name  = "ep93xx-i2s",
-       .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
+       .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
                          SND_SOC_DAIFMT_CBS_CFS,
        .ops            = &snappercl15_ops,
 };
index 9548f63ca531c89ec682819e22d5b34584df7f0b..63cf62e9c9aa67733908f4011c30482b09e72457 100644 (file)
@@ -106,6 +106,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_MAX9877 if I2C
        select SND_SOC_MC13783 if MFD_MC13XXX
        select SND_SOC_ML26124 if I2C
+       select SND_SOC_MT6351 if MTK_PMIC_WRAP
        select SND_SOC_NAU8540 if I2C
        select SND_SOC_NAU8810 if I2C
        select SND_SOC_NAU8824 if I2C
@@ -126,6 +127,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_RT274 if I2C
        select SND_SOC_RT286 if I2C
        select SND_SOC_RT298 if I2C
+       select SND_SOC_RT1305 if I2C
        select SND_SOC_RT5514 if I2C
        select SND_SOC_RT5616 if I2C
        select SND_SOC_RT5631 if I2C
@@ -136,12 +138,14 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_RT5660 if I2C
        select SND_SOC_RT5663 if I2C
        select SND_SOC_RT5665 if I2C
+       select SND_SOC_RT5668 if I2C
        select SND_SOC_RT5670 if I2C
        select SND_SOC_RT5677 if I2C && SPI_MASTER
        select SND_SOC_SGTL5000 if I2C
        select SND_SOC_SI476X if MFD_SI476X_CORE
        select SND_SOC_SIRF_AUDIO_CODEC
        select SND_SOC_SPDIF
+       select SND_SOC_SSM2305
        select SND_SOC_SSM2518 if I2C
        select SND_SOC_SSM2602_SPI if SPI_MASTER
        select SND_SOC_SSM2602_I2C if I2C
@@ -168,6 +172,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_TPA6130A2 if I2C
        select SND_SOC_TLV320DAC33 if I2C
        select SND_SOC_TSCS42XX if I2C
+       select SND_SOC_TSCS454 if I2C
        select SND_SOC_TS3A227E if I2C
        select SND_SOC_TWL4030 if TWL4030_CORE
        select SND_SOC_TWL6040 if TWL6040_CORE
@@ -770,8 +775,10 @@ config SND_SOC_RL6231
        default y if SND_SOC_RT5660=y
        default y if SND_SOC_RT5663=y
        default y if SND_SOC_RT5665=y
+       default y if SND_SOC_RT5668=y
        default y if SND_SOC_RT5670=y
        default y if SND_SOC_RT5677=y
+       default y if SND_SOC_RT1305=y
        default m if SND_SOC_RT5514=m
        default m if SND_SOC_RT5616=m
        default m if SND_SOC_RT5640=m
@@ -781,8 +788,10 @@ config SND_SOC_RL6231
        default m if SND_SOC_RT5660=m
        default m if SND_SOC_RT5663=m
        default m if SND_SOC_RT5665=m
+       default m if SND_SOC_RT5668=m
        default m if SND_SOC_RT5670=m
        default m if SND_SOC_RT5677=m
+       default m if SND_SOC_RT1305=m
 
 config SND_SOC_RL6347A
        tristate
@@ -805,6 +814,9 @@ config SND_SOC_RT298
        tristate
        depends on I2C
 
+config SND_SOC_RT1305
+       tristate
+
 config SND_SOC_RT5514
        tristate
 
@@ -844,6 +856,9 @@ config SND_SOC_RT5663
 config SND_SOC_RT5665
        tristate
 
+config SND_SOC_RT5668
+       tristate
+
 config SND_SOC_RT5670
        tristate
 
@@ -883,6 +898,12 @@ config SND_SOC_SIRF_AUDIO_CODEC
 config SND_SOC_SPDIF
        tristate "S/PDIF CODEC"
 
+config SND_SOC_SSM2305
+       tristate "Analog Devices SSM2305 Class-D Amplifier"
+       help
+         Enable support for Analog Devices SSM2305 filterless
+         high-efficiency mono Class-D audio power amplifiers.
+
 config SND_SOC_SSM2518
        tristate
 
@@ -1011,6 +1032,13 @@ config SND_SOC_TSCS42XX
        help
          Add support for Tempo Semiconductor's TSCS42xx audio CODEC.
 
+config SND_SOC_TSCS454
+       tristate "Tempo Semiconductor TSCS454 CODEC"
+       depends on I2C
+       select REGMAP_I2C
+       help
+         Add support for Tempo Semiconductor's TSCS454 audio CODEC.
+
 config SND_SOC_TWL4030
        select MFD_TWL4030_AUDIO
        tristate
@@ -1111,7 +1139,7 @@ config SND_SOC_WM8776
        depends on SND_SOC_I2C_AND_SPI
 
 config SND_SOC_WM8782
-       tristate
+       tristate "Wolfson Microelectronics WM8782 ADC"
 
 config SND_SOC_WM8804
        tristate
@@ -1247,6 +1275,9 @@ config SND_SOC_MC13783
 config SND_SOC_ML26124
        tristate
 
+config SND_SOC_MT6351
+       tristate "MediaTek MT6351 Codec"
+
 config SND_SOC_NAU8540
        tristate "Nuvoton Technology Corporation NAU85L40 CODEC"
        depends on I2C
index e849d1495308f96acc49417a5b0fbfcba1975b93..e023fdf852215dea0e27bb5a9e2f7ac97e26a003 100644 (file)
@@ -102,6 +102,7 @@ snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
 snd-soc-msm8916-analog-objs := msm8916-wcd-analog.o
 snd-soc-msm8916-digital-objs := msm8916-wcd-digital.o
+snd-soc-mt6351-objs := mt6351.o
 snd-soc-nau8540-objs := nau8540.o
 snd-soc-nau8810-objs := nau8810.o
 snd-soc-nau8824-objs := nau8824.o
@@ -126,6 +127,7 @@ snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
 snd-soc-pcm512x-spi-objs := pcm512x-spi.o
 snd-soc-rl6231-objs := rl6231.o
 snd-soc-rl6347a-objs := rl6347a.o
+snd-soc-rt1305-objs := rt1305.o
 snd-soc-rt274-objs := rt274.o
 snd-soc-rt286-objs := rt286.o
 snd-soc-rt298-objs := rt298.o