Merge tag 'sound-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Sep 2021 17:29:29 +0000 (10:29 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Sep 2021 17:29:29 +0000 (10:29 -0700)
Pull sound updates from Takashi Iwai:
 "There are a few intensive changes in ALSA core side at this time that
  helped with significant code reduction. Meanwhile we keep getting new
  stuff, so the total size still grows...

  Anyway, the below are some highlights in this development cycle.

  ALSA core:

   - New helpers to manage page allocations and card object with devres

   - Refactoring for memory allocation with wc-pages

   - A new PCM hardware flag SNDRV_PCM_INFO_EXPLICIT_SYNC for
     controlling the explicit sync of the stream control; it'll be used
     for ASoC SOF and non-coherent memory in future

  ASoC:

   - Lots of cleanups and improvements to the Intel drivers, including
     some new systems support

   - New support for AMD Vangoh, CUI CMM-4030D-261, Mediatek Mt8195,
     Renesas RZ/G2L Mediatek Mt8195, RealTek RT101P, Renesas RZ/G2L,
     Rockchip RK3568 S/PDIF

  USB-audio:

   - Re-organized the quirk handling and a new option quirk_flags

   - Fix for a regression in 5.14 code change for JACK

   - Quirks for Sony WALKMAN, Digidesign mbox

  HD-audio:

   - Enhanced support for CS8409 codec

   - More consistent shutdown behavior with the runtime PM

   - The model option can accept the PCI or codec SSID as an alias

   - Quirks for ASUS ROG, HP Spectre x360

  Others:

   - Lots of code reduction in legacy drivers with devres helpers

   - FireWire MOTU 896HD support"

* tag 'sound-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (421 commits)
  ASoC: Revert PCM trigger changes
  ALSA: usb-audio: Add lowlatency module option
  ALSA: hda/cs8409: Initialize Codec only in init fixup.
  ALSA: hda/cs8409: Ensure Type Detection is only run on startup when necessary
  ALSA: usb-audio: Work around for XRUN with low latency playback
  ALSA: pcm: fix divide error in snd_pcm_lib_ioctl
  ASoC: soc-pcm: test refcount before triggering
  ASoC: soc-pcm: protect BE dailink state changes in trigger
  ASoC: wcd9335: Disable irq on slave ports in the remove function
  ASoC: wcd9335: Fix a memory leak in the error handling path of the probe function
  ASoC: wcd9335: Fix a double irq free in the remove function
  ALSA: hda: Disable runtime resume at shutdown
  ASoC: rockchip: i2s: Add support for frame inversion
  ASoC: dt-bindings: rockchip: Add compatible strings for more SoCs
  ASoC: rockchip: i2s: Add compatible for more SoCs
  ASoC: rockchip: i2s: Make playback/capture optional
  ASoC: rockchip: i2s: Fixup config for DAIFMT_DSP_A/B
  ASoC: dt-bindings: rockchip: Document reset property for i2s
  ASoC: rockchip: i2s: Fix regmap_ops hang
  ASoC: rockchip: i2s: Improve dma data transfer efficiency
  ...

363 files changed:
Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
Documentation/devicetree/bindings/sound/ics43432.txt
Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/sound/realtek,rt1015p.yaml
Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
Documentation/devicetree/bindings/vendor-prefixes.yaml
Documentation/sound/alsa-configuration.rst
Documentation/sound/hd-audio/notes.rst
Documentation/sound/kernel-api/writing-an-alsa-driver.rst
drivers/soundwire/intel.c
drivers/soundwire/intel_init.c
include/linux/platform_data/davinci_asp.h
include/linux/soundwire/sdw_intel.h
include/sound/compress_driver.h
include/sound/core.h
include/sound/emu10k1.h
include/sound/emu8000.h
include/sound/hda_codec.h
include/sound/hdaudio_ext.h
include/sound/memalloc.h
include/sound/pcm.h
include/sound/pxa2xx-lib.h
include/sound/sof.h
include/uapi/sound/asound.h
include/uapi/sound/snd_sst_tokens.h
sound/arm/pxa2xx-ac97.c
sound/arm/pxa2xx-pcm-lib.c
sound/core/compress_offload.c
sound/core/control_led.c
sound/core/init.c
sound/core/isadma.c
sound/core/memalloc.c
sound/core/memalloc_local.h
sound/core/pcm_lib.c
sound/core/pcm_memory.c
sound/core/pcm_native.c
sound/core/seq/seq_dummy.c
sound/core/sgbuf.c
sound/drivers/Kconfig
sound/drivers/aloop.c
sound/drivers/dummy.c
sound/drivers/mpu401/mpu401.c
sound/drivers/mtpav.c
sound/drivers/pcsp/pcsp.c
sound/drivers/pcsp/pcsp_input.c
sound/drivers/pcsp/pcsp_input.h
sound/drivers/serial-u16550.c
sound/drivers/virmidi.c
sound/drivers/vx/vx_core.c
sound/firewire/motu/motu-protocol-v2.c
sound/firewire/motu/motu.c
sound/firewire/motu/motu.h
sound/isa/ad1816a/ad1816a.c
sound/isa/ad1816a/ad1816a_lib.c
sound/isa/ad1848/ad1848.c
sound/isa/adlib.c
sound/isa/als100.c
sound/isa/azt2320.c
sound/isa/cmi8328.c
sound/isa/cmi8330.c
sound/isa/cs423x/cs4231.c
sound/isa/cs423x/cs4236.c
sound/isa/cs423x/cs4236_lib.c
sound/isa/es1688/es1688.c
sound/isa/es18xx.c
sound/isa/galaxy/galaxy.c
sound/isa/gus/gus_main.c
sound/isa/gus/gusclassic.c
sound/isa/gus/gusextreme.c
sound/isa/gus/gusmax.c
sound/isa/gus/interwave.c
sound/isa/msnd/msnd.c
sound/isa/msnd/msnd_pinnacle.c
sound/isa/opl3sa2.c
sound/isa/opti9xx/miro.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/isa/sb/emu8000.c
sound/isa/sb/jazz16.c
sound/isa/sb/sb16.c
sound/isa/sb/sb8.c
sound/isa/sb/sb_common.c
sound/isa/sc6000.c
sound/isa/sscape.c
sound/isa/wavefront/wavefront.c
sound/isa/wss/wss_lib.c
sound/parisc/harmony.c
sound/pci/ad1889.c
sound/pci/ali5451/ali5451.c
sound/pci/als300.c
sound/pci/als4000.c
sound/pci/atiixp.c
sound/pci/atiixp_modem.c
sound/pci/au88x0/au88x0.c
sound/pci/aw2/aw2-alsa.c
sound/pci/azt3328.c
sound/pci/bt87x.c
sound/pci/ca0106/ca0106.h
sound/pci/ca0106/ca0106_main.c
sound/pci/cmipci.c
sound/pci/cs4281.c
sound/pci/cs46xx/cs46xx.c
sound/pci/cs46xx/cs46xx.h
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/cs5530.c
sound/pci/cs5535audio/cs5535audio.c
sound/pci/cs5535audio/cs5535audio_olpc.c
sound/pci/echoaudio/echoaudio.c
sound/pci/echoaudio/echoaudio.h
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/emu10k1/p16v.c
sound/pci/ens1370.c
sound/pci/es1938.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/Kconfig
sound/pci/hda/Makefile
sound/pci/hda/hda_auto_parser.c
sound/pci/hda/hda_bind.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_controller.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.h
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_cs8409-tables.c [new file with mode: 0644]
sound/pci/hda/patch_cs8409.c [new file with mode: 0644]
sound/pci/hda/patch_cs8409.h [new file with mode: 0644]
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1724.c
sound/pci/intel8x0.c
sound/pci/intel8x0m.c
sound/pci/korg1212/korg1212.c
sound/pci/lola/lola.c
sound/pci/lola/lola.h
sound/pci/lola/lola_pcm.c
sound/pci/lx6464es/lx6464es.c
sound/pci/maestro3.c
sound/pci/nm256/nm256.c
sound/pci/oxygen/oxygen.c
sound/pci/oxygen/oxygen.h
sound/pci/oxygen/oxygen_lib.c
sound/pci/oxygen/se6x.c
sound/pci/oxygen/virtuoso.c
sound/pci/pcxhr/pcxhr.c
sound/pci/riptide/riptide.c
sound/pci/rme32.c
sound/pci/rme96.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/pci/rme9652/rme9652.c
sound/pci/sis7019.c
sound/pci/sonicvibes.c
sound/pci/trident/trident.c
sound/pci/trident/trident.h
sound/pci/trident/trident_main.c
sound/pci/trident/trident_memory.c
sound/pci/via82xx.c
sound/pci/via82xx_modem.c
sound/pci/vx222/vx222.c
sound/pci/ymfpci/ymfpci.c
sound/pci/ymfpci/ymfpci.h
sound/pci/ymfpci/ymfpci_main.c
sound/pcmcia/vx/vxpocket.c
sound/soc/amd/Kconfig
sound/soc/amd/Makefile
sound/soc/amd/acp-da7219-max98357a.c
sound/soc/amd/acp-pcm-dma.c
sound/soc/amd/acp3x-rt5682-max9836.c
sound/soc/amd/raven/acp3x-pcm-dma.c
sound/soc/amd/renoir/acp3x-pdm-dma.c
sound/soc/amd/renoir/acp3x-rn.c
sound/soc/amd/vangogh/Makefile [new file with mode: 0644]
sound/soc/amd/vangogh/acp5x-i2s.c [new file with mode: 0644]
sound/soc/amd/vangogh/acp5x-pcm-dma.c [new file with mode: 0644]
sound/soc/amd/vangogh/acp5x.h [new file with mode: 0644]
sound/soc/amd/vangogh/pci-acp5x.c [new file with mode: 0644]
sound/soc/amd/vangogh/vg_chip_offset_byte.h [new file with mode: 0644]
sound/soc/atmel/Kconfig
sound/soc/atmel/mchp-spdifrx.c
sound/soc/atmel/mchp-spdiftx.c
sound/soc/atmel/tse850-pcm5142.c
sound/soc/bcm/bcm63xx-pcm-whistler.c
sound/soc/bcm/cygnus-pcm.c
sound/soc/codecs/Kconfig
sound/soc/codecs/ad193x.c
sound/soc/codecs/ad193x.h
sound/soc/codecs/cs42l42.c
sound/soc/codecs/cx20442.c
sound/soc/codecs/ics43432.c
sound/soc/codecs/lpass-rx-macro.c
sound/soc/codecs/max98090.c
sound/soc/codecs/max98390.c
sound/soc/codecs/max98390.h
sound/soc/codecs/mt6359-accdet.c
sound/soc/codecs/rt1015.c
sound/soc/codecs/rt1015.h
sound/soc/codecs/rt1015p.c
sound/soc/codecs/rt5514.c
sound/soc/codecs/rt5640.c
sound/soc/codecs/rt5640.h
sound/soc/codecs/rt5682-i2c.c
sound/soc/codecs/rt5682.c
sound/soc/codecs/tlv320aic32x4.c
sound/soc/codecs/wcd9335.c
sound/soc/codecs/wcd938x.c
sound/soc/codecs/wcd938x.h
sound/soc/codecs/wm_adsp.c
sound/soc/dwc/dwc-i2s.c
sound/soc/fsl/fsl_asrc_dma.c
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/fsl_rpmsg.c
sound/soc/fsl/fsl_xcvr.c
sound/soc/fsl/imx-pcm-fiq.c
sound/soc/fsl/imx-pcm-rpmsg.c
sound/soc/fsl/imx-rpmsg.c
sound/soc/fsl/mpc5200_dma.c
sound/soc/generic/simple-card-utils.c
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/soc/intel/atom/sst/sst_ipc.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/kbl_da7219_max98927.c
sound/soc/intel/boards/sof_cs42l42.c
sound/soc/intel/boards/sof_maxim_common.c
sound/soc/intel/boards/sof_maxim_common.h
sound/soc/intel/boards/sof_pcm512x.c
sound/soc/intel/boards/sof_rt5682.c
sound/soc/intel/boards/sof_sdw.c
sound/soc/intel/boards/sof_sdw_common.h
sound/soc/intel/boards/sof_sdw_max98373.c
sound/soc/intel/boards/sof_sdw_rt1308.c
sound/soc/intel/boards/sof_sdw_rt1316.c
sound/soc/intel/boards/sof_sdw_rt5682.c
sound/soc/intel/boards/sof_sdw_rt700.c
sound/soc/intel/boards/sof_sdw_rt711.c
sound/soc/intel/boards/sof_sdw_rt711_sdca.c
sound/soc/intel/boards/sof_sdw_rt715.c
sound/soc/intel/boards/sof_sdw_rt715_sdca.c
sound/soc/intel/common/soc-acpi-intel-cml-match.c
sound/soc/intel/common/soc-acpi-intel-jsl-match.c
sound/soc/intel/common/soc-acpi-intel-kbl-match.c
sound/soc/intel/common/soc-acpi-intel-tgl-match.c
sound/soc/intel/skylake/skl-messages.c
sound/soc/intel/skylake/skl-pcm.c
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl-topology.h
sound/soc/mediatek/Kconfig
sound/soc/mediatek/Makefile
sound/soc/mediatek/common/mtk-afe-fe-dai.c
sound/soc/mediatek/common/mtk-base-afe.h
sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
sound/soc/mediatek/mt8195/Makefile [new file with mode: 0644]
sound/soc/mediatek/mt8195/mt8195-afe-clk.c [new file with mode: 0644]
sound/soc/mediatek/mt8195/mt8195-afe-clk.h [new file with mode: 0644]
sound/soc/mediatek/mt8195/mt8195-afe-common.h [new file with mode: 0644]
sound/soc/mediatek/mt8195/mt8195-afe-pcm.c [new file with mode: 0644]
sound/soc/mediatek/mt8195/mt8195-audsys-clk.c [new file with mode: 0644]
sound/soc/mediatek/mt8195/mt8195-audsys-clk.h [new file with mode: 0644]
sound/soc/mediatek/mt8195/mt8195-audsys-clkid.h [new file with mode: 0644]
sound/soc/mediatek/mt8195/mt8195-dai-adda.c [new file with mode: 0644]
sound/soc/mediatek/mt8195/mt8195-dai-etdm.c [new file with mode: 0644]
sound/soc/mediatek/mt8195/mt8195-dai-pcm.c [new file with mode: 0644]
sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c [new file with mode: 0644]
sound/soc/mediatek/mt8195/mt8195-reg.h [new file with mode: 0644]
sound/soc/pxa/pxa-ssp.c
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/pxa/pxa2xx-i2s.c
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/qcom/apq8016_sbc.c
sound/soc/qcom/lpass-platform.c
sound/soc/qcom/qdsp6/q6adm.c
sound/soc/qcom/qdsp6/q6asm-dai.c
sound/soc/qcom/qdsp6/q6asm.c
sound/soc/rockchip/rockchip_i2s.c
sound/soc/rockchip/rockchip_i2s.h
sound/soc/rockchip/rockchip_spdif.c
sound/soc/samsung/aries_wm8994.c
sound/soc/samsung/arndale.c
sound/soc/samsung/h1940_uda1380.c
sound/soc/samsung/littlemill.c
sound/soc/samsung/midas_wm1811.c
sound/soc/samsung/neo1973_wm8753.c
sound/soc/samsung/rx1950_uda1380.c
sound/soc/samsung/smartq_wm8987.c
sound/soc/samsung/smdk_wm8580.c
sound/soc/samsung/smdk_wm8994.c
sound/soc/samsung/smdk_wm8994pcm.c
sound/soc/samsung/tm2_wm5110.c
sound/soc/samsung/tobermory.c
sound/soc/sh/Kconfig
sound/soc/sh/Makefile
sound/soc/sh/rcar/adg.c
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/dma.c
sound/soc/sh/rcar/ssi.c
sound/soc/sh/rz-ssi.c [new file with mode: 0644]
sound/soc/soc-ac97.c
sound/soc/soc-component.c
sound/soc/soc-compress.c
sound/soc/soc-core.c
sound/soc/soc-dai.c
sound/soc/soc-dapm.c
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-jack.c
sound/soc/soc-ops.c
sound/soc/soc-pcm.c
sound/soc/soc-topology.c
sound/soc/sof/intel/Kconfig
sound/soc/sof/intel/cnl.c
sound/soc/sof/intel/hda-pcm.c
sound/soc/sof/intel/hda-stream.c
sound/soc/sof/intel/hda.c
sound/soc/sof/intel/hda.h
sound/soc/sof/intel/icl.c
sound/soc/sof/intel/pci-tng.c
sound/soc/sof/intel/shim.h
sound/soc/sof/intel/tgl.c
sound/soc/sof/sof-audio.c
sound/soc/sof/sof-pci-dev.c
sound/soc/sprd/sprd-pcm-dma.c
sound/soc/tegra/tegra210_admaif.c
sound/soc/tegra/tegra30_ahub.c
sound/soc/tegra/tegra30_i2s.c
sound/soc/tegra/tegra_pcm.c
sound/soc/tegra/tegra_pcm.h
sound/soc/ti/Kconfig
sound/soc/ti/davinci-mcasp.c
sound/soc/ti/j721e-evm.c
sound/soc/ti/omap-abe-twl6040.c
sound/soc/uniphier/aio-cpu.c
sound/usb/card.c
sound/usb/card.h
sound/usb/clock.c
sound/usb/endpoint.c
sound/usb/format.c
sound/usb/implicit.c
sound/usb/mixer.c
sound/usb/mixer.h
sound/usb/mixer_maps.c
sound/usb/mixer_quirks.c
sound/usb/pcm.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/quirks.h
sound/usb/stream.c
sound/usb/usbaudio.h
sound/x86/intel_hdmi_audio.c
sound/x86/intel_hdmi_audio.h

index c483dce..bd863bd 100644 (file)
@@ -6,6 +6,7 @@ Required properties:
        "ti,da830-mcasp-audio"  : for both DA830 & DA850 platforms
        "ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, AM43xx, TI81xx)
        "ti,dra7-mcasp-audio"   : for DRA7xx platforms
+       "ti,omap4-mcasp-audio"  : for OMAP4
 
 - reg : Should contain reg specifiers for the entries in the reg-names property.
 - reg-names : Should contain:
index b02e3a6..e6f05f2 100644 (file)
@@ -1,4 +1,4 @@
-Invensense ICS-43432 MEMS microphone with I2S output.
+Invensense ICS-43432-compatible MEMS microphone with I2S output.
 
 There are no software configuration options for this device, indeed, the only
 host connection is the I2S interface. Apart from requirements on clock
@@ -8,7 +8,9 @@ contain audio data. A hardware pin determines if the device outputs data
 on the left or right channel of the I2S frame.
 
 Required properties:
-  - compatible : Must be "invensense,ics43432"
+  - compatible: should be one of the following.
+     "invensense,ics43432": For the Invensense ICS43432
+     "cui,cmm-4030d-261": For the CUI CMM-4030D-261-I2S-TR
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml b/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml
new file mode 100644 (file)
index 0000000..53e9434
--- /dev/null
@@ -0,0 +1,184 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mt8195-afe-pcm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek AFE PCM controller for mt8195
+
+maintainers:
+  - Trevor Wu <trevor.wu@mediatek.com>
+
+properties:
+  compatible:
+    const: mediatek,mt8195-audio
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  mediatek,topckgen:
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+    description: The phandle of the mediatek topckgen controller
+
+  power-domains:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: 26M clock
+      - description: audio pll1 clock
+      - description: audio pll2 clock
+      - description: clock divider for i2si1_mck
+      - description: clock divider for i2si2_mck
+      - description: clock divider for i2so1_mck
+      - description: clock divider for i2so2_mck
+      - description: clock divider for dptx_mck
+      - description: a1sys hoping clock
+      - description: audio intbus clock
+      - description: audio hires clock
+      - description: audio local bus clock
+      - description: mux for dptx_mck
+      - description: mux for i2so1_mck
+      - description: mux for i2so2_mck
+      - description: mux for i2si1_mck
+      - description: mux for i2si2_mck
+      - description: audio infra 26M clock
+      - description: infra bus clock
+
+  clock-names:
+    items:
+      - const: clk26m
+      - const: apll1_ck
+      - const: apll2_ck
+      - const: apll12_div0
+      - const: apll12_div1
+      - const: apll12_div2
+      - const: apll12_div3
+      - const: apll12_div9
+      - const: a1sys_hp_sel
+      - const: aud_intbus_sel
+      - const: audio_h_sel
+      - const: audio_local_bus_sel
+      - const: dptx_m_sel
+      - const: i2so1_m_sel
+      - const: i2so2_m_sel
+      - const: i2si1_m_sel
+      - const: i2si2_m_sel
+      - const: infra_ao_audio_26m_b
+      - const: scp_adsp_audiodsp
+
+  mediatek,etdm-in1-chn-disabled:
+    $ref: /schemas/types.yaml#/definitions/uint8-array
+    maxItems: 24
+    description: Specify which input channel should be disabled.
+
+  mediatek,etdm-in2-chn-disabled:
+    $ref: /schemas/types.yaml#/definitions/uint8-array
+    maxItems: 16
+    description: Specify which input channel should be disabled.
+
+patternProperties:
+  "^mediatek,etdm-in[1-2]-mclk-always-on-rate-hz$":
+    description: Specify etdm in mclk output rate for always on case.
+
+  "^mediatek,etdm-out[1-3]-mclk-always-on-rate-hz$":
+    description: Specify etdm out mclk output rate for always on case.
+
+  "^mediatek,etdm-in[1-2]-multi-pin-mode$":
+    type: boolean
+    description: if present, the etdm data mode is I2S.
+
+  "^mediatek,etdm-out[1-3]-multi-pin-mode$":
+    type: boolean
+    description: if present, the etdm data mode is I2S.
+
+  "^mediatek,etdm-in[1-2]-cowork-source$":
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      etdm modules can share the same external clock pin. Specify
+      which etdm clock source is required by this etdm in moudule.
+    enum:
+      - 0 # etdm1_in
+      - 1 # etdm2_in
+      - 2 # etdm1_out
+      - 3 # etdm2_out
+
+  "^mediatek,etdm-out[1-2]-cowork-source$":
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      etdm modules can share the same external clock pin. Specify
+      which etdm clock source is required by this etdm out moudule.
+    enum:
+      - 0 # etdm1_in
+      - 1 # etdm2_in
+      - 2 # etdm1_out
+      - 3 # etdm2_out
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - mediatek,topckgen
+  - power-domains
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/mt8195-clk.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/power/mt8195-power.h>
+
+    afe: mt8195-afe-pcm@10890000 {
+        compatible = "mediatek,mt8195-audio";
+        reg = <0x10890000 0x10000>;
+        interrupts = <GIC_SPI 822 IRQ_TYPE_LEVEL_HIGH 0>;
+        mediatek,topckgen = <&topckgen>;
+        power-domains = <&spm MT8195_POWER_DOMAIN_AUDIO>;
+        clocks = <&clk26m>,
+                 <&topckgen CLK_TOP_APLL1>,
+                 <&topckgen CLK_TOP_APLL2>,
+                 <&topckgen CLK_TOP_APLL12_DIV0>,
+                 <&topckgen CLK_TOP_APLL12_DIV1>,
+                 <&topckgen CLK_TOP_APLL12_DIV2>,
+                 <&topckgen CLK_TOP_APLL12_DIV3>,
+                 <&topckgen CLK_TOP_APLL12_DIV9>,
+                 <&topckgen CLK_TOP_A1SYS_HP_SEL>,
+                 <&topckgen CLK_TOP_AUD_INTBUS_SEL>,
+                 <&topckgen CLK_TOP_AUDIO_H_SEL>,
+                 <&topckgen CLK_TOP_AUDIO_LOCAL_BUS_SEL>,
+                 <&topckgen CLK_TOP_DPTX_M_SEL>,
+                 <&topckgen CLK_TOP_I2SO1_M_SEL>,
+                 <&topckgen CLK_TOP_I2SO2_M_SEL>,
+                 <&topckgen CLK_TOP_I2SI1_M_SEL>,
+                 <&topckgen CLK_TOP_I2SI2_M_SEL>,
+                 <&infracfg_ao CLK_INFRA_AO_AUDIO_26M_B>,
+                 <&scp_adsp CLK_SCP_ADSP_AUDIODSP>;
+        clock-names = "clk26m",
+                      "apll1_ck",
+                      "apll2_ck",
+                      "apll12_div0",
+                      "apll12_div1",
+                      "apll12_div2",
+                      "apll12_div3",
+                      "apll12_div9",
+                      "a1sys_hp_sel",
+                      "aud_intbus_sel",
+                      "audio_h_sel",
+                      "audio_local_bus_sel",
+                      "dptx_m_sel",
+                      "i2so1_m_sel",
+                      "i2so2_m_sel",
+                      "i2si1_m_sel",
+                      "i2si2_m_sel",
+                      "infra_ao_audio_26m_b",
+                      "scp_adsp_audiodsp";
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml b/Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml
new file mode 100644 (file)
index 0000000..20bc0ff
--- /dev/null
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mt8195-mt6359-rt1019-rt5682.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT8195 with MT6359, RT1019 and RT5682 ASoC sound card driver
+
+maintainers:
+  - Trevor Wu <trevor.wu@mediatek.com>
+
+description:
+  This binding describes the MT8195 sound card.
+
+properties:
+  compatible:
+    const: mediatek,mt8195_mt6359_rt1019_rt5682
+
+  mediatek,platform:
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+    description: The phandle of MT8195 ASoC platform.
+
+  mediatek,dptx-codec:
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+    description: The phandle of MT8195 Display Port Tx codec node.
+
+  mediatek,hdmi-codec:
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+    description: The phandle of MT8195 HDMI codec node.
+
+additionalProperties: false
+
+required:
+  - compatible
+  - mediatek,platform
+
+examples:
+  - |
+
+    sound: mt8195-sound {
+        compatible = "mediatek,mt8195_mt6359_rt1019_rt5682";
+        mediatek,platform = <&afe>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&aud_pins_default>;
+    };
+
+...
index 644b68e..fdb7f29 100644 (file)
@@ -15,7 +15,9 @@ description: |
 
 properties:
   compatible:
-    const: realtek,rt1015p
+    enum:
+      - realtek,rt1015p
+      - realtek,rt1019p
 
   sdb-gpios:
     description:
diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
new file mode 100644 (file)
index 0000000..414ff80
--- /dev/null
@@ -0,0 +1,118 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/renesas,rz-ssi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G2L ASoC Sound Serial Interface (SSIF-2)
+
+maintainers:
+  - Biju Das <biju.das.jz@bp.renesas.com>
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - renesas,r9a07g044-ssi  # RZ/G2{L,LC}
+      - const: renesas,rz-ssi
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 4
+
+  interrupt-names:
+    items:
+      - const: int_req
+      - const: dma_rx
+      - const: dma_tx
+      - const: dma_rt
+
+  clocks:
+    maxItems: 4
+
+  clock-names:
+    items:
+      - const: ssi
+      - const: ssi_sfr
+      - const: audio_clk1
+      - const: audio_clk2
+
+  power-domains:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  dmas:
+    minItems: 1
+    maxItems: 2
+    description:
+      The first cell represents a phandle to dmac
+      The second cell specifies the encoded MID/RID values of the SSI port
+      connected to the DMA client and the slave channel configuration
+      parameters.
+      bits[0:9]   - Specifies MID/RID value of a SSI channel as below
+                    MID/RID value of SSI rx0 = 0x256
+                    MID/RID value of SSI tx0 = 0x255
+                    MID/RID value of SSI rx1 = 0x25a
+                    MID/RID value of SSI tx1 = 0x259
+                    MID/RID value of SSI rt2 = 0x25f
+                    MID/RID value of SSI rx3 = 0x262
+                    MID/RID value of SSI tx3 = 0x261
+      bit[10]     - HIEN = 1, Detects a request in response to the rising edge
+                    of the signal
+      bit[11]     - LVL = 0, Detects based on the edge
+      bits[12:14] - AM = 2, Bus cycle mode
+      bit[15]     - TM = 0, Single transfer mode
+
+  dma-names:
+    oneOf:
+      - items:
+          - const: tx
+          - const: rx
+      - items:
+          - const: rt
+
+  '#sound-dai-cells':
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - interrupt-names
+  - clocks
+  - clock-names
+  - resets
+  - '#sound-dai-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/r9a07g044-cpg.h>
+
+    ssi0: ssi@10049c00 {
+        compatible = "renesas,r9a07g044-ssi",
+                     "renesas,rz-ssi";
+            reg = <0x10049c00 0x400>;
+            interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 327 IRQ_TYPE_EDGE_RISING>,
+                         <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>,
+                         <GIC_SPI 329 IRQ_TYPE_EDGE_RISING>;
+            interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt";
+            clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>,
+                     <&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>,
+                     <&audio_clk1>,
+                     <&audio_clk2>;
+            clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
+            power-domains = <&cpg>;
+            resets = <&cpg R9A07G044_SSI0_RST_M2_REG>;
+            dmas = <&dmac 0x2655>,
+                   <&dmac 0x2656>;
+            dma-names = "tx", "rx";
+            #sound-dai-cells = <0>;
+    };
index 245895b..5ea16b8 100644 (file)
@@ -20,7 +20,9 @@ properties:
       - items:
           - enum:
               - rockchip,px30-i2s
+              - rockchip,rk1808-i2s
               - rockchip,rk3036-i2s
+              - rockchip,rk3128-i2s
               - rockchip,rk3188-i2s
               - rockchip,rk3228-i2s
               - rockchip,rk3288-i2s
@@ -29,6 +31,7 @@ properties:
               - rockchip,rk3366-i2s
               - rockchip,rk3368-i2s
               - rockchip,rk3399-i2s
+              - rockchip,rv1126-i2s
           - const: rockchip,rk3066-i2s
 
   reg:
@@ -61,6 +64,14 @@ properties:
   power-domains:
     maxItems: 1
 
+  reset-names:
+    items:
+      - const: reset-m
+      - const: reset-h
+
+  resets:
+    maxItems: 2
+
   rockchip,capture-channels:
     $ref: /schemas/types.yaml#/definitions/uint32
     default: 2
index 62a61b6..d0a24bf 100644 (file)
@@ -23,6 +23,7 @@ properties:
       - const: rockchip,rk3366-spdif
       - const: rockchip,rk3368-spdif
       - const: rockchip,rk3399-spdif
+      - const: rockchip,rk3568-spdif
       - items:
           - enum:
               - rockchip,rk3188-spdif
index 07fb0d2..ed4f66e 100644 (file)
@@ -271,6 +271,8 @@ patternProperties:
     description: Shenzen Chuangsiqi Technology Co.,Ltd.
   "^cubietech,.*":
     description: Cubietech, Ltd.
+  "^cui,.*":
+    description: CUI Devices
   "^cypress,.*":
     description: Cypress Semiconductor Corporation
   "^cznic,.*":
index b36af65..65f6169 100644 (file)
@@ -1059,6 +1059,12 @@ The model name ``generic`` is treated as a special case.  When this
 model is given, the driver uses the generic codec parser without
 "codec-patch".  It's sometimes good for testing and debugging.
 
+The model option can be used also for aliasing to another PCI or codec
+SSID.  When it's passed in the form of ``model=XXXX:YYYY`` where XXXX
+and YYYY are the sub-vendor and sub-device IDs in hex numbers,
+respectively, the driver will refer to that SSID as a reference to the
+quirk table.
+
 If the default configuration doesn't work and one of the above
 matches with your device, report it together with alsa-info.sh
 output (with ``--no-upload`` option) to kernel bugzilla or alsa-devel
@@ -2252,6 +2258,27 @@ delayed_register
     The driver prints a message like "Found post-registration device
     assignment: 1234abcd:04" for such a device, so that user can
     notice the need.
+quirk_flags
+    Contains the bit flags for various device specific workarounds.
+    Applied to the corresponding card index.
+
+        * bit 0: Skip reading sample rate for devices
+        * bit 1: Create Media Controller API entries
+        * bit 2: Allow alignment on audio sub-slot at transfer
+        * bit 3: Add length specifier to transfers
+        * bit 4: Start playback stream at first in implement feedback mode
+        * bit 5: Skip clock selector setup
+        * bit 6: Ignore errors from clock source search
+        * bit 7: Indicates ITF-USB DSD based DACs
+        * bit 8: Add a delay of 20ms at each control message handling
+        * bit 9: Add a delay of 1-2ms at each control message handling
+        * bit 10: Add a delay of 5-6ms at each control message handling
+        * bit 11: Add a delay of 50ms at each interface setup
+        * bit 12: Perform sample rate validations at probe
+        * bit 13: Disable runtime PM autosuspend
+        * bit 14: Ignore errors for mixer access
+        * bit 15: Support generic DSD raw U32_BE format
+        * bit 16: Set up the interface at first like UAC1
 
 This module supports multiple devices, autoprobe and hotplugging.
 
@@ -2261,11 +2288,14 @@ check.
 
 NB: ``ignore_ctl_error=1`` may help when you get an error at accessing
 the mixer element such as URB error -22.  This happens on some
-buggy USB device or the controller.
+buggy USB device or the controller.  This workaround corresponds to
+the ``quirk_flags`` bit 14, too.
 
-NB: quirk_alias option is provided only for testing / development.
+NB: ``quirk_alias`` option is provided only for testing / development.
 If you want to have a proper support, contact to upstream for
 adding the matching quirk in the driver code statically.
+Ditto for ``quirk_flags``.  If a device is known to require specific
+workarounds, please report to the upstream.
 
 Module snd-usb-caiaq
 --------------------
index cf4d715..d118b6f 100644 (file)
@@ -215,6 +215,17 @@ There are a few special model option values:
 * when ``generic`` is passed, the codec-specific parser is skipped and
   only the generic parser is used.
 
+A new style for the model option that was introduced since 5.15 kernel
+is to pass the PCI or codec SSID in the form of ``model=XXXX:YYYY``
+where XXXX and YYYY are the sub-vendor and sub-device IDs in hex
+numbers, respectively.  This is a kind of aliasing to another device;
+when this form is given, the driver will refer to that SSID as a
+reference to the quirk table.  It'd be useful especially when the
+target quirk isn't listed in the model table.  For example, passing
+model=103c:8862 will apply the quirk for HP ProBook 445 G8 (which
+isn't found in the model table as of writing) as long as the device is
+handled equivalently by the same driver.
+
 
 Speaker and Headphone Output
 ----------------------------
index 01d59b8..255b7d3 100644 (file)
@@ -4172,6 +4172,39 @@ module license as GPL, etc., otherwise the system is shown as “tainted”.
   MODULE_LICENSE("GPL");
 
 
+Device-Managed Resources
+========================
+
+In the examples above, all resources are allocated and released
+manually.  But human beings are lazy in nature, especially developers
+are lazier.  So there are some ways to automate the release part; it's
+the (device-)managed resources aka devres or devm family.  For
+example, an object allocated via :c:func:`devm_kmalloc()` will be
+freed automatically at unbinding the device.
+
+ALSA core provides also the device-managed helper, namely,
+:c:func:`snd_devm_card_new()` for creating a card object.
+Call this functions instead of the normal :c:func:`snd_card_new()`,
+and you can forget the explicit :c:func:`snd_card_free()` call, as
+it's called automagically at error and removal paths.
+
+One caveat is that the call of :c:func:`snd_card_free()` would be put
+at the beginning of the call chain only after you call
+:c:func:`snd_card_register()`.
+
+Also, the ``private_free`` callback is always called at the card free,
+so be careful to put the hardware clean-up procedure in
+``private_free`` callback.  It might be called even before you
+actually set up at an earlier error path.  For avoiding such an
+invalid initialization, you can set ``private_free`` callback after
+:c:func:`snd_card_register()` call succeeds.
+
+Another thing to be remarked is that you should use device-managed
+helpers for each component as much as possible once when you manage
+the card in that way.  Mixing up with the normal and the managed
+resources may screw up the release order.
+
+
 How To Put Your Driver Into ALSA Tree
 =====================================
 
index f66fcbc..78037ff 100644 (file)
@@ -41,80 +41,6 @@ static int md_flags;
 module_param_named(sdw_md_flags, md_flags, int, 0444);
 MODULE_PARM_DESC(sdw_md_flags, "SoundWire Intel Master device flags (0x0 all off)");
 
-/* Intel SHIM Registers Definition */
-#define SDW_SHIM_LCAP                  0x0
-#define SDW_SHIM_LCTL                  0x4
-#define SDW_SHIM_IPPTR                 0x8
-#define SDW_SHIM_SYNC                  0xC
-
-#define SDW_SHIM_CTLSCAP(x)            (0x010 + 0x60 * (x))
-#define SDW_SHIM_CTLS0CM(x)            (0x012 + 0x60 * (x))
-#define SDW_SHIM_CTLS1CM(x)            (0x014 + 0x60 * (x))
-#define SDW_SHIM_CTLS2CM(x)            (0x016 + 0x60 * (x))
-#define SDW_SHIM_CTLS3CM(x)            (0x018 + 0x60 * (x))
-#define SDW_SHIM_PCMSCAP(x)            (0x020 + 0x60 * (x))
-
-#define SDW_SHIM_PCMSYCHM(x, y)                (0x022 + (0x60 * (x)) + (0x2 * (y)))
-#define SDW_SHIM_PCMSYCHC(x, y)                (0x042 + (0x60 * (x)) + (0x2 * (y)))
-#define SDW_SHIM_PDMSCAP(x)            (0x062 + 0x60 * (x))
-#define SDW_SHIM_IOCTL(x)              (0x06C + 0x60 * (x))
-#define SDW_SHIM_CTMCTL(x)             (0x06E + 0x60 * (x))
-
-#define SDW_SHIM_WAKEEN                        0x190
-#define SDW_SHIM_WAKESTS               0x192
-
-#define SDW_SHIM_LCTL_SPA              BIT(0)
-#define SDW_SHIM_LCTL_SPA_MASK         GENMASK(3, 0)
-#define SDW_SHIM_LCTL_CPA              BIT(8)
-#define SDW_SHIM_LCTL_CPA_MASK         GENMASK(11, 8)
-
-#define SDW_SHIM_SYNC_SYNCPRD_VAL_24   (24000 / SDW_CADENCE_GSYNC_KHZ - 1)
-#define SDW_SHIM_SYNC_SYNCPRD_VAL_38_4 (38400 / SDW_CADENCE_GSYNC_KHZ - 1)
-#define SDW_SHIM_SYNC_SYNCPRD          GENMASK(14, 0)
-#define SDW_SHIM_SYNC_SYNCCPU          BIT(15)
-#define SDW_SHIM_SYNC_CMDSYNC_MASK     GENMASK(19, 16)
-#define SDW_SHIM_SYNC_CMDSYNC          BIT(16)
-#define SDW_SHIM_SYNC_SYNCGO           BIT(24)
-
-#define SDW_SHIM_PCMSCAP_ISS           GENMASK(3, 0)
-#define SDW_SHIM_PCMSCAP_OSS           GENMASK(7, 4)
-#define SDW_SHIM_PCMSCAP_BSS           GENMASK(12, 8)
-
-#define SDW_SHIM_PCMSYCM_LCHN          GENMASK(3, 0)
-#define SDW_SHIM_PCMSYCM_HCHN          GENMASK(7, 4)
-#define SDW_SHIM_PCMSYCM_STREAM                GENMASK(13, 8)
-#define SDW_SHIM_PCMSYCM_DIR           BIT(15)
-
-#define SDW_SHIM_PDMSCAP_ISS           GENMASK(3, 0)
-#define SDW_SHIM_PDMSCAP_OSS           GENMASK(7, 4)
-#define SDW_SHIM_PDMSCAP_BSS           GENMASK(12, 8)
-#define SDW_SHIM_PDMSCAP_CPSS          GENMASK(15, 13)
-
-#define SDW_SHIM_IOCTL_MIF             BIT(0)
-#define SDW_SHIM_IOCTL_CO              BIT(1)
-#define SDW_SHIM_IOCTL_COE             BIT(2)
-#define SDW_SHIM_IOCTL_DO              BIT(3)
-#define SDW_SHIM_IOCTL_DOE             BIT(4)
-#define SDW_SHIM_IOCTL_BKE             BIT(5)
-#define SDW_SHIM_IOCTL_WPDD            BIT(6)
-#define SDW_SHIM_IOCTL_CIBD            BIT(8)
-#define SDW_SHIM_IOCTL_DIBD            BIT(9)
-
-#define SDW_SHIM_CTMCTL_DACTQE         BIT(0)
-#define SDW_SHIM_CTMCTL_DODS           BIT(1)
-#define SDW_SHIM_CTMCTL_DOAIS          GENMASK(4, 3)
-
-#define SDW_SHIM_WAKEEN_ENABLE         BIT(0)
-#define SDW_SHIM_WAKESTS_STATUS                BIT(0)
-
-/* Intel ALH Register definitions */
-#define SDW_ALH_STRMZCFG(x)            (0x000 + (0x4 * (x)))
-#define SDW_ALH_NUM_STREAMS            64
-
-#define SDW_ALH_STRMZCFG_DMAT_VAL      0x3
-#define SDW_ALH_STRMZCFG_DMAT          GENMASK(7, 0)
-#define SDW_ALH_STRMZCFG_CHN           GENMASK(19, 16)
-
 enum intel_pdi_type {
        INTEL_PDI_IN = 0,
        INTEL_PDI_OUT = 1,
index 9e283be..e329022 100644 (file)
 #include "cadence_master.h"
 #include "intel.h"
 
-#define SDW_SHIM_LCAP          0x0
-#define SDW_SHIM_BASE          0x2C000
-#define SDW_ALH_BASE           0x2C800
-#define SDW_LINK_BASE          0x30000
-#define SDW_LINK_SIZE          0x10000
-
 static void intel_link_dev_release(struct device *dev)
 {
        struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
@@ -69,8 +63,8 @@ static struct sdw_intel_link_dev *intel_link_dev_register(struct sdw_intel_res *
        link->mmio_base = res->mmio_base;
        link->registers = res->mmio_base + SDW_LINK_BASE
                + (SDW_LINK_SIZE * link_id);
-       link->shim = res->mmio_base + SDW_SHIM_BASE;
-       link->alh = res->mmio_base + SDW_ALH_BASE;
+       link->shim = res->mmio_base + res->shim_base;
+       link->alh = res->mmio_base + res->alh_base;
 
        link->ops = res->ops;
        link->dev = res->dev;
@@ -220,6 +214,8 @@ static struct sdw_intel_ctx
        }
 
        ctx->mmio_base = res->mmio_base;
+       ctx->shim_base = res->shim_base;
+       ctx->alh_base = res->alh_base;
        ctx->link_mask = res->link_mask;
        ctx->handle = res->handle;
        mutex_init(&ctx->shim_lock);
@@ -308,7 +304,7 @@ sdw_intel_startup_controller(struct sdw_intel_ctx *ctx)
                return -EINVAL;
 
        /* Check SNDWLCAP.LCOUNT */
-       caps = ioread32(ctx->mmio_base + SDW_SHIM_BASE + SDW_SHIM_LCAP);
+       caps = ioread32(ctx->mmio_base + ctx->shim_base + SDW_SHIM_LCAP);
        caps &= GENMASK(2, 0);
 
        /* Check HW supported vs property value */
index 5d1fb0d..76b13ef 100644 (file)
@@ -96,6 +96,7 @@ enum {
        MCASP_VERSION_2,        /* DA8xx/OMAPL1x */
        MCASP_VERSION_3,        /* TI81xx/AM33xx */
        MCASP_VERSION_4,        /* DRA7xxx */
+       MCASP_VERSION_OMAP,     /* OMAP4/5 */
 };
 
 enum mcbsp_clk_input_pin {
index 1ebea77..8a463b8 100644 (file)
@@ -7,6 +7,85 @@
 #include <linux/irqreturn.h>
 #include <linux/soundwire/sdw.h>
 
+#define SDW_SHIM_BASE                  0x2C000
+#define SDW_ALH_BASE                   0x2C800
+#define SDW_LINK_BASE                  0x30000
+#define SDW_LINK_SIZE                  0x10000
+
+/* Intel SHIM Registers Definition */
+#define SDW_SHIM_LCAP                  0x0
+#define SDW_SHIM_LCTL                  0x4
+#define SDW_SHIM_IPPTR                 0x8
+#define SDW_SHIM_SYNC                  0xC
+
+#define SDW_SHIM_CTLSCAP(x)            (0x010 + 0x60 * (x))
+#define SDW_SHIM_CTLS0CM(x)            (0x012 + 0x60 * (x))
+#define SDW_SHIM_CTLS1CM(x)            (0x014 + 0x60 * (x))
+#define SDW_SHIM_CTLS2CM(x)            (0x016 + 0x60 * (x))
+#define SDW_SHIM_CTLS3CM(x)            (0x018 + 0x60 * (x))
+#define SDW_SHIM_PCMSCAP(x)            (0x020 + 0x60 * (x))
+
+#define SDW_SHIM_PCMSYCHM(x, y)                (0x022 + (0x60 * (x)) + (0x2 * (y)))
+#define SDW_SHIM_PCMSYCHC(x, y)                (0x042 + (0x60 * (x)) + (0x2 * (y)))
+#define SDW_SHIM_PDMSCAP(x)            (0x062 + 0x60 * (x))
+#define SDW_SHIM_IOCTL(x)              (0x06C + 0x60 * (x))
+#define SDW_SHIM_CTMCTL(x)             (0x06E + 0x60 * (x))
+
+#define SDW_SHIM_WAKEEN                        0x190
+#define SDW_SHIM_WAKESTS               0x192
+
+#define SDW_SHIM_LCTL_SPA              BIT(0)
+#define SDW_SHIM_LCTL_SPA_MASK         GENMASK(3, 0)
+#define SDW_SHIM_LCTL_CPA              BIT(8)
+#define SDW_SHIM_LCTL_CPA_MASK         GENMASK(11, 8)
+
+#define SDW_SHIM_SYNC_SYNCPRD_VAL_24   (24000 / SDW_CADENCE_GSYNC_KHZ - 1)
+#define SDW_SHIM_SYNC_SYNCPRD_VAL_38_4 (38400 / SDW_CADENCE_GSYNC_KHZ - 1)
+#define SDW_SHIM_SYNC_SYNCPRD          GENMASK(14, 0)
+#define SDW_SHIM_SYNC_SYNCCPU          BIT(15)
+#define SDW_SHIM_SYNC_CMDSYNC_MASK     GENMASK(19, 16)
+#define SDW_SHIM_SYNC_CMDSYNC          BIT(16)
+#define SDW_SHIM_SYNC_SYNCGO           BIT(24)
+
+#define SDW_SHIM_PCMSCAP_ISS           GENMASK(3, 0)
+#define SDW_SHIM_PCMSCAP_OSS           GENMASK(7, 4)
+#define SDW_SHIM_PCMSCAP_BSS           GENMASK(12, 8)
+
+#define SDW_SHIM_PCMSYCM_LCHN          GENMASK(3, 0)
+#define SDW_SHIM_PCMSYCM_HCHN          GENMASK(7, 4)
+#define SDW_SHIM_PCMSYCM_STREAM                GENMASK(13, 8)
+#define SDW_SHIM_PCMSYCM_DIR           BIT(15)
+
+#define SDW_SHIM_PDMSCAP_ISS           GENMASK(3, 0)
+#define SDW_SHIM_PDMSCAP_OSS           GENMASK(7, 4)
+#define SDW_SHIM_PDMSCAP_BSS           GENMASK(12, 8)
+#define SDW_SHIM_PDMSCAP_CPSS          GENMASK(15, 13)
+
+#define SDW_SHIM_IOCTL_MIF             BIT(0)
+#define SDW_SHIM_IOCTL_CO              BIT(1)
+#define SDW_SHIM_IOCTL_COE             BIT(2)
+#define SDW_SHIM_IOCTL_DO              BIT(3)
+#define SDW_SHIM_IOCTL_DOE             BIT(4)
+#define SDW_SHIM_IOCTL_BKE             BIT(5)
+#define SDW_SHIM_IOCTL_WPDD            BIT(6)
+#define SDW_SHIM_IOCTL_CIBD            BIT(8)
+#define SDW_SHIM_IOCTL_DIBD            BIT(9)
+
+#define SDW_SHIM_CTMCTL_DACTQE         BIT(0)
+#define SDW_SHIM_CTMCTL_DODS           BIT(1)
+#define SDW_SHIM_CTMCTL_DOAIS          GENMASK(4, 3)
+
+#define SDW_SHIM_WAKEEN_ENABLE         BIT(0)
+#define SDW_SHIM_WAKESTS_STATUS                BIT(0)
+
+/* Intel ALH Register definitions */
+#define SDW_ALH_STRMZCFG(x)            (0x000 + (0x4 * (x)))
+#define SDW_ALH_NUM_STREAMS            64
+
+#define SDW_ALH_STRMZCFG_DMAT_VAL      0x3
+#define SDW_ALH_STRMZCFG_DMAT          GENMASK(7, 0)
+#define SDW_ALH_STRMZCFG_CHN           GENMASK(19, 16)
+
 /**
  * struct sdw_intel_stream_params_data: configuration passed during
  * the @params_stream callback, e.g. for interaction with DSP
@@ -116,6 +195,8 @@ struct sdw_intel_slave_id {
  * @link_list: list to handle interrupts across all links
  * @shim_lock: mutex to handle concurrent rmw access to shared SHIM registers.
  * @shim_mask: flags to track initialization of SHIM shared registers
+ * @shim_base: sdw shim base.
+ * @alh_base: sdw alh base.
  */
 struct sdw_intel_ctx {
        int count;
@@ -128,6 +209,8 @@ struct sdw_intel_ctx {
        struct list_head link_list;
        struct mutex shim_lock; /* lock for access to shared SHIM registers */
        u32 shim_mask;
+       u32 shim_base;
+       u32 alh_base;
 };
 
 /**
@@ -146,6 +229,8 @@ struct sdw_intel_ctx {
  * machine-specific quirks are handled in the DSP driver.
  * @clock_stop_quirks: mask array of possible behaviors requested by the
  * DSP driver. The quirks are common for all links for now.
+ * @shim_base: sdw shim base.
+ * @alh_base: sdw alh base.
  */
 struct sdw_intel_res {
        int count;
@@ -157,6 +242,8 @@ struct sdw_intel_res {
        struct device *dev;
        u32 link_mask;
        u32 clock_stop_quirks;
+       u32 shim_base;
+       u32 alh_base;
 };
 
 /*
index 277087f..d91289c 100644 (file)
@@ -165,8 +165,6 @@ struct snd_compr {
 };
 
 /* compress device register APIs */
-int snd_compress_register(struct snd_compr *device);
-int snd_compress_deregister(struct snd_compr *device);
 int snd_compress_new(struct snd_card *card, int device,
                        int type, const char *id, struct snd_compr *compr);
 
index c4ade12..b7e9b58 100644 (file)
@@ -117,6 +117,8 @@ struct snd_card {
        struct device card_dev;         /* cardX object for sysfs */
        const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */
        bool registered;                /* card_dev is registered? */
+       bool managed;                   /* managed via devres */
+       bool releasing;                 /* during card free process */
        int sync_irq;                   /* assigned irq, used for PCM sync */
        wait_queue_head_t remove_sleep;
 
@@ -274,6 +276,9 @@ extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd);
 int snd_card_new(struct device *parent, int idx, const char *xid,
                 struct module *module, int extra_size,
                 struct snd_card **card_ret);
+int snd_devm_card_new(struct device *parent, int idx, const char *xid,
+                     struct module *module, size_t extra_size,
+                     struct snd_card **card_ret);
 
 int snd_card_disconnect(struct snd_card *card);
 void snd_card_disconnect_sync(struct snd_card *card);
@@ -324,6 +329,7 @@ int snd_device_get_state(struct snd_card *card, void *device_data);
 void snd_dma_program(unsigned long dma, unsigned long addr, unsigned int size, unsigned short mode);
 void snd_dma_disable(unsigned long dma);
 unsigned int snd_dma_pointer(unsigned long dma, unsigned int size);
+int snd_devm_request_dma(struct device *dev, int dma, const char *name);
 #endif
 
 /* misc.c */
index 468e38c..39787fe 100644 (file)
@@ -1701,7 +1701,7 @@ struct snd_emu10k1 {
        struct snd_dma_buffer silent_page;      /* silent page */
        struct snd_dma_buffer ptb_pages;        /* page table pages */
        struct snd_dma_device p16v_dma_dev;
-       struct snd_dma_buffer p16v_buffer;
+       struct snd_dma_buffer *p16v_buffer;
 
        struct snd_util_memhdr *memhdr;         /* page allocation list */
 
@@ -1796,14 +1796,12 @@ int snd_emu10k1_create(struct snd_card *card,
                       unsigned short extout_mask,
                       long max_cache_bytes,
                       int enable_ir,
-                      uint subsystem,
-                      struct snd_emu10k1 ** remu);
+                      uint subsystem);
 
 int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device);
 int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device);
 int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device);
 int snd_p16v_pcm(struct snd_emu10k1 *emu, int device);
-int snd_p16v_free(struct snd_emu10k1 * emu);
 int snd_p16v_mixer(struct snd_emu10k1 * emu);
 int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device);
 int snd_emu10k1_fx8010_pcm(struct snd_emu10k1 *emu, int device);
index ad0365d..072791b 100644 (file)
@@ -56,9 +56,6 @@ struct snd_emu8000 {
        unsigned long port1;    /* Port usually base+0 */
        unsigned long port2;    /* Port usually at base+0x400 */
        unsigned long port3;    /* Port usually at base+0x800 */
-       struct resource *res_port1;
-       struct resource *res_port2;
-       struct resource *res_port3;
        unsigned short last_reg;/* Last register command */
        spinlock_t reg_lock;
 
index 2e8d519..01570db 100644 (file)
@@ -114,7 +114,6 @@ struct hda_codec_ops {
        int (*resume)(struct hda_codec *codec);
        int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid);
 #endif
-       void (*reboot_notify)(struct hda_codec *codec);
        void (*stream_pm)(struct hda_codec *codec, hda_nid_t nid, bool on);
 };
 
index a125e38..3755816 100644 (file)
@@ -51,7 +51,7 @@ enum hdac_ext_stream_type {
  * @decoupled: stream host and link is decoupled
  * @link_locked: link is locked
  * @link_prepared: link is prepared
- * link_substream: link substream
+ * @link_substream: link substream
  */
 struct hdac_ext_stream {
        struct hdac_stream hstream;
index 44d8777..b197e3f 100644 (file)
@@ -31,13 +31,13 @@ struct snd_dma_device {
 #define SNDRV_DMA_TYPE_UNKNOWN         0       /* not defined */
 #define SNDRV_DMA_TYPE_CONTINUOUS      1       /* continuous no-DMA memory */
 #define SNDRV_DMA_TYPE_DEV             2       /* generic device continuous */
-#define SNDRV_DMA_TYPE_DEV_UC          5       /* continuous non-cahced */
+#define SNDRV_DMA_TYPE_DEV_WC          5       /* continuous write-combined */
 #ifdef CONFIG_SND_DMA_SGBUF
 #define SNDRV_DMA_TYPE_DEV_SG          3       /* generic device SG-buffer */
-#define SNDRV_DMA_TYPE_DEV_UC_SG       6       /* SG non-cached */
+#define SNDRV_DMA_TYPE_DEV_WC_SG       6       /* SG write-combined */
 #else
 #define SNDRV_DMA_TYPE_DEV_SG  SNDRV_DMA_TYPE_DEV /* no SG-buf support */
-#define SNDRV_DMA_TYPE_DEV_UC_SG       SNDRV_DMA_TYPE_DEV_UC
+#define SNDRV_DMA_TYPE_DEV_WC_SG       SNDRV_DMA_TYPE_DEV_WC
 #endif
 #ifdef CONFIG_GENERIC_ALLOCATOR
 #define SNDRV_DMA_TYPE_DEV_IRAM                4       /* generic device iram-buffer */
@@ -79,5 +79,9 @@ struct page *snd_sgbuf_get_page(struct snd_dma_buffer *dmab, size_t offset);
 unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
                                      unsigned int ofs, unsigned int size);
 
+/* device-managed memory allocator */
+struct snd_dma_buffer *snd_devm_alloc_pages(struct device *dev, int type,
+                                           size_t size);
+
 #endif /* __SOUND_MEMALLOC_H */
 
index 938f360..33451f8 100644 (file)
@@ -1204,11 +1204,48 @@ void snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
 int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size);
 int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream);
 
-void snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
-                               struct device *data, size_t size, size_t max);
-void snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
-                                   struct device *data,
-                                   size_t size, size_t max);
+int snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
+                              struct device *data, size_t size, size_t max);
+int snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
+                                  struct device *data,
+                                  size_t size, size_t max);
+
+/**
+ * snd_pcm_set_fixed_buffer - Preallocate and set up the fixed size PCM buffer
+ * @substream: the pcm substream instance
+ * @type: DMA type (SNDRV_DMA_TYPE_*)
+ * @data: DMA type dependent data
+ * @size: the requested pre-allocation size in bytes
+ *
+ * This is a variant of snd_pcm_set_managed_buffer(), but this pre-allocates
+ * only the given sized buffer and doesn't allow re-allocation nor dynamic
+ * allocation of a larger buffer unlike the standard one.
+ * The function may return -ENOMEM error, hence the caller must check it.
+ */
+static inline int __must_check
+snd_pcm_set_fixed_buffer(struct snd_pcm_substream *substream, int type,
+                                struct device *data, size_t size)
+{
+       return snd_pcm_set_managed_buffer(substream, type, data, size, 0);
+}
+
+/**
+ * snd_pcm_set_fixed_buffer_all - Preallocate and set up the fixed size PCM buffer
+ * @pcm: the pcm instance
+ * @type: DMA type (SNDRV_DMA_TYPE_*)
+ * @data: DMA type dependent data
+ * @size: the requested pre-allocation size in bytes
+ *
+ * Apply the set up of the fixed buffer via snd_pcm_set_fixed_buffer() for
+ * all substream.  If any of allocation fails, it returns -ENOMEM, hence the
+ * caller must check the return value.
+ */
+static inline int __must_check
+snd_pcm_set_fixed_buffer_all(struct snd_pcm *pcm, int type,
+                            struct device *data, size_t size)
+{
+       return snd_pcm_set_managed_buffer_all(pcm, type, data, size, 0);
+}
 
 int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
                                      size_t size, gfp_t gfp_flags);
index 0feaf16..95100cf 100644 (file)
@@ -14,18 +14,12 @@ struct snd_soc_component;
 
 extern int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params);
-extern int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream);
 extern int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
 extern snd_pcm_uframes_t pxa2xx_pcm_pointer(struct snd_pcm_substream *substream);
 extern int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream);
 extern int pxa2xx_pcm_open(struct snd_pcm_substream *substream);
 extern int pxa2xx_pcm_close(struct snd_pcm_substream *substream);
-extern int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
-       struct vm_area_struct *vma);
-extern int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream);
-extern void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm);
-extern void pxa2xx_soc_pcm_free(struct snd_soc_component *component,
-                               struct snd_pcm *pcm);
+extern int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm);
 extern int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
                              struct snd_soc_pcm_runtime *rtd);
 extern int pxa2xx_soc_pcm_open(struct snd_soc_component *component,
@@ -35,8 +29,6 @@ extern int pxa2xx_soc_pcm_close(struct snd_soc_component *component,
 extern int pxa2xx_soc_pcm_hw_params(struct snd_soc_component *component,
                                    struct snd_pcm_substream *substream,
                                    struct snd_pcm_hw_params *params);
-extern int pxa2xx_soc_pcm_hw_free(struct snd_soc_component *component,
-                                 struct snd_pcm_substream *substream);
 extern int pxa2xx_soc_pcm_prepare(struct snd_soc_component *component,
                                  struct snd_pcm_substream *substream);
 extern int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component,
@@ -44,9 +36,6 @@ extern int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component,
 extern snd_pcm_uframes_t
 pxa2xx_soc_pcm_pointer(struct snd_soc_component *component,
                       struct snd_pcm_substream *substream);
-extern int pxa2xx_soc_pcm_mmap(struct snd_soc_component *component,
-                              struct snd_pcm_substream *substream,
-                              struct vm_area_struct *vma);
 
 /* AC97 */
 
index 502ed9b..6a1cd8e 100644 (file)
@@ -101,5 +101,6 @@ struct sof_dev_desc {
 };
 
 int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd);
+int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd);
 
 #endif
index d17c061..1d84ec9 100644 (file)
@@ -299,6 +299,7 @@ typedef int __bitwise snd_pcm_subformat_t;
 #define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME     0x02000000  /* report absolute hardware link audio time, not reset on startup */
 #define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME    0x04000000  /* report estimated link audio time */
 #define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000  /* report synchronized audio/system time */
+#define SNDRV_PCM_INFO_EXPLICIT_SYNC   0x10000000      /* needs explicit sync of pointers and data */
 
 #define SNDRV_PCM_INFO_DRAIN_TRIGGER   0x40000000              /* internal kernel flag - trigger in drain */
 #define SNDRV_PCM_INFO_FIFO_IN_FRAMES  0x80000000      /* internal kernel flag - FIFO size is in frames */
index 8ba0112..ff3748e 100644 (file)
  *
  * %SKL_TKN_U32_ASTATE_CLK_SRC: Clock source for A-State entry
  *
+ * %SKL_TKN_U32_FMT_CFG_IDX:    Format config index
+ *
  * module_id and loadable flags dont have tokens as these values will be
  * read from the DSP FW manifest
  *
@@ -324,7 +326,9 @@ enum SKL_TKNS {
        SKL_TKN_U32_ASTATE_COUNT,
        SKL_TKN_U32_ASTATE_KCPS,
        SKL_TKN_U32_ASTATE_CLK_SRC,
-       SKL_TKN_MAX = SKL_TKN_U32_ASTATE_CLK_SRC,
+
+       SKL_TKN_U32_FMT_CFG_IDX = 96,
+       SKL_TKN_MAX = SKL_TKN_U32_FMT_CFG_IDX,
 };
 
 #endif
index a67e668..c17a19f 100644 (file)
@@ -172,38 +172,28 @@ static const struct snd_pcm_ops pxa2xx_ac97_pcm_ops = {
        .open           = pxa2xx_ac97_pcm_open,
        .close          = pxa2xx_ac97_pcm_close,
        .hw_params      = pxa2xx_pcm_hw_params,
-       .hw_free        = pxa2xx_pcm_hw_free,
        .prepare        = pxa2xx_ac97_pcm_prepare,
        .trigger        = pxa2xx_pcm_trigger,
        .pointer        = pxa2xx_pcm_pointer,
-       .mmap           = pxa2xx_pcm_mmap,
 };
 
 
 static int pxa2xx_ac97_pcm_new(struct snd_card *card)
 {
        struct snd_pcm *pcm;
-       int stream, ret;
+       int ret;
 
        ret = snd_pcm_new(card, "PXA2xx-PCM", 0, 1, 1, &pcm);
        if (ret)
                goto out;
 
-       pcm->private_free = pxa2xx_pcm_free_dma_buffers;
-
        ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
        if (ret)
                goto out;
 
-       stream = SNDRV_PCM_STREAM_PLAYBACK;
-       snd_pcm_set_ops(pcm, stream, &pxa2xx_ac97_pcm_ops);
-       ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
-       if (ret)
-               goto out;
-
-       stream = SNDRV_PCM_STREAM_CAPTURE;
-       snd_pcm_set_ops(pcm, stream, &pxa2xx_ac97_pcm_ops);
-       ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pxa2xx_ac97_pcm_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pxa2xx_ac97_pcm_ops);
+       ret = pxa2xx_pcm_preallocate_dma_buffer(pcm);
        if (ret)
                goto out;
 
index e81083e..0a48805 100644 (file)
@@ -54,19 +54,10 @@ int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
        if (ret)
                return ret;
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
        return 0;
 }
 EXPORT_SYMBOL(pxa2xx_pcm_hw_params);
 
-int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       snd_pcm_set_runtime_buffer(substream, NULL);
-       return 0;
-}
-EXPORT_SYMBOL(pxa2xx_pcm_hw_free);
-
 int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        return snd_dmaengine_pcm_trigger(substream, cmd);
@@ -131,56 +122,14 @@ int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
 }
 EXPORT_SYMBOL(pxa2xx_pcm_close);
 
-int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
-       struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
-                          runtime->dma_addr, runtime->dma_bytes);
-}
-EXPORT_SYMBOL(pxa2xx_pcm_mmap);
-
-int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm)
 {
-       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-       struct snd_dma_buffer *buf = &substream->dma_buffer;
        size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
-       buf->dev.type = SNDRV_DMA_TYPE_DEV;
-       buf->dev.dev = pcm->card->dev;
-       buf->private_data = NULL;
-       buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL);
-       if (!buf->area)
-               return -ENOMEM;
-       buf->bytes = size;
-       return 0;
-}
-EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer);
 
-void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       struct snd_dma_buffer *buf;
-       int stream;
-
-       for (stream = 0; stream < 2; stream++) {
-               substream = pcm->streams[stream].substream;
-               if (!substream)
-                       continue;
-               buf = &substream->dma_buffer;
-               if (!buf->area)
-                       continue;
-               dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr);
-               buf->area = NULL;
-       }
-}
-EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers);
-
-void pxa2xx_soc_pcm_free(struct snd_soc_component *component,
-                        struct snd_pcm *pcm)
-{
-       pxa2xx_pcm_free_dma_buffers(pcm);
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
+                                           pcm->card->dev, size);
 }
-EXPORT_SYMBOL(pxa2xx_soc_pcm_free);
+EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer);
 
 int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
                       struct snd_soc_pcm_runtime *rtd)
@@ -193,21 +142,7 @@ int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
        if (ret)
                return ret;
 
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
-                       SNDRV_PCM_STREAM_PLAYBACK);
-               if (ret)
-                       goto out;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
-                       SNDRV_PCM_STREAM_CAPTURE);
-               if (ret)
-                       goto out;
-       }
- out:
-       return ret;
+       return pxa2xx_pcm_preallocate_dma_buffer(pcm);
 }
 EXPORT_SYMBOL(pxa2xx_soc_pcm_new);
 
@@ -233,13 +168,6 @@ int pxa2xx_soc_pcm_hw_params(struct snd_soc_component *component,
 }
 EXPORT_SYMBOL(pxa2xx_soc_pcm_hw_params);
 
-int pxa2xx_soc_pcm_hw_free(struct snd_soc_component *component,
-                          struct snd_pcm_substream *substream)
-{
-       return pxa2xx_pcm_hw_free(substream);
-}
-EXPORT_SYMBOL(pxa2xx_soc_pcm_hw_free);
-
 int pxa2xx_soc_pcm_prepare(struct snd_soc_component *component,
                           struct snd_pcm_substream *substream)
 {
@@ -262,14 +190,6 @@ pxa2xx_soc_pcm_pointer(struct snd_soc_component *component,
 }
 EXPORT_SYMBOL(pxa2xx_soc_pcm_pointer);
 
-int pxa2xx_soc_pcm_mmap(struct snd_soc_component *component,
-                       struct snd_pcm_substream *substream,
-                       struct vm_area_struct *vma)
-{
-       return pxa2xx_pcm_mmap(substream, vma);
-}
-EXPORT_SYMBOL(pxa2xx_soc_pcm_mmap);
-
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("Intel PXA2xx sound library");
 MODULE_LICENSE("GPL");
index 21ce4c0..de514ec 100644 (file)
@@ -47,8 +47,6 @@
  *     driver should be able to register multiple nodes
  */
 
-static DEFINE_MUTEX(device_mutex);
-
 struct snd_compr_file {
        unsigned long caps;
        struct snd_compr_stream stream;
@@ -1179,6 +1177,7 @@ int snd_compress_new(struct snd_card *card, int device,
        compr->card = card;
        compr->device = device;
        compr->direction = dirn;
+       mutex_init(&compr->lock);
 
        snd_compress_set_id(compr, id);
 
@@ -1193,72 +1192,6 @@ int snd_compress_new(struct snd_card *card, int device,
 }
 EXPORT_SYMBOL_GPL(snd_compress_new);
 
-static int snd_compress_add_device(struct snd_compr *device)
-{
-       int ret;
-
-       if (!device->card)
-               return -EINVAL;
-
-       /* register the card */
-       ret = snd_card_register(device->card);
-       if (ret)
-               goto out;
-       return 0;
-
-out:
-       pr_err("failed with %d\n", ret);
-       return ret;
-
-}
-
-static int snd_compress_remove_device(struct snd_compr *device)
-{
-       return snd_card_free(device->card);
-}
-
-/**
- * snd_compress_register - register compressed device
- *
- * @device: compressed device to register
- */
-int snd_compress_register(struct snd_compr *device)
-{
-       int retval;
-
-       if (device->name == NULL || device->ops == NULL)
-               return -EINVAL;
-
-       pr_debug("Registering compressed device %s\n", device->name);
-       if (snd_BUG_ON(!device->ops->open))
-               return -EINVAL;
-       if (snd_BUG_ON(!device->ops->free))
-               return -EINVAL;
-       if (snd_BUG_ON(!device->ops->set_params))
-               return -EINVAL;
-       if (snd_BUG_ON(!device->ops->trigger))
-               return -EINVAL;
-
-       mutex_init(&device->lock);
-
-       /* register a compressed card */
-       mutex_lock(&device_mutex);
-       retval = snd_compress_add_device(device);
-       mutex_unlock(&device_mutex);
-       return retval;
-}
-EXPORT_SYMBOL_GPL(snd_compress_register);
-
-int snd_compress_deregister(struct snd_compr *device)
-{
-       pr_debug("Removing compressed device %s\n", device->name);
-       mutex_lock(&device_mutex);
-       snd_compress_remove_device(device);
-       mutex_unlock(&device_mutex);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(snd_compress_deregister);
-
 MODULE_DESCRIPTION("ALSA Compressed offload framework");
 MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
 MODULE_LICENSE("GPL v2");
index 764058c..a95332b 100644 (file)
@@ -564,7 +564,7 @@ static ssize_t set_led_id(struct snd_ctl_led_card *led_card, const char *buf, si
                        else {
                                for (; *s >= ' '; s++);
                                *s = '\0';
-                               strlcpy(id.name, buf2, sizeof(id.name));
+                               strscpy(id.name, buf2, sizeof(id.name));
                        }
                        break;
                }
index 1490568..ac335f5 100644 (file)
@@ -134,6 +134,9 @@ void snd_device_initialize(struct device *dev, struct snd_card *card)
 }
 EXPORT_SYMBOL_GPL(snd_device_initialize);
 
+static int snd_card_init(struct snd_card *card, struct device *parent,
+                        int idx, const char *xid, struct module *module,
+                        size_t extra_size);
 static int snd_card_do_free(struct snd_card *card);
 static const struct attribute_group card_dev_attr_group;
 
@@ -163,9 +166,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
 {
        struct snd_card *card;
        int err;
-#ifdef CONFIG_SND_DEBUG
-       char name[8];
-#endif
 
        if (snd_BUG_ON(!card_ret))
                return -EINVAL;
@@ -176,6 +176,74 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
        card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
        if (!card)
                return -ENOMEM;
+
+       err = snd_card_init(card, parent, idx, xid, module, extra_size);
+       if (err < 0) {
+               kfree(card);
+               return err;
+       }
+
+       *card_ret = card;
+       return 0;
+}
+EXPORT_SYMBOL(snd_card_new);
+
+static void __snd_card_release(struct device *dev, void *data)
+{
+       snd_card_free(data);
+}
+
+/**
+ * snd_devm_card_new - managed snd_card object creation
+ * @parent: the parent device object
+ * @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
+ * @xid: card identification (ASCII string)
+ * @module: top level module for locking
+ * @extra_size: allocate this extra size after the main soundcard structure
+ * @card_ret: the pointer to store the created card instance
+ *
+ * This function works like snd_card_new() but manages the allocated resource
+ * via devres, i.e. you don't need to free explicitly.
+ *
+ * When a snd_card object is created with this function and registered via
+ * snd_card_register(), the very first devres action to call snd_card_free()
+ * is added automatically.  In that way, the resource disconnection is assured
+ * at first, then released in the expected order.
+ */
+int snd_devm_card_new(struct device *parent, int idx, const char *xid,
+                     struct module *module, size_t extra_size,
+                     struct snd_card **card_ret)
+{
+       struct snd_card *card;
+       int err;
+
+       *card_ret = NULL;
+       card = devres_alloc(__snd_card_release, sizeof(*card) + extra_size,
+                           GFP_KERNEL);
+       if (!card)
+               return -ENOMEM;
+       card->managed = true;
+       err = snd_card_init(card, parent, idx, xid, module, extra_size);
+       if (err < 0) {
+               devres_free(card);
+               return err;
+       }
+
+       devres_add(parent, card);
+       *card_ret = card;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_devm_card_new);
+
+static int snd_card_init(struct snd_card *card, struct device *parent,
+                        int idx, const char *xid, struct module *module,
+                        size_t extra_size)
+{
+       int err;
+#ifdef CONFIG_SND_DEBUG
+       char name[8];
+#endif
+
        if (extra_size > 0)
                card->private_data = (char *)card + sizeof(struct snd_card);
        if (xid)
@@ -197,7 +265,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
                mutex_unlock(&snd_card_mutex);
                dev_err(parent, "cannot find the slot for index %d (range 0-%i), error: %d\n",
                         idx, snd_ecards_limit - 1, err);
-               kfree(card);
                return err;
        }
        set_bit(idx, snd_cards_lock);           /* lock it */
@@ -256,8 +323,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
        sprintf(name, "card%d", idx);
        card->debugfs_root = debugfs_create_dir(name, sound_debugfs_root);
 #endif
-
-       *card_ret = card;
        return 0;
 
       __error_ctl:
@@ -266,7 +331,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
        put_device(&card->card_dev);
        return err;
 }
-EXPORT_SYMBOL(snd_card_new);
 
 /**
  * snd_card_ref - Get the card object from the index
@@ -481,6 +545,7 @@ EXPORT_SYMBOL_GPL(snd_card_disconnect_sync);
 
 static int snd_card_do_free(struct snd_card *card)
 {
+       card->releasing = true;
 #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
        if (snd_mixer_oss_notify_callback)
                snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
@@ -498,7 +563,8 @@ static int snd_card_do_free(struct snd_card *card)
 #endif
        if (card->release_completion)
                complete(card->release_completion);
-       kfree(card);
+       if (!card->managed)
+               kfree(card);
        return 0;
 }
 
@@ -539,6 +605,15 @@ int snd_card_free(struct snd_card *card)
        DECLARE_COMPLETION_ONSTACK(released);
        int ret;
 
+       /* The call of snd_card_free() is allowed from various code paths;
+        * a manual call from the driver and the call via devres_free, and
+        * we need to avoid double-free. Moreover, the release via devres
+        * may call snd_card_free() twice due to its nature, we need to have
+        * the check here at the beginning.
+        */
+       if (card->releasing)
+               return 0;
+
        card->release_completion = &released;
        ret = snd_card_free_when_closed(card);
        if (ret)
@@ -745,6 +820,11 @@ int snd_card_add_dev_attr(struct snd_card *card,
 }
 EXPORT_SYMBOL_GPL(snd_card_add_dev_attr);
 
+static void trigger_card_free(void *data)
+{
+       snd_card_free(data);
+}
+
 /**
  *  snd_card_register - register the soundcard
  *  @card: soundcard structure
@@ -768,6 +848,15 @@ int snd_card_register(struct snd_card *card)
                if (err < 0)
                        return err;
                card->registered = true;
+       } else {
+               if (card->managed)
+                       devm_remove_action(card->dev, trigger_card_free, card);
+       }
+
+       if (card->managed) {
+               err = devm_add_action(card->dev, trigger_card_free, card);
+               if (err < 0)
+                       return err;
        }
 
        err = snd_device_register_all(card);
index c3d789e..1f45ede 100644 (file)
@@ -97,3 +97,41 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
                return size - result;
 }
 EXPORT_SYMBOL(snd_dma_pointer);
+
+struct snd_dma_data {
+       int dma;
+};
+
+static void __snd_release_dma(struct device *dev, void *data)
+{
+       struct snd_dma_data *p = data;
+
+       snd_dma_disable(p->dma);
+       free_dma(p->dma);
+}
+
+/**
+ * snd_devm_request_dma - the managed version of request_dma()
+ * @dev: the device pointer
+ * @dma: the dma number
+ * @name: the name string of the requester
+ *
+ * Returns zero on success, or a negative error code.
+ * The requested DMA will be automatically released at unbinding via devres.
+ */
+int snd_devm_request_dma(struct device *dev, int dma, const char *name)
+{
+       struct snd_dma_data *p;
+
+       if (request_dma(dma, name))
+               return -EBUSY;
+       p = devres_alloc(__snd_release_dma, sizeof(*p), GFP_KERNEL);
+       if (!p) {
+               free_dma(dma);
+               return -ENOMEM;
+       }
+       p->dma = dma;
+       devres_add(dev, p);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_devm_request_dma);
index 439a358..c7c943c 100644 (file)
@@ -29,12 +29,12 @@ static inline gfp_t snd_mem_get_gfp_flags(const struct snd_dma_buffer *dmab,
                return (__force gfp_t)(unsigned long)dmab->dev.dev;
 }
 
-static int __snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
+static void *__snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
 {
        const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
 
        if (WARN_ON_ONCE(!ops || !ops->alloc))
-               return -EINVAL;
+               return NULL;
        return ops->alloc(dmab, size);
 }
 
@@ -54,8 +54,6 @@ static int __snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
 int snd_dma_alloc_pages(int type, struct device *device, size_t size,
                        struct snd_dma_buffer *dmab)
 {
-       int err;
-
        if (WARN_ON(!size))
                return -ENXIO;
        if (WARN_ON(!dmab))
@@ -65,12 +63,9 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
        dmab->dev.type = type;
        dmab->dev.dev = device;
        dmab->bytes = 0;
-       dmab->area = NULL;
        dmab->addr = 0;
        dmab->private_data = NULL;
-       err = __snd_dma_alloc_pages(dmab, size);
-       if (err < 0)
-               return err;
+       dmab->area = __snd_dma_alloc_pages(dmab, size);
        if (!dmab->area)
                return -ENOMEM;
        dmab->bytes = size;
@@ -127,6 +122,52 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
 }
 EXPORT_SYMBOL(snd_dma_free_pages);
 
+/* called by devres */
+static void __snd_release_pages(struct device *dev, void *res)
+{
+       snd_dma_free_pages(res);
+}
+
+/**
+ * snd_devm_alloc_pages - allocate the buffer and manage with devres
+ * @dev: the device pointer
+ * @type: the DMA buffer type
+ * @size: the buffer size to allocate
+ *
+ * Allocate buffer pages depending on the given type and manage using devres.
+ * The pages will be released automatically at the device removal.
+ *
+ * Unlike snd_dma_alloc_pages(), this function requires the real device pointer,
+ * hence it can't work with SNDRV_DMA_TYPE_CONTINUOUS or
+ * SNDRV_DMA_TYPE_VMALLOC type.
+ *
+ * The function returns the snd_dma_buffer object at success, or NULL if failed.
+ */
+struct snd_dma_buffer *
+snd_devm_alloc_pages(struct device *dev, int type, size_t size)
+{
+       struct snd_dma_buffer *dmab;
+       int err;
+
+       if (WARN_ON(type == SNDRV_DMA_TYPE_CONTINUOUS ||
+                   type == SNDRV_DMA_TYPE_VMALLOC))
+               return NULL;
+
+       dmab = devres_alloc(__snd_release_pages, sizeof(*dmab), GFP_KERNEL);
+       if (!dmab)
+               return NULL;
+
+       err = snd_dma_alloc_pages(type, dev, size, dmab);
+       if (err < 0) {
+               devres_free(dmab);
+               return NULL;
+       }
+
+       devres_add(dev, dmab);
+       return dmab;
+}
+EXPORT_SYMBOL_GPL(snd_devm_alloc_pages);
+
 /**
  * snd_dma_buffer_mmap - perform mmap of the given DMA buffer
  * @dmab: buffer allocation information
@@ -198,12 +239,14 @@ EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);
 /*
  * Continuous pages allocator
  */
-static int snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
        gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL);
+       void *p = alloc_pages_exact(size, gfp);
 
-       dmab->area = alloc_pages_exact(size, gfp);
-       return 0;
+       if (p)
+               dmab->addr = page_to_phys(virt_to_page(p));
+       return p;
 }
 
 static void snd_dma_continuous_free(struct snd_dma_buffer *dmab)
@@ -215,7 +258,7 @@ static int snd_dma_continuous_mmap(struct snd_dma_buffer *dmab,
                                   struct vm_area_struct *area)
 {
        return remap_pfn_range(area, area->vm_start,
-                              page_to_pfn(virt_to_page(dmab->area)),
+                              dmab->addr >> PAGE_SHIFT,
                               area->vm_end - area->vm_start,
                               area->vm_page_prot);
 }
@@ -229,12 +272,11 @@ static const struct snd_malloc_ops snd_dma_continuous_ops = {
 /*
  * VMALLOC allocator
  */
-static int snd_dma_vmalloc_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_vmalloc_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
        gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL | __GFP_HIGHMEM);
 
-       dmab->area = __vmalloc(size, gfp);
-       return 0;
+       return __vmalloc(size, gfp);
 }
 
 static void snd_dma_vmalloc_free(struct snd_dma_buffer *dmab)
@@ -248,11 +290,13 @@ static int snd_dma_vmalloc_mmap(struct snd_dma_buffer *dmab,
        return remap_vmalloc_range(area, dmab->area, 0);
 }
 
+#define get_vmalloc_page_addr(dmab, offset) \
+       page_to_phys(vmalloc_to_page((dmab)->area + (offset)))
+
 static dma_addr_t snd_dma_vmalloc_get_addr(struct snd_dma_buffer *dmab,
                                           size_t offset)
 {
-       return page_to_phys(vmalloc_to_page(dmab->area + offset)) +
-               offset % PAGE_SIZE;
+       return get_vmalloc_page_addr(dmab, offset) + offset % PAGE_SIZE;
 }
 
 static struct page *snd_dma_vmalloc_get_page(struct snd_dma_buffer *dmab,
@@ -265,11 +309,23 @@ static unsigned int
 snd_dma_vmalloc_get_chunk_size(struct snd_dma_buffer *dmab,
                               unsigned int ofs, unsigned int size)
 {
-       ofs %= PAGE_SIZE;
-       size += ofs;
-       if (size > PAGE_SIZE)
-               size = PAGE_SIZE;
-       return size - ofs;
+       unsigned int start, end;
+       unsigned long addr;
+
+       start = ALIGN_DOWN(ofs, PAGE_SIZE);
+       end = ofs + size - 1; /* the last byte address */
+       /* check page continuity */
+       addr = get_vmalloc_page_addr(dmab, start);
+       for (;;) {
+               start += PAGE_SIZE;
+               if (start > end)
+                       break;
+               addr += PAGE_SIZE;
+               if (get_vmalloc_page_addr(dmab, start) != addr)
+                       return start - ofs;
+       }
+       /* ok, all on continuous pages */
+       return size;
 }
 
 static const struct snd_malloc_ops snd_dma_vmalloc_ops = {
@@ -286,20 +342,20 @@ static const struct snd_malloc_ops snd_dma_vmalloc_ops = {
  * IRAM allocator
  */
 #ifdef CONFIG_GENERIC_ALLOCATOR
-static int snd_dma_iram_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_iram_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
        struct device *dev = dmab->dev.dev;
        struct gen_pool *pool;
+       void *p;
 
        if (dev->of_node) {
                pool = of_gen_pool_get(dev->of_node, "iram", 0);
                /* Assign the pool into private_data field */
                dmab->private_data = pool;
 
-               dmab->area = gen_pool_dma_alloc_align(pool, size, &dmab->addr,
-                                                     PAGE_SIZE);
-               if (dmab->area)
-                       return 0;
+               p = gen_pool_dma_alloc_align(pool, size, &dmab->addr, PAGE_SIZE);
+               if (p)
+                       return p;
        }
 
        /* Internal memory might have limited size and no enough space,
@@ -334,31 +390,31 @@ static const struct snd_malloc_ops snd_dma_iram_ops = {
 };
 #endif /* CONFIG_GENERIC_ALLOCATOR */
 
+#define DEFAULT_GFP \
+       (GFP_KERNEL | \
+        __GFP_COMP |    /* compound page lets parts be mapped */ \
+        __GFP_NORETRY | /* don't trigger OOM-killer */ \
+        __GFP_NOWARN)   /* no stack trace print - this call is non-critical */
+
 /*
  * Coherent device pages allocator
  */
-static int snd_dma_dev_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_dev_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
-       gfp_t gfp_flags;
-
-       gfp_flags = GFP_KERNEL
-               | __GFP_COMP    /* compound page lets parts be mapped */
-               | __GFP_NORETRY /* don't trigger OOM-killer */
-               | __GFP_NOWARN; /* no stack trace print - this call is non-critical */
-       dmab->area = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr,
-                                       gfp_flags);
+       void *p;
+
+       p = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
 #ifdef CONFIG_X86
-       if (dmab->area && dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
-               set_memory_wc((unsigned long)dmab->area,
-                             PAGE_ALIGN(size) >> PAGE_SHIFT);
+       if (p && dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
+               set_memory_wc((unsigned long)p, PAGE_ALIGN(size) >> PAGE_SHIFT);
 #endif
-       return 0;
+       return p;
 }
 
 static void snd_dma_dev_free(struct snd_dma_buffer *dmab)
 {
 #ifdef CONFIG_X86
-       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
                set_memory_wb((unsigned long)dmab->area,
                              PAGE_ALIGN(dmab->bytes) >> PAGE_SHIFT);
 #endif
@@ -368,6 +424,10 @@ static void snd_dma_dev_free(struct snd_dma_buffer *dmab)
 static int snd_dma_dev_mmap(struct snd_dma_buffer *dmab,
                            struct vm_area_struct *area)
 {
+#ifdef CONFIG_X86
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
+               area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+#endif
        return dma_mmap_coherent(dmab->dev.dev, area,
                                 dmab->area, dmab->addr, dmab->bytes);
 }
@@ -377,6 +437,37 @@ static const struct snd_malloc_ops snd_dma_dev_ops = {
        .free = snd_dma_dev_free,
        .mmap = snd_dma_dev_mmap,
 };
+
+/*
+ * Write-combined pages
+ */
+#ifdef CONFIG_X86
+/* On x86, share the same ops as the standard dev ops */
+#define snd_dma_wc_ops snd_dma_dev_ops
+#else /* CONFIG_X86 */
+static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
+{
+       return dma_alloc_wc(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
+}
+
+static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
+{
+       dma_free_wc(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
+}
+
+static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
+                          struct vm_area_struct *area)
+{
+       return dma_mmap_wc(dmab->dev.dev, area,
+                          dmab->area, dmab->addr, dmab->bytes);
+}
+
+static const struct snd_malloc_ops snd_dma_wc_ops = {
+       .alloc = snd_dma_wc_alloc,
+       .free = snd_dma_wc_free,
+       .mmap = snd_dma_wc_mmap,
+};
+#endif /* CONFIG_X86 */
 #endif /* CONFIG_HAS_DMA */
 
 /*
@@ -387,14 +478,14 @@ static const struct snd_malloc_ops *dma_ops[] = {
        [SNDRV_DMA_TYPE_VMALLOC] = &snd_dma_vmalloc_ops,
 #ifdef CONFIG_HAS_DMA
        [SNDRV_DMA_TYPE_DEV] = &snd_dma_dev_ops,
-       [SNDRV_DMA_TYPE_DEV_UC] = &snd_dma_dev_ops,
+       [SNDRV_DMA_TYPE_DEV_WC] = &snd_dma_wc_ops,
 #ifdef CONFIG_GENERIC_ALLOCATOR
        [SNDRV_DMA_TYPE_DEV_IRAM] = &snd_dma_iram_ops,
 #endif /* CONFIG_GENERIC_ALLOCATOR */
 #endif /* CONFIG_HAS_DMA */
 #ifdef CONFIG_SND_DMA_SGBUF
        [SNDRV_DMA_TYPE_DEV_SG] = &snd_dma_sg_ops,
-       [SNDRV_DMA_TYPE_DEV_UC_SG] = &snd_dma_sg_ops,
+       [SNDRV_DMA_TYPE_DEV_WC_SG] = &snd_dma_sg_ops,
 #endif
 };
 
index dbea7f2..9f2e0a6 100644 (file)
@@ -3,7 +3,7 @@
 #define __MEMALLOC_LOCAL_H
 
 struct snd_malloc_ops {
-       int (*alloc)(struct snd_dma_buffer *dmab, size_t size);
+       void *(*alloc)(struct snd_dma_buffer *dmab, size_t size);
        void (*free)(struct snd_dma_buffer *dmab);
        dma_addr_t (*get_addr)(struct snd_dma_buffer *dmab, size_t offset);
        struct page *(*get_page)(struct snd_dma_buffer *dmab, size_t offset);
index 7d58834..a144a3f 100644 (file)
@@ -1746,7 +1746,7 @@ static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream,
                channels = params_channels(params);
                frame_size = snd_pcm_format_size(format, channels);
                if (frame_size > 0)
-                       params->fifo_size /= (unsigned)frame_size;
+                       params->fifo_size /= frame_size;
        }
        return 0;
 }
index d7621ed..7fbd1cc 100644 (file)
@@ -67,7 +67,8 @@ static void do_free_pages(struct snd_card *card, struct snd_dma_buffer *dmab)
  *
  * the minimum size is snd_minimum_buffer.  it should be power of 2.
  */
-static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t size)
+static int preallocate_pcm_pages(struct snd_pcm_substream *substream,
+                                size_t size, bool no_fallback)
 {
        struct snd_dma_buffer *dmab = &substream->dma_buffer;
        struct snd_card *card = substream->pcm->card;
@@ -79,6 +80,8 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz
                                     size, dmab);
                if (err != -ENOMEM)
                        return err;
+               if (no_fallback)
+                       break;
                size >>= 1;
        } while (size >= snd_minimum_buffer);
        dmab->bytes = 0; /* tell error */
@@ -86,7 +89,7 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz
                substream->pcm->card->number, substream->pcm->device,
                substream->stream ? 'c' : 'p', substream->number,
                substream->pcm->name, orig_size);
-       return 0;
+       return -ENOMEM;
 }
 
 /**
@@ -222,18 +225,31 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
 /*
  * pre-allocate the buffer and create a proc file for the substream
  */
-static void preallocate_pages(struct snd_pcm_substream *substream,
+static int preallocate_pages(struct snd_pcm_substream *substream,
                              int type, struct device *data,
                              size_t size, size_t max, bool managed)
 {
+       int err;
+
        if (snd_BUG_ON(substream->dma_buffer.dev.type))
-               return;
+               return -EINVAL;
 
        substream->dma_buffer.dev.type = type;
        substream->dma_buffer.dev.dev = data;
 
-       if (size > 0 && preallocate_dma && substream->number < maximum_substreams)
-               preallocate_pcm_pages(substream, size);
+       if (size > 0) {
+               if (!max) {
+                       /* no fallback, only also inform -ENOMEM */
+                       err = preallocate_pcm_pages(substream, size, true);
+                       if (err < 0)
+                               return err;
+               } else if (preallocate_dma &&
+                          substream->number < maximum_substreams) {
+                       err = preallocate_pcm_pages(substream, size, false);
+                       if (err < 0 && err != -ENOMEM)
+                               return err;
+               }
+       }
 
        if (substream->dma_buffer.bytes > 0)
                substream->buffer_bytes_max = substream->dma_buffer.bytes;
@@ -242,17 +258,22 @@ static void preallocate_pages(struct snd_pcm_substream *substream,
                preallocate_info_init(substream);
        if (managed)
                substream->managed_buffer_alloc = 1;
+       return 0;
 }
 
-static void preallocate_pages_for_all(struct snd_pcm *pcm, int type,
+static int preallocate_pages_for_all(struct snd_pcm *pcm, int type,
                                      void *data, size_t size, size_t max,
                                      bool managed)
 {
        struct snd_pcm_substream *substream;
-       int stream;
+       int stream, err;
 
-       for_each_pcm_substream(pcm, stream, substream)
-               preallocate_pages(substream, type, data, size, max, managed);
+       for_each_pcm_substream(pcm, stream, substream) {
+               err = preallocate_pages(substream, type, data, size, max, managed);
+               if (err < 0)
+                       return err;
+       }
+       return 0;
 }
 
 /**
@@ -309,11 +330,22 @@ EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
  * When a buffer is actually allocated before the PCM hw_params call, it
  * turns on the runtime buffer_changed flag for drivers changing their h/w
  * parameters accordingly.
+ *
+ * When @size is non-zero and @max is zero, this tries to allocate for only
+ * the exact buffer size without fallback, and may return -ENOMEM.
+ * Otherwise, the function tries to allocate smaller chunks if the allocation
+ * fails.  This is the behavior of snd_pcm_set_fixed_buffer().
+ *
+ * When both @size and @max are zero, the function only sets up the buffer
+ * for later dynamic allocations. It's used typically for buffers with
+ * SNDRV_DMA_TYPE_VMALLOC type.
+ *
+ * Upon successful buffer allocation and setup, the function returns 0.
  */
-void snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
+int snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
                                struct device *data, size_t size, size_t max)
 {
-       preallocate_pages(substream, type, data, size, max, true);
+       return preallocate_pages(substream, type, data, size, max, true);
 }
 EXPORT_SYMBOL(snd_pcm_set_managed_buffer);
 
@@ -329,11 +361,11 @@ EXPORT_SYMBOL(snd_pcm_set_managed_buffer);
  * Do pre-allocation to all substreams of the given pcm for the specified DMA
  * type and size, and set the managed_buffer_alloc flag to each substream.
  */
-void snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
-                                   struct device *data,
-                                   size_t size, size_t max)
+int snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
+                                  struct device *data,
+                                  size_t size, size_t max)
 {
-       preallocate_pages_for_all(pcm, type, data, size, max, true);
+       return preallocate_pages_for_all(pcm, type, data, size, max, true);
 }
 EXPORT_SYMBOL(snd_pcm_set_managed_buffer_all);
 
@@ -376,6 +408,9 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
            substream->dma_buffer.bytes >= size) {
                dmab = &substream->dma_buffer; /* use the pre-allocated buffer */
        } else {
+               /* dma_max=0 means the fixed size preallocation */
+               if (substream->dma_buffer.area && !substream->dma_max)
+                       return -ENOMEM;
                dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
                if (! dmab)
                        return -ENOMEM;
index 71323d8..d233cb3 100644 (file)
@@ -243,13 +243,18 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
 
 static bool hw_support_mmap(struct snd_pcm_substream *substream)
 {
+       struct snd_dma_buffer *dmabuf;
+
        if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
                return false;
 
        if (substream->ops->mmap || substream->ops->page)
                return true;
 
-       switch (substream->dma_buffer.dev.type) {
+       dmabuf = snd_pcm_get_dma_buf(substream);
+       if (!dmabuf)
+               dmabuf = &substream->dma_buffer;
+       switch (dmabuf->dev.type) {
        case SNDRV_DMA_TYPE_UNKNOWN:
                /* we can't know the device, so just assume that the driver does
                 * everything right
@@ -259,7 +264,7 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
        case SNDRV_DMA_TYPE_VMALLOC:
                return true;
        default:
-               return dma_can_mmap(substream->dma_buffer.dev.dev);
+               return dma_can_mmap(dmabuf->dev.dev);
        }
 }
 
@@ -3616,6 +3621,12 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
 
 static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
 {
+       /* If drivers require the explicit sync (typically for non-coherent
+        * pages), we have to disable the mmap of status and control data
+        * to enforce the control via SYNC_PTR ioctl.
+        */
+       if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_EXPLICIT_SYNC)
+               return false;
        /* See pcm_control_mmap_allowed() below.
         * Since older alsa-lib requires both status and control mmaps to be
         * coupled, we have to disable the status mmap for old alsa-lib, too.
@@ -3630,6 +3641,9 @@ static bool pcm_control_mmap_allowed(struct snd_pcm_file *pcm_file)
 {
        if (pcm_file->no_compat_mmap)
                return false;
+       /* see above */
+       if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_EXPLICIT_SYNC)
+               return false;
        /* Disallow the control mmap when SYNC_APPLPTR flag is set;
         * it enforces the user-space to fall back to snd_pcm_sync_ptr(),
         * thus it effectively assures the manual update of appl_ptr.
index ac760b1..8c18d8c 100644 (file)
   are redirected to output port immediately.
   The routing can be done via aconnect program in alsa-utils.
 
-  Each client has a static client number 62 (= SNDRV_SEQ_CLIENT_DUMMY).
+  Each client has a static client number 14 (= SNDRV_SEQ_CLIENT_DUMMY).
   If you want to auto-load this module, you may add the following alias
   in your /etc/conf.modules file.
 
-       alias snd-seq-client-62  snd-seq-dummy
+       alias snd-seq-client-14  snd-seq-dummy
 
-  The module is loaded on demand for client 62, or /proc/asound/seq/
+  The module is loaded on demand for client 14, or /proc/asound/seq/
   is accessed.  If you don't need this module to be loaded, alias
-  snd-seq-client-62 as "off".  This will help modprobe.
+  snd-seq-client-14 as "off".  This will help modprobe.
 
   The number of ports to be created can be specified via the module
   parameter "ports".  For example, to create four ports, add the
index 232cf3f..8352a5c 100644 (file)
@@ -43,8 +43,8 @@ static void snd_dma_sg_free(struct snd_dma_buffer *dmab)
        dmab->area = NULL;
 
        tmpb.dev.type = SNDRV_DMA_TYPE_DEV;
-       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC_SG)
-               tmpb.dev.type = SNDRV_DMA_TYPE_DEV_UC;
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
+               tmpb.dev.type = SNDRV_DMA_TYPE_DEV_WC;
        tmpb.dev.dev = sgbuf->dev;
        for (i = 0; i < sgbuf->pages; i++) {
                if (!(sgbuf->table[i].addr & ~PAGE_MASK))
@@ -63,7 +63,7 @@ static void snd_dma_sg_free(struct snd_dma_buffer *dmab)
 
 #define MAX_ALLOC_PAGES                32
 
-static int snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
        struct snd_sg_buf *sgbuf;
        unsigned int i, pages, chunk, maxpages;
@@ -72,12 +72,13 @@ static int snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
        struct page **pgtable;
        int type = SNDRV_DMA_TYPE_DEV;
        pgprot_t prot = PAGE_KERNEL;
+       void *area;
 
        dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
        if (!sgbuf)
-               return -ENOMEM;
-       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC_SG) {
-               type = SNDRV_DMA_TYPE_DEV_UC;
+               return NULL;
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG) {
+               type = SNDRV_DMA_TYPE_DEV_WC;
 #ifdef pgprot_noncached
                prot = pgprot_noncached(PAGE_KERNEL);
 #endif
@@ -127,14 +128,14 @@ static int snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
        }
 
        sgbuf->size = size;
-       dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, prot);
-       if (! dmab->area)
+       area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, prot);
+       if (!area)
                goto _failed;
-       return 0;
+       return area;
 
  _failed:
        snd_dma_sg_free(dmab); /* free the table */
-       return -ENOMEM;
+       return NULL;
 }
 
 static dma_addr_t snd_dma_sg_get_addr(struct snd_dma_buffer *dmab,
@@ -182,10 +183,19 @@ static unsigned int snd_dma_sg_get_chunk_size(struct snd_dma_buffer *dmab,
        return size;
 }
 
+static int snd_dma_sg_mmap(struct snd_dma_buffer *dmab,
+                          struct vm_area_struct *area)
+{
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
+               area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+       return -ENOENT; /* continue with the default mmap handler */
+}
+
 const struct snd_malloc_ops snd_dma_sg_ops = {
        .alloc = snd_dma_sg_alloc,
        .free = snd_dma_sg_free,
        .get_addr = snd_dma_sg_get_addr,
        .get_page = snd_dma_sg_get_page,
        .get_chunk_size = snd_dma_sg_get_chunk_size,
+       .mmap = snd_dma_sg_mmap,
 };
index 7141f73..ca4cdf6 100644 (file)
@@ -102,7 +102,7 @@ config SND_ALOOP
          configured number of substreams (see the pcm_substreams module
          parameter).
 
-         The loopback device allows time sychronization with an external
+         The loopback device allows time synchronization with an external
          timing source using the time shift universal control (+-20%
          of system time).
 
index 80b814b..9b4a7cd 100644 (file)
@@ -1712,8 +1712,8 @@ static int loopback_probe(struct platform_device *devptr)
        int dev = devptr->id;
        int err;
 
-       err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct loopback), &card);
+       err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct loopback), &card);
        if (err < 0)
                return err;
        loopback = card->private_data;
@@ -1730,13 +1730,13 @@ static int loopback_probe(struct platform_device *devptr)
 
        err = loopback_pcm_new(loopback, 0, pcm_substreams[dev]);
        if (err < 0)
-               goto __nodev;
+               return err;
        err = loopback_pcm_new(loopback, 1, pcm_substreams[dev]);
        if (err < 0)
-               goto __nodev;
+               return err;
        err = loopback_mixer_new(loopback, pcm_notify[dev] ? 1 : 0);
        if (err < 0)
-               goto __nodev;
+               return err;
        loopback_cable_proc_new(loopback, 0);
        loopback_cable_proc_new(loopback, 1);
        loopback_timer_source_proc_new(loopback);
@@ -1744,18 +1744,9 @@ static int loopback_probe(struct platform_device *devptr)
        strcpy(card->shortname, "Loopback");
        sprintf(card->longname, "Loopback %i", dev + 1);
        err = snd_card_register(card);
-       if (!err) {
-               platform_set_drvdata(devptr, card);
-               return 0;
-       }
-      __nodev:
-       snd_card_free(card);
-       return err;
-}
-
-static int loopback_remove(struct platform_device *devptr)
-{
-       snd_card_free(platform_get_drvdata(devptr));
+       if (err < 0)
+               return err;
+       platform_set_drvdata(devptr, card);
        return 0;
 }
 
@@ -1786,7 +1777,6 @@ static SIMPLE_DEV_PM_OPS(loopback_pm, loopback_suspend, loopback_resume);
 
 static struct platform_driver loopback_driver = {
        .probe          = loopback_probe,
-       .remove         = loopback_remove,
        .driver         = {
                .name   = SND_LOOPBACK_DRIVER,
                .pm     = LOOPBACK_PM_OPS,
index 01a3eab..2a7fc49 100644 (file)
@@ -1025,8 +1025,8 @@ static int snd_dummy_probe(struct platform_device *devptr)
        int idx, err;
        int dev = devptr->id;
 
-       err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_dummy), &card);
+       err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_dummy), &card);
        if (err < 0)
                return err;
        dummy = card->private_data;
@@ -1047,7 +1047,7 @@ static int snd_dummy_probe(struct platform_device *devptr)
                        pcm_substreams[dev] = MAX_PCM_SUBSTREAMS;
                err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev]);
                if (err < 0)
-                       goto __nodev;
+                       return err;
        }
 
        dummy->pcm_hw = dummy_pcm_hardware;
@@ -1078,7 +1078,7 @@ static int snd_dummy_probe(struct platform_device *devptr)
 
        err = snd_card_dummy_new_mixer(dummy);
        if (err < 0)
-               goto __nodev;
+               return err;
        strcpy(card->driver, "Dummy");
        strcpy(card->shortname, "Dummy");
        sprintf(card->longname, "Dummy %i", dev + 1);
@@ -1086,18 +1086,9 @@ static int snd_dummy_probe(struct platform_device *devptr)
        dummy_proc_init(dummy);
 
        err = snd_card_register(card);
-       if (err == 0) {
-               platform_set_drvdata(devptr, card);
-               return 0;
-       }
-      __nodev:
-       snd_card_free(card);
-       return err;
-}
-
-static int snd_dummy_remove(struct platform_device *devptr)
-{
-       snd_card_free(platform_get_drvdata(devptr));
+       if (err < 0)
+               return err;
+       platform_set_drvdata(devptr, card);
        return 0;
 }
 
@@ -1128,7 +1119,6 @@ static SIMPLE_DEV_PM_OPS(snd_dummy_pm, snd_dummy_suspend, snd_dummy_resume);
 
 static struct platform_driver snd_dummy_driver = {
        .probe          = snd_dummy_probe,
-       .remove         = snd_dummy_remove,
        .driver         = {
                .name   = SND_DUMMY_DRIVER,
                .pm     = SND_DUMMY_PM_OPS,
index d0b55db..3398aee 100644 (file)
@@ -59,8 +59,8 @@ static int snd_mpu401_create(struct device *devptr, int dev,
                snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n");
 
        *rcard = NULL;
-       err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
+                               0, &card);
        if (err < 0)
                return err;
        strcpy(card->driver, "MPU-401 UART");
@@ -76,15 +76,11 @@ static int snd_mpu401_create(struct device *devptr, int dev,
                                  irq[dev], NULL);
        if (err < 0) {
                printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
-               goto _err;
+               return err;
        }
 
        *rcard = card;
        return 0;
-
- _err:
-       snd_card_free(card);
-       return err;
 }
 
 static int snd_mpu401_probe(struct platform_device *devptr)
@@ -105,25 +101,16 @@ static int snd_mpu401_probe(struct platform_device *devptr)
        if (err < 0)
                return err;
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        platform_set_drvdata(devptr, card);
        return 0;
 }
 
-static int snd_mpu401_remove(struct platform_device *devptr)
-{
-       snd_card_free(platform_get_drvdata(devptr));
-       return 0;
-}
-
 #define SND_MPU401_DRIVER      "snd_mpu401"
 
 static struct platform_driver snd_mpu401_driver = {
        .probe          = snd_mpu401_probe,
-       .remove         = snd_mpu401_remove,
        .driver         = {
                .name   = SND_MPU401_DRIVER,
        },
@@ -184,10 +171,8 @@ static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
                if (err < 0)
                        return err;
                err = snd_card_register(card);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
                pnp_set_drvdata(pnp_dev, card);
                snd_mpu401_devices++;
                ++dev;
@@ -196,19 +181,10 @@ static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
        return -ENODEV;
 }
 
-static void snd_mpu401_pnp_remove(struct pnp_dev *dev)
-{
-       struct snd_card *card = (struct snd_card *) pnp_get_drvdata(dev);
-
-       snd_card_disconnect(card);
-       snd_card_free_when_closed(card);
-}
-
 static struct pnp_driver snd_mpu401_pnp_driver = {
        .name = "mpu401",
        .id_table = snd_mpu401_pnpids,
        .probe = snd_mpu401_pnp_probe,
-       .remove = snd_mpu401_pnp_remove,
 };
 #else
 static struct pnp_driver snd_mpu401_pnp_driver;
index 0e95b08..11235ba 100644 (file)
@@ -566,13 +566,15 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id)
  */
 static int snd_mtpav_get_ISA(struct mtpav *mcard)
 {
-       mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI");
+       mcard->res_port = devm_request_region(mcard->card->dev, port, 3,
+                                             "MotuMTPAV MIDI");
        if (!mcard->res_port) {
                snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port);
                return -EBUSY;
        }
        mcard->port = port;
-       if (request_irq(irq, snd_mtpav_irqh, 0, "MOTU MTPAV", mcard)) {
+       if (devm_request_irq(mcard->card->dev, irq, snd_mtpav_irqh, 0,
+                            "MOTU MTPAV", mcard)) {
                snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq);
                return -EBUSY;
        }
@@ -667,9 +669,6 @@ static void snd_mtpav_free(struct snd_card *card)
        if (crd->istimer > 0)
                snd_mtpav_remove_output_timer(crd);
        spin_unlock_irqrestore(&crd->spinlock, flags);
-       if (crd->irq >= 0)
-               free_irq(crd->irq, (void *)crd);
-       release_and_free_resource(crd->res_port);
 }
 
 /*
@@ -680,8 +679,8 @@ static int snd_mtpav_probe(struct platform_device *dev)
        int err;
        struct mtpav *mtp_card;
 
-       err = snd_card_new(&dev->dev, index, id, THIS_MODULE,
-                          sizeof(*mtp_card), &card);
+       err = snd_devm_card_new(&dev->dev, index, id, THIS_MODULE,
+                               sizeof(*mtp_card), &card);
        if (err < 0)
                return err;
 
@@ -698,13 +697,13 @@ static int snd_mtpav_probe(struct platform_device *dev)
 
        err = snd_mtpav_get_RAWMIDI(mtp_card);
        if (err < 0)
-               goto __error;
+               return err;
 
        mtp_card->inmidiport = mtp_card->num_ports + MTPAV_PIDX_BROADCAST;
 
        err = snd_mtpav_get_ISA(mtp_card);
        if (err < 0)
-               goto __error;
+               return err;
 
        strcpy(card->driver, "MTPAV");
        strcpy(card->shortname, "MTPAV on parallel port");
@@ -715,28 +714,17 @@ static int snd_mtpav_probe(struct platform_device *dev)
 
        err = snd_card_register(mtp_card->card);
        if (err < 0)
-               goto __error;
+               return err;
 
        platform_set_drvdata(dev, card);
        printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port);
        return 0;
-
- __error:
-       snd_card_free(card);
-       return err;
-}
-
-static int snd_mtpav_remove(struct platform_device *devptr)
-{
-       snd_card_free(platform_get_drvdata(devptr));
-       return 0;
 }
 
 #define SND_MTPAV_DRIVER       "snd_mtpav"
 
 static struct platform_driver snd_mtpav_driver = {
        .probe          = snd_mtpav_probe,
-       .remove         = snd_mtpav_remove,
        .driver         = {
                .name   = SND_MTPAV_DRIVER,
        },
index 7689fa2..c7be1c3 100644 (file)
@@ -42,9 +42,8 @@ struct snd_pcsp pcsp_chip;
 
 static int snd_pcsp_create(struct snd_card *card)
 {
-       static const struct snd_device_ops ops = { };
        unsigned int resolution = hrtimer_resolution;
-       int err, div, min_div, order;
+       int div, min_div, order;
 
        if (!nopcm) {
                if (resolution > PCSP_MAX_PERIOD_NS) {
@@ -83,15 +82,18 @@ static int snd_pcsp_create(struct snd_card *card)
        pcsp_chip.port = 0x61;
        pcsp_chip.irq = -1;
        pcsp_chip.dma = -1;
-
-       /* Register device */
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, &pcsp_chip, &ops);
-       if (err < 0)
-               return err;
+       card->private_data = &pcsp_chip;
 
        return 0;
 }
 
+static void pcsp_stop_beep(struct snd_pcsp *chip);
+
+static void alsa_card_pcsp_free(struct snd_card *card)
+{
+       pcsp_stop_beep(card->private_data);
+}
+
 static int snd_card_pcsp_probe(int devnum, struct device *dev)
 {
        struct snd_card *card;
@@ -103,22 +105,22 @@ static int snd_card_pcsp_probe(int devnum, struct device *dev)
        hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        pcsp_chip.timer.function = pcsp_do_timer;
 
-       err = snd_card_new(dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(dev, index, id, THIS_MODULE, 0, &card);
        if (err < 0)
                return err;
 
        err = snd_pcsp_create(card);
        if (err < 0)
-               goto free_card;
+               return err;
 
        if (!nopcm) {
                err = snd_pcsp_new_pcm(&pcsp_chip);
                if (err < 0)
-                       goto free_card;
+                       return err;
        }
        err = snd_pcsp_new_mixer(&pcsp_chip, nopcm);
        if (err < 0)
-               goto free_card;
+               return err;
 
        strcpy(card->driver, "PC-Speaker");
        strcpy(card->shortname, "pcsp");
@@ -127,13 +129,10 @@ static int snd_card_pcsp_probe(int devnum, struct device *dev)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto free_card;
+               return err;
+       card->private_free = alsa_card_pcsp_free;
 
        return 0;
-
-free_card:
-       snd_card_free(card);
-       return err;
 }
 
 static int alsa_card_pcsp_init(struct device *dev)
@@ -155,11 +154,6 @@ static int alsa_card_pcsp_init(struct device *dev)
        return 0;
 }
 
-static void alsa_card_pcsp_exit(struct snd_pcsp *chip)
-{
-       snd_card_free(chip->card);
-}
-
 static int pcsp_probe(struct platform_device *dev)
 {
        int err;
@@ -169,23 +163,13 @@ static int pcsp_probe(struct platform_device *dev)
                return err;
 
        err = alsa_card_pcsp_init(&dev->dev);
-       if (err < 0) {
-               pcspkr_input_remove(pcsp_chip.input_dev);
+       if (err < 0)
                return err;
-       }
 
        platform_set_drvdata(dev, &pcsp_chip);
        return 0;
 }
 
-static int pcsp_remove(struct platform_device *dev)
-{
-       struct snd_pcsp *chip = platform_get_drvdata(dev);
-       pcspkr_input_remove(chip->input_dev);
-       alsa_card_pcsp_exit(chip);
-       return 0;
-}
-
 static void pcsp_stop_beep(struct snd_pcsp *chip)
 {
        pcsp_sync_stop(chip);
@@ -218,7 +202,6 @@ static struct platform_driver pcsp_platform_driver = {
                .pm     = PCSP_PM_OPS,
        },
        .probe          = pcsp_probe,
-       .remove         = pcsp_remove,
        .shutdown       = pcsp_shutdown,
 };
 
index e79603f..5a799f7 100644 (file)
@@ -78,7 +78,7 @@ int pcspkr_input_init(struct input_dev **rdev, struct device *dev)
 {
        int err;
 
-       struct input_dev *input_dev = input_allocate_device();
+       struct input_dev *input_dev = devm_input_allocate_device(dev);
        if (!input_dev)
                return -ENOMEM;
 
@@ -95,19 +95,9 @@ int pcspkr_input_init(struct input_dev **rdev, struct device *dev)
        input_dev->event = pcspkr_input_event;
 
        err = input_register_device(input_dev);
-       if (err) {
-               input_free_device(input_dev);
+       if (err)
                return err;
-       }
 
        *rdev = input_dev;
        return 0;
 }
-
-int pcspkr_input_remove(struct input_dev *dev)
-{
-       pcspkr_stop_sound();
-       input_unregister_device(dev);   /* this also does kfree() */
-
-       return 0;
-}
index e80079b..42bfc9e 100644 (file)
@@ -9,7 +9,6 @@
 #define __PCSP_INPUT_H__
 
 int pcspkr_input_init(struct input_dev **rdev, struct device *dev);
-int pcspkr_input_remove(struct input_dev *dev);
 void pcspkr_stop_sound(void);
 
 #endif
index da9983c..3cbc7a4 100644 (file)
@@ -115,7 +115,6 @@ struct snd_uart16550 {
        int irq;
 
        unsigned long base;
-       struct resource *res_base;
 
        unsigned int speed;
        unsigned int speed_base;
@@ -323,8 +322,7 @@ static int snd_uart16550_detect(struct snd_uart16550 *uart)
                return -ENODEV; /* Not configured */
        }
 
-       uart->res_base = request_region(io_base, 8, "Serial MIDI");
-       if (uart->res_base == NULL) {
+       if (!devm_request_region(uart->card->dev, io_base, 8, "Serial MIDI")) {
                snd_printk(KERN_ERR "u16550: can't grab port 0x%lx\n", io_base);
                return -EBUSY;
        }
@@ -752,21 +750,6 @@ static const struct snd_rawmidi_ops snd_uart16550_input =
        .trigger =      snd_uart16550_input_trigger,
 };
 
-static int snd_uart16550_free(struct snd_uart16550 *uart)
-{
-       if (uart->irq >= 0)
-               free_irq(uart->irq, uart);
-       release_and_free_resource(uart->res_base);
-       kfree(uart);
-       return 0;
-};
-
-static int snd_uart16550_dev_free(struct snd_device *device)
-{
-       struct snd_uart16550 *uart = device->device_data;
-       return snd_uart16550_free(uart);
-}
-
 static int snd_uart16550_create(struct snd_card *card,
                                unsigned long iobase,
                                int irq,
@@ -776,14 +759,11 @@ static int snd_uart16550_create(struct snd_card *card,
                                int droponfull,
                                struct snd_uart16550 **ruart)
 {
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_uart16550_dev_free,
-       };
        struct snd_uart16550 *uart;
        int err;
 
 
-       uart = kzalloc(sizeof(*uart), GFP_KERNEL);
+       uart = devm_kzalloc(card->dev, sizeof(*uart), GFP_KERNEL);
        if (!uart)
                return -ENOMEM;
        uart->adaptor = adaptor;
@@ -796,13 +776,12 @@ static int snd_uart16550_create(struct snd_card *card,
        err = snd_uart16550_detect(uart);
        if (err <= 0) {
                printk(KERN_ERR "no UART detected at 0x%lx\n", iobase);
-               snd_uart16550_free(uart);
                return -ENODEV;
        }
 
        if (irq >= 0 && irq != SNDRV_AUTO_IRQ) {
-               if (request_irq(irq, snd_uart16550_interrupt,
-                               0, "Serial MIDI", uart)) {
+               if (devm_request_irq(card->dev, irq, snd_uart16550_interrupt,
+                                    0, "Serial MIDI", uart)) {
                        snd_printk(KERN_WARNING
                                   "irq %d busy. Using Polling.\n", irq);
                } else {
@@ -819,13 +798,6 @@ static int snd_uart16550_create(struct snd_card *card,
        timer_setup(&uart->buffer_timer, snd_uart16550_buffer_timer, 0);
        uart->timer_running = 0;
 
-       /* Register device */
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, uart, &ops);
-       if (err < 0) {
-               snd_uart16550_free(uart);
-               return err;
-       }
-
        switch (uart->adaptor) {
        case SNDRV_SERIAL_MS124W_SA:
        case SNDRV_SERIAL_MS124W_MB:
@@ -927,8 +899,8 @@ static int snd_serial_probe(struct platform_device *devptr)
                return -ENODEV;
        }
 
-       err  = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
-                           0, &card);
+       err  = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
+                                0, &card);
        if (err < 0)
                return err;
 
@@ -939,11 +911,11 @@ static int snd_serial_probe(struct platform_device *devptr)
                                   base[dev], adaptor[dev], droponfull[dev],
                                   &uart);
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi);
        if (err < 0)
-               goto _err;
+               return err;
 
        sprintf(card->longname, "%s [%s] at %#lx, irq %d",
                card->shortname,
@@ -953,27 +925,16 @@ static int snd_serial_probe(struct platform_device *devptr)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto _err;
+               return err;
 
        platform_set_drvdata(devptr, card);
        return 0;
-
- _err:
-       snd_card_free(card);
-       return err;
-}
-
-static int snd_serial_remove(struct platform_device *devptr)
-{
-       snd_card_free(platform_get_drvdata(devptr));
-       return 0;
 }
 
 #define SND_SERIAL_DRIVER      "snd_serial_u16550"
 
 static struct platform_driver snd_serial_driver = {
        .probe          = snd_serial_probe,
-       .remove         =  snd_serial_remove,
        .driver         = {
                .name   = SND_SERIAL_DRIVER,
        },
index 4206d93..7f7eed6 100644 (file)
@@ -75,8 +75,8 @@ static int snd_virmidi_probe(struct platform_device *devptr)
        int idx, err;
        int dev = devptr->id;
 
-       err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_card_virmidi), &card);
+       err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_card_virmidi), &card);
        if (err < 0)
                return err;
        vmidi = card->private_data;
@@ -94,7 +94,7 @@ static int snd_virmidi_probe(struct platform_device *devptr)
 
                err = snd_virmidi_new(card, idx, &rmidi);
                if (err < 0)
-                       goto __nodev;
+                       return err;
                rdev = rmidi->private_data;
                vmidi->midi[idx] = rmidi;
                strcpy(rmidi->name, "Virtual Raw MIDI");
@@ -106,18 +106,10 @@ static int snd_virmidi_probe(struct platform_device *devptr)
        sprintf(card->longname, "Virtual MIDI Card %i", dev + 1);
 
        err = snd_card_register(card);
-       if (!err) {
-               platform_set_drvdata(devptr, card);
-               return 0;
-       }
-__nodev:
-       snd_card_free(card);
-       return err;
-}
+       if (err)
+               return err;
 
-static int snd_virmidi_remove(struct platform_device *devptr)
-{
-       snd_card_free(platform_get_drvdata(devptr));
+       platform_set_drvdata(devptr, card);
        return 0;
 }
 
@@ -125,7 +117,6 @@ static int snd_virmidi_remove(struct platform_device *devptr)
 
 static struct platform_driver snd_virmidi_driver = {
        .probe          = snd_virmidi_probe,
-       .remove         = snd_virmidi_remove,
        .driver         = {
                .name   = SND_VIRMIDI_DRIVER,
        },
index a10449a..18901e5 100644 (file)
@@ -774,6 +774,11 @@ int snd_vx_resume(struct vx_core *chip)
 EXPORT_SYMBOL(snd_vx_resume);
 #endif
 
+static void snd_vx_release(struct device *dev, void *data)
+{
+       snd_vx_free_firmware(data);
+}
+
 /**
  * snd_vx_create - constructor for struct vx_core
  * @card: card instance
@@ -784,6 +789,8 @@ EXPORT_SYMBOL(snd_vx_resume);
  * this function allocates the instance and prepare for the hardware
  * initialization.
  *
+ * The object is managed via devres, and will be automatically released.
+ *
  * return the instance pointer if successful, NULL in error.
  */
 struct vx_core *snd_vx_create(struct snd_card *card,
@@ -796,8 +803,9 @@ struct vx_core *snd_vx_create(struct snd_card *card,
        if (snd_BUG_ON(!card || !hw || !ops))
                return NULL;
 
-       chip = kzalloc(sizeof(*chip) + extra_size, GFP_KERNEL);
-       if (! chip)
+       chip = devres_alloc(snd_vx_release, sizeof(*chip) + extra_size,
+                           GFP_KERNEL);
+       if (!chip)
                return NULL;
        mutex_init(&chip->lock);
        chip->irq = -1;
index 93d5df1..2bd4485 100644 (file)
 #define  V2_CLOCK_RATE_SHIFT                   3
 #define  V2_CLOCK_SRC_MASK                     0x00000007
 #define  V2_CLOCK_SRC_SHIFT                    0
-#define   V2_CLOCK_SRC_AESEBU_ON_XLR           0x07
+#define   V2_CLOCK_SRC_AESEBU_ON_XLR           0x07    // In Traveler.
 #define   V2_CLOCK_SRC_ADAT_ON_DSUB            0x05
 #define   V2_CLOCK_SRC_WORD_ON_BNC             0x04
 #define   V2_CLOCK_SRC_SPH                     0x03
-#define   V2_CLOCK_SRC_SPDIF                   0x02    // on either coaxial or optical
+#define   V2_CLOCK_SRC_SPDIF                   0x02    // on either coaxial or optical. AES/EBU in 896HD.
 #define   V2_CLOCK_SRC_ADAT_ON_OPT             0x01
 #define   V2_CLOCK_SRC_INTERNAL                        0x00
 #define  V2_CLOCK_FETCH_ENABLE                 0x02000000
@@ -100,7 +100,9 @@ static int get_clock_source(struct snd_motu *motu, u32 data,
                bool support_iec60958_on_opt = (motu->spec == &snd_motu_spec_828mk2 ||
                                                motu->spec == &snd_motu_spec_traveler);
 
-               if (!support_iec60958_on_opt) {
+               if (motu->spec == &snd_motu_spec_896hd) {
+                       *src = SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR;
+               } else if (!support_iec60958_on_opt) {
                        *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
                } else {
                        __be32 reg;
@@ -129,6 +131,7 @@ static int get_clock_source(struct snd_motu *motu, u32 data,
                *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB;
                break;
        case V2_CLOCK_SRC_AESEBU_ON_XLR:
+               // For Traveler.
                *src = SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR;
                break;
        default:
@@ -153,7 +156,7 @@ int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu,
        return get_clock_source(motu, be32_to_cpu(reg), src);
 }
 
-// Expected for Traveler and 896HD, which implements Altera Cyclone EP1C3.
+// Expected for Traveler, which implements Altera Cyclone EP1C3.
 static int switch_fetching_mode_cyclone(struct snd_motu *motu, u32 *data,
                                        bool enable)
 {
@@ -190,6 +193,9 @@ int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu,
        if (motu->spec == &snd_motu_spec_828mk2) {
                // 828mkII implements Altera ACEX 1K EP1K30. Nothing to do.
                return 0;
+       } else if (motu->spec == &snd_motu_spec_896hd) {
+               // 896HD implements Altera Cyclone EP1C3 but nothing to do.
+               return 0;
        } else {
                __be32 reg;
                u32 data;
@@ -274,6 +280,14 @@ const struct snd_motu_spec snd_motu_spec_828mk2 = {
        .rx_fixed_pcm_chunks = {14, 14, 0},
 };
 
+const struct snd_motu_spec snd_motu_spec_896hd = {
+       .name = "896HD",
+       .protocol_version = SND_MOTU_PROTOCOL_V2,
+       // No support for MIDI.
+       .tx_fixed_pcm_chunks = {14, 14, 8},
+       .rx_fixed_pcm_chunks = {14, 14, 8},
+};
+
 const struct snd_motu_spec snd_motu_spec_traveler = {
        .name = "Traveler",
        .protocol_version = SND_MOTU_PROTOCOL_V2,
index 5431365..f654262 100644 (file)
@@ -153,6 +153,7 @@ static const struct ieee1394_device_id motu_id_table[] = {
        SND_MOTU_DEV_ENTRY(0x000001, &snd_motu_spec_828),
        SND_MOTU_DEV_ENTRY(0x000002, &snd_motu_spec_896),
        SND_MOTU_DEV_ENTRY(0x000003, &snd_motu_spec_828mk2),
+       SND_MOTU_DEV_ENTRY(0x000005, &snd_motu_spec_896hd),
        SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler),
        SND_MOTU_DEV_ENTRY(0x00000d, &snd_motu_spec_ultralite),
        SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre),
index 73f36d1..f1a830b 100644 (file)
@@ -126,6 +126,7 @@ extern const struct snd_motu_spec snd_motu_spec_828;
 extern const struct snd_motu_spec snd_motu_spec_896;
 
 extern const struct snd_motu_spec snd_motu_spec_828mk2;
+extern const struct snd_motu_spec snd_motu_spec_896hd;
 extern const struct snd_motu_spec snd_motu_spec_traveler;
 extern const struct snd_motu_spec snd_motu_spec_ultralite;
 extern const struct snd_motu_spec snd_motu_spec_8pre;
index fa5bed0..9ac8737 100644 (file)
@@ -124,28 +124,24 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
        struct snd_ad1816a *chip;
        struct snd_opl3 *opl3;
 
-       error = snd_card_new(&pcard->card->dev,
-                            index[dev], id[dev], THIS_MODULE,
-                            sizeof(struct snd_ad1816a), &card);
+       error = snd_devm_card_new(&pcard->card->dev,
+                                 index[dev], id[dev], THIS_MODULE,
+                                 sizeof(struct snd_ad1816a), &card);
        if (error < 0)
                return error;
        chip = card->private_data;
 
        error = snd_card_ad1816a_pnp(dev, pcard, pid);
-       if (error) {
-               snd_card_free(card);
+       if (error)
                return error;
-       }
 
        error = snd_ad1816a_create(card, port[dev],
                                   irq[dev],
                                   dma1[dev],
                                   dma2[dev],
                                   chip);
-       if (error) {
-               snd_card_free(card);
+       if (error)
                return error;
-       }
        if (clockfreq[dev] >= 5000 && clockfreq[dev] <= 100000)
                chip->clock_freq = clockfreq[dev];
 
@@ -155,22 +151,16 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
                card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
 
        error = snd_ad1816a_pcm(chip, 0);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        error = snd_ad1816a_mixer(chip);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        error = snd_ad1816a_timer(chip, 0);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        if (mpu_port[dev] > 0) {
                if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
@@ -186,18 +176,14 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
                        printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx.\n", fm_port[dev], fm_port[dev] + 2);
                } else {
                        error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-                       if (error < 0) {
-                               snd_card_free(card);
+                       if (error < 0)
                                return error;
-                       }
                }
        }
 
        error = snd_card_register(card);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        pnp_set_card_drvdata(pcard, card);
        return 0;
 }
@@ -223,12 +209,6 @@ static int snd_ad1816a_pnp_detect(struct pnp_card_link *card,
         return -ENODEV;
 }
 
-static void snd_ad1816a_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_ad1816a_pnp_suspend(struct pnp_card_link *pcard,
                                   pm_message_t state)
@@ -255,7 +235,6 @@ static struct pnp_card_driver ad1816a_pnpc_driver = {
        .name           = "ad1816a",
        .id_table       = snd_ad1816a_pnpids,
        .probe          = snd_ad1816a_pnp_detect,
-       .remove         = snd_ad1816a_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_ad1816a_pnp_suspend,
        .resume         = snd_ad1816a_pnp_resume,
index 6d4999b..132a095 100644 (file)
@@ -541,28 +541,6 @@ static int snd_ad1816a_probe(struct snd_ad1816a *chip)
        return 0;
 }
 
-static int snd_ad1816a_free(struct snd_ad1816a *chip)
-{
-       release_and_free_resource(chip->res_port);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, (void *) chip);
-       if (chip->dma1 >= 0) {
-               snd_dma_disable(chip->dma1);
-               free_dma(chip->dma1);
-       }
-       if (chip->dma2 >= 0) {
-               snd_dma_disable(chip->dma2);
-               free_dma(chip->dma2);
-       }
-       return 0;
-}
-
-static int snd_ad1816a_dev_free(struct snd_device *device)
-{
-       struct snd_ad1816a *chip = device->device_data;
-       return snd_ad1816a_free(chip);
-}
-
 static const char *snd_ad1816a_chip_id(struct snd_ad1816a *chip)
 {
        switch (chip->hardware) {
@@ -580,37 +558,31 @@ int snd_ad1816a_create(struct snd_card *card,
                       unsigned long port, int irq, int dma1, int dma2,
                       struct snd_ad1816a *chip)
 {
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_ad1816a_dev_free,
-       };
        int error;
 
        chip->irq = -1;
        chip->dma1 = -1;
        chip->dma2 = -1;
 
-       chip->res_port = request_region(port, 16, "AD1816A");
+       chip->res_port = devm_request_region(card->dev, port, 16, "AD1816A");
        if (!chip->res_port) {
                snd_printk(KERN_ERR "ad1816a: can't grab port 0x%lx\n", port);
-               snd_ad1816a_free(chip);
                return -EBUSY;
        }
-       if (request_irq(irq, snd_ad1816a_interrupt, 0, "AD1816A", (void *) chip)) {
+       if (devm_request_irq(card->dev, irq, snd_ad1816a_interrupt, 0,
+                            "AD1816A", (void *) chip)) {
                snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq);
-               snd_ad1816a_free(chip);
                return -EBUSY;
        }
        chip->irq = irq;
        card->sync_irq = chip->irq;
-       if (request_dma(dma1, "AD1816A - 1")) {
+       if (snd_devm_request_dma(card->dev, dma1, "AD1816A - 1")) {
                snd_printk(KERN_ERR "ad1816a: can't grab DMA1 %d\n", dma1);
-               snd_ad1816a_free(chip);
                return -EBUSY;
        }
        chip->dma1 = dma1;
-       if (request_dma(dma2, "AD1816A - 2")) {
+       if (snd_devm_request_dma(card->dev, dma2, "AD1816A - 2")) {
                snd_printk(KERN_ERR "ad1816a: can't grab DMA2 %d\n", dma2);
-               snd_ad1816a_free(chip);
                return -EBUSY;
        }
        chip->dma2 = dma2;
@@ -620,20 +592,11 @@ int snd_ad1816a_create(struct snd_card *card,
        spin_lock_init(&chip->lock);
 
        error = snd_ad1816a_probe(chip);
-       if (error) {
-               snd_ad1816a_free(chip);
+       if (error)
                return error;
-       }
 
        snd_ad1816a_init(chip);
 
-       /* Register device */
-       error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (error < 0) {
-               snd_ad1816a_free(chip);
-               return error;
-       }
-
        return 0;
 }
 
index edafb49..c471ac2 100644 (file)
@@ -72,7 +72,7 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n)
        struct snd_wss *chip;
        int error;
 
-       error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
+       error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
        if (error < 0)
                return error;
 
@@ -80,17 +80,17 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n)
                        thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT,
                        0, &chip);
        if (error < 0)
-               goto out;
+               return error;
 
        card->private_data = chip;
 
        error = snd_wss_pcm(chip, 0);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_wss_mixer(chip);
        if (error < 0)
-               goto out;
+               return error;
 
        strscpy(card->driver, "AD1848", sizeof(card->driver));
        strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
@@ -106,18 +106,10 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n)
 
        error = snd_card_register(card);
        if (error < 0)
-               goto out;
+               return error;
 
        dev_set_drvdata(dev, card);
        return 0;
-
-out:   snd_card_free(card);
-       return error;
-}
-
-static void snd_ad1848_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 #ifdef CONFIG_PM
@@ -145,7 +137,6 @@ static int snd_ad1848_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_ad1848_driver = {
        .match          = snd_ad1848_match,
        .probe          = snd_ad1848_probe,
-       .remove         = snd_ad1848_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_ad1848_suspend,
        .resume         = snd_ad1848_resume,
index e6cd7c4..f079ba4 100644 (file)
@@ -43,30 +43,23 @@ static int snd_adlib_match(struct device *dev, unsigned int n)
        return 1;
 }
 
-static void snd_adlib_free(struct snd_card *card)
-{
-       release_and_free_resource(card->private_data);
-}
-
 static int snd_adlib_probe(struct device *dev, unsigned int n)
 {
        struct snd_card *card;
        struct snd_opl3 *opl3;
        int error;
 
-       error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
+       error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
        if (error < 0) {
                dev_err(dev, "could not create card\n");
                return error;
        }
 
-       card->private_data = request_region(port[n], 4, CRD_NAME);
+       card->private_data = devm_request_region(dev, port[n], 4, CRD_NAME);
        if (!card->private_data) {
                dev_err(dev, "could not grab ports\n");
-               error = -EBUSY;
-               goto out;
+               return -EBUSY;
        }
-       card->private_free = snd_adlib_free;
 
        strcpy(card->driver, DEV_NAME);
        strcpy(card->shortname, CRD_NAME);
@@ -75,37 +68,28 @@ static int snd_adlib_probe(struct device *dev, unsigned int n)
        error = snd_opl3_create(card, port[n], port[n] + 2, OPL3_HW_AUTO, 1, &opl3);
        if (error < 0) {
                dev_err(dev, "could not create OPL\n");
-               goto out;
+               return error;
        }
 
        error = snd_opl3_hwdep_new(opl3, 0, 0, NULL);
        if (error < 0) {
                dev_err(dev, "could not create FM\n");
-               goto out;
+               return error;
        }
 
        error = snd_card_register(card);
        if (error < 0) {
                dev_err(dev, "could not register card\n");
-               goto out;
+               return error;
        }
 
        dev_set_drvdata(dev, card);
        return 0;
-
-out:   snd_card_free(card);
-       return error;
-}
-
-static void snd_adlib_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 static struct isa_driver snd_adlib_driver = {
        .match          = snd_adlib_match,
        .probe          = snd_adlib_probe,
-       .remove         = snd_adlib_remove,
 
        .driver         = {
                .name   = DEV_NAME
index d4597fd..d582eff 100644 (file)
@@ -170,18 +170,16 @@ static int snd_card_als100_probe(int dev,
        struct snd_card_als100 *acard;
        struct snd_opl3 *opl3;
 
-       error = snd_card_new(&pcard->card->dev,
-                            index[dev], id[dev], THIS_MODULE,
-                            sizeof(struct snd_card_als100), &card);
+       error = snd_devm_card_new(&pcard->card->dev,
+                                 index[dev], id[dev], THIS_MODULE,
+                                 sizeof(struct snd_card_als100), &card);
        if (error < 0)
                return error;
        acard = card->private_data;
 
        error = snd_card_als100_pnp(dev, acard, pcard, pid);
-       if (error) {
-               snd_card_free(card);
+       if (error)
                return error;
-       }
 
        if (pid->driver_data == SB_HW_DT019X)
                dma16[dev] = -1;
@@ -191,10 +189,8 @@ static int snd_card_als100_probe(int dev,
                                  dma8[dev], dma16[dev],
                                  pid->driver_data,
                                  &chip);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        acard->chip = chip;
 
        if (pid->driver_data == SB_HW_DT019X) {
@@ -213,16 +209,12 @@ static int snd_card_als100_probe(int dev,
        }
 
        error = snd_sb16dsp_pcm(chip, 0);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        error = snd_sbmixer_new(chip);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
                int mpu_type = MPU401_HW_ALS100;
@@ -249,23 +241,17 @@ static int snd_card_als100_probe(int dev,
                                   fm_port[dev], fm_port[dev] + 2);
                } else {
                        error = snd_opl3_timer_new(opl3, 0, 1);
-                       if (error < 0) {
-                               snd_card_free(card);
+                       if (error < 0)
                                return error;
-                       }
                        error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-                       if (error < 0) {
-                               snd_card_free(card);
+                       if (error < 0)
                                return error;
-                       }
                }
        }
 
        error = snd_card_register(card);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        pnp_set_card_drvdata(pcard, card);
        return 0;
 }
@@ -291,12 +277,6 @@ static int snd_als100_pnp_detect(struct pnp_card_link *card,
        return -ENODEV;
 }
 
-static void snd_als100_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_als100_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -327,7 +307,6 @@ static struct pnp_card_driver als100_pnpc_driver = {
        .name           = "als100",
         .id_table       = snd_als100_pnpids,
         .probe          = snd_als100_pnp_detect,
-       .remove         = snd_als100_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_als100_pnp_suspend,
        .resume         = snd_als100_pnp_resume,
index dd5c059..761cd19 100644 (file)
@@ -169,33 +169,27 @@ static int snd_card_azt2320_probe(int dev,
        struct snd_wss *chip;
        struct snd_opl3 *opl3;
 
-       error = snd_card_new(&pcard->card->dev,
-                            index[dev], id[dev], THIS_MODULE,
-                            sizeof(struct snd_card_azt2320), &card);
+       error = snd_devm_card_new(&pcard->card->dev,
+                                 index[dev], id[dev], THIS_MODULE,
+                                 sizeof(struct snd_card_azt2320), &card);
        if (error < 0)
                return error;
        acard = card->private_data;
 
        error = snd_card_azt2320_pnp(dev, acard, pcard, pid);
-       if (error) {
-               snd_card_free(card);
+       if (error)
                return error;
-       }
 
        error = snd_card_azt2320_enable_wss(port[dev]);
-       if (error) {
-               snd_card_free(card);
+       if (error)
                return error;
-       }
 
        error = snd_wss_create(card, wss_port[dev], -1,
                               irq[dev],
                               dma1[dev], dma2[dev],
                               WSS_HW_DETECT, 0, &chip);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        strcpy(card->driver, "AZT2320");
        strcpy(card->shortname, "Aztech AZT2320");
@@ -203,20 +197,14 @@ static int snd_card_azt2320_probe(int dev,
                card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
 
        error = snd_wss_pcm(chip, 0);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        error = snd_wss_mixer(chip);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        error = snd_wss_timer(chip, 0);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
                if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320,
@@ -233,23 +221,17 @@ static int snd_card_azt2320_probe(int dev,
                                   fm_port[dev], fm_port[dev] + 2);
                } else {
                        error = snd_opl3_timer_new(opl3, 1, 2);
-                       if (error < 0) {
-                               snd_card_free(card);
+                       if (error < 0)
                                return error;
-                       }
                        error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-                       if (error < 0) {
-                               snd_card_free(card);
+                       if (error < 0)
                                return error;
-                       }
                }
        }
 
        error = snd_card_register(card);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        pnp_set_card_drvdata(pcard, card);
        return 0;
 }
@@ -275,12 +257,6 @@ static int snd_azt2320_pnp_detect(struct pnp_card_link *card,
         return -ENODEV;
 }
 
-static void snd_azt2320_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_azt2320_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -310,7 +286,6 @@ static struct pnp_card_driver azt2320_pnpc_driver = {
        .name           = "azt2320",
        .id_table       = snd_azt2320_pnpids,
        .probe          = snd_azt2320_pnp_detect,
-       .remove         = snd_azt2320_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_azt2320_pnp_suspend,
        .resume         = snd_azt2320_pnp_resume,
index 3b9fbb0..8902cfb 100644 (file)
@@ -294,8 +294,8 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
        }
        outb(val, port);
 
-       err = snd_card_new(pdev, index[ndev], id[ndev], THIS_MODULE,
-                          sizeof(struct snd_cmi8328), &card);
+       err = snd_devm_card_new(pdev, index[ndev], id[ndev], THIS_MODULE,
+                               sizeof(struct snd_cmi8328), &card);
        if (err < 0)
                return err;
        cmi = card->private_data;
@@ -306,18 +306,18 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
        err = snd_wss_create(card, port + 4, -1, irq[ndev], dma1[ndev],
                        dma2[ndev], WSS_HW_DETECT, 0, &cmi->wss);
        if (err < 0)
-               goto error;
+               return err;
 
        err = snd_wss_pcm(cmi->wss, 0);
        if (err < 0)
-               goto error;
+               return err;
 
        err = snd_wss_mixer(cmi->wss);
        if (err < 0)
-               goto error;
+               return err;
        err = snd_cmi8328_mixer(cmi->wss);
        if (err < 0)
-               goto error;
+               return err;
 
        if (snd_wss_timer(cmi->wss, 0) < 0)
                snd_printk(KERN_WARNING "error initializing WSS timer\n");
@@ -371,24 +371,21 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
        dev_set_drvdata(pdev, card);
        err = snd_card_register(card);
        if (err < 0)
-               goto error;
+               return err;
 #ifdef SUPPORT_JOYSTICK
        if (!gameport[ndev])
                return 0;
        /* gameport is hardwired to 0x200 */
-       res = request_region(0x200, 8, "CMI8328 gameport");
+       res = devm_request_region(pdev, 0x200, 8, "CMI8328 gameport");
        if (!res)
                snd_printk(KERN_WARNING "unable to allocate gameport I/O port\n");
        else {
                struct gameport *gp = cmi->gameport = gameport_allocate_port();
-               if (!cmi->gameport)
-                       release_and_free_resource(res);
-               else {
+               if (cmi->gameport) {
                        gameport_set_name(gp, "CMI8328 Gameport");
                        gameport_set_phys(gp, "%s/gameport0", dev_name(pdev));
                        gameport_set_dev_parent(gp, pdev);
                        gp->io = 0x200;
-                       gameport_set_port_data(gp, res);
                        /* Enable gameport */
                        snd_cmi8328_cfg_write(port, CFG1,
                                        CFG1_SB_DISABLE | CFG1_GAMEPORT);
@@ -397,10 +394,6 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
        }
 #endif
        return 0;
-error:
-       snd_card_free(card);
-
-       return err;
 }
 
 static void snd_cmi8328_remove(struct device *pdev, unsigned int dev)
@@ -409,17 +402,13 @@ static void snd_cmi8328_remove(struct device *pdev, unsigned int dev)
        struct snd_cmi8328 *cmi = card->private_data;
 
 #ifdef SUPPORT_JOYSTICK
-       if (cmi->gameport) {
-               struct resource *res = gameport_get_port_data(cmi->gameport);
+       if (cmi->gameport)
                gameport_unregister_port(cmi->gameport);
-               release_and_free_resource(res);
-       }
 #endif
        /* disable everything */
        snd_cmi8328_cfg_write(cmi->port, CFG1, CFG1_SB_DISABLE);
        snd_cmi8328_cfg_write(cmi->port, CFG2, 0);
        snd_cmi8328_cfg_write(cmi->port, CFG3, 0);
-       snd_card_free(card);
 }
 
 #ifdef CONFIG_PM
index ef6d0a2..f209b16 100644 (file)
@@ -507,8 +507,8 @@ static int snd_cmi8330_card_new(struct device *pdev, int dev,
        struct snd_cmi8330 *acard;
        int err;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_cmi8330), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_cmi8330), &card);
        if (err < 0) {
                snd_printk(KERN_ERR PFX "could not get a new card\n");
                return err;
@@ -629,20 +629,12 @@ static int snd_cmi8330_isa_probe(struct device *pdev,
        if (err < 0)
                return err;
        err = snd_cmi8330_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        dev_set_drvdata(pdev, card);
        return 0;
 }
 
-static void snd_cmi8330_isa_remove(struct device *devptr,
-                                 unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-}
-
 #ifdef CONFIG_PM
 static int snd_cmi8330_isa_suspend(struct device *dev, unsigned int n,
                                   pm_message_t state)
@@ -661,7 +653,6 @@ static int snd_cmi8330_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_cmi8330_driver = {
        .match          = snd_cmi8330_isa_match,
        .probe          = snd_cmi8330_isa_probe,
-       .remove         = snd_cmi8330_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cmi8330_isa_suspend,
        .resume         = snd_cmi8330_isa_resume,
@@ -693,25 +684,16 @@ static int snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
        res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid);
        if (res < 0) {
                snd_printk(KERN_ERR PFX "PnP detection failed\n");
-               snd_card_free(card);
                return res;
        }
        res = snd_cmi8330_probe(card, dev);
-       if (res < 0) {
-               snd_card_free(card);
+       if (res < 0)
                return res;
-       }
        pnp_set_card_drvdata(pcard, card);
        dev++;
        return 0;
 }
 
-static void snd_cmi8330_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_cmi8330_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -729,7 +711,6 @@ static struct pnp_card_driver cmi8330_pnpc_driver = {
        .name = "cmi8330",
        .id_table = snd_cmi8330_pnpids,
        .probe = snd_cmi8330_pnp_detect,
-       .remove = snd_cmi8330_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cmi8330_pnp_suspend,
        .resume         = snd_cmi8330_pnp_resume,
index ec054b9..1e89233 100644 (file)
@@ -79,20 +79,20 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n)
        struct snd_wss *chip;
        int error;
 
-       error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
+       error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
        if (error < 0)
                return error;
 
        error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n],
                        WSS_HW_DETECT, 0, &chip);
        if (error < 0)
-               goto out;
+               return error;
 
        card->private_data = chip;
 
        error = snd_wss_pcm(chip, 0);
        if (error < 0)
-               goto out;
+               return error;
 
        strscpy(card->driver, "CS4231", sizeof(card->driver));
        strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
@@ -108,11 +108,11 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n)
 
        error = snd_wss_mixer(chip);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_wss_timer(chip, 0);
        if (error < 0)
-               goto out;
+               return error;
 
        if (mpu_port[n] > 0 && mpu_port[n] != SNDRV_AUTO_PORT) {
                if (mpu_irq[n] == SNDRV_AUTO_IRQ)
@@ -125,18 +125,10 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n)
 
        error = snd_card_register(card);
        if (error < 0)
-               goto out;
+               return error;
 
        dev_set_drvdata(dev, card);
        return 0;
-
-out:   snd_card_free(card);
-       return error;
-}
-
-static void snd_cs4231_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 #ifdef CONFIG_PM
@@ -164,7 +156,6 @@ static int snd_cs4231_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_cs4231_driver = {
        .match          = snd_cs4231_match,
        .probe          = snd_cs4231_probe,
-       .remove         = snd_cs4231_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cs4231_suspend,
        .resume         = snd_cs4231_resume,
index 0b7fd17..b6bdebd 100644 (file)
@@ -76,7 +76,6 @@ static int pnp_registered;
 
 struct snd_card_cs4236 {
        struct snd_wss *chip;
-       struct resource *res_sb_port;
 #ifdef CONFIG_PNP
        struct pnp_dev *wss;
        struct pnp_dev *ctrl;
@@ -309,24 +308,16 @@ static int snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard,
 #define is_isapnp_selected(dev)                0
 #endif
 
-static void snd_card_cs4236_free(struct snd_card *card)
-{
-       struct snd_card_cs4236 *acard = card->private_data;
-
-       release_and_free_resource(acard->res_sb_port);
-}
-
 static int snd_cs423x_card_new(struct device *pdev, int dev,
                               struct snd_card **cardp)
 {
        struct snd_card *card;
        int err;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_card_cs4236), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_card_cs4236), &card);
        if (err < 0)
                return err;
-       card->private_free = snd_card_cs4236_free;
        *cardp = card;
        return 0;
 }
@@ -340,8 +331,8 @@ static int snd_cs423x_probe(struct snd_card *card, int dev)
 
        acard = card->private_data;
        if (sb_port[dev] > 0 && sb_port[dev] != SNDRV_AUTO_PORT) {
-               acard->res_sb_port = request_region(sb_port[dev], 16, IDENT " SB");
-               if (!acard->res_sb_port) {
+               if (!devm_request_region(card->dev, sb_port[dev], 16,
+                                        IDENT " SB")) {
                        printk(KERN_ERR IDENT ": unable to register SB port at 0x%lx\n", sb_port[dev]);
                        return -EBUSY;
                }
@@ -448,21 +439,12 @@ static int snd_cs423x_isa_probe(struct device *pdev,
        if (err < 0)
                return err;
        err = snd_cs423x_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
-
        dev_set_drvdata(pdev, card);
        return 0;
 }
 
-static void snd_cs423x_isa_remove(struct device *pdev,
-                                unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(pdev));
-}
-
 #ifdef CONFIG_PM
 static int snd_cs423x_suspend(struct snd_card *card)
 {
@@ -495,7 +477,6 @@ static int snd_cs423x_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver cs423x_isa_driver = {
        .match          = snd_cs423x_isa_match,
        .probe          = snd_cs423x_isa_probe,
-       .remove         = snd_cs423x_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cs423x_isa_suspend,
        .resume         = snd_cs423x_isa_resume,
@@ -539,24 +520,16 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
        err = snd_card_cs423x_pnp(dev, card->private_data, pdev, cdev);
        if (err < 0) {
                printk(KERN_ERR "PnP BIOS detection failed for " IDENT "\n");
-               snd_card_free(card);
                return err;
        }
        err = snd_cs423x_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pnp_set_drvdata(pdev, card);
        dev++;
        return 0;
 }
 
-static void snd_cs423x_pnp_remove(struct pnp_dev *pdev)
-{
-       snd_card_free(pnp_get_drvdata(pdev));
-}
-
 #ifdef CONFIG_PM
 static int snd_cs423x_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
 {
@@ -573,7 +546,6 @@ static struct pnp_driver cs423x_pnp_driver = {
        .name = "cs423x-pnpbios",
        .id_table = snd_cs423x_pnpbiosids,
        .probe = snd_cs423x_pnpbios_detect,
-       .remove = snd_cs423x_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cs423x_pnp_suspend,
        .resume         = snd_cs423x_pnp_resume,
@@ -601,25 +573,16 @@ static int snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
        if (res < 0) {
                printk(KERN_ERR "isapnp detection failed and probing for " IDENT
                       " is not supported\n");
-               snd_card_free(card);
                return res;
        }
        res = snd_cs423x_probe(card, dev);
-       if (res < 0) {
-               snd_card_free(card);
+       if (res < 0)
                return res;
-       }
        pnp_set_card_drvdata(pcard, card);
        dev++;
        return 0;
 }
 
-static void snd_cs423x_pnpc_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_cs423x_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -637,7 +600,6 @@ static struct pnp_card_driver cs423x_pnpc_driver = {
        .name = CS423X_ISAPNP_DRIVER,
        .id_table = snd_cs423x_pnpids,
        .probe = snd_cs423x_pnpc_detect,
-       .remove = snd_cs423x_pnpc_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cs423x_pnpc_suspend,
        .resume         = snd_cs423x_pnpc_resume,
index 63957ae..35f2591 100644 (file)
@@ -298,7 +298,6 @@ int snd_cs4236_create(struct snd_card *card,
        if (cport < 0x100 || cport == SNDRV_AUTO_PORT) {
                snd_printk(KERN_ERR "please, specify control port "
                           "for CS4236+ chips\n");
-               snd_device_free(card, chip);
                return -ENODEV;
        }
        ver1 = snd_cs4236_ctrl_in(chip, 1);
@@ -308,7 +307,6 @@ int snd_cs4236_create(struct snd_card *card,
        if (ver1 != ver2) {
                snd_printk(KERN_ERR "CS4236+ chip detected, but "
                           "control port 0x%lx is not valid\n", cport);
-               snd_device_free(card, chip);
                return -ENODEV;
        }
        snd_cs4236_ctrl_out(chip, 0, 0x00);
index 750d499..f935b56 100644 (file)
@@ -166,36 +166,27 @@ static int snd_es1688_isa_probe(struct device *dev, unsigned int n)
        struct snd_card *card;
        int error;
 
-       error = snd_card_new(dev, index[n], id[n], THIS_MODULE,
-                            sizeof(struct snd_es1688), &card);
+       error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE,
+                                 sizeof(struct snd_es1688), &card);
        if (error < 0)
                return error;
 
        error = snd_es1688_legacy_create(card, dev, n);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_es1688_probe(card, n);
        if (error < 0)
-               goto out;
+               return error;
 
        dev_set_drvdata(dev, card);
 
        return 0;
-out:
-       snd_card_free(card);
-       return error;
-}
-
-static void snd_es1688_isa_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 static struct isa_driver snd_es1688_driver = {
        .match          = snd_es1688_match,
        .probe          = snd_es1688_isa_probe,
-       .remove         = snd_es1688_isa_remove,
 #if 0  /* FIXME */
        .suspend        = snd_es1688_suspend,
        .resume         = snd_es1688_resume,
@@ -249,22 +240,18 @@ static int snd_es968_pnp_detect(struct pnp_card_link *pcard,
        if (dev == SNDRV_CARDS)
                return -ENODEV;
 
-       error = snd_card_new(&pcard->card->dev,
-                            index[dev], id[dev], THIS_MODULE,
-                            sizeof(struct snd_es1688), &card);
+       error = snd_devm_card_new(&pcard->card->dev,
+                                 index[dev], id[dev], THIS_MODULE,
+                                 sizeof(struct snd_es1688), &card);
        if (error < 0)
                return error;
 
        error = snd_card_es968_pnp(card, dev, pcard, pid);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        error = snd_es1688_probe(card, dev);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        pnp_set_card_drvdata(pcard, card);
        snd_es968_pnp_is_probed = 1;
        return 0;
@@ -272,8 +259,6 @@ static int snd_es968_pnp_detect(struct pnp_card_link *pcard,
 
 static void snd_es968_pnp_remove(struct pnp_card_link *pcard)
 {
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
        snd_es968_pnp_is_probed = 0;
 }
 
index 68b9c59..3fcd168 100644 (file)
@@ -87,9 +87,6 @@
 struct snd_es18xx {
        unsigned long port;             /* port of ESS chip */
        unsigned long ctrl_port;        /* Control port of ESS chip */
-       struct resource *res_port;
-       struct resource *res_mpu_port;
-       struct resource *res_ctrl_port;
        int irq;                        /* IRQ number of ESS chip */
        int dma1;                       /* DMA1 */
        int dma2;                       /* DMA2 */
@@ -1531,7 +1528,7 @@ static int snd_es18xx_initialize(struct snd_es18xx *chip,
         return 0;
 }
 
-static int snd_es18xx_identify(struct snd_es18xx *chip)
+static int snd_es18xx_identify(struct snd_card *card, struct snd_es18xx *chip)
 {
        int hi,lo;
 
@@ -1573,8 +1570,8 @@ static int snd_es18xx_identify(struct snd_es18xx *chip)
                udelay(10);
                chip->ctrl_port += inb(chip->port + 0x05);
 
-               chip->res_ctrl_port = request_region(chip->ctrl_port, 8, "ES18xx - CTRL");
-               if (!chip->res_ctrl_port) {
+               if (!devm_request_region(card->dev, chip->ctrl_port, 8,
+                                        "ES18xx - CTRL")) {
                        snd_printk(KERN_ERR PFX "unable go grab port 0x%lx\n", chip->ctrl_port);
                        return -EBUSY;
                }
@@ -1601,11 +1598,12 @@ static int snd_es18xx_identify(struct snd_es18xx *chip)
        return 0;
 }
 
-static int snd_es18xx_probe(struct snd_es18xx *chip,
+static int snd_es18xx_probe(struct snd_card *card,
+                           struct snd_es18xx *chip,
                            unsigned long mpu_port,
                            unsigned long fm_port)
 {
-       if (snd_es18xx_identify(chip) < 0) {
+       if (snd_es18xx_identify(card, chip) < 0) {
                snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port);
                 return -ENODEV;
        }
@@ -1722,31 +1720,6 @@ static int snd_es18xx_resume(struct snd_card *card)
 }
 #endif /* CONFIG_PM */
 
-static int snd_es18xx_free(struct snd_card *card)
-{
-       struct snd_es18xx *chip = card->private_data;
-
-       release_and_free_resource(chip->res_port);
-       release_and_free_resource(chip->res_ctrl_port);
-       release_and_free_resource(chip->res_mpu_port);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, (void *) card);
-       if (chip->dma1 >= 0) {
-               disable_dma(chip->dma1);
-               free_dma(chip->dma1);
-       }
-       if (chip->dma2 >= 0 && chip->dma1 != chip->dma2) {
-               disable_dma(chip->dma2);
-               free_dma(chip->dma2);
-       }
-       return 0;
-}
-
-static int snd_es18xx_dev_free(struct snd_device *device)
-{
-       return snd_es18xx_free(device->card);
-}
-
 static int snd_es18xx_new_device(struct snd_card *card,
                                 unsigned long port,
                                 unsigned long mpu_port,
@@ -1754,10 +1727,6 @@ static int snd_es18xx_new_device(struct snd_card *card,
                                 int irq, int dma1, int dma2)
 {
        struct snd_es18xx *chip = card->private_data;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_es18xx_dev_free,
-        };
-       int err;
 
        spin_lock_init(&chip->reg_lock);
        spin_lock_init(&chip->mixer_lock);
@@ -1768,45 +1737,34 @@ static int snd_es18xx_new_device(struct snd_card *card,
         chip->audio2_vol = 0x00;
        chip->active = 0;
 
-       chip->res_port = request_region(port, 16, "ES18xx");
-       if (chip->res_port == NULL) {
-               snd_es18xx_free(card);
+       if (!devm_request_region(card->dev, port, 16, "ES18xx")) {
                snd_printk(KERN_ERR PFX "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1);
                return -EBUSY;
        }
 
-       if (request_irq(irq, snd_es18xx_interrupt, 0, "ES18xx",
-                       (void *) card)) {
-               snd_es18xx_free(card);
+       if (devm_request_irq(card->dev, irq, snd_es18xx_interrupt, 0, "ES18xx",
+                            (void *) card)) {
                snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq);
                return -EBUSY;
        }
        chip->irq = irq;
        card->sync_irq = chip->irq;
 
-       if (request_dma(dma1, "ES18xx DMA 1")) {
-               snd_es18xx_free(card);
+       if (snd_devm_request_dma(card->dev, dma1, "ES18xx DMA 1")) {
                snd_printk(KERN_ERR PFX "unable to grap DMA1 %d\n", dma1);
                return -EBUSY;
        }
        chip->dma1 = dma1;
 
-       if (dma2 != dma1 && request_dma(dma2, "ES18xx DMA 2")) {
-               snd_es18xx_free(card);
+       if (dma2 != dma1 &&
+           snd_devm_request_dma(card->dev, dma2, "ES18xx DMA 2")) {
                snd_printk(KERN_ERR PFX "unable to grap DMA2 %d\n", dma2);
                return -EBUSY;
        }
        chip->dma2 = dma2;
 
-       if (snd_es18xx_probe(chip, mpu_port, fm_port) < 0) {
-               snd_es18xx_free(card);
+       if (snd_es18xx_probe(card, chip, mpu_port, fm_port) < 0)
                return -ENODEV;
-       }
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_es18xx_free(card);
-               return err;
-       }
         return 0;
 }
 
@@ -2088,8 +2046,8 @@ static int snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip,
 static int snd_es18xx_card_new(struct device *pdev, int dev,
                               struct snd_card **cardp)
 {
-       return snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                           sizeof(struct snd_es18xx), cardp);
+       return snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                                sizeof(struct snd_es18xx), cardp);
 }
 
 static int snd_audiodrive_probe(struct snd_card *card, int dev)
@@ -2164,10 +2122,8 @@ static int snd_es18xx_isa_probe1(int dev, struct device *devptr)
        if (err < 0)
                return err;
        err = snd_audiodrive_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        dev_set_drvdata(devptr, card);
        return 0;
 }
@@ -2215,12 +2171,6 @@ static int snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
        }
 }
 
-static void snd_es18xx_isa_remove(struct device *devptr,
-                                 unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-}
-
 #ifdef CONFIG_PM
 static int snd_es18xx_isa_suspend(struct device *dev, unsigned int n,
                                  pm_message_t state)
@@ -2239,7 +2189,6 @@ static int snd_es18xx_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_es18xx_isa_driver = {
        .match          = snd_es18xx_isa_match,
        .probe          = snd_es18xx_isa_probe,
-       .remove         = snd_es18xx_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_es18xx_isa_suspend,
        .resume         = snd_es18xx_isa_resume,
@@ -2271,25 +2220,16 @@ static int snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
        if (err < 0)
                return err;
        err = snd_audiodrive_pnp(dev, card->private_data, pdev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_audiodrive_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pnp_set_drvdata(pdev, card);
        dev++;
        return 0;
 }
 
-static void snd_audiodrive_pnp_remove(struct pnp_dev *pdev)
-{
-       snd_card_free(pnp_get_drvdata(pdev));
-}
-
 #ifdef CONFIG_PM
 static int snd_audiodrive_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
 {
@@ -2305,7 +2245,6 @@ static struct pnp_driver es18xx_pnp_driver = {
        .name = "es18xx-pnpbios",
        .id_table = snd_audiodrive_pnpbiosids,
        .probe = snd_audiodrive_pnp_detect,
-       .remove = snd_audiodrive_pnp_remove,
 #ifdef CONFIG_PM
        .suspend = snd_audiodrive_pnp_suspend,
        .resume = snd_audiodrive_pnp_resume,
@@ -2331,27 +2270,17 @@ static int snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
                return res;
 
        res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid);
-       if (res < 0) {
-               snd_card_free(card);
+       if (res < 0)
                return res;
-       }
        res = snd_audiodrive_probe(card, dev);
-       if (res < 0) {
-               snd_card_free(card);
+       if (res < 0)
                return res;
-       }
 
        pnp_set_card_drvdata(pcard, card);
        dev++;
        return 0;
 }
 
-static void snd_audiodrive_pnpc_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_audiodrive_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -2370,7 +2299,6 @@ static struct pnp_card_driver es18xx_pnpc_driver = {
        .name = "es18xx",
        .id_table = snd_audiodrive_pnpids,
        .probe = snd_audiodrive_pnpc_detect,
-       .remove = snd_audiodrive_pnpc_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_audiodrive_pnpc_suspend,
        .resume         = snd_audiodrive_pnpc_resume,
index d33d69f..ea001c8 100644 (file)
@@ -472,20 +472,10 @@ static void snd_galaxy_free(struct snd_card *card)
 {
        struct snd_galaxy *galaxy = card->private_data;
 
-       if (galaxy->wss_port) {
+       if (galaxy->wss_port)
                wss_set_config(galaxy->wss_port, 0);
-               ioport_unmap(galaxy->wss_port);
-               release_and_free_resource(galaxy->res_wss_port);
-       }
-       if (galaxy->config_port) {
+       if (galaxy->config_port)
                galaxy_set_config(galaxy, galaxy->config);
-               ioport_unmap(galaxy->config_port);
-               release_and_free_resource(galaxy->res_config_port);
-       }
-       if (galaxy->port) {
-               ioport_unmap(galaxy->port);
-               release_and_free_resource(galaxy->res_port);
-       }
 }
 
 static int snd_galaxy_probe(struct device *dev, unsigned int n)
@@ -496,56 +486,60 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n)
        u8 type;
        int err;
 
-       err = snd_card_new(dev, index[n], id[n], THIS_MODULE,
-                          sizeof(*galaxy), &card);
+       err = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE,
+                               sizeof(*galaxy), &card);
        if (err < 0)
                return err;
 
        card->private_free = snd_galaxy_free;
        galaxy = card->private_data;
 
-       galaxy->res_port = request_region(port[n], 16, DRV_NAME);
+       galaxy->res_port = devm_request_region(dev, port[n], 16, DRV_NAME);
        if (!galaxy->res_port) {
                dev_err(dev, "could not grab ports %#lx-%#lx\n", port[n],
                        port[n] + 15);
-               err = -EBUSY;
-               goto error;
+               return -EBUSY;
        }
-       galaxy->port = ioport_map(port[n], 16);
+       galaxy->port = devm_ioport_map(dev, port[n], 16);
+       if (!galaxy->port)
+               return -ENOMEM;
 
        err = galaxy_init(galaxy, &type);
        if (err < 0) {
                dev_err(dev, "did not find a Sound Galaxy at %#lx\n", port[n]);
-               goto error;
+               return err;
        }
        dev_info(dev, "Sound Galaxy (type %d) found at %#lx\n", type, port[n]);
 
-       galaxy->res_config_port = request_region(port[n] + GALAXY_PORT_CONFIG,
-                                                16, DRV_NAME);
+       galaxy->res_config_port =
+               devm_request_region(dev, port[n] + GALAXY_PORT_CONFIG, 16,
+                                   DRV_NAME);
        if (!galaxy->res_config_port) {
                dev_err(dev, "could not grab ports %#lx-%#lx\n",
                        port[n] + GALAXY_PORT_CONFIG,
                        port[n] + GALAXY_PORT_CONFIG + 15);
-               err = -EBUSY;
-               goto error;
+               return -EBUSY;
        }
-       galaxy->config_port = ioport_map(port[n] + GALAXY_PORT_CONFIG, 16);
-
+       galaxy->config_port =
+               devm_ioport_map(dev, port[n] + GALAXY_PORT_CONFIG, 16);
+       if (!galaxy->config_port)
+               return -ENOMEM;
        galaxy_config(galaxy, config[n]);
 
-       galaxy->res_wss_port = request_region(wss_port[n], 4, DRV_NAME);
+       galaxy->res_wss_port = devm_request_region(dev, wss_port[n], 4, DRV_NAME);
        if (!galaxy->res_wss_port)  {
                dev_err(dev, "could not grab ports %#lx-%#lx\n", wss_port[n],
                        wss_port[n] + 3);
-               err = -EBUSY;
-               goto error;
+               return -EBUSY;
        }
-       galaxy->wss_port = ioport_map(wss_port[n], 4);
+       galaxy->wss_port = devm_ioport_map(dev, wss_port[n], 4);
+       if (!galaxy->wss_port)
+               return -ENOMEM;
 
        err = galaxy_wss_config(galaxy, wss_config[n]);
        if (err < 0) {
                dev_err(dev, "could not configure WSS\n");
-               goto error;
+               return err;
        }
 
        strcpy(card->driver, DRV_NAME);
@@ -557,25 +551,25 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n)
        err = snd_wss_create(card, wss_port[n] + 4, -1, irq[n], dma1[n],
                             dma2[n], WSS_HW_DETECT, 0, &chip);
        if (err < 0)
-               goto error;
+               return err;
 
        err = snd_wss_pcm(chip, 0);
        if (err < 0)
-               goto error;
+               return err;
 
        err = snd_wss_mixer(chip);
        if (err < 0)
-               goto error;
+               return err;
 
        err = snd_wss_timer(chip, 0);
        if (err < 0)
-               goto error;
+               return err;
 
        if (mpu_port[n] >= 0) {
                err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
                                          mpu_port[n], 0, mpu_irq[n], NULL);
                if (err < 0)
-                       goto error;
+                       return err;
        }
 
        if (fm_port[n] >= 0) {
@@ -585,38 +579,28 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n)
                                      OPL3_HW_AUTO, 0, &opl3);
                if (err < 0) {
                        dev_err(dev, "no OPL device at %#lx\n", fm_port[n]);
-                       goto error;
+                       return err;
                }
                err = snd_opl3_timer_new(opl3, 1, 2);
                if (err < 0)
-                       goto error;
+                       return err;
 
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                if (err < 0)
-                       goto error;
+                       return err;
        }
 
        err = snd_card_register(card);
        if (err < 0)
-               goto error;
+               return err;
 
        dev_set_drvdata(dev, card);
        return 0;
-
-error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_galaxy_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 static struct isa_driver snd_galaxy_driver = {
        .match          = snd_galaxy_match,
        .probe          = snd_galaxy_probe,
-       .remove         = snd_galaxy_remove,
 
        .driver         = {
                .name   = DEV_NAME
index 3b46490..ae1e254 100644 (file)
@@ -87,24 +87,10 @@ static void snd_gus_init_control(struct snd_gus_card *gus)
 
 static int snd_gus_free(struct snd_gus_card *gus)
 {
-       if (gus->gf1.res_port2 == NULL)
-               goto __hw_end;
-       snd_gf1_stop(gus);
-       snd_gus_init_dma_irq(gus, 0);
-      __hw_end:
-       release_and_free_resource(gus->gf1.res_port1);
-       release_and_free_resource(gus->gf1.res_port2);
-       if (gus->gf1.irq >= 0)
-               free_irq(gus->gf1.irq, (void *) gus);
-       if (gus->gf1.dma1 >= 0) {
-               disable_dma(gus->gf1.dma1);
-               free_dma(gus->gf1.dma1);
+       if (gus->gf1.res_port2) {
+               snd_gf1_stop(gus);
+               snd_gus_init_dma_irq(gus, 0);
        }
-       if (!gus->equal_dma && gus->gf1.dma2 >= 0) {
-               disable_dma(gus->gf1.dma2);
-               free_dma(gus->gf1.dma2);
-       }
-       kfree(gus);
        return 0;
 }
 
@@ -130,7 +116,7 @@ int snd_gus_create(struct snd_card *card,
        };
 
        *rgus = NULL;
-       gus = kzalloc(sizeof(*gus), GFP_KERNEL);
+       gus = devm_kzalloc(card->dev, sizeof(*gus), GFP_KERNEL);
        if (gus == NULL)
                return -ENOMEM;
        spin_lock_init(&gus->reg_lock);
@@ -156,35 +142,33 @@ int snd_gus_create(struct snd_card *card,
        gus->gf1.reg_timerctrl = GUSP(gus, TIMERCNTRL);
        gus->gf1.reg_timerdata = GUSP(gus, TIMERDATA);
        /* allocate resources */
-       gus->gf1.res_port1 = request_region(port, 16, "GUS GF1 (Adlib/SB)");
+       gus->gf1.res_port1 = devm_request_region(card->dev, port, 16,
+                                                "GUS GF1 (Adlib/SB)");
        if (!gus->gf1.res_port1) {
                snd_printk(KERN_ERR "gus: can't grab SB port 0x%lx\n", port);
-               snd_gus_free(gus);
                return -EBUSY;
        }
-       gus->gf1.res_port2 = request_region(port + 0x100, 12, "GUS GF1 (Synth)");
+       gus->gf1.res_port2 = devm_request_region(card->dev, port + 0x100, 12,
+                                                "GUS GF1 (Synth)");
        if (!gus->gf1.res_port2) {
                snd_printk(KERN_ERR "gus: can't grab synth port 0x%lx\n", port + 0x100);
-               snd_gus_free(gus);
                return -EBUSY;
        }
-       if (irq >= 0 && request_irq(irq, snd_gus_interrupt, 0, "GUS GF1", (void *) gus)) {
+       if (irq >= 0 && devm_request_irq(card->dev, irq, snd_gus_interrupt, 0,
+                                        "GUS GF1", (void *) gus)) {
                snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq);
-               snd_gus_free(gus);
                return -EBUSY;
        }
        gus->gf1.irq = irq;
        card->sync_irq = irq;
-       if (request_dma(dma1, "GUS - 1")) {
+       if (snd_devm_request_dma(card->dev, dma1, "GUS - 1")) {
                snd_printk(KERN_ERR "gus: can't grab DMA1 %d\n", dma1);
-               snd_gus_free(gus);
                return -EBUSY;
        }
        gus->gf1.dma1 = dma1;
        if (dma2 >= 0 && dma1 != dma2) {
-               if (request_dma(dma2, "GUS - 2")) {
+               if (snd_devm_request_dma(card->dev, dma2, "GUS - 2")) {
                        snd_printk(KERN_ERR "gus: can't grab DMA2 %d\n", dma2);
-                       snd_gus_free(gus);
                        return -EBUSY;
                }
                gus->gf1.dma2 = dma2;
@@ -209,10 +193,8 @@ int snd_gus_create(struct snd_card *card,
        gus->gf1.volume_ramp = 25;
        gus->gf1.smooth_pan = 1;
        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops);
-       if (err < 0) {
-               snd_gus_free(gus);
+       if (err < 0)
                return err;
-       }
        *rgus = gus;
        return 0;
 }
index bca1caa..09cc53c 100644 (file)
@@ -135,7 +135,7 @@ static int snd_gusclassic_probe(struct device *dev, unsigned int n)
        struct snd_gus_card *gus;
        int error;
 
-       error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
+       error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
        if (error < 0)
                return error;
 
@@ -144,37 +144,37 @@ static int snd_gusclassic_probe(struct device *dev, unsigned int n)
 
        error = snd_gusclassic_create(card, dev, n, &gus);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_gusclassic_detect(gus);
        if (error < 0)
-               goto out;
+               return error;
 
        gus->joystick_dac = joystick_dac[n];
 
        error = snd_gus_initialize(gus);
        if (error < 0)
-               goto out;
+               return error;
 
        error = -ENODEV;
        if (gus->max_flag || gus->ess_flag) {
                dev_err(dev, "GUS Classic or ACE soundcard was "
                        "not detected at 0x%lx\n", gus->gf1.port);
-               goto out;
+               return error;
        }
 
        error = snd_gf1_new_mixer(gus);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_gf1_pcm_new(gus, 0, 0);
        if (error < 0)
-               goto out;
+               return error;
 
        if (!gus->ace_flag) {
                error = snd_gf1_rawmidi_new(gus, 0);
                if (error < 0)
-                       goto out;
+                       return error;
        }
 
        sprintf(card->longname + strlen(card->longname),
@@ -187,27 +187,17 @@ static int snd_gusclassic_probe(struct device *dev, unsigned int n)
 
        error = snd_card_register(card);
        if (error < 0)
-               goto out;
+               return error;
 
        dev_set_drvdata(dev, card);
        return 0;
-
-out:   snd_card_free(card);
-       return error;
-}
-
-static void snd_gusclassic_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 static struct isa_driver snd_gusclassic_driver = {
        .match          = snd_gusclassic_match,
        .probe          = snd_gusclassic_probe,
-       .remove         = snd_gusclassic_remove,
 #if 0  /* FIXME */
        .suspend        = snd_gusclassic_suspend,
-       .remove         = snd_gusclassic_remove,
 #endif
        .driver         = {
                .name   = DEV_NAME
index a409a4a..63d9f2d 100644 (file)
@@ -228,8 +228,8 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n)
        struct snd_opl3 *opl3;
        int error;
 
-       error = snd_card_new(dev, index[n], id[n], THIS_MODULE,
-                            sizeof(struct snd_es1688), &card);
+       error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE,
+                                 sizeof(struct snd_es1688), &card);
        if (error < 0)
                return error;
 
@@ -243,56 +243,56 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n)
 
        error = snd_gusextreme_es1688_create(card, es1688, dev, n);
        if (error < 0)
-               goto out;
+               return error;
 
        if (gf1_port[n] < 0)
                gf1_port[n] = es1688->port + 0x20;
 
        error = snd_gusextreme_gus_card_create(card, dev, n, &gus);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_gusextreme_detect(gus, es1688);
        if (error < 0)
-               goto out;
+               return error;
 
        gus->joystick_dac = joystick_dac[n];
 
        error = snd_gus_initialize(gus);
        if (error < 0)
-               goto out;
+               return error;
 
        error = -ENODEV;
        if (!gus->ess_flag) {
                dev_err(dev, "GUS Extreme soundcard was not "
                        "detected at 0x%lx\n", gus->gf1.port);
-               goto out;
+               return error;
        }
        gus->codec_flag = 1;
 
        error = snd_es1688_pcm(card, es1688, 0);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_es1688_mixer(card, es1688);
        if (error < 0)
-               goto out;
+               return error;
 
        snd_component_add(card, "ES1688");
 
        if (pcm_channels[n] > 0) {
                error = snd_gf1_pcm_new(gus, 1, 1);
                if (error < 0)
-                       goto out;
+                       return error;
        }
 
        error = snd_gf1_new_mixer(gus);
        if (error < 0)
-               goto out;
+               return error;
 
        error = snd_gusextreme_mixer(card);
        if (error < 0)
-               goto out;
+               return error;
 
        if (snd_opl3_create(card, es1688->port, es1688->port + 2,
                        OPL3_HW_OPL3, 0, &opl3) < 0)
@@ -300,14 +300,14 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n)
        else {
                error = snd_opl3_hwdep_new(opl3, 0, 2, NULL);
                if (error < 0)
-                       goto out;
+                       return error;
        }
 
        if (es1688->mpu_port >= 0x300) {
                error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
                                es1688->mpu_port, 0, mpu_irq[n], NULL);
                if (error < 0)
-                       goto out;
+                       return error;
        }
 
        sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, "
@@ -316,24 +316,15 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n)
 
        error = snd_card_register(card);
        if (error < 0)
-               goto out;
+               return error;
 
        dev_set_drvdata(dev, card);
        return 0;
-
-out:   snd_card_free(card);
-       return error;
-}
-
-static void snd_gusextreme_remove(struct device *dev, unsigned int n)
-{
-       snd_card_free(dev_get_drvdata(dev));
 }
 
 static struct isa_driver snd_gusextreme_driver = {
        .match          = snd_gusextreme_match,
        .probe          = snd_gusextreme_probe,
-       .remove         = snd_gusextreme_remove,
 #if 0  /* FIXME */
        .suspend        = snd_gusextreme_suspend,
        .resume         = snd_gusextreme_resume,
index ad118d4..6834c05 100644 (file)
@@ -179,16 +179,6 @@ static int snd_gusmax_mixer(struct snd_wss *chip)
        return 0;
 }
 
-static void snd_gusmax_free(struct snd_card *card)
-{
-       struct snd_gusmax *maxcard = card->private_data;
-       
-       if (maxcard == NULL)
-               return;
-       if (maxcard->irq >= 0)
-               free_irq(maxcard->irq, (void *)maxcard);
-}
-
 static int snd_gusmax_match(struct device *pdev, unsigned int dev)
 {
        return enable[dev];
@@ -204,11 +194,10 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
        struct snd_wss *wss;
        struct snd_gusmax *maxcard;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_gusmax), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_gusmax), &card);
        if (err < 0)
                return err;
-       card->private_free = snd_gusmax_free;
        maxcard = card->private_data;
        maxcard->card = card;
        maxcard->irq = -1;
@@ -218,8 +207,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
                xirq = snd_legacy_find_free_irq(possible_irqs);
                if (xirq < 0) {
                        snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
-                       err = -EBUSY;
-                       goto _err;
+                       return -EBUSY;
                }
        }
        xdma1 = dma1[dev];
@@ -227,8 +215,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
                xdma1 = snd_legacy_find_free_dma(possible_dmas);
                if (xdma1 < 0) {
                        snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
-                       err = -EBUSY;
-                       goto _err;
+                       return -EBUSY;
                }
        }
        xdma2 = dma2[dev];
@@ -236,8 +223,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
                xdma2 = snd_legacy_find_free_dma(possible_dmas);
                if (xdma2 < 0) {
                        snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
-                       err = -EBUSY;
-                       goto _err;
+                       return -EBUSY;
                }
        }
 
@@ -267,29 +253,28 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
                }
        }
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_gusmax_detect(gus);
        if (err < 0)
-               goto _err;
+               return err;
 
        maxcard->gus_status_reg = gus->gf1.reg_irqstat;
        maxcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
        snd_gusmax_init(dev, card, gus);
        err = snd_gus_initialize(gus);
        if (err < 0)
-               goto _err;
+               return err;
 
        if (!gus->max_flag) {
                snd_printk(KERN_ERR PFX "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port);
-               err = -ENODEV;
-               goto _err;
+               return -ENODEV;
        }
 
-       if (request_irq(xirq, snd_gusmax_interrupt, 0, "GUS MAX", (void *)maxcard)) {
+       if (devm_request_irq(card->dev, xirq, snd_gusmax_interrupt, 0,
+                            "GUS MAX", (void *)maxcard)) {
                snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
-               err = -EBUSY;
-               goto _err;
+               return -EBUSY;
        }
        maxcard->irq = xirq;
        card->sync_irq = maxcard->irq;
@@ -303,32 +288,32 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
                             WSS_HWSHARE_DMA2,
                             &wss);
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_wss_pcm(wss, 0);
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_wss_mixer(wss);
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_wss_timer(wss, 2);
        if (err < 0)
-               goto _err;
+               return err;
 
        if (pcm_channels[dev] > 0) {
                err = snd_gf1_pcm_new(gus, 1, 1);
                if (err < 0)
-                       goto _err;
+                       return err;
        }
        err = snd_gusmax_mixer(wss);
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_gf1_rawmidi_new(gus, 0);
        if (err < 0)
-               goto _err;
+               return err;
 
        sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1);
        if (xdma2 >= 0)
@@ -336,22 +321,13 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto _err;
+               return err;
                
        maxcard->gus = gus;
        maxcard->wss = wss;
 
        dev_set_drvdata(pdev, card);
        return 0;
-
- _err:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_gusmax_remove(struct device *devptr, unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
 }
 
 #define DEV_NAME "gusmax"
@@ -359,7 +335,6 @@ static void snd_gusmax_remove(struct device *devptr, unsigned int dev)
 static struct isa_driver snd_gusmax_driver = {
        .match          = snd_gusmax_match,
        .probe          = snd_gusmax_probe,
-       .remove         = snd_gusmax_remove,
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = DEV_NAME
index 755de47..20f490e 100644 (file)
@@ -204,13 +204,15 @@ static int snd_interwave_detect_stb(struct snd_interwave *iwcard,
                        port = 0x360;
                }
                while (port <= 0x380) {
-                       iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)");
+                       iwcard->i2c_res = devm_request_region(card->dev, port, 1,
+                                                             "InterWave (I2C bus)");
                        if (iwcard->i2c_res)
                                break;
                        port += 0x10;
                }
        } else {
-               iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)");
+               iwcard->i2c_res = devm_request_region(card->dev, port, 1,
+                                                     "InterWave (I2C bus)");
        }
        if (iwcard->i2c_res == NULL) {
                snd_printk(KERN_ERR "interwave: can't grab i2c bus port\n");
@@ -598,19 +600,6 @@ static int snd_interwave_pnp(int dev, struct snd_interwave *iwcard,
 }
 #endif /* CONFIG_PNP */
 
-static void snd_interwave_free(struct snd_card *card)
-{
-       struct snd_interwave *iwcard = card->private_data;
-
-       if (iwcard == NULL)
-               return;
-#ifdef SNDRV_STB
-       release_and_free_resource(iwcard->i2c_res);
-#endif
-       if (iwcard->irq >= 0)
-               free_irq(iwcard->irq, (void *)iwcard);
-}
-
 static int snd_interwave_card_new(struct device *pdev, int dev,
                                  struct snd_card **cardp)
 {
@@ -618,14 +607,13 @@ static int snd_interwave_card_new(struct device *pdev, int dev,
        struct snd_interwave *iwcard;
        int err;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_interwave), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_interwave), &card);
        if (err < 0)
                return err;
        iwcard = card->private_data;
        iwcard->card = card;
        iwcard->irq = -1;
-       card->private_free = snd_interwave_free;
        *cardp = card;
        return 0;
 }
@@ -671,8 +659,8 @@ static int snd_interwave_probe(struct snd_card *card, int dev)
        if (err < 0)
                return err;
 
-       if (request_irq(xirq, snd_interwave_interrupt, 0,
-                       "InterWave", iwcard)) {
+       if (devm_request_irq(card->dev, xirq, snd_interwave_interrupt, 0,
+                            "InterWave", iwcard)) {
                snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
                return -EBUSY;
        }
@@ -779,10 +767,8 @@ static int snd_interwave_isa_probe1(int dev, struct device *devptr)
                return err;
 
        err = snd_interwave_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        dev_set_drvdata(devptr, card);
        return 0;
 }
@@ -843,15 +829,9 @@ static int snd_interwave_isa_probe(struct device *pdev,
        }
 }
 
-static void snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-}
-
 static struct isa_driver snd_interwave_driver = {
        .match          = snd_interwave_isa_match,
        .probe          = snd_interwave_isa_probe,
-       .remove         = snd_interwave_isa_remove,
        /* FIXME: suspend,resume */
        .driver         = {
                .name   = INTERWAVE_DRIVER
@@ -878,32 +858,21 @@ static int snd_interwave_pnp_detect(struct pnp_card_link *pcard,
                return res;
 
        res = snd_interwave_pnp(dev, card->private_data, pcard, pid);
-       if (res < 0) {
-               snd_card_free(card);
+       if (res < 0)
                return res;
-       }
        res = snd_interwave_probe(card, dev);
-       if (res < 0) {
-               snd_card_free(card);
+       if (res < 0)
                return res;
-       }
        pnp_set_card_drvdata(pcard, card);
        dev++;
        return 0;
 }
 
-static void snd_interwave_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 static struct pnp_card_driver interwave_pnpc_driver = {
        .flags = PNP_DRIVER_RES_DISABLE,
        .name = INTERWAVE_PNP_DRIVER,
        .id_table = snd_interwave_pnpids,
        .probe = snd_interwave_pnp_detect,
-       .remove = snd_interwave_pnp_remove,
        /* FIXME: suspend,resume */
 };
 
index 4fbc22a..c3fd1eb 100644 (file)
@@ -425,7 +425,7 @@ static void snd_msnd_capture_reset_queue(struct snd_msnd *chip,
 }
 
 static const struct snd_pcm_hardware snd_msnd_playback = {
-       .info =                 SNDRV_PCM_INFO_MMAP |
+       .info =                 SNDRV_PCM_INFO_MMAP_IOMEM |
                                SNDRV_PCM_INFO_INTERLEAVED |
                                SNDRV_PCM_INFO_MMAP_VALID |
                                SNDRV_PCM_INFO_BATCH,
@@ -444,7 +444,7 @@ static const struct snd_pcm_hardware snd_msnd_playback = {
 };
 
 static const struct snd_pcm_hardware snd_msnd_capture = {
-       .info =                 SNDRV_PCM_INFO_MMAP |
+       .info =                 SNDRV_PCM_INFO_MMAP_IOMEM |
                                SNDRV_PCM_INFO_INTERLEAVED |
                                SNDRV_PCM_INFO_MMAP_VALID |
                                SNDRV_PCM_INFO_BATCH,
@@ -473,6 +473,7 @@ static int snd_msnd_playback_open(struct snd_pcm_substream *substream)
        snd_msnd_enable_irq(chip);
 
        runtime->dma_area = (__force void *)chip->mappedbase;
+       runtime->dma_addr = chip->base;
        runtime->dma_bytes = 0x3000;
 
        chip->playback_substream = substream;
@@ -566,6 +567,7 @@ static const struct snd_pcm_ops snd_msnd_playback_ops = {
        .prepare =      snd_msnd_playback_prepare,
        .trigger =      snd_msnd_playback_trigger,
        .pointer =      snd_msnd_playback_pointer,
+       .mmap =         snd_pcm_lib_mmap_iomem,
 };
 
 static int snd_msnd_capture_open(struct snd_pcm_substream *substream)
@@ -576,6 +578,7 @@ static int snd_msnd_capture_open(struct snd_pcm_substream *substream)
        set_bit(F_AUDIO_READ_INUSE, &chip->flags);
        snd_msnd_enable_irq(chip);
        runtime->dma_area = (__force void *)chip->mappedbase + 0x3000;
+       runtime->dma_addr = chip->base + 0x3000;
        runtime->dma_bytes = 0x3000;
        memset(runtime->dma_area, 0, runtime->dma_bytes);
        chip->capture_substream = substream;
@@ -662,6 +665,7 @@ static const struct snd_pcm_ops snd_msnd_capture_ops = {
        .prepare =      snd_msnd_capture_prepare,
        .trigger =      snd_msnd_capture_trigger,
        .pointer =      snd_msnd_capture_pointer,
+       .mmap =         snd_pcm_lib_mmap_iomem,
 };
 
 
index 69647b4..4433a92 100644 (file)
@@ -472,11 +472,6 @@ static int snd_msnd_dsp_full_reset(struct snd_card *card)
        return rv;
 }
 
-static int snd_msnd_dev_free(struct snd_device *device)
-{
-       snd_printdd("snd_msnd_chip_free()\n");
-       return 0;
-}
 
 static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd)
 {
@@ -528,58 +523,47 @@ static int snd_msnd_attach(struct snd_card *card)
 {
        struct snd_msnd *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =      snd_msnd_dev_free,
-               };
 
-       err = request_irq(chip->irq, snd_msnd_interrupt, 0, card->shortname,
-                         chip);
+       err = devm_request_irq(card->dev, chip->irq, snd_msnd_interrupt, 0,
+                              card->shortname, chip);
        if (err < 0) {
                printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq);
                return err;
        }
        card->sync_irq = chip->irq;
-       if (request_region(chip->io, DSP_NUMIO, card->shortname) == NULL) {
-               free_irq(chip->irq, chip);
+       if (!devm_request_region(card->dev, chip->io, DSP_NUMIO,
+                                card->shortname))
                return -EBUSY;
-       }
 
-       if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) {
+       if (!devm_request_mem_region(card->dev, chip->base, BUFFSIZE,
+                                    card->shortname)) {
                printk(KERN_ERR LOGNAME
                        ": unable to grab memory region 0x%lx-0x%lx\n",
                        chip->base, chip->base + BUFFSIZE - 1);
-               release_region(chip->io, DSP_NUMIO);
-               free_irq(chip->irq, chip);
                return -EBUSY;
        }
-       chip->mappedbase = ioremap(chip->base, 0x8000);
+       chip->mappedbase = devm_ioremap(card->dev, chip->base, 0x8000);
        if (!chip->mappedbase) {
                printk(KERN_ERR LOGNAME
                        ": unable to map memory region 0x%lx-0x%lx\n",
                        chip->base, chip->base + BUFFSIZE - 1);
-               err = -EIO;
-               goto err_release_region;
+               return -EIO;
        }
 
        err = snd_msnd_dsp_full_reset(card);
        if (err < 0)
-               goto err_release_region;
-
-       /* Register device */
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto err_release_region;
+               return err;
 
        err = snd_msnd_pcm(card, 0);
        if (err < 0) {
                printk(KERN_ERR LOGNAME ": error creating new PCM device\n");
-               goto err_release_region;
+               return err;
        }
 
        err = snd_msndmix_new(card);
        if (err < 0) {
                printk(KERN_ERR LOGNAME ": error creating new Mixer device\n");
-               goto err_release_region;
+               return err;
        }
 
 
@@ -595,7 +579,7 @@ static int snd_msnd_attach(struct snd_card *card)
                if (err < 0) {
                        printk(KERN_ERR LOGNAME
                                ": error creating new Midi device\n");
-                       goto err_release_region;
+                       return err;
                }
                mpu = chip->rmidi->private_data;
 
@@ -610,30 +594,12 @@ static int snd_msnd_attach(struct snd_card *card)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto err_release_region;
+               return err;
 
        return 0;
-
-err_release_region:
-       iounmap(chip->mappedbase);
-       release_mem_region(chip->base, BUFFSIZE);
-       release_region(chip->io, DSP_NUMIO);
-       free_irq(chip->irq, chip);
-       return err;
 }
 
 
-static void snd_msnd_unload(struct snd_card *card)
-{
-       struct snd_msnd *chip = card->private_data;
-
-       iounmap(chip->mappedbase);
-       release_mem_region(chip->base, BUFFSIZE);
-       release_region(chip->io, DSP_NUMIO);
-       free_irq(chip->irq, chip);
-       snd_card_free(card);
-}
-
 #ifndef MSND_CLASSIC
 
 /* Pinnacle/Fiji Logical Device Configuration */
@@ -892,8 +858,8 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
                return -ENODEV;
        }
 
-       err = snd_card_new(pdev, index[idx], id[idx], THIS_MODULE,
-                          sizeof(struct snd_msnd), &card);
+       err = snd_devm_card_new(pdev, index[idx], id[idx], THIS_MODULE,
+                               sizeof(struct snd_msnd), &card);
        if (err < 0)
                return err;
 
@@ -934,17 +900,15 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
        printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%lx\n",
                        cfg[idx]);
 
-       if (!request_region(cfg[idx], 2, "Pinnacle/Fiji Config")) {
+       if (!devm_request_region(card->dev, cfg[idx], 2,
+                                "Pinnacle/Fiji Config")) {
                printk(KERN_ERR LOGNAME ": Config port 0x%lx conflict\n",
                           cfg[idx]);
-               snd_card_free(card);
                return -EIO;
        }
        if (reset[idx])
-               if (snd_msnd_pinnacle_cfg_reset(cfg[idx])) {
-                       err = -EIO;
-                       goto cfg_error;
-               }
+               if (snd_msnd_pinnacle_cfg_reset(cfg[idx]))
+                       return -EIO;
 
        /* DSP */
        err = snd_msnd_write_cfg_logical(cfg[idx], 0,
@@ -952,7 +916,7 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
                                         irq[idx], mem[idx]);
 
        if (err)
-               goto cfg_error;
+               return err;
 
        /* The following are Pinnacle specific */
 
@@ -967,7 +931,7 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
                                                 mpu_irq[idx], 0);
 
                if (err)
-                       goto cfg_error;
+                       return err;
        }
 
        /* IDE */
@@ -982,7 +946,7 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
                                                 ide_irq[idx], 0);
 
                if (err)
-                       goto cfg_error;
+                       return err;
        }
 
        /* Joystick */
@@ -995,9 +959,8 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
                                                 0, 0);
 
                if (err)
-                       goto cfg_error;
+                       return err;
        }
-       release_region(cfg[idx], 2);
 
 #endif /* MSND_CLASSIC */
 
@@ -1027,37 +990,22 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
        err = snd_msnd_probe(card);
        if (err < 0) {
                printk(KERN_ERR LOGNAME ": Probe failed\n");
-               snd_card_free(card);
                return err;
        }
 
        err = snd_msnd_attach(card);
        if (err < 0) {
                printk(KERN_ERR LOGNAME ": Attach failed\n");
-               snd_card_free(card);
                return err;
        }
        dev_set_drvdata(pdev, card);
 
        return 0;
-
-#ifndef MSND_CLASSIC
-cfg_error:
-       release_region(cfg[idx], 2);
-       snd_card_free(card);
-       return err;
-#endif
-}
-
-static void snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
-{
-       snd_msnd_unload(dev_get_drvdata(pdev));
 }
 
 static struct isa_driver snd_msnd_driver = {
        .match          = snd_msnd_isa_match,
        .probe          = snd_msnd_isa_probe,
-       .remove         = snd_msnd_isa_remove,
        /* FIXME: suspend, resume */
        .driver         = {
                .name   = DEV_NAME
@@ -1107,9 +1055,9 @@ static int snd_msnd_pnp_detect(struct pnp_card_link *pcard,
         * Create a new ALSA sound card entry, in anticipation
         * of detecting our hardware ...
         */
-       ret = snd_card_new(&pcard->card->dev,
-                          index[idx], id[idx], THIS_MODULE,
-                          sizeof(struct snd_msnd), &card);
+       ret = snd_devm_card_new(&pcard->card->dev,
+                               index[idx], id[idx], THIS_MODULE,
+                               sizeof(struct snd_msnd), &card);
        if (ret < 0)
                return ret;
 
@@ -1151,28 +1099,18 @@ static int snd_msnd_pnp_detect(struct pnp_card_link *pcard,
        ret = snd_msnd_probe(card);
        if (ret < 0) {
                printk(KERN_ERR LOGNAME ": Probe failed\n");
-               goto _release_card;
+               return ret;
        }
 
        ret = snd_msnd_attach(card);
        if (ret < 0) {
                printk(KERN_ERR LOGNAME ": Attach failed\n");
-               goto _release_card;
+               return ret;
        }
 
        pnp_set_card_drvdata(pcard, card);
        ++idx;
        return 0;
-
-_release_card:
-       snd_card_free(card);
-       return ret;
-}
-
-static void snd_msnd_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_msnd_unload(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
 }
 
 static int isa_registered;
@@ -1191,7 +1129,6 @@ static struct pnp_card_driver msnd_pnpc_driver = {
        .name = "msnd_pinnacle",
        .id_table = msnd_pnpids,
        .probe = snd_msnd_pnp_detect,
-       .remove = snd_msnd_pnp_remove,
 };
 #endif /* CONFIG_PNP */
 
index 6f42f86..bad1490 100644 (file)
@@ -208,7 +208,8 @@ static int snd_opl3sa2_detect(struct snd_card *card)
        char str[2];
 
        port = chip->port;
-       chip->res_port = request_region(port, 2, "OPL3-SA control");
+       chip->res_port = devm_request_region(card->dev, port, 2,
+                                            "OPL3-SA control");
        if (!chip->res_port) {
                snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port);
                return -EBUSY;
@@ -609,14 +610,6 @@ static int snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip,
 }
 #endif /* CONFIG_PNP */
 
-static void snd_opl3sa2_free(struct snd_card *card)
-{
-       struct snd_opl3sa2 *chip = card->private_data;
-       if (chip->irq >= 0)
-               free_irq(chip->irq, card);
-       release_and_free_resource(chip->res_port);
-}
-
 static int snd_opl3sa2_card_new(struct device *pdev, int dev,
                                struct snd_card **cardp)
 {
@@ -624,8 +617,8 @@ static int snd_opl3sa2_card_new(struct device *pdev, int dev,
        struct snd_opl3sa2 *chip;
        int err;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_opl3sa2), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_opl3sa2), &card);
        if (err < 0)
                return err;
        strcpy(card->driver, "OPL3SA2");
@@ -633,7 +626,6 @@ static int snd_opl3sa2_card_new(struct device *pdev, int dev,
        chip = card->private_data;
        spin_lock_init(&chip->reg_lock);
        chip->irq = -1;
-       card->private_free = snd_opl3sa2_free;
        *cardp = card;
        return 0;
 }
@@ -658,8 +650,8 @@ static int snd_opl3sa2_probe(struct snd_card *card, int dev)
        err = snd_opl3sa2_detect(card);
        if (err < 0)
                return err;
-       err = request_irq(xirq, snd_opl3sa2_interrupt, 0,
-                         "OPL3-SA2", card);
+       err = devm_request_irq(card->dev, xirq, snd_opl3sa2_interrupt, 0,
+                              "OPL3-SA2", card);
        if (err) {
                snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq);
                return -ENODEV;
@@ -737,25 +729,16 @@ static int snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
        if (err < 0)
                return err;
        err = snd_opl3sa2_pnp(dev, card->private_data, pdev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_opl3sa2_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pnp_set_drvdata(pdev, card);
        dev++;
        return 0;
 }
 
-static void snd_opl3sa2_pnp_remove(struct pnp_dev *pdev)
-{
-       snd_card_free(pnp_get_drvdata(pdev));
-}
-
 #ifdef CONFIG_PM
 static int snd_opl3sa2_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
 {
@@ -771,7 +754,6 @@ static struct pnp_driver opl3sa2_pnp_driver = {
        .name = "snd-opl3sa2-pnpbios",
        .id_table = snd_opl3sa2_pnpbiosids,
        .probe = snd_opl3sa2_pnp_detect,
-       .remove = snd_opl3sa2_pnp_remove,
 #ifdef CONFIG_PM
        .suspend = snd_opl3sa2_pnp_suspend,
        .resume = snd_opl3sa2_pnp_resume,
@@ -803,26 +785,16 @@ static int snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
        if (err < 0)
                return err;
        err = snd_opl3sa2_pnp(dev, card->private_data, pdev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_opl3sa2_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pnp_set_card_drvdata(pcard, card);
        dev++;
        return 0;
 }
 
-static void snd_opl3sa2_pnp_cremove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_opl3sa2_pnp_csuspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -839,7 +811,6 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = {
        .name = "snd-opl3sa2-cpnp",
        .id_table = snd_opl3sa2_pnpids,
        .probe = snd_opl3sa2_pnp_cdetect,
-       .remove = snd_opl3sa2_pnp_cremove,
 #ifdef CONFIG_PM
        .suspend = snd_opl3sa2_pnp_csuspend,
        .resume = snd_opl3sa2_pnp_cresume,
@@ -885,20 +856,12 @@ static int snd_opl3sa2_isa_probe(struct device *pdev,
        if (err < 0)
                return err;
        err = snd_opl3sa2_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        dev_set_drvdata(pdev, card);
        return 0;
 }
 
-static void snd_opl3sa2_isa_remove(struct device *devptr,
-                                 unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-}
-
 #ifdef CONFIG_PM
 static int snd_opl3sa2_isa_suspend(struct device *dev, unsigned int n,
                                   pm_message_t state)
@@ -917,7 +880,6 @@ static int snd_opl3sa2_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_opl3sa2_isa_driver = {
        .match          = snd_opl3sa2_isa_match,
        .probe          = snd_opl3sa2_isa_probe,
-       .remove         = snd_opl3sa2_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_opl3sa2_isa_suspend,
        .resume         = snd_opl3sa2_isa_resume,
index e1fb756..59242ba 100644 (file)
@@ -1159,12 +1159,13 @@ __skip_mpu:
        return 0;
 }
 
-static int snd_miro_opti_check(struct snd_miro *chip)
+static int snd_miro_opti_check(struct snd_card *card, struct snd_miro *chip)
 {
        unsigned char value;
 
-       chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size,
-                                          "OPTi9xx MC");
+       chip->res_mc_base =
+               devm_request_region(card->dev, chip->mc_base,
+                                   chip->mc_base_size, "OPTi9xx MC");
        if (chip->res_mc_base == NULL)
                return -ENOMEM;
 
@@ -1173,7 +1174,7 @@ static int snd_miro_opti_check(struct snd_miro *chip)
                if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1)))
                        return 0;
 
-       release_and_free_resource(chip->res_mc_base);
+       devm_release_resource(card->dev, chip->res_mc_base);
        chip->res_mc_base = NULL;
 
        return -ENODEV;
@@ -1190,7 +1191,7 @@ static int snd_card_miro_detect(struct snd_card *card,
                if (err < 0)
                        return err;
 
-               err = snd_miro_opti_check(chip);
+               err = snd_miro_opti_check(card, chip);
                if (err == 0)
                        return 1;
        }
@@ -1214,7 +1215,8 @@ static int snd_card_miro_aci_detect(struct snd_card *card,
        regval=inb(miro->mc_base + 4);
        aci->aci_port = (regval & 0x10) ? 0x344 : 0x354;
 
-       miro->res_aci_port = request_region(aci->aci_port, 3, "miro aci");
+       miro->res_aci_port =
+               devm_request_region(card->dev, aci->aci_port, 3, "miro aci");
        if (miro->res_aci_port == NULL) {
                snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n", 
                           aci->aci_port, aci->aci_port+2);
@@ -1253,16 +1255,6 @@ static int snd_card_miro_aci_detect(struct snd_card *card,
        return 0;
 }
 
-static void snd_card_miro_free(struct snd_card *card)
-{
-       struct snd_miro *miro = card->private_data;
-
-       release_and_free_resource(miro->res_aci_port);
-       if (miro->aci)
-               miro->aci->aci_port = 0;
-       release_and_free_resource(miro->res_mc_base);
-}
-
 static int snd_miro_probe(struct snd_card *card)
 {
        int error;
@@ -1271,9 +1263,10 @@ static int snd_miro_probe(struct snd_card *card)
        struct snd_rawmidi *rmidi;
 
        if (!miro->res_mc_base) {
-               miro->res_mc_base = request_region(miro->mc_base,
-                                               miro->mc_base_size,
-                                               "miro (OPTi9xx MC)");
+               miro->res_mc_base = devm_request_region(card->dev,
+                                                       miro->mc_base,
+                                                       miro->mc_base_size,
+                                                       "miro (OPTi9xx MC)");
                if (miro->res_mc_base == NULL) {
                        snd_printk(KERN_ERR "request for OPTI9xx MC failed\n");
                        return -ENOMEM;
@@ -1408,17 +1401,15 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        struct snd_miro *miro;
        struct snd_card *card;
 
-       error = snd_card_new(devptr, index, id, THIS_MODULE,
-                            sizeof(struct snd_miro), &card);
+       error = snd_devm_card_new(devptr, index, id, THIS_MODULE,
+                                 sizeof(struct snd_miro), &card);
        if (error < 0)
                return error;
 
-       card->private_free = snd_card_miro_free;
        miro = card->private_data;
 
        error = snd_card_miro_detect(card, miro);
        if (error < 0) {
-               snd_card_free(card);
                snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n");
                return -ENODEV;
        }
@@ -1426,7 +1417,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        if (port == SNDRV_AUTO_PORT) {
                port = snd_legacy_find_free_ioport(possible_ports, 4);
                if (port < 0) {
-                       snd_card_free(card);
                        snd_printk(KERN_ERR "unable to find a free WSS port\n");
                        return -EBUSY;
                }
@@ -1435,7 +1425,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        if (mpu_port == SNDRV_AUTO_PORT) {
                mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2);
                if (mpu_port < 0) {
-                       snd_card_free(card);
                        snd_printk(KERN_ERR
                                   "unable to find a free MPU401 port\n");
                        return -EBUSY;
@@ -1445,7 +1434,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        if (irq == SNDRV_AUTO_IRQ) {
                irq = snd_legacy_find_free_irq(possible_irqs);
                if (irq < 0) {
-                       snd_card_free(card);
                        snd_printk(KERN_ERR "unable to find a free IRQ\n");
                        return -EBUSY;
                }
@@ -1453,7 +1441,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        if (mpu_irq == SNDRV_AUTO_IRQ) {
                mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs);
                if (mpu_irq < 0) {
-                       snd_card_free(card);
                        snd_printk(KERN_ERR
                                   "unable to find a free MPU401 IRQ\n");
                        return -EBUSY;
@@ -1462,7 +1449,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        if (dma1 == SNDRV_AUTO_DMA) {
                dma1 = snd_legacy_find_free_dma(possible_dma1s);
                if (dma1 < 0) {
-                       snd_card_free(card);
                        snd_printk(KERN_ERR "unable to find a free DMA1\n");
                        return -EBUSY;
                }
@@ -1470,34 +1456,24 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        if (dma2 == SNDRV_AUTO_DMA) {
                dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4]);
                if (dma2 < 0) {
-                       snd_card_free(card);
                        snd_printk(KERN_ERR "unable to find a free DMA2\n");
                        return -EBUSY;
                }
        }
 
        error = snd_miro_probe(card);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
 
        dev_set_drvdata(devptr, card);
        return 0;
 }
 
-static void snd_miro_isa_remove(struct device *devptr,
-                              unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-}
-
 #define DEV_NAME "miro"
 
 static struct isa_driver snd_miro_driver = {
        .match          = snd_miro_isa_match,
        .probe          = snd_miro_isa_probe,
-       .remove         = snd_miro_isa_remove,
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = DEV_NAME
@@ -1578,39 +1554,31 @@ static int snd_miro_pnp_probe(struct pnp_card_link *pcard,
                return -EBUSY;
        if (!isapnp)
                return -ENODEV;
-       err = snd_card_new(&pcard->card->dev, index, id, THIS_MODULE,
-                          sizeof(struct snd_miro), &card);
+       err = snd_devm_card_new(&pcard->card->dev, index, id, THIS_MODULE,
+                               sizeof(struct snd_miro), &card);
        if (err < 0)
                return err;
 
-       card->private_free = snd_card_miro_free;
        miro = card->private_data;
 
        err = snd_card_miro_pnp(miro, pcard, pid);
-       if (err) {
-               snd_card_free(card);
+       if (err)
                return err;
-       }
 
        /* only miroSOUND PCM20 and PCM12 == OPTi924 */
        err = snd_miro_init(miro, OPTi9XX_HW_82C924);
-       if (err) {
-               snd_card_free(card);
+       if (err)
                return err;
-       }
 
-       err = snd_miro_opti_check(miro);
+       err = snd_miro_opti_check(card, miro);
        if (err) {
                snd_printk(KERN_ERR "OPTI chip not found\n");
-               snd_card_free(card);
                return err;
        }
 
        err = snd_miro_probe(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pnp_set_card_drvdata(pcard, card);
        snd_miro_pnp_is_probed = 1;
        return 0;
@@ -1618,8 +1586,6 @@ static int snd_miro_pnp_probe(struct pnp_card_link *pcard,
 
 static void snd_miro_pnp_remove(struct pnp_card_link *pcard)
 {
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
        snd_miro_pnp_is_probed = 0;
 }
 
index 4bd1dc6..4beeb32 100644 (file)
@@ -654,16 +654,18 @@ static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
 
 #endif /* OPTi93X */
 
-static int snd_opti9xx_read_check(struct snd_opti9xx *chip)
+static int snd_opti9xx_read_check(struct snd_card *card,
+                                 struct snd_opti9xx *chip)
 {
        unsigned char value;
 #ifdef OPTi93X
        unsigned long flags;
 #endif
 
-       chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size,
-                                          "OPTi9xx MC");
-       if (chip->res_mc_base == NULL)
+       chip->res_mc_base =
+               devm_request_region(card->dev, chip->mc_base,
+                                   chip->mc_base_size, "OPTi9xx MC");
+       if (!chip->res_mc_base)
                return -EBUSY;
 #ifndef OPTi93X
        value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1));
@@ -671,9 +673,10 @@ static int snd_opti9xx_read_check(struct snd_opti9xx *chip)
                if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)))
                        return 0;
 #else  /* OPTi93X */
-       chip->res_mc_indir = request_region(chip->mc_indir_index, 2,
-                                           "OPTi93x MC");
-       if (chip->res_mc_indir == NULL)
+       chip->res_mc_indir =
+               devm_request_region(card->dev, chip->mc_indir_index, 2,
+                                   "OPTi93x MC");
+       if (!chip->res_mc_indir)
                return -EBUSY;
 
        spin_lock_irqsave(&chip->lock, flags);
@@ -686,10 +689,10 @@ static int snd_opti9xx_read_check(struct snd_opti9xx *chip)
        if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value)
                return 0;
 
-       release_and_free_resource(chip->res_mc_indir);
+       devm_release_resource(card->dev, chip->res_mc_indir);
        chip->res_mc_indir = NULL;
 #endif /* OPTi93X */
-       release_and_free_resource(chip->res_mc_base);
+       devm_release_resource(card->dev, chip->res_mc_base);
        chip->res_mc_base = NULL;
 
        return -ENODEV;
@@ -709,7 +712,7 @@ static int snd_card_opti9xx_detect(struct snd_card *card,
                if (err < 0)
                        return err;
 
-               err = snd_opti9xx_read_check(chip);
+               err = snd_opti9xx_read_check(card, chip);
                if (err == 0)
                        return 1;
 #ifdef OPTi93X
@@ -789,22 +792,6 @@ static int snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
 }
 #endif /* CONFIG_PNP */
 
-static void snd_card_opti9xx_free(struct snd_card *card)
-{
-       struct snd_opti9xx *chip = card->private_data;
-
-       if (chip) {
-#ifdef OPTi93X
-               if (chip->irq > 0) {
-                       disable_irq(chip->irq);
-                       free_irq(chip->irq, chip);
-               }
-               release_and_free_resource(chip->res_mc_indir);
-#endif
-               release_and_free_resource(chip->res_mc_base);
-       }
-}
-
 static int snd_opti9xx_probe(struct snd_card *card)
 {
        static const long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
@@ -860,8 +847,8 @@ static int snd_opti9xx_probe(struct snd_card *card)
                return error;
 #endif
 #ifdef OPTi93X
-       error = request_irq(irq, snd_opti93x_interrupt,
-                           0, DEV_NAME" - WSS", chip);
+       error = devm_request_irq(card->dev, irq, snd_opti93x_interrupt,
+                                0, DEV_NAME" - WSS", chip);
        if (error < 0) {
                snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq);
                return error;
@@ -931,11 +918,10 @@ static int snd_opti9xx_card_new(struct device *pdev, struct snd_card **cardp)
        struct snd_card *card;
        int err;
 
-       err = snd_card_new(pdev, index, id, THIS_MODULE,
-                          sizeof(struct snd_opti9xx), &card);
+       err = snd_devm_card_new(pdev, index, id, THIS_MODULE,
+                               sizeof(struct snd_opti9xx), &card);
        if (err < 0)
                return err;
-       card->private_free = snd_card_opti9xx_free;
        *cardp = card;
        return 0;
 }
@@ -1012,25 +998,15 @@ static int snd_opti9xx_isa_probe(struct device *devptr,
                return error;
 
        error = snd_card_opti9xx_detect(card, card->private_data);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        error = snd_opti9xx_probe(card);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        dev_set_drvdata(devptr, card);
        return 0;
 }
 
-static void snd_opti9xx_isa_remove(struct device *devptr,
-                                  unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-}
-
 #ifdef CONFIG_PM
 static int snd_opti9xx_suspend(struct snd_card *card)
 {
@@ -1075,7 +1051,6 @@ static int snd_opti9xx_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_opti9xx_driver = {
        .match          = snd_opti9xx_isa_match,
        .probe          = snd_opti9xx_isa_probe,
-       .remove         = snd_opti9xx_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_opti9xx_isa_suspend,
        .resume         = snd_opti9xx_isa_resume,
@@ -1114,26 +1089,20 @@ static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
                hw = OPTi9XX_HW_82C931;
                break;
        default:
-               snd_card_free(card);
                return -ENODEV;
        }
 
        error = snd_opti9xx_init(chip, hw);
-       if (error) {
-               snd_card_free(card);
+       if (error)
                return error;
-       }
-       error = snd_opti9xx_read_check(chip);
+       error = snd_opti9xx_read_check(card, chip);
        if (error) {
                snd_printk(KERN_ERR "OPTI chip not found\n");
-               snd_card_free(card);
                return error;
        }
        error = snd_opti9xx_probe(card);
-       if (error < 0) {
-               snd_card_free(card);
+       if (error < 0)
                return error;
-       }
        pnp_set_card_drvdata(pcard, card);
        snd_opti9xx_pnp_is_probed = 1;
        return 0;
@@ -1141,8 +1110,6 @@ static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
 
 static void snd_opti9xx_pnp_remove(struct pnp_card_link *pcard)
 {
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
        snd_opti9xx_pnp_is_probed = 0;
 }
 
index 5e41879..e020296 100644 (file)
@@ -1048,27 +1048,6 @@ __error:
        return err;
 }
 
-
-/*
- * free resources
- */
-static int snd_emu8000_free(struct snd_emu8000 *hw)
-{
-       release_and_free_resource(hw->res_port1);
-       release_and_free_resource(hw->res_port2);
-       release_and_free_resource(hw->res_port3);
-       kfree(hw);
-       return 0;
-}
-
-/*
- */
-static int snd_emu8000_dev_free(struct snd_device *device)
-{
-       struct snd_emu8000 *hw = device->device_data;
-       return snd_emu8000_free(hw);
-}
-
 /*
  * initialize and register emu8000 synth device.
  */
@@ -1079,9 +1058,6 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
        struct snd_seq_device *awe;
        struct snd_emu8000 *hw;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_emu8000_dev_free,
-       };
 
        if (awe_ret)
                *awe_ret = NULL;
@@ -1089,7 +1065,7 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
        if (seq_ports <= 0)
                return 0;
 
-       hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+       hw = devm_kzalloc(card->dev, sizeof(*hw), GFP_KERNEL);
        if (hw == NULL)
                return -ENOMEM;
        spin_lock_init(&hw->reg_lock);
@@ -1097,12 +1073,10 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
        hw->port1 = port;
        hw->port2 = port + 0x400;
        hw->port3 = port + 0x800;
-       hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1");
-       hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2");
-       hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3");
-       if (!hw->res_port1 || !hw->res_port2 || !hw->res_port3) {
+       if (!devm_request_region(card->dev, hw->port1, 4, "Emu8000-1") ||
+           !devm_request_region(card->dev, hw->port2, 4, "Emu8000-2") ||
+           !devm_request_region(card->dev, hw->port3, 4, "Emu8000-3")) {
                snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3);
-               snd_emu8000_free(hw);
                return -EBUSY;
        }
        hw->mem_size = 0;
@@ -1115,23 +1089,13 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
        hw->fm_chorus_depth = 0;
        hw->fm_reverb_depth = 0;
 
-       if (snd_emu8000_detect(hw) < 0) {
-               snd_emu8000_free(hw);
+       if (snd_emu8000_detect(hw) < 0)
                return -ENODEV;
-       }
 
        snd_emu8000_init_hw(hw);
        err = snd_emu8000_create_mixer(card, hw);
-       if (err < 0) {
-               snd_emu8000_free(hw);
+       if (err < 0)
                return err;
-       }
-       
-       err = snd_device_new(card, SNDRV_DEV_CODEC, hw, &ops);
-       if (err < 0) {
-               snd_emu8000_free(hw);
-               return err;
-       }
 #if IS_ENABLED(CONFIG_SND_SEQUENCER)
        if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
                               sizeof(struct snd_emu8000*), &awe) >= 0) {
index 7ba5dd1..64936c9 100644 (file)
@@ -226,8 +226,8 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
        static const int possible_dmas16[] = {5, 7, -1};
        int err, xirq, xdma8, xdma16, xmpu_port, xmpu_irq;
 
-       err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_card_jazz16), &card);
+       err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_card_jazz16), &card);
        if (err < 0)
                return err;
 
@@ -238,8 +238,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
                xirq = snd_legacy_find_free_irq(possible_irqs);
                if (xirq < 0) {
                        snd_printk(KERN_ERR "unable to find a free IRQ\n");
-                       err = -EBUSY;
-                       goto err_free;
+                       return -EBUSY;
                }
        }
        xdma8 = dma8[dev];
@@ -247,8 +246,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
                xdma8 = snd_legacy_find_free_dma(possible_dmas8);
                if (xdma8 < 0) {
                        snd_printk(KERN_ERR "unable to find a free DMA8\n");
-                       err = -EBUSY;
-                       goto err_free;
+                       return -EBUSY;
                }
        }
        xdma16 = dma16[dev];
@@ -256,8 +254,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
                xdma16 = snd_legacy_find_free_dma(possible_dmas16);
                if (xdma16 < 0) {
                        snd_printk(KERN_ERR "unable to find a free DMA16\n");
-                       err = -EBUSY;
-                       goto err_free;
+                       return -EBUSY;
                }
        }
 
@@ -267,7 +264,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
        err = jazz16_detect_board(port[dev], xmpu_port);
        if (err < 0) {
                printk(KERN_ERR "Media Vision Jazz16 board not detected\n");
-               goto err_free;
+               return err;
        }
        err = snd_sbdsp_create(card, port[dev], irq[dev],
                               jazz16_interrupt,
@@ -275,7 +272,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
                               SB_HW_JAZZ16,
                               &chip);
        if (err < 0)
-               goto err_free;
+               return err;
 
        xmpu_irq = mpu_irq[dev];
        if (xmpu_irq == SNDRV_AUTO_IRQ || mpu_port[dev] == SNDRV_AUTO_PORT)
@@ -283,7 +280,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
        err = jazz16_configure_board(chip, xmpu_irq);
        if (err < 0) {
                printk(KERN_ERR "Media Vision Jazz16 configuration failed\n");
-               goto err_free;
+               return err;
        }
 
        jazz16->chip = chip;
@@ -296,10 +293,10 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
 
        err = snd_sb8dsp_pcm(chip, 0);
        if (err < 0)
-               goto err_free;
+               return err;
        err = snd_sbmixer_new(chip);
        if (err < 0)
-               goto err_free;
+               return err;
 
        err = snd_opl3_create(card, chip->port, chip->port + 2,
                              OPL3_HW_AUTO, 1, &opl3);
@@ -309,7 +306,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
        else {
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                if (err < 0)
-                       goto err_free;
+                       return err;
        }
        if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
                if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
@@ -326,21 +323,10 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto err_free;
+               return err;
 
        dev_set_drvdata(devptr, card);
        return 0;
-
-err_free:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_jazz16_remove(struct device *devptr, unsigned int dev)
-{
-       struct snd_card *card = dev_get_drvdata(devptr);
-
-       snd_card_free(card);
 }
 
 #ifdef CONFIG_PM
@@ -372,7 +358,6 @@ static int snd_jazz16_resume(struct device *pdev, unsigned int n)
 static struct isa_driver snd_jazz16_driver = {
        .match          = snd_jazz16_match,
        .probe          = snd_jazz16_probe,
-       .remove         = snd_jazz16_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_jazz16_suspend,
        .resume         = snd_jazz16_resume,
index d0f797c..e89b095 100644 (file)
@@ -285,15 +285,6 @@ __wt_error:
 
 #endif /* CONFIG_PNP */
 
-static void snd_sb16_free(struct snd_card *card)
-{
-       struct snd_card_sb16 *acard = card->private_data;
-        
-       if (acard == NULL)
-               return;
-       release_and_free_resource(acard->fm_res);
-}
-
 #ifdef CONFIG_PNP
 #define is_isapnp_selected(dev)                isapnp[dev]
 #else
@@ -306,11 +297,10 @@ static int snd_sb16_card_new(struct device *devptr, int dev,
        struct snd_card *card;
        int err;
 
-       err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_card_sb16), &card);
+       err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_card_sb16), &card);
        if (err < 0)
                return err;
-       card->private_free = snd_sb16_free;
        *cardp = card;
        return 0;
 }
@@ -482,17 +472,16 @@ static int snd_sb16_isa_probe1(int dev, struct device *pdev)
        /* non-PnP FM port address is hardwired with base port address */
        fm_port[dev] = port[dev];
        /* block the 0x388 port to avoid PnP conflicts */
-       acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
+       acard->fm_res = devm_request_region(card->dev, 0x388, 4,
+                                           "SoundBlaster FM");
 #ifdef SNDRV_SBAWE_EMU8000
        /* non-PnP AWE port address is hardwired with base port address */
        awe_port[dev] = port[dev] + 0x400;
 #endif
 
        err = snd_sb16_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        dev_set_drvdata(pdev, card);
        return 0;
 }
@@ -547,11 +536,6 @@ static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
        }
 }
 
-static void snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(pdev));
-}
-
 #ifdef CONFIG_PM
 static int snd_sb16_isa_suspend(struct device *dev, unsigned int n,
                                pm_message_t state)
@@ -574,7 +558,6 @@ static int snd_sb16_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_sb16_isa_driver = {
        .match          = snd_sb16_isa_match,
        .probe          = snd_sb16_isa_probe,
-       .remove         = snd_sb16_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_sb16_isa_suspend,
        .resume         = snd_sb16_isa_resume,
@@ -600,15 +583,11 @@ static int snd_sb16_pnp_detect(struct pnp_card_link *pcard,
                if (res < 0)
                        return res;
                res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid);
-               if (res < 0) {
-                       snd_card_free(card);
+               if (res < 0)
                        return res;
-               }
                res = snd_sb16_probe(card, dev);
-               if (res < 0) {
-                       snd_card_free(card);
+               if (res < 0)
                        return res;
-               }
                pnp_set_card_drvdata(pcard, card);
                dev++;
                return 0;
@@ -617,12 +596,6 @@ static int snd_sb16_pnp_detect(struct pnp_card_link *pcard,
        return -ENODEV;
 }
 
-static void snd_sb16_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 #ifdef CONFIG_PM
 static int snd_sb16_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
 {
@@ -643,7 +616,6 @@ static struct pnp_card_driver sb16_pnpc_driver = {
 #endif
        .id_table = snd_sb16_pnpids,
        .probe = snd_sb16_pnp_detect,
-       .remove = snd_sb16_pnp_remove,
 #ifdef CONFIG_PM
        .suspend = snd_sb16_pnp_suspend,
        .resume = snd_sb16_pnp_resume,
index b08e6e7..e5ef177 100644 (file)
@@ -54,15 +54,6 @@ static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id)
        }
 }
 
-static void snd_sb8_free(struct snd_card *card)
-{
-       struct snd_sb8 *acard = card->private_data;
-
-       if (acard == NULL)
-               return;
-       release_and_free_resource(acard->fm_res);
-}
-
 static int snd_sb8_match(struct device *pdev, unsigned int dev)
 {
        if (!enable[dev])
@@ -86,26 +77,26 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
        struct snd_opl3 *opl3;
        int err;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_sb8), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_sb8), &card);
        if (err < 0)
                return err;
        acard = card->private_data;
-       card->private_free = snd_sb8_free;
 
        /*
         * Block the 0x388 port to avoid PnP conflicts.
         * No need to check this value after request_region,
         * as we never do anything with it.
         */
-       acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
+       acard->fm_res = devm_request_region(card->dev, 0x388, 4,
+                                           "SoundBlaster FM");
 
        if (port[dev] != SNDRV_AUTO_PORT) {
                err = snd_sbdsp_create(card, port[dev], irq[dev],
                                       snd_sb8_interrupt, dma8[dev],
                                       -1, SB_HW_AUTO, &chip);
                if (err < 0)
-                       goto _err;
+                       return err;
        } else {
                /* auto-probe legacy ports */
                static const unsigned long possible_ports[] = {
@@ -125,10 +116,8 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
                                break;
                        }
                }
-               if (i >= ARRAY_SIZE(possible_ports)) {
-                       err = -EINVAL;
-                       goto _err;
-               }
+               if (i >= ARRAY_SIZE(possible_ports))
+                       return -EINVAL;
        }
        acard->chip = chip;
                        
@@ -139,17 +128,16 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
                else
                        snd_printk(KERN_WARNING "SB 16 chip detected at 0x%lx, try snd-sb16 module\n",
                                   port[dev]);
-               err = -ENODEV;
-               goto _err;
+               return -ENODEV;
        }
 
        err = snd_sb8dsp_pcm(chip, 0);
        if (err < 0)
-               goto _err;
+               return err;
 
        err = snd_sbmixer_new(chip);
        if (err < 0)
-               goto _err;
+               return err;
 
        if (chip->hardware == SB_HW_10 || chip->hardware == SB_HW_20) {
                err = snd_opl3_create(card, chip->port + 8, 0,
@@ -167,12 +155,12 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
        if (err >= 0) {
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                if (err < 0)
-                       goto _err;
+                       return err;
        }
 
        err = snd_sb8dsp_midi(chip, 0);
        if (err < 0)
-               goto _err;
+               return err;
 
        strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8");
        strcpy(card->shortname, chip->name);
@@ -183,19 +171,10 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto _err;
+               return err;
 
        dev_set_drvdata(pdev, card);
        return 0;
-
- _err:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_sb8_remove(struct device *pdev, unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(pdev));
 }
 
 #ifdef CONFIG_PM
@@ -229,7 +208,6 @@ static int snd_sb8_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_sb8_driver = {
        .match          = snd_sb8_match,
        .probe          = snd_sb8_probe,
-       .remove         = snd_sb8_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_sb8_suspend,
        .resume         = snd_sb8_resume,
index 5712121..c0e319d 100644 (file)
@@ -168,31 +168,6 @@ static int snd_sbdsp_probe(struct snd_sb * chip)
        return 0;
 }
 
-static int snd_sbdsp_free(struct snd_sb *chip)
-{
-       release_and_free_resource(chip->res_port);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, (void *) chip);
-#ifdef CONFIG_ISA
-       if (chip->dma8 >= 0) {
-               disable_dma(chip->dma8);
-               free_dma(chip->dma8);
-       }
-       if (chip->dma16 >= 0 && chip->dma16 != chip->dma8) {
-               disable_dma(chip->dma16);
-               free_dma(chip->dma16);
-       }
-#endif
-       kfree(chip);
-       return 0;
-}
-
-static int snd_sbdsp_dev_free(struct snd_device *device)
-{
-       struct snd_sb *chip = device->device_data;
-       return snd_sbdsp_free(chip);
-}
-
 int snd_sbdsp_create(struct snd_card *card,
                     unsigned long port,
                     int irq,
@@ -204,15 +179,12 @@ int snd_sbdsp_create(struct snd_card *card,
 {
        struct snd_sb *chip;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_sbdsp_dev_free,
-       };
 
        if (snd_BUG_ON(!r_chip))
                return -EINVAL;
        *r_chip = NULL;
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL)
+       chip = devm_kzalloc(card->dev, sizeof(*chip), GFP_KERNEL);
+       if (!chip)
                return -ENOMEM;
        spin_lock_init(&chip->reg_lock);
        spin_lock_init(&chip->open_lock);
@@ -223,13 +195,12 @@ int snd_sbdsp_create(struct snd_card *card,
        chip->dma16 = -1;
        chip->port = port;
        
-       if (request_irq(irq, irq_handler,
-                       (hardware == SB_HW_ALS4000 ||
-                        hardware == SB_HW_CS5530) ?
-                       IRQF_SHARED : 0,
-                       "SoundBlaster", (void *) chip)) {
+       if (devm_request_irq(card->dev, irq, irq_handler,
+                            (hardware == SB_HW_ALS4000 ||
+                             hardware == SB_HW_CS5530) ?
+                            IRQF_SHARED : 0,
+                            "SoundBlaster", (void *) chip)) {
                snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq);
-               snd_sbdsp_free(chip);
                return -EBUSY;
        }
        chip->irq = irq;
@@ -238,17 +209,17 @@ int snd_sbdsp_create(struct snd_card *card,
        if (hardware == SB_HW_ALS4000)
                goto __skip_allocation;
        
-       chip->res_port = request_region(port, 16, "SoundBlaster");
+       chip->res_port = devm_request_region(card->dev, port, 16,
+                                            "SoundBlaster");
        if (!chip->res_port) {
                snd_printk(KERN_ERR "sb: can't grab port 0x%lx\n", port);
-               snd_sbdsp_free(chip);
                return -EBUSY;
        }
 
 #ifdef CONFIG_ISA
-       if (dma8 >= 0 && request_dma(dma8, "SoundBlaster - 8bit")) {
+       if (dma8 >= 0 && snd_devm_request_dma(card->dev, dma8,
+                                             "SoundBlaster - 8bit")) {
                snd_printk(KERN_ERR "sb: can't grab DMA8 %d\n", dma8);
-               snd_sbdsp_free(chip);
                return -EBUSY;
        }
        chip->dma8 = dma8;
@@ -256,9 +227,9 @@ int snd_sbdsp_create(struct snd_card *card,
                if (hardware != SB_HW_ALS100 && (dma16 < 5 || dma16 > 7)) {
                        /* no duplex */
                        dma16 = -1;
-               } else if (request_dma(dma16, "SoundBlaster - 16bit")) {
+               } else if (snd_devm_request_dma(card->dev, dma16,
+                                               "SoundBlaster - 16bit")) {
                        snd_printk(KERN_ERR "sb: can't grab DMA16 %d\n", dma16);
-                       snd_sbdsp_free(chip);
                        return -EBUSY;
                }
        }
@@ -269,15 +240,8 @@ int snd_sbdsp_create(struct snd_card *card,
        chip->card = card;
        chip->hardware = hardware;
        err = snd_sbdsp_probe(chip);
-       if (err < 0) {
-               snd_sbdsp_free(chip);
+       if (err < 0)
                return err;
-       }
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_sbdsp_free(chip);
-               return err;
-       }
        *r_chip = chip;
        return 0;
 }
index 3462663..26ab7ff 100644 (file)
@@ -529,6 +529,14 @@ static int snd_sc6000_match(struct device *devptr, unsigned int dev)
        return 1;
 }
 
+static void snd_sc6000_free(struct snd_card *card)
+{
+       char __iomem *vport = (char __force __iomem *)card->private_data;
+
+       if (vport)
+               sc6000_setup_board(vport, 0);
+}
+
 static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
 {
        static const int possible_irqs[] = { 5, 7, 9, 10, 11, -1 };
@@ -539,22 +547,19 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
        struct snd_card *card;
        struct snd_wss *chip;
        struct snd_opl3 *opl3;
-       char __iomem **vport;
+       char __iomem *vport;
        char __iomem *vmss_port;
 
-
-       err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE,
-                          sizeof(vport), &card);
+       err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
+                               0, &card);
        if (err < 0)
                return err;
 
-       vport = card->private_data;
        if (xirq == SNDRV_AUTO_IRQ) {
                xirq = snd_legacy_find_free_irq(possible_irqs);
                if (xirq < 0) {
                        snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
-                       err = -EBUSY;
-                       goto err_exit;
+                       return -EBUSY;
                }
        }
 
@@ -562,68 +567,65 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
                xdma = snd_legacy_find_free_dma(possible_dmas);
                if (xdma < 0) {
                        snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
-                       err = -EBUSY;
-                       goto err_exit;
+                       return -EBUSY;
                }
        }
 
-       if (!request_region(port[dev], 0x10, DRV_NAME)) {
+       if (!devm_request_region(devptr, port[dev], 0x10, DRV_NAME)) {
                snd_printk(KERN_ERR PFX
                           "I/O port region is already in use.\n");
-               err = -EBUSY;
-               goto err_exit;
+               return -EBUSY;
        }
-       *vport = devm_ioport_map(devptr, port[dev], 0x10);
-       if (*vport == NULL) {
+       vport = devm_ioport_map(devptr, port[dev], 0x10);
+       if (!vport) {
                snd_printk(KERN_ERR PFX
                           "I/O port cannot be iomapped.\n");
-               err = -EBUSY;
-               goto err_unmap1;
+               return -EBUSY;
        }
+       card->private_data = (void __force *)vport;
 
        /* to make it marked as used */
-       if (!request_region(mss_port[dev], 4, DRV_NAME)) {
+       if (!devm_request_region(devptr, mss_port[dev], 4, DRV_NAME)) {
                snd_printk(KERN_ERR PFX
                           "SC-6000 port I/O port region is already in use.\n");
-               err = -EBUSY;
-               goto err_unmap1;
+               return -EBUSY;
        }
        vmss_port = devm_ioport_map(devptr, mss_port[dev], 4);
        if (!vmss_port) {
                snd_printk(KERN_ERR PFX
                           "MSS port I/O cannot be iomapped.\n");
-               err = -EBUSY;
-               goto err_unmap2;
+               return -EBUSY;
        }
 
        snd_printd("Initializing BASE[0x%lx] IRQ[%d] DMA[%d] MIRQ[%d]\n",
                   port[dev], xirq, xdma,
                   mpu_irq[dev] == SNDRV_AUTO_IRQ ? 0 : mpu_irq[dev]);
 
-       err = sc6000_init_board(*vport, vmss_port, dev);
+       err = sc6000_init_board(vport, vmss_port, dev);
        if (err < 0)
-               goto err_unmap2;
+               return err;
+       card->private_free = snd_sc6000_free;
 
        err = snd_wss_create(card, mss_port[dev] + 4,  -1, xirq, xdma, -1,
                             WSS_HW_DETECT, 0, &chip);
        if (err < 0)
-               goto err_unmap2;
+               return err;
 
        err = snd_wss_pcm(chip, 0);
        if (err < 0) {
                snd_printk(KERN_ERR PFX
                           "error creating new WSS PCM device\n");
-               goto err_unmap2;
+               return err;
        }
        err = snd_wss_mixer(chip);
        if (err < 0) {
                snd_printk(KERN_ERR PFX "error creating new WSS mixer\n");
-               goto err_unmap2;
+               return err;
        }
        err = snd_sc6000_mixer(chip);
        if (err < 0) {
                snd_printk(KERN_ERR PFX "the mixer rewrite failed\n");
-               goto err_unmap2;
+               return err;
        }
        if (snd_opl3_create(card,
                            0x388, 0x388 + 2,
@@ -633,7 +635,7 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
        } else {
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                if (err < 0)
-                       goto err_unmap2;
+                       return err;
        }
 
        if (mpu_port[dev] != SNDRV_AUTO_PORT) {
@@ -654,39 +656,15 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto err_unmap2;
+               return err;
 
        dev_set_drvdata(devptr, card);
        return 0;
-
-err_unmap2:
-       sc6000_setup_board(*vport, 0);
-       release_region(mss_port[dev], 4);
-err_unmap1:
-       release_region(port[dev], 0x10);
-err_exit:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_sc6000_remove(struct device *devptr, unsigned int dev)
-{
-       struct snd_card *card = dev_get_drvdata(devptr);
-       char __iomem **vport = card->private_data;
-
-       if (sc6000_setup_board(*vport, 0) < 0)
-               snd_printk(KERN_WARNING "sc6000_setup_board failed on exit!\n");
-
-       release_region(port[dev], 0x10);
-       release_region(mss_port[dev], 4);
-
-       snd_card_free(card);
 }
 
 static struct isa_driver snd_sc6000_driver = {
        .match          = snd_sc6000_match,
        .probe          = snd_sc6000_probe,
-       .remove         = snd_sc6000_remove,
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = DRV_NAME,
index e70ef9a..0bc0025 100644 (file)
@@ -327,17 +327,6 @@ static void activate_ad1845_unsafe(unsigned io_base)
        sscape_write_unsafe(io_base, GA_CDCFG_REG, 0x80);
 }
 
-/*
- * Do the necessary ALSA-level cleanup to deallocate our driver ...
- */
-static void soundscape_free(struct snd_card *c)
-{
-       struct soundscape *sscape = get_card_soundscape(c);
-       release_and_free_resource(sscape->io_res);
-       release_and_free_resource(sscape->wss_res);
-       free_dma(sscape->chip->dma1);
-}
-
 /*
  * Tell the SoundScape to begin a DMA transfer using the given channel.
  * All locking issues are left to the caller.
@@ -941,7 +930,7 @@ static int create_sscape(int dev, struct snd_card *card)
         * Grab IO ports that we will need to probe so that we
         * can detect and control this hardware ...
         */
-       io_res = request_region(port[dev], 8, "SoundScape");
+       io_res = devm_request_region(card->dev, port[dev], 8, "SoundScape");
        if (!io_res) {
                snd_printk(KERN_ERR
                           "sscape: can't grab port 0x%lx\n", port[dev]);
@@ -949,22 +938,22 @@ static int create_sscape(int dev, struct snd_card *card)
        }
        wss_res = NULL;
        if (sscape->type == SSCAPE_VIVO) {
-               wss_res = request_region(wss_port[dev], 4, "SoundScape");
+               wss_res = devm_request_region(card->dev, wss_port[dev], 4,
+                                             "SoundScape");
                if (!wss_res) {
                        snd_printk(KERN_ERR "sscape: can't grab port 0x%lx\n",
                                            wss_port[dev]);
-                       err = -EBUSY;
-                       goto _release_region;
+                       return -EBUSY;
                }
        }
 
        /*
         * Grab one DMA channel ...
         */
-       err = request_dma(dma[dev], "SoundScape");
+       err = snd_devm_request_dma(card->dev, dma[dev], "SoundScape");
        if (err < 0) {
                snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]);
-               goto _release_region;
+               return err;
        }
 
        spin_lock_init(&sscape->lock);
@@ -975,8 +964,7 @@ static int create_sscape(int dev, struct snd_card *card)
        if (!detect_sscape(sscape, wss_port[dev])) {
                printk(KERN_ERR "sscape: hardware not detected at 0x%x\n",
                        sscape->io_base);
-               err = -ENODEV;
-               goto _release_dma;
+               return -ENODEV;
        }
 
        switch (sscape->type) {
@@ -1006,15 +994,13 @@ static int create_sscape(int dev, struct snd_card *card)
        irq_cfg = get_irq_config(sscape->type, irq[dev]);
        if (irq_cfg == INVALID_IRQ) {
                snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
-               err = -ENXIO;
-               goto _release_dma;
+               return -ENXIO;
        }
 
        mpu_irq_cfg = get_irq_config(sscape->type, mpu_irq[dev]);
        if (mpu_irq_cfg == INVALID_IRQ) {
                snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
-               err = -ENXIO;
-               goto _release_dma;
+               return -ENXIO;
        }
 
        /*
@@ -1060,7 +1046,7 @@ static int create_sscape(int dev, struct snd_card *card)
                snd_printk(KERN_ERR
                                "sscape: No AD1845 device at 0x%lx, IRQ %d\n",
                                wss_port[dev], irq[dev]);
-               goto _release_dma;
+               return err;
        }
        strcpy(card->driver, "SoundScape");
        strcpy(card->shortname, name);
@@ -1082,7 +1068,7 @@ static int create_sscape(int dev, struct snd_card *card)
                                snd_printk(KERN_ERR "sscape: Failed to create "
                                                "MPU-401 device at 0x%lx\n",
                                                port[dev]);
-                               goto _release_dma;
+                               return err;
                        }
 
                        /*
@@ -1109,24 +1095,7 @@ static int create_sscape(int dev, struct snd_card *card)
                }
        }
 
-       /*
-        * Now that we have successfully created this sound card,
-        * it is safe to store the pointer.
-        * NOTE: we only register the sound card's "destructor"
-        *       function now that our "constructor" has completed.
-        */
-       card->private_free = soundscape_free;
-
        return 0;
-
-_release_dma:
-       free_dma(dma[dev]);
-
-_release_region:
-       release_and_free_resource(wss_res);
-       release_and_free_resource(io_res);
-
-       return err;
 }
 
 
@@ -1156,8 +1125,8 @@ static int snd_sscape_probe(struct device *pdev, unsigned int dev)
        struct soundscape *sscape;
        int ret;
 
-       ret = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct soundscape), &card);
+       ret = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct soundscape), &card);
        if (ret < 0)
                return ret;
 
@@ -1168,24 +1137,15 @@ static int snd_sscape_probe(struct device *pdev, unsigned int dev)
 
        ret = create_sscape(dev, card);
        if (ret < 0)
-               goto _release_card;
+               return ret;
 
        ret = snd_card_register(card);
        if (ret < 0) {
                snd_printk(KERN_ERR "sscape: Failed to register sound card\n");
-               goto _release_card;
+               return ret;
        }
        dev_set_drvdata(pdev, card);
        return 0;
-
-_release_card:
-       snd_card_free(card);
-       return ret;
-}
-
-static void snd_sscape_remove(struct device *devptr, unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
 }
 
 #define DEV_NAME "sscape"
@@ -1193,7 +1153,6 @@ static void snd_sscape_remove(struct device *devptr, unsigned int dev)
 static struct isa_driver snd_sscape_driver = {
        .match          = snd_sscape_match,
        .probe          = snd_sscape_probe,
-       .remove         = snd_sscape_remove,
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = DEV_NAME
@@ -1244,9 +1203,9 @@ static int sscape_pnp_detect(struct pnp_card_link *pcard,
         * Create a new ALSA sound card entry, in anticipation
         * of detecting our hardware ...
         */
-       ret = snd_card_new(&pcard->card->dev,
-                          index[idx], id[idx], THIS_MODULE,
-                          sizeof(struct soundscape), &card);
+       ret = snd_devm_card_new(&pcard->card->dev,
+                               index[idx], id[idx], THIS_MODULE,
+                               sizeof(struct soundscape), &card);
        if (ret < 0)
                return ret;
 
@@ -1277,27 +1236,17 @@ static int sscape_pnp_detect(struct pnp_card_link *pcard,
 
        ret = create_sscape(idx, card);
        if (ret < 0)
-               goto _release_card;
+               return ret;
 
        ret = snd_card_register(card);
        if (ret < 0) {
                snd_printk(KERN_ERR "sscape: Failed to register sound card\n");
-               goto _release_card;
+               return ret;
        }
 
        pnp_set_card_drvdata(pcard, card);
        ++idx;
        return 0;
-
-_release_card:
-       snd_card_free(card);
-       return ret;
-}
-
-static void sscape_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
 }
 
 static struct pnp_card_driver sscape_pnpc_driver = {
@@ -1305,7 +1254,6 @@ static struct pnp_card_driver sscape_pnpc_driver = {
        .name = "sscape",
        .id_table = sscape_pnpids,
        .probe = sscape_pnp_detect,
-       .remove = sscape_pnp_remove,
 };
 
 #endif /* CONFIG_PNP */
index dfdeaf7..e6e46a0 100644 (file)
@@ -308,18 +308,6 @@ static struct snd_rawmidi *snd_wavefront_new_midi(struct snd_card *card,
        return rmidi;
 }
 
-static void
-snd_wavefront_free(struct snd_card *card)
-{
-       snd_wavefront_card_t *acard = (snd_wavefront_card_t *)card->private_data;
-       
-       if (acard) {
-               release_and_free_resource(acard->wavefront.res_base);
-               if (acard->wavefront.irq > 0)
-                       free_irq(acard->wavefront.irq, (void *)acard);
-       }
-}
-
 static int snd_wavefront_card_new(struct device *pdev, int dev,
                                  struct snd_card **cardp)
 {
@@ -327,8 +315,8 @@ static int snd_wavefront_card_new(struct device *pdev, int dev,
        snd_wavefront_card_t *acard;
        int err;
 
-       err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(snd_wavefront_card_t), &card);
+       err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(snd_wavefront_card_t), &card);
        if (err < 0)
                return err;
 
@@ -339,7 +327,6 @@ static int snd_wavefront_card_new(struct device *pdev, int dev,
        spin_lock_init(&acard->wavefront.midi.open);
        spin_lock_init(&acard->wavefront.midi.virtual);
        acard->wavefront.card = card;
-       card->private_free = snd_wavefront_free;
 
        *cardp = card;
        return 0;
@@ -394,15 +381,17 @@ snd_wavefront_probe (struct snd_card *card, int dev)
 
        /* ------- ICS2115 Wavetable synth ------- */
 
-       acard->wavefront.res_base = request_region(ics2115_port[dev], 16,
-                                                  "ICS2115");
+       acard->wavefront.res_base =
+               devm_request_region(card->dev, ics2115_port[dev], 16,
+                                   "ICS2115");
        if (acard->wavefront.res_base == NULL) {
                snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n",
                           ics2115_port[dev], ics2115_port[dev] + 16 - 1);
                return -EBUSY;
        }
-       if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt,
-                       0, "ICS2115", acard)) {
+       if (devm_request_irq(card->dev, ics2115_irq[dev],
+                            snd_wavefront_ics2115_interrupt,
+                            0, "ICS2115", acard)) {
                snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]);
                return -EBUSY;
        }
@@ -556,27 +545,18 @@ static int snd_wavefront_isa_probe(struct device *pdev,
        if (err < 0)
                return err;
        err = snd_wavefront_probe(card, dev);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        
        dev_set_drvdata(pdev, card);
        return 0;
 }
 
-static void snd_wavefront_isa_remove(struct device *devptr,
-                                   unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-}
-
 #define DEV_NAME "wavefront"
 
 static struct isa_driver snd_wavefront_driver = {
        .match          = snd_wavefront_isa_match,
        .probe          = snd_wavefront_isa_probe,
-       .remove         = snd_wavefront_isa_remove,
        /* FIXME: suspend, resume */
        .driver         = {
                .name   = DEV_NAME
@@ -606,7 +586,6 @@ static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
        if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) {
                if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
                        snd_printk (KERN_ERR "isapnp detection failed\n");
-                       snd_card_free (card);
                        return -ENODEV;
                }
        }
@@ -620,18 +599,11 @@ static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
        return 0;
 }
 
-static void snd_wavefront_pnp_remove(struct pnp_card_link *pcard)
-{
-       snd_card_free(pnp_get_card_drvdata(pcard));
-       pnp_set_card_drvdata(pcard, NULL);
-}
-
 static struct pnp_card_driver wavefront_pnpc_driver = {
        .flags          = PNP_DRIVER_RES_DISABLE,
        .name           = "wavefront",
        .id_table       = snd_wavefront_pnpids,
        .probe          = snd_wavefront_pnp_detect,
-       .remove         = snd_wavefront_pnp_remove,
        /* FIXME: suspend,resume */
 };
 
index 743e0f0..026061b 100644 (file)
@@ -1655,36 +1655,6 @@ static void snd_wss_resume(struct snd_wss *chip)
 }
 #endif /* CONFIG_PM */
 
-static int snd_wss_free(struct snd_wss *chip)
-{
-       release_and_free_resource(chip->res_port);
-       release_and_free_resource(chip->res_cport);
-       if (chip->irq >= 0) {
-               disable_irq(chip->irq);
-               if (!(chip->hwshare & WSS_HWSHARE_IRQ))
-                       free_irq(chip->irq, (void *) chip);
-       }
-       if (!(chip->hwshare & WSS_HWSHARE_DMA1) && chip->dma1 >= 0) {
-               snd_dma_disable(chip->dma1);
-               free_dma(chip->dma1);
-       }
-       if (!(chip->hwshare & WSS_HWSHARE_DMA2) &&
-           chip->dma2 >= 0 && chip->dma2 != chip->dma1) {
-               snd_dma_disable(chip->dma2);
-               free_dma(chip->dma2);
-       }
-       if (chip->timer)
-               snd_device_free(chip->card, chip->timer);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_wss_dev_free(struct snd_device *device)
-{
-       struct snd_wss *chip = device->device_data;
-       return snd_wss_free(chip);
-}
-
 const char *snd_wss_chip_id(struct snd_wss *chip)
 {
        switch (chip->hardware) {
@@ -1738,7 +1708,7 @@ static int snd_wss_new(struct snd_card *card,
        struct snd_wss *chip;
 
        *rchip = NULL;
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+       chip = devm_kzalloc(card->dev, sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
        chip->hardware = hardware;
@@ -1774,9 +1744,6 @@ int snd_wss_create(struct snd_card *card,
                      unsigned short hwshare,
                      struct snd_wss **rchip)
 {
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_wss_dev_free,
-       };
        struct snd_wss *chip;
        int err;
 
@@ -1788,42 +1755,39 @@ int snd_wss_create(struct snd_card *card,
        chip->dma1 = -1;
        chip->dma2 = -1;
 
-       chip->res_port = request_region(port, 4, "WSS");
+       chip->res_port = devm_request_region(card->dev, port, 4, "WSS");
        if (!chip->res_port) {
                snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port);
-               snd_wss_free(chip);
                return -EBUSY;
        }
        chip->port = port;
        if ((long)cport >= 0) {
-               chip->res_cport = request_region(cport, 8, "CS4232 Control");
+               chip->res_cport = devm_request_region(card->dev, cport, 8,
+                                                     "CS4232 Control");
                if (!chip->res_cport) {
                        snd_printk(KERN_ERR
                                "wss: can't grab control port 0x%lx\n", cport);
-                       snd_wss_free(chip);
                        return -ENODEV;
                }
        }
        chip->cport = cport;
        if (!(hwshare & WSS_HWSHARE_IRQ))
-               if (request_irq(irq, snd_wss_interrupt, 0,
-                               "WSS", (void *) chip)) {
+               if (devm_request_irq(card->dev, irq, snd_wss_interrupt, 0,
+                                    "WSS", (void *) chip)) {
                        snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
-                       snd_wss_free(chip);
                        return -EBUSY;
                }
        chip->irq = irq;
        card->sync_irq = chip->irq;
-       if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) {
+       if (!(hwshare & WSS_HWSHARE_DMA1) &&
+           snd_devm_request_dma(card->dev, dma1, "WSS - 1")) {
                snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1);
-               snd_wss_free(chip);
                return -EBUSY;
        }
        chip->dma1 = dma1;
-       if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 &&
-             dma2 >= 0 && request_dma(dma2, "WSS - 2")) {
+       if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 && dma2 >= 0 &&
+           snd_devm_request_dma(card->dev, dma2, "WSS - 2")) {
                snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2);
-               snd_wss_free(chip);
                return -EBUSY;
        }
        if (dma1 == dma2 || dma2 < 0) {
@@ -1839,10 +1803,8 @@ int snd_wss_create(struct snd_card *card,
        }
 
        /* global setup */
-       if (snd_wss_probe(chip) < 0) {
-               snd_wss_free(chip);
+       if (snd_wss_probe(chip) < 0)
                return -ENODEV;
-       }
        snd_wss_init(chip);
 
 #if 0
@@ -1853,13 +1815,6 @@ int snd_wss_create(struct snd_card *card,
        }
 #endif
 
-       /* Register device */
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_wss_free(chip);
-               return err;
-       }
-
 #ifdef CONFIG_PM
        /* Power Management */
        chip->suspend = snd_wss_suspend;
index 1440db8..ec4fda3 100644 (file)
@@ -563,22 +563,9 @@ snd_harmony_capture_close(struct snd_pcm_substream *ss)
         return 0;
 }
 
-static int 
-snd_harmony_hw_params(struct snd_pcm_substream *ss,
-                     struct snd_pcm_hw_params *hw)
-{
-       struct snd_harmony *h = snd_pcm_substream_chip(ss);
-       
-       if (h->dma.type == SNDRV_DMA_TYPE_CONTINUOUS)
-               ss->runtime->dma_addr = __pa(ss->runtime->dma_area);
-
-       return 0;
-}
-
 static const struct snd_pcm_ops snd_harmony_playback_ops = {
        .open = snd_harmony_playback_open,
        .close = snd_harmony_playback_close,
-       .hw_params = snd_harmony_hw_params,
        .prepare = snd_harmony_playback_prepare,
        .trigger = snd_harmony_playback_trigger,
        .pointer = snd_harmony_playback_pointer,
@@ -587,7 +574,6 @@ static const struct snd_pcm_ops snd_harmony_playback_ops = {
 static const struct snd_pcm_ops snd_harmony_capture_ops = {
         .open = snd_harmony_capture_open,
         .close = snd_harmony_capture_close,
-        .hw_params = snd_harmony_hw_params,
         .prepare = snd_harmony_capture_prepare,
         .trigger = snd_harmony_capture_trigger,
         .pointer = snd_harmony_capture_pointer,
index 5c78951..bba4dae 100644 (file)
@@ -740,20 +740,6 @@ snd_ad1889_ac97_xinit(struct snd_ad1889 *chip)
 
 }
 
-static void
-snd_ad1889_ac97_bus_free(struct snd_ac97_bus *bus)
-{
-       struct snd_ad1889 *chip = bus->private_data;
-       chip->ac97_bus = NULL;
-}
-
-static void
-snd_ad1889_ac97_free(struct snd_ac97 *ac97)
-{
-       struct snd_ad1889 *chip = ac97->private_data;
-       chip->ac97 = NULL;
-}
-
 static int
 snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
 {
@@ -771,11 +757,8 @@ snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
        if (err < 0)
                return err;
        
-       chip->ac97_bus->private_free = snd_ad1889_ac97_bus_free;
-
        memset(&ac97, 0, sizeof(ac97));
        ac97.private_data = chip;
-       ac97.private_free = snd_ad1889_ac97_free;
        ac97.pci = chip->pci;
 
        err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97);
@@ -787,11 +770,10 @@ snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
        return 0;
 }
 
-static int
-snd_ad1889_free(struct snd_ad1889 *chip)
+static void
+snd_ad1889_free(struct snd_card *card)
 {
-       if (chip->irq < 0)
-               goto skip_hw;
+       struct snd_ad1889 *chip = card->private_data;
 
        spin_lock_irq(&chip->lock);
 
@@ -805,125 +787,60 @@ snd_ad1889_free(struct snd_ad1889 *chip)
        ad1889_readl(chip, AD_DMA_DISR);        /* flush, dammit! */
 
        spin_unlock_irq(&chip->lock);
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-
-skip_hw:
-       iounmap(chip->iobase);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int
-snd_ad1889_dev_free(struct snd_device *device) 
-{
-       struct snd_ad1889 *chip = device->device_data;
-       return snd_ad1889_free(chip);
-}
-
-static int
-snd_ad1889_init(struct snd_ad1889 *chip) 
-{
-       ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
-       ad1889_readw(chip, AD_DS_CCS);  /* flush posted write */
-
-       usleep_range(10000, 11000);
-
-       /* enable Master and Target abort interrupts */
-       ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE);
-
-       return 0;
 }
 
 static int
-snd_ad1889_create(struct snd_card *card,
-                 struct pci_dev *pci,
-                 struct snd_ad1889 **rchip)
+snd_ad1889_create(struct snd_card *card, struct pci_dev *pci)
 {
+       struct snd_ad1889 *chip = card->private_data;
        int err;
 
-       struct snd_ad1889 *chip;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_ad1889_dev_free,
-       };
-
-       *rchip = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        /* check PCI availability (32bit DMA) */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_err(card->dev, "error setting 32-bit DMA mask.\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       /* allocate chip specific data with zero-filled memory */
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (!chip) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
-       card->private_data = chip;
        chip->pci = pci;
        chip->irq = -1;
 
        /* (1) PCI resource allocation */
-       err = pci_request_regions(pci, card->driver);
+       err = pcim_iomap_regions(pci, 1 << 0, card->driver);
        if (err < 0)
-               goto free_and_ret;
+               return err;
 
        chip->bar = pci_resource_start(pci, 0);
-       chip->iobase = pci_ioremap_bar(pci, 0);
-       if (chip->iobase == NULL) {
-               dev_err(card->dev, "unable to reserve region.\n");
-               err = -EBUSY;
-               goto free_and_ret;
-       }
+       chip->iobase = pcim_iomap_table(pci)[0];
        
        pci_set_master(pci);
 
        spin_lock_init(&chip->lock);    /* only now can we call ad1889_free */
 
-       if (request_irq(pci->irq, snd_ad1889_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_ad1889_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "cannot obtain IRQ %d\n", pci->irq);
-               snd_ad1889_free(chip);
                return -EBUSY;
        }
 
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_ad1889_free;
 
        /* (2) initialization of the chip hardware */
-       err = snd_ad1889_init(chip);
-       if (err < 0) {
-               snd_ad1889_free(chip);
-               return err;
-       }
+       ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
+       ad1889_readw(chip, AD_DS_CCS);  /* flush posted write */
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_ad1889_free(chip);
-               return err;
-       }
+       usleep_range(10000, 11000);
 
-       *rchip = chip;
+       /* enable Master and Target abort interrupts */
+       ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE);
 
        return 0;
-
-free_and_ret:
-       kfree(chip);
-       pci_disable_device(pci);
-
-       return err;
 }
 
 static int
@@ -944,19 +861,19 @@ snd_ad1889_probe(struct pci_dev *pci,
        }
 
        /* (2) */
-       err = snd_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE,
-                          0, &card);
-       /* XXX REVISIT: we can probably allocate chip in this call */
+       err = snd_devm_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        strcpy(card->driver, "AD1889");
        strcpy(card->shortname, "Analog Devices AD1889");
 
        /* (3) */
-       err = snd_ad1889_create(card, pci, &chip);
+       err = snd_ad1889_create(card, pci);
        if (err < 0)
-               goto free_and_ret;
+               return err;
 
        /* (4) */
        sprintf(card->longname, "%s at 0x%lx irq %i",
@@ -966,11 +883,11 @@ snd_ad1889_probe(struct pci_dev *pci,
        /* register AC97 mixer */
        err = snd_ad1889_ac97_init(chip, ac97_quirk[devno]);
        if (err < 0)
-               goto free_and_ret;
+               return err;
        
        err = snd_ad1889_pcm_init(chip, 0);
        if (err < 0)
-               goto free_and_ret;
+               return err;
 
        /* register proc interface */
        snd_ad1889_proc_init(chip);
@@ -978,23 +895,13 @@ snd_ad1889_probe(struct pci_dev *pci,
        /* (6) */
        err = snd_card_register(card);
        if (err < 0)
-               goto free_and_ret;
+               return err;
 
        /* (7) */
        pci_set_drvdata(pci, card);
 
        devno++;
        return 0;
-
-free_and_ret:
-       snd_card_free(card);
-       return err;
-}
-
-static void
-snd_ad1889_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static const struct pci_device_id snd_ad1889_ids[] = {
@@ -1007,7 +914,6 @@ static struct pci_driver ad1889_pci_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ad1889_ids,
        .probe = snd_ad1889_probe,
-       .remove = snd_ad1889_remove,
 };
 
 module_pci_driver(ad1889_pci_driver);
index 0d66b92..92eb59d 100644 (file)
@@ -1914,22 +1914,14 @@ static SIMPLE_DEV_PM_OPS(ali_pm, ali_suspend, ali_resume);
 #define ALI_PM_OPS     NULL
 #endif /* CONFIG_PM_SLEEP */
 
-static int snd_ali_free(struct snd_ali * codec)
+static void snd_ali_free(struct snd_card *card)
 {
+       struct snd_ali *codec = card->private_data;
+
        if (codec->hw_initialized)
                snd_ali_disable_address_interrupt(codec);
-       if (codec->irq >= 0)
-               free_irq(codec->irq, codec);
-       if (codec->port)
-               pci_release_regions(codec->pci);
-       pci_disable_device(codec->pci);
-#ifdef CONFIG_PM_SLEEP
-       kfree(codec->image);
-#endif
        pci_dev_put(codec->pci_m1533);
        pci_dev_put(codec->pci_m7101);
-       kfree(codec);
-       return 0;
 }
 
 static int snd_ali_chip_init(struct snd_ali *codec)
@@ -2017,8 +2009,9 @@ static int snd_ali_resources(struct snd_ali *codec)
                return err;
        codec->port = pci_resource_start(codec->pci, 0);
 
-       if (request_irq(codec->pci->irq, snd_ali_card_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, codec)) {
+       if (devm_request_irq(&codec->pci->dev, codec->pci->irq,
+                            snd_ali_card_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, codec)) {
                dev_err(codec->card->dev, "Unable to request irq.\n");
                return -EBUSY;
        }
@@ -2027,48 +2020,29 @@ static int snd_ali_resources(struct snd_ali *codec)
        dev_dbg(codec->card->dev, "resources allocated.\n");
        return 0;
 }
-static int snd_ali_dev_free(struct snd_device *device)
-{
-       struct snd_ali *codec = device->device_data;
-       snd_ali_free(codec);
-       return 0;
-}
 
 static int snd_ali_create(struct snd_card *card,
                          struct pci_dev *pci,
                          int pcm_streams,
-                         int spdif_support,
-                         struct snd_ali **r_ali)
+                         int spdif_support)
 {
-       struct snd_ali *codec;
+       struct snd_ali *codec = card->private_data;
        int i, err;
        unsigned short cmdw;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_ali_dev_free,
-        };
-
-       *r_ali = NULL;
 
        dev_dbg(card->dev, "creating ...\n");
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 31 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31))) {
                dev_err(card->dev,
                        "architecture does not support 31bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       codec = kzalloc(sizeof(*codec), GFP_KERNEL);
-       if (!codec) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&codec->reg_lock);
        spin_lock_init(&codec->voice_alloc);
 
@@ -2089,12 +2063,10 @@ static int snd_ali_create(struct snd_card *card,
                cmdw |= PCI_COMMAND_IO;
                pci_write_config_word(pci, PCI_COMMAND, cmdw);
        }
-       pci_set_master(pci);
        
-       if (snd_ali_resources(codec)) {
-               snd_ali_free(codec);
+       if (snd_ali_resources(codec))
                return -EBUSY;
-       }
+       card->private_free = snd_ali_free;
 
        codec->synth.chmap = 0;
        codec->synth.chcnt = 0;
@@ -2121,24 +2093,15 @@ static int snd_ali_create(struct snd_card *card,
        codec->pci_m1533 = pci_get_device(0x10b9, 0x1533, NULL);
        if (!codec->pci_m1533) {
                dev_err(card->dev, "cannot find ALi 1533 chip.\n");
-               snd_ali_free(codec);
                return -ENODEV;
        }
        /* M7101: power management */
        codec->pci_m7101 = pci_get_device(0x10b9, 0x7101, NULL);
        if (!codec->pci_m7101 && codec->revision == ALI_5451_V02) {
                dev_err(card->dev, "cannot find ALi 7101 chip.\n");
-               snd_ali_free(codec);
                return -ENODEV;
        }
 
-       dev_dbg(card->dev, "snd_device_new is called.\n");
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops);
-       if (err < 0) {
-               snd_ali_free(codec);
-               return err;
-       }
-
        /* initialise synth voices*/
        for (i = 0; i < ALI_CHANNELS; i++)
                codec->synth.voices[i].number = i;
@@ -2150,16 +2113,14 @@ static int snd_ali_create(struct snd_card *card,
        }
 
 #ifdef CONFIG_PM_SLEEP
-       codec->image = kmalloc(sizeof(*codec->image), GFP_KERNEL);
+       codec->image = devm_kmalloc(&pci->dev, sizeof(*codec->image),
+                                   GFP_KERNEL);
        if (!codec->image)
                dev_warn(card->dev, "can't allocate apm buffer\n");
 #endif
 
        snd_ali_enable_address_interrupt(codec);
        codec->hw_initialized = 1;
-
-       *r_ali = codec;
-       dev_dbg(card->dev, "created.\n");
        return 0;
 }
 
@@ -2172,24 +2133,25 @@ static int snd_ali_probe(struct pci_dev *pci,
 
        dev_dbg(&pci->dev, "probe ...\n");
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*codec), &card);
        if (err < 0)
                return err;
+       codec = card->private_data;
 
-       err = snd_ali_create(card, pci, pcm_channels, spdif, &codec);
+       err = snd_ali_create(card, pci, pcm_channels, spdif);
        if (err < 0)
-               goto error;
-       card->private_data = codec;
+               return err;
 
        dev_dbg(&pci->dev, "mixer building ...\n");
        err = snd_ali_mixer(codec);
        if (err < 0)
-               goto error;
+               return err;
        
        dev_dbg(&pci->dev, "pcm building ...\n");
        err = snd_ali_build_pcms(codec);
        if (err < 0)
-               goto error;
+               return err;
 
        snd_ali_proc_init(codec);
 
@@ -2202,26 +2164,16 @@ static int snd_ali_probe(struct pci_dev *pci,
        dev_dbg(&pci->dev, "register card.\n");
        err = snd_card_register(card);
        if (err < 0)
-               goto error;
+               return err;
 
        pci_set_drvdata(pci, card);
        return 0;
-
- error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_ali_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver ali5451_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ali_ids,
        .probe = snd_ali_probe,
-       .remove = snd_ali_remove,
        .driver = {
                .pm = ALI_PM_OPS,
        },
index 668008f..b86565d 100644 (file)
@@ -163,21 +163,11 @@ static void snd_als300_set_irq_flag(struct snd_als300 *chip, int cmd)
        snd_als300_gcr_write(chip->port, MISC_CONTROL, tmp);
 }
 
-static int snd_als300_free(struct snd_als300 *chip)
+static void snd_als300_free(struct snd_card *card)
 {
-       snd_als300_set_irq_flag(chip, IRQ_DISABLE);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
+       struct snd_als300 *chip = card->private_data;
 
-static int snd_als300_dev_free(struct snd_device *device)
-{
-       struct snd_als300 *chip = device->device_data;
-       return snd_als300_free(chip);
+       snd_als300_set_irq_flag(chip, IRQ_DISABLE);
 }
 
 static irqreturn_t snd_als300_interrupt(int irq, void *dev_id)
@@ -248,11 +238,6 @@ static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static void snd_als300_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static unsigned short snd_als300_ac97_read(struct snd_ac97 *ac97,
                                                        unsigned short reg)
 {
@@ -610,35 +595,22 @@ static void snd_als300_init(struct snd_als300 *chip)
 }
 
 static int snd_als300_create(struct snd_card *card,
-                            struct pci_dev *pci, int chip_type,
-                            struct snd_als300 **rchip)
+                            struct pci_dev *pci, int chip_type)
 {
-       struct snd_als300 *chip;
+       struct snd_als300 *chip = card->private_data;
        void *irq_handler;
        int err;
 
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_als300_dev_free,
-       };
-       *rchip = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
                dev_err(card->dev, "error setting 28bit DMA mask\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
        pci_set_master(pci);
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
@@ -646,11 +618,9 @@ static int snd_als300_create(struct snd_card *card,
        spin_lock_init(&chip->reg_lock);
 
        err = pci_request_regions(pci, "ALS300");
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
+
        chip->port = pci_resource_start(pci, 0);
 
        if (chip->chip_type == DEVICE_ALS300_PLUS)
@@ -658,38 +628,29 @@ static int snd_als300_create(struct snd_card *card,
        else
                irq_handler = snd_als300_interrupt;
 
-       if (request_irq(pci->irq, irq_handler, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, irq_handler, IRQF_SHARED,
+                            KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_als300_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_als300_free;
 
        snd_als300_init(chip);
 
        err = snd_als300_ac97(chip);
        if (err < 0) {
                dev_err(card->dev, "Could not create ac97\n");
-               snd_als300_free(chip);
                return err;
        }
 
        err = snd_als300_new_pcm(chip);
        if (err < 0) {
                dev_err(card->dev, "Could not create PCM\n");
-               snd_als300_free(chip);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_als300_free(chip);
                return err;
        }
 
-       *rchip = chip;
        return 0;
 }
 
@@ -737,20 +698,17 @@ static int snd_als300_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
-
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        chip_type = pci_id->driver_data;
 
-       err = snd_als300_create(card, pci, chip_type, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_als300_create(card, pci, chip_type);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        strcpy(card->driver, "ALS300");
        if (chip->chip_type == DEVICE_ALS300_PLUS)
@@ -764,10 +722,9 @@ static int snd_als300_probe(struct pci_dev *pci,
                                card->shortname, chip->port, chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
+
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
@@ -777,7 +734,6 @@ static struct pci_driver als300_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_als300_ids,
        .probe = snd_als300_probe,
-       .remove = snd_als300_remove,
        .driver = {
                .pm = SND_ALS300_PM_OPS,
        },
index 509f317..535eccd 100644 (file)
@@ -746,13 +746,15 @@ static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
 
        if (joystick_port[dev] == 1) { /* auto-detect */
                for (io_port = 0x200; io_port <= 0x218; io_port += 8) {
-                       r = request_region(io_port, 8, "ALS4000 gameport");
+                       r = devm_request_region(&acard->pci->dev, io_port, 8,
+                                               "ALS4000 gameport");
                        if (r)
                                break;
                }
        } else {
                io_port = joystick_port[dev];
-               r = request_region(io_port, 8, "ALS4000 gameport");
+               r = devm_request_region(&acard->pci->dev, io_port, 8,
+                                       "ALS4000 gameport");
        }
 
        if (!r) {
@@ -763,7 +765,6 @@ static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
        acard->gameport = gp = gameport_allocate_port();
        if (!gp) {
                dev_err(&acard->pci->dev, "cannot allocate memory for gameport\n");
-               release_and_free_resource(r);
                return -ENOMEM;
        }
 
@@ -771,7 +772,6 @@ static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
        gameport_set_phys(gp, "pci%s/gameport0", pci_name(acard->pci));
        gameport_set_dev_parent(gp, &acard->pci->dev);
        gp->io = io_port;
-       gameport_set_port_data(gp, r);
 
        /* Enable legacy joystick port */
        snd_als4000_set_addr(acard->iobase, 0, 0, 0, 1);
@@ -784,15 +784,11 @@ static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
 static void snd_als4000_free_gameport(struct snd_card_als4000 *acard)
 {
        if (acard->gameport) {
-               struct resource *r = gameport_get_port_data(acard->gameport);
-
                gameport_unregister_port(acard->gameport);
                acard->gameport = NULL;
 
                /* disable joystick */
                snd_als4000_set_addr(acard->iobase, 0, 0, 0, 0);
-
-               release_and_free_resource(r);
        }
 }
 #else
@@ -808,8 +804,6 @@ static void snd_card_als4000_free( struct snd_card *card )
        snd_als4k_gcr_write_addr(acard->iobase, ALS4K_GCR8C_MISC_CTRL, 0);
        /* free resources */
        snd_als4000_free_gameport(acard);
-       pci_release_regions(acard->pci);
-       pci_disable_device(acard->pci);
 }
 
 static int snd_card_als4000_probe(struct pci_dev *pci,
@@ -832,36 +826,30 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
        }
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        /* check, if we can restrict PCI DMA transfers to 24 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
                dev_err(&pci->dev, "architecture does not support 24bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
        err = pci_request_regions(pci, "ALS4000");
-       if (err < 0) {
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        iobase = pci_resource_start(pci, 0);
 
        pci_read_config_word(pci, PCI_COMMAND, &word);
        pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO);
        pci_set_master(pci);
        
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(*acard) /* private_data: acard */,
-                          &card);
-       if (err < 0) {
-               pci_release_regions(pci);
-               pci_disable_device(pci);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*acard) /* private_data: acard */,
+                               &card);
+       if (err < 0)
                return err;
-       }
 
        acard = card->private_data;
        acard->pci = pci;
@@ -881,7 +869,7 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
                               SB_HW_ALS4000,
                               &chip);
        if (err < 0)
-               goto out_err;
+               return err;
        acard->chip = chip;
 
        chip->pci = pci;
@@ -902,7 +890,7 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
        if (err < 0) {
                dev_err(&pci->dev, "no MPU-401 device at 0x%lx?\n",
                                iobase + ALS4K_IOB_30_MIDI_DATA);
-               goto out_err;
+               return err;
        }
        /* FIXME: ALS4000 has interesting MPU401 configuration features
         * at ALS4K_CR1A_MPU401_UART_MODE_CONTROL
@@ -912,11 +900,11 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
 
        err = snd_als4000_pcm(chip, 0);
        if (err < 0)
-               goto out_err;
+               return err;
 
        err = snd_sbmixer_new(chip);
        if (err < 0)
-               goto out_err;
+               return err;
 
        if (snd_opl3_create(card,
                                iobase + ALS4K_IOB_10_ADLIB_ADDR0,
@@ -928,30 +916,18 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
        } else {
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                if (err < 0)
-                       goto out_err;
+                       return err;
        }
 
        snd_als4000_create_gameport(acard, dev);
 
        err = snd_card_register(card);
        if (err < 0)
-               goto out_err;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
-       err = 0;
-       goto out;
-
-out_err:
-       snd_card_free(card);
-       
-out:
-       return err;
-}
-
-static void snd_card_als4000_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
+       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -996,7 +972,6 @@ static struct pci_driver als4000_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_als4000_ids,
        .probe = snd_card_als4000_probe,
-       .remove = snd_card_als4000_remove,
        .driver = {
                .pm = SND_ALS4000_PM_OPS,
        },
index 5f8aa35..b8e035d 100644 (file)
@@ -1530,87 +1530,44 @@ static void snd_atiixp_proc_init(struct atiixp *chip)
  * destructor
  */
 
-static int snd_atiixp_free(struct atiixp *chip)
+static void snd_atiixp_free(struct snd_card *card)
 {
-       if (chip->irq < 0)
-               goto __hw_end;
-       snd_atiixp_chip_stop(chip);
-
-      __hw_end:
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       iounmap(chip->remap_addr);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_atiixp_dev_free(struct snd_device *device)
-{
-       struct atiixp *chip = device->device_data;
-       return snd_atiixp_free(chip);
+       snd_atiixp_chip_stop(card->private_data);
 }
 
 /*
  * constructor for chip instance
  */
-static int snd_atiixp_create(struct snd_card *card,
-                            struct pci_dev *pci,
-                            struct atiixp **r_chip)
+static int snd_atiixp_init(struct snd_card *card, struct pci_dev *pci)
 {
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_atiixp_dev_free,
-       };
-       struct atiixp *chip;
+       struct atiixp *chip = card->private_data;
        int err;
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&chip->reg_lock);
        mutex_init(&chip->open_mutex);
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
-       err = pci_request_regions(pci, "ATI IXP AC97");
-       if (err < 0) {
-               pci_disable_device(pci);
-               kfree(chip);
+       err = pcim_iomap_regions(pci, 1 << 0, "ATI IXP AC97");
+       if (err < 0)
                return err;
-       }
        chip->addr = pci_resource_start(pci, 0);
-       chip->remap_addr = pci_ioremap_bar(pci, 0);
-       if (chip->remap_addr == NULL) {
-               dev_err(card->dev, "AC'97 space ioremap problem\n");
-               snd_atiixp_free(chip);
-               return -EIO;
-       }
+       chip->remap_addr = pcim_iomap_table(pci)[0];
 
-       if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_atiixp_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_atiixp_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_atiixp_free;
        pci_set_master(pci);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_atiixp_free(chip);
-               return err;
-       }
-
-       *r_chip = chip;
        return 0;
 }
 
@@ -1622,30 +1579,31 @@ static int snd_atiixp_probe(struct pci_dev *pci,
        struct atiixp *chip;
        int err;
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA");
        strcpy(card->shortname, "ATI IXP");
-       err = snd_atiixp_create(card, pci, &chip);
+       err = snd_atiixp_init(card, pci);
        if (err < 0)
-               goto __error;
-       card->private_data = chip;
+               return err;
 
        err = snd_atiixp_aclink_reset(chip);
        if (err < 0)
-               goto __error;
+               return err;
 
        chip->spdif_over_aclink = spdif_aclink;
 
        err = snd_atiixp_mixer_new(chip, ac97_clock, ac97_quirk);
        if (err < 0)
-               goto __error;
+               return err;
 
        err = snd_atiixp_pcm_new(chip);
        if (err < 0)
-               goto __error;
+               return err;
        
        snd_atiixp_proc_init(chip);
 
@@ -1659,26 +1617,16 @@ static int snd_atiixp_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto __error;
+               return err;
 
        pci_set_drvdata(pci, card);
        return 0;
-
- __error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_atiixp_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver atiixp_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_atiixp_ids,
        .probe = snd_atiixp_probe,
-       .remove = snd_atiixp_remove,
        .driver = {
                .pm = SND_ATIIXP_PM_OPS,
        },
index 9739c3a..178dce8 100644 (file)
@@ -1159,87 +1159,44 @@ static void snd_atiixp_proc_init(struct atiixp_modem *chip)
  * destructor
  */
 
-static int snd_atiixp_free(struct atiixp_modem *chip)
+static void snd_atiixp_free(struct snd_card *card)
 {
-       if (chip->irq < 0)
-               goto __hw_end;
-       snd_atiixp_chip_stop(chip);
-
-      __hw_end:
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       iounmap(chip->remap_addr);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_atiixp_dev_free(struct snd_device *device)
-{
-       struct atiixp_modem *chip = device->device_data;
-       return snd_atiixp_free(chip);
+       snd_atiixp_chip_stop(card->private_data);
 }
 
 /*
  * constructor for chip instance
  */
-static int snd_atiixp_create(struct snd_card *card,
-                            struct pci_dev *pci,
-                            struct atiixp_modem **r_chip)
+static int snd_atiixp_init(struct snd_card *card, struct pci_dev *pci)
 {
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_atiixp_dev_free,
-       };
-       struct atiixp_modem *chip;
+       struct atiixp_modem *chip = card->private_data;
        int err;
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&chip->reg_lock);
        mutex_init(&chip->open_mutex);
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
-       err = pci_request_regions(pci, "ATI IXP MC97");
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       err = pcim_iomap_regions(pci, 1 << 0, "ATI IXP MC97");
+       if (err < 0)
                return err;
-       }
        chip->addr = pci_resource_start(pci, 0);
-       chip->remap_addr = pci_ioremap_bar(pci, 0);
-       if (chip->remap_addr == NULL) {
-               dev_err(card->dev, "AC'97 space ioremap problem\n");
-               snd_atiixp_free(chip);
-               return -EIO;
-       }
+       chip->remap_addr = pcim_iomap_table(pci)[0];
 
-       if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_atiixp_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_atiixp_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_atiixp_free;
        pci_set_master(pci);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_atiixp_free(chip);
-               return err;
-       }
-
-       *r_chip = chip;
        return 0;
 }
 
@@ -1251,28 +1208,29 @@ static int snd_atiixp_probe(struct pci_dev *pci,
        struct atiixp_modem *chip;
        int err;
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        strcpy(card->driver, "ATIIXP-MODEM");
        strcpy(card->shortname, "ATI IXP Modem");
-       err = snd_atiixp_create(card, pci, &chip);
+       err = snd_atiixp_init(card, pci);
        if (err < 0)
-               goto __error;
-       card->private_data = chip;
+               return err;
 
        err = snd_atiixp_aclink_reset(chip);
        if (err < 0)
-               goto __error;
+               return err;
 
        err = snd_atiixp_mixer_new(chip, ac97_clock);
        if (err < 0)
-               goto __error;
+               return err;
 
        err = snd_atiixp_pcm_new(chip);
        if (err < 0)
-               goto __error;
+               return err;
        
        snd_atiixp_proc_init(chip);
 
@@ -1283,26 +1241,16 @@ static int snd_atiixp_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto __error;
+               return err;
 
        pci_set_drvdata(pci, card);
        return 0;
-
- __error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_atiixp_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver atiixp_modem_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_atiixp_ids,
        .probe = snd_atiixp_probe,
-       .remove = snd_atiixp_remove,
        .driver = {
                .pm = SND_ATIIXP_PM_OPS,
        },
index 1f7fee4..342ef2a 100644 (file)
@@ -123,56 +123,35 @@ static void snd_vortex_workaround(struct pci_dev *vortex, int fix)
 
 // component-destructor
 // (see "Management of Cards and Components")
-static int snd_vortex_dev_free(struct snd_device *device)
+static void snd_vortex_free(struct snd_card *card)
 {
-       vortex_t *vortex = device->device_data;
+       vortex_t *vortex = card->private_data;
 
        vortex_gameport_unregister(vortex);
        vortex_core_shutdown(vortex);
-       // Take down PCI interface.
-       free_irq(vortex->irq, vortex);
-       iounmap(vortex->mmio);
-       pci_release_regions(vortex->pci_dev);
-       pci_disable_device(vortex->pci_dev);
-       kfree(vortex);
-
-       return 0;
 }
 
 // chip-specific constructor
 // (see "Management of Cards and Components")
 static int
-snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
+snd_vortex_create(struct snd_card *card, struct pci_dev *pci)
 {
-       vortex_t *chip;
+       vortex_t *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_vortex_dev_free,
-       };
-
-       *rchip = NULL;
 
        // check PCI availability (DMA).
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_err(card->dev, "error to set DMA mask\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
 
        // initialize the stuff
        chip->pci_dev = pci;
-       chip->io = pci_resource_start(pci, 0);
        chip->vendor = pci->vendor;
        chip->device = pci->device;
        chip->card = card;
@@ -181,16 +160,12 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
        // (1) PCI resource allocation
        // Get MMIO area
        //
-       err = pci_request_regions(pci, CARD_NAME_SHORT);
+       err = pcim_iomap_regions(pci, 1 << 0, CARD_NAME_SHORT);
        if (err)
-               goto regions_out;
+               return err;
 
-       chip->mmio = pci_ioremap_bar(pci, 0);
-       if (!chip->mmio) {
-               dev_err(card->dev, "MMIO area remap failed.\n");
-               err = -ENOMEM;
-               goto ioremap_out;
-       }
+       chip->io = pci_resource_start(pci, 0);
+       chip->mmio = pcim_iomap_table(pci)[0];
 
        /* Init audio core.
         * This must be done before we do request_irq otherwise we can get spurious
@@ -198,44 +173,22 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
        err = vortex_core_init(chip);
        if (err) {
                dev_err(card->dev, "hw core init failed\n");
-               goto core_out;
+               return err;
        }
 
-       err = request_irq(pci->irq, vortex_interrupt,
-                         IRQF_SHARED, KBUILD_MODNAME, chip);
+       err = devm_request_irq(&pci->dev, pci->irq, vortex_interrupt,
+                              IRQF_SHARED, KBUILD_MODNAME, chip);
        if (err) {
                dev_err(card->dev, "cannot grab irq\n");
-               goto irq_out;
+               return err;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_vortex_free;
 
        pci_set_master(pci);
        // End of PCI setup.
-
-       // Register alsa root device.
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto alloc_out;
-
-       *rchip = chip;
-
        return 0;
-
-      alloc_out:
-       free_irq(chip->irq, chip);
-      irq_out:
-       vortex_core_shutdown(chip);
-      core_out:
-       iounmap(chip->mmio);
-      ioremap_out:
-       pci_release_regions(chip->pci_dev);
-      regions_out:
-       pci_disable_device(chip->pci_dev);
-       //FIXME: this not the right place to unregister the gameport
-       vortex_gameport_unregister(chip);
-       kfree(chip);
-       return err;
 }
 
 // constructor -- see "Constructor" sub-section
@@ -255,17 +208,16 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                return -ENOENT;
        }
        // (2)
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        // (3)
-       err = snd_vortex_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_vortex_create(card, pci);
+       if (err < 0)
                return err;
-       }
        snd_vortex_workaround(pci, pcifix[dev]);
 
        // Card details needed in snd_vortex_midi
@@ -276,50 +228,37 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 
        // (4) Alloc components.
        err = snd_vortex_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        // ADB pcm.
        err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_PCM);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #ifndef CHIP_AU8820
        // ADB SPDIF
        err = snd_vortex_new_pcm(chip, VORTEX_PCM_SPDIF, 1);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        // A3D
        err = snd_vortex_new_pcm(chip, VORTEX_PCM_A3D, NR_A3D);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #endif
        /*
           // ADB I2S
           if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_I2S, 1)) < 0) {
-          snd_card_free(card);
           return err;
           }
         */
 #ifndef CHIP_AU8810
        // WT pcm.
        err = snd_vortex_new_pcm(chip, VORTEX_PCM_WT, NR_WT);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #endif
        err = snd_vortex_midi(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        vortex_gameport_register(chip);
 
@@ -342,15 +281,11 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 
        // (5)
        err = pci_read_config_word(pci, PCI_DEVICE_ID, &chip->device);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }       
        err = pci_read_config_word(pci, PCI_VENDOR_ID, &chip->vendor);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        chip->rev = pci->revision;
 #ifdef CHIP_AU8830
        if ((chip->rev) != 0xfe && (chip->rev) != 0xfa) {
@@ -359,18 +294,14 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                       chip->rev);
                dev_alert(card->dev,
                          "Please email the results of 'lspci -vv' to openvortex-dev@nongnu.org.\n");
-               snd_card_free(card);
-               err = -ENODEV;
-               return err;
+               return -ENODEV;
        }
 #endif
 
        // (6)
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        // (7)
        pci_set_drvdata(pci, card);
        dev++;
@@ -379,18 +310,11 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        return 0;
 }
 
-// destructor -- see "Destructor" sub-section
-static void snd_vortex_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 // pci_driver definition
 static struct pci_driver vortex_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_vortex_ids,
        .probe = snd_vortex_probe,
-       .remove = snd_vortex_remove,
 };
 
 module_pci_driver(vortex_driver);
index 4339684..d56f126 100644 (file)
@@ -99,12 +99,9 @@ struct aw2 {
 /*********************************
  * FUNCTION DECLARATIONS
  ********************************/
-static int snd_aw2_dev_free(struct snd_device *device);
-static int snd_aw2_create(struct snd_card *card,
-                         struct pci_dev *pci, struct aw2 **rchip);
+static int snd_aw2_create(struct snd_card *card, struct pci_dev *pci);
 static int snd_aw2_probe(struct pci_dev *pci,
                         const struct pci_device_id *pci_id);
-static void snd_aw2_remove(struct pci_dev *pci);
 static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream);
 static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream);
 static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream);
@@ -157,7 +154,6 @@ static struct pci_driver aw2_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_aw2_ids,
        .probe = snd_aw2_probe,
-       .remove = snd_aw2_remove,
 };
 
 module_pci_driver(aw2_driver);
@@ -196,41 +192,23 @@ static const struct snd_kcontrol_new aw2_control = {
  ********************************/
 
 /* component-destructor */
-static int snd_aw2_dev_free(struct snd_device *device)
+static void snd_aw2_free(struct snd_card *card)
 {
-       struct aw2 *chip = device->device_data;
+       struct aw2 *chip = card->private_data;
 
        /* Free hardware */
        snd_aw2_saa7146_free(&chip->saa7146);
-
-       /* release the irq */
-       if (chip->irq >= 0)
-               free_irq(chip->irq, (void *)chip);
-       /* release the i/o ports & memory */
-       iounmap(chip->iobase_virt);
-       pci_release_regions(chip->pci);
-       /* disable the PCI entry */
-       pci_disable_device(chip->pci);
-       /* release the data */
-       kfree(chip);
-
-       return 0;
 }
 
 /* chip-specific constructor */
 static int snd_aw2_create(struct snd_card *card,
-                         struct pci_dev *pci, struct aw2 **rchip)
+                         struct pci_dev *pci)
 {
-       struct aw2 *chip;
+       struct aw2 *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_aw2_dev_free,
-       };
-
-       *rchip = NULL;
 
        /* initialize the PCI entry */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        pci_set_master(pci);
@@ -238,14 +216,8 @@ static int snd_aw2_create(struct snd_card *card,
        /* check PCI availability (32bit DMA) */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_err(card->dev, "Impossible to set 32bit mask DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
 
        /* initialize the stuff */
        chip->card = card;
@@ -253,52 +225,23 @@ static int snd_aw2_create(struct snd_card *card,
        chip->irq = -1;
 
        /* (1) PCI resource allocation */
-       err = pci_request_regions(pci, "Audiowerk2");
-       if (err < 0) {
-               pci_disable_device(pci);
-               kfree(chip);
+       err = pcim_iomap_regions(pci, 1 << 0, "Audiowerk2");
+       if (err < 0)
                return err;
-       }
        chip->iobase_phys = pci_resource_start(pci, 0);
-       chip->iobase_virt =
-               ioremap(chip->iobase_phys,
-                               pci_resource_len(pci, 0));
-
-       if (chip->iobase_virt == NULL) {
-               dev_err(card->dev, "unable to remap memory region");
-               pci_release_regions(pci);
-               pci_disable_device(pci);
-               kfree(chip);
-               return -ENOMEM;
-       }
+       chip->iobase_virt = pcim_iomap_table(pci)[0];
 
        /* (2) initialization of the chip hardware */
        snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt);
 
-       if (request_irq(pci->irq, snd_aw2_saa7146_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_aw2_saa7146_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "Cannot grab irq %d\n", pci->irq);
-
-               iounmap(chip->iobase_virt);
-               pci_release_regions(chip->pci);
-               pci_disable_device(chip->pci);
-               kfree(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               free_irq(chip->irq, (void *)chip);
-               iounmap(chip->iobase_virt);
-               pci_release_regions(chip->pci);
-               pci_disable_device(chip->pci);
-               kfree(chip);
-               return err;
-       }
-
-       *rchip = chip;
+       card->private_free = snd_aw2_free;
 
        dev_info(card->dev,
                 "Audiowerk 2 sound card (saa7146 chipset) detected and managed\n");
@@ -323,17 +266,16 @@ static int snd_aw2_probe(struct pci_dev *pci,
        }
 
        /* (2) Create card instance */
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        /* (3) Create main component */
-       err = snd_aw2_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_aw2_create(card, pci);
+       if (err < 0)
                return err;
-       }
 
        /* initialize mutex */
        mutex_init(&chip->mtx);
@@ -351,10 +293,8 @@ static int snd_aw2_probe(struct pci_dev *pci,
 
        /* (6) Register card instance */
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        /* (7) Set PCI driver data */
        pci_set_drvdata(pci, card);
@@ -363,12 +303,6 @@ static int snd_aw2_probe(struct pci_dev *pci,
        return 0;
 }
 
-/* destructor */
-static void snd_aw2_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 /* open callback */
 static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream)
 {
index 4ee7ab4..0890504 100644 (file)
@@ -2244,32 +2244,15 @@ out:
 
 /******************************************************************/
 
-static int
-snd_azf3328_free(struct snd_azf3328 *chip)
+static void
+snd_azf3328_free(struct snd_card *card)
 {
-       if (chip->irq < 0)
-               goto __end_hw;
+       struct snd_azf3328 *chip = card->private_data;
 
        snd_azf3328_mixer_reset(chip);
 
        snd_azf3328_timer_stop(chip->timer);
        snd_azf3328_gameport_free(chip);
-
-__end_hw:
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-
-       kfree(chip);
-       return 0;
-}
-
-static int
-snd_azf3328_dev_free(struct snd_device *device)
-{
-       struct snd_azf3328 *chip = device->device_data;
-       return snd_azf3328_free(chip);
 }
 
 #if 0
@@ -2350,29 +2333,18 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
 static int
 snd_azf3328_create(struct snd_card *card,
                   struct pci_dev *pci,
-                  unsigned long device_type,
-                  struct snd_azf3328 **rchip)
+                  unsigned long device_type)
 {
-       struct snd_azf3328 *chip;
+       struct snd_azf3328 *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_azf3328_dev_free,
-       };
        u8 dma_init;
        enum snd_azf3328_codec_type codec_type;
        struct snd_azf3328_codec_data *codec_setup;
 
-       *rchip = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               err = -ENOMEM;
-               goto out_err;
-       }
        spin_lock_init(&chip->reg_lock);
        chip->card = card;
        chip->pci = pci;
@@ -2383,13 +2355,12 @@ snd_azf3328_create(struct snd_card *card,
                dev_err(card->dev,
                        "architecture does not support 24bit PCI busmaster DMA\n"
                );
-               err = -ENXIO;
-               goto out_err;
+               return -ENXIO;
        }
 
        err = pci_request_regions(pci, "Aztech AZF3328");
        if (err < 0)
-               goto out_err;
+               return err;
 
        chip->ctrl_io  = pci_resource_start(pci, 0);
        chip->game_io  = pci_resource_start(pci, 1);
@@ -2415,26 +2386,22 @@ snd_azf3328_create(struct snd_card *card,
        codec_setup->type = AZF_CODEC_I2S_OUT;
        codec_setup->name = "I2S_OUT";
 
-       if (request_irq(pci->irq, snd_azf3328_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_azf3328_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               err = -EBUSY;
-               goto out_err;
+               return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_azf3328_free;
        pci_set_master(pci);
 
        snd_azf3328_debug_show_ports(chip);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto out_err;
-
        /* create mixer interface & switches */
        err = snd_azf3328_mixer_new(chip);
        if (err < 0)
-               goto out_err;
+               return err;
 
        /* standard codec init stuff */
                /* default DMA init value */
@@ -2456,18 +2423,7 @@ snd_azf3328_create(struct snd_card *card,
                spin_unlock_irq(codec->lock);
        }
 
-       *rchip = chip;
-
-       err = 0;
-       goto out;
-
-out_err:
-       if (chip)
-               snd_azf3328_free(chip);
-       pci_disable_device(pci);
-
-out:
-       return err;
+       return 0;
 }
 
 static int
@@ -2479,29 +2435,25 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        struct snd_opl3 *opl3;
        int err;
 
-       if (dev >= SNDRV_CARDS) {
-               err = -ENODEV;
-               goto out;
-       }
+       if (dev >= SNDRV_CARDS)
+               return -ENODEV;
        if (!enable[dev]) {
                dev++;
-               err = -ENOENT;
-               goto out;
+               return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
-               goto out;
+               return err;
+       chip = card->private_data;
 
        strcpy(card->driver, "AZF3328");
        strcpy(card->shortname, "Aztech AZF3328 (PCI168)");
 
-       err = snd_azf3328_create(card, pci, pci_id->driver_data, &chip);
+       err = snd_azf3328_create(card, pci, pci_id->driver_data);
        if (err < 0)
-               goto out_err;
-
-       card->private_data = chip;
+               return err;
 
        /* chose to use MPU401_HW_AZT2320 ID instead of MPU401_HW_MPU401,
           since our hardware ought to be similar, thus use same ID. */
@@ -2515,16 +2467,16 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                dev_err(card->dev, "no MPU-401 device at 0x%lx?\n",
                                chip->mpu_io
                );
-               goto out_err;
+               return err;
        }
 
        err = snd_azf3328_timer(chip, 0);
        if (err < 0)
-               goto out_err;
+               return err;
 
        err = snd_azf3328_pcm(chip);
        if (err < 0)
-               goto out_err;
+               return err;
 
        if (snd_opl3_create(card, chip->opl3_io, chip->opl3_io+2,
                            OPL3_HW_AUTO, 1, &opl3) < 0) {
@@ -2535,10 +2487,10 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                /* need to use IDs 1, 2 since ID 0 is snd_azf3328_timer above */
                err = snd_opl3_timer_new(opl3, 1, 2);
                if (err < 0)
-                       goto out_err;
+                       return err;
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                if (err < 0)
-                       goto out_err;
+                       return err;
                opl3->private_data = chip;
        }
 
@@ -2547,7 +2499,7 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto out_err;
+               return err;
 
 #ifdef MODULE
        dev_info(card->dev,
@@ -2565,22 +2517,7 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 
        pci_set_drvdata(pci, card);
        dev++;
-
-       err = 0;
-       goto out;
-
-out_err:
-       dev_err(card->dev, "something failed, exiting\n");
-       snd_card_free(card);
-
-out:
-       return err;
-}
-
-static void
-snd_azf3328_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
+       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -2709,7 +2646,6 @@ static struct pci_driver azf3328_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_azf3328_ids,
        .probe = snd_azf3328_probe,
-       .remove = snd_azf3328_remove,
        .driver = {
                .pm = SND_AZF3328_PM_OPS,
        },
index 39bcfb8..d23f931 100644 (file)
@@ -656,23 +656,11 @@ static const struct snd_kcontrol_new snd_bt87x_capture_source = {
        .put = snd_bt87x_capture_source_put,
 };
 
-static int snd_bt87x_free(struct snd_bt87x *chip)
-{
-       if (chip->mmio)
-               snd_bt87x_stop(chip);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       iounmap(chip->mmio);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_bt87x_dev_free(struct snd_device *device)
+static void snd_bt87x_free(struct snd_card *card)
 {
-       struct snd_bt87x *chip = device->device_data;
-       return snd_bt87x_free(chip);
+       struct snd_bt87x *chip = card->private_data;
+
+       snd_bt87x_stop(chip);
 }
 
 static int snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
@@ -694,43 +682,24 @@ static int snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
 }
 
 static int snd_bt87x_create(struct snd_card *card,
-                           struct pci_dev *pci,
-                           struct snd_bt87x **rchip)
+                           struct pci_dev *pci)
 {
-       struct snd_bt87x *chip;
+       struct snd_bt87x *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_bt87x_dev_free
-       };
-
-       *rchip = NULL;
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (!chip) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
        spin_lock_init(&chip->reg_lock);
 
-       err = pci_request_regions(pci, "Bt87x audio");
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       err = pcim_iomap_regions(pci, 1 << 0, "Bt87x audio");
+       if (err < 0)
                return err;
-       }
-       chip->mmio = pci_ioremap_bar(pci, 0);
-       if (!chip->mmio) {
-               dev_err(card->dev, "cannot remap io memory\n");
-               err = -ENOMEM;
-               goto fail;
-       }
+       chip->mmio = pcim_iomap_table(pci)[0];
 
        chip->reg_control = CTL_A_PWRDN | CTL_DA_ES2 |
                            CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT);
@@ -739,26 +708,18 @@ static int snd_bt87x_create(struct snd_card *card,
        snd_bt87x_writel(chip, REG_INT_MASK, 0);
        snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS);
 
-       err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED,
-                         KBUILD_MODNAME, chip);
+       err = devm_request_irq(&pci->dev, pci->irq, snd_bt87x_interrupt,
+                              IRQF_SHARED, KBUILD_MODNAME, chip);
        if (err < 0) {
                dev_err(card->dev, "cannot grab irq %d\n", pci->irq);
-               goto fail;
+               return err;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_bt87x_free;
        pci_set_master(pci);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto fail;
-
-       *rchip = chip;
        return 0;
-
-fail:
-       snd_bt87x_free(chip);
-       return err;
 }
 
 #define BT_DEVICE(chip, subvend, subdev, id) \
@@ -868,14 +829,15 @@ static int snd_bt87x_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       err = snd_bt87x_create(card, pci, &chip);
+       err = snd_bt87x_create(card, pci);
        if (err < 0)
-               goto _error;
+               return err;
 
        memcpy(&chip->board, &snd_bt87x_boards[boardid], sizeof(chip->board));
 
@@ -887,24 +849,24 @@ static int snd_bt87x_probe(struct pci_dev *pci,
 
                err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital");
                if (err < 0)
-                       goto _error;
+                       return err;
        }
        if (!chip->board.no_analog) {
                err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog");
                if (err < 0)
-                       goto _error;
+                       return err;
                err = snd_ctl_add(card, snd_ctl_new1(
                                  &snd_bt87x_capture_volume, chip));
                if (err < 0)
-                       goto _error;
+                       return err;
                err = snd_ctl_add(card, snd_ctl_new1(
                                  &snd_bt87x_capture_boost, chip));
                if (err < 0)
-                       goto _error;
+                       return err;
                err = snd_ctl_add(card, snd_ctl_new1(
                                  &snd_bt87x_capture_source, chip));
                if (err < 0)
-                       goto _error;
+                       return err;
        }
        dev_info(card->dev, "bt87x%d: Using board %d, %sanalog, %sdigital "
                   "(rate %d Hz)\n", dev, boardid,
@@ -920,20 +882,11 @@ static int snd_bt87x_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto _error;
+               return err;
 
        pci_set_drvdata(pci, card);
        ++dev;
        return 0;
-
-_error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_bt87x_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 /* default entries for all Bt87x cards - it's not exported */
@@ -948,7 +901,6 @@ static struct pci_driver driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_bt87x_ids,
        .probe = snd_bt87x_probe,
-       .remove = snd_bt87x_remove,
 };
 
 static int __init alsa_card_bt87x_init(void)
index 62a22ca..f246e60 100644 (file)
@@ -667,7 +667,6 @@ struct snd_ca0106 {
        struct pci_dev *pci;
 
        unsigned long port;
-       struct resource *res_port;
        int irq;
 
        unsigned int serial;            /* serial number */
@@ -688,7 +687,7 @@ struct snd_ca0106 {
        u8 i2c_capture_volume[4][2];
        int capture_mic_line_in;
 
-       struct snd_dma_buffer buffer;
+       struct snd_dma_buffer *buffer;
 
        struct snd_ca_midi midi;
        struct snd_ca_midi midi2;
index 9977871..36fb150 100644 (file)
@@ -718,7 +718,7 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_ca0106_pcm *epcm = runtime->private_data;
        int channel = epcm->channel_id;
-       u32 *table_base = (u32 *)(emu->buffer.area+(8*16*channel));
+       u32 *table_base = (u32 *)(emu->buffer->area+(8*16*channel));
        u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
        u32 hcfg_mask = HCFG_PLAYBACK_S32_LE;
        u32 hcfg_set = 0x00000000;
@@ -746,7 +746,7 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
                   runtime->dma_addr, runtime->dma_area, table_base);
        dev_dbg(emu->card->dev,
                "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
-                  emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+                  emu->buffer->addr, emu->buffer->area, emu->buffer->bytes);
 #endif /* debug */
        /* Rate can be set per channel. */
        /* reg40 control host to fifo */
@@ -796,13 +796,13 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
        reg71 = (reg71 & ~reg71_mask) | reg71_set;
        snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
 
-       /* FIXME: Check emu->buffer.size before actually writing to it. */
+       /* FIXME: Check emu->buffer->size before actually writing to it. */
         for(i=0; i < runtime->periods; i++) {
                table_base[i*2] = runtime->dma_addr + (i * period_size_bytes);
                table_base[i*2+1] = period_size_bytes << 16;
        }
  
-       snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel));
+       snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer->addr+(8*16*channel));
        snd_ca0106_ptr_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
        snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0);
        snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
@@ -853,7 +853,7 @@ static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream)
                   runtime->dma_addr, runtime->dma_area, table_base);
        dev_dbg(emu->card->dev,
                "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
-                  emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+                  emu->buffer->addr, emu->buffer->area, emu->buffer->bytes);
 #endif /* debug */
        /* reg71 controls ADC rate. */
        switch (runtime->rate) {
@@ -1183,32 +1183,11 @@ static int snd_ca0106_ac97(struct snd_ca0106 *chip)
 
 static void ca0106_stop_chip(struct snd_ca0106 *chip);
 
-static int snd_ca0106_free(struct snd_ca0106 *chip)
+static void snd_ca0106_free(struct snd_card *card)
 {
-       if (chip->res_port != NULL) {
-               /* avoid access to already used hardware */
-               ca0106_stop_chip(chip);
-       }
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       // release the data
-#if 1
-       if (chip->buffer.area)
-               snd_dma_free_pages(&chip->buffer);
-#endif
-
-       // release the i/o port
-       release_and_free_resource(chip->res_port);
-
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
+       struct snd_ca0106 *chip = card->private_data;
 
-static int snd_ca0106_dev_free(struct snd_device *device)
-{
-       struct snd_ca0106 *chip = device->device_data;
-       return snd_ca0106_free(chip);
+       ca0106_stop_chip(chip);
 }
 
 static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id)
@@ -1594,50 +1573,33 @@ static void ca0106_stop_chip(struct snd_ca0106 *chip)
 }
 
 static int snd_ca0106_create(int dev, struct snd_card *card,
-                                        struct pci_dev *pci,
-                                        struct snd_ca0106 **rchip)
+                            struct pci_dev *pci)
 {
-       struct snd_ca0106 *chip;
+       struct snd_ca0106 *chip = card->private_data;
        const struct snd_ca0106_details *c;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_ca0106_dev_free,
-       };
-
-       *rchip = NULL;
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_err(card->dev, "error to set 32bit mask DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
 
        spin_lock_init(&chip->emu_lock);
 
+       err = pci_request_regions(pci, "snd_ca0106");
+       if (err < 0)
+               return err;
        chip->port = pci_resource_start(pci, 0);
-       chip->res_port = request_region(chip->port, 0x20, "snd_ca0106");
-       if (!chip->res_port) {
-               snd_ca0106_free(chip);
-               dev_err(card->dev, "cannot allocate the port\n");
-               return -EBUSY;
-       }
 
-       if (request_irq(pci->irq, snd_ca0106_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, chip)) {
-               snd_ca0106_free(chip);
+       if (devm_request_irq(&pci->dev, pci->irq, snd_ca0106_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "cannot grab irq\n");
                return -EBUSY;
        }
@@ -1645,11 +1607,9 @@ static int snd_ca0106_create(int dev, struct snd_card *card,
        card->sync_irq = chip->irq;
 
        /* This stores the periods table. */
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               1024, &chip->buffer) < 0) {
-               snd_ca0106_free(chip);
+       chip->buffer = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 1024);
+       if (!chip->buffer)
                return -ENOMEM;
-       }
 
        pci_set_master(pci);
        /* read serial */
@@ -1678,13 +1638,6 @@ static int snd_ca0106_create(int dev, struct snd_card *card,
                c->name, chip->port, chip->irq);
 
        ca0106_init_chip(chip, 0);
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_ca0106_free(chip);
-               return err;
-       }
-       *rchip = chip;
        return 0;
 }
 
@@ -1787,36 +1740,37 @@ static int snd_ca0106_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       err = snd_ca0106_create(dev, card, pci, &chip);
+       err = snd_ca0106_create(dev, card, pci);
        if (err < 0)
-               goto error;
-       card->private_data = chip;
+               return err;
+       card->private_free = snd_ca0106_free;
 
        for (i = 0; i < 4; i++) {
                err = snd_ca0106_pcm(chip, i);
                if (err < 0)
-                       goto error;
+                       return err;
        }
 
        if (chip->details->ac97 == 1) {
                /* The SB0410 and SB0413 do not have an AC97 chip. */
                err = snd_ca0106_ac97(chip);
                if (err < 0)
-                       goto error;
+                       return err;
        }
        err = snd_ca0106_mixer(chip);
        if (err < 0)
-               goto error;
+               return err;
 
        dev_dbg(card->dev, "probe for MIDI channel A ...");
        err = snd_ca0106_midi(chip, CA0106_MIDI_CHAN_A);
        if (err < 0)
-               goto error;
+               return err;
        dev_dbg(card->dev, " done.\n");
 
 #ifdef CONFIG_SND_PROC_FS
@@ -1825,20 +1779,11 @@ static int snd_ca0106_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto error;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
- error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_ca0106_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -1894,7 +1839,6 @@ static struct pci_driver ca0106_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ca0106_ids,
        .probe = snd_ca0106_probe,
-       .remove = snd_ca0106_remove,
        .driver = {
                .pm = SND_CA0106_PM_OPS,
        },
index f44f118..ea20236 100644 (file)
@@ -2852,13 +2852,15 @@ static int snd_cmipci_create_gameport(struct cmipci *cm, int dev)
        if (joystick_port[dev] == 1) { /* auto-detect */
                for (i = 0; ports[i]; i++) {
                        io_port = ports[i];
-                       r = request_region(io_port, 1, "CMIPCI gameport");
+                       r = devm_request_region(&cm->pci->dev, io_port, 1,
+                                               "CMIPCI gameport");
                        if (r)
                                break;
                }
        } else {
                io_port = joystick_port[dev];
-               r = request_region(io_port, 1, "CMIPCI gameport");
+               r = devm_request_region(&cm->pci->dev, io_port, 1,
+                                       "CMIPCI gameport");
        }
 
        if (!r) {
@@ -2869,14 +2871,12 @@ static int snd_cmipci_create_gameport(struct cmipci *cm, int dev)
        cm->gameport = gp = gameport_allocate_port();
        if (!gp) {
                dev_err(cm->card->dev, "cannot allocate memory for gameport\n");
-               release_and_free_resource(r);
                return -ENOMEM;
        }
        gameport_set_name(gp, "C-Media Gameport");
        gameport_set_phys(gp, "pci%s/gameport0", pci_name(cm->pci));
        gameport_set_dev_parent(gp, &cm->pci->dev);
        gp->io = io_port;
-       gameport_set_port_data(gp, r);
 
        snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
 
@@ -2888,13 +2888,10 @@ static int snd_cmipci_create_gameport(struct cmipci *cm, int dev)
 static void snd_cmipci_free_gameport(struct cmipci *cm)
 {
        if (cm->gameport) {
-               struct resource *r = gameport_get_port_data(cm->gameport);
-
                gameport_unregister_port(cm->gameport);
                cm->gameport = NULL;
 
                snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
-               release_and_free_resource(r);
        }
 }
 #else
@@ -2902,34 +2899,22 @@ static inline int snd_cmipci_create_gameport(struct cmipci *cm, int dev) { retur
 static inline void snd_cmipci_free_gameport(struct cmipci *cm) { }
 #endif
 
-static int snd_cmipci_free(struct cmipci *cm)
+static void snd_cmipci_free(struct snd_card *card)
 {
-       if (cm->irq >= 0) {
-               snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN);
-               snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT);
-               snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0);  /* disable ints */
-               snd_cmipci_ch_reset(cm, CM_CH_PLAY);
-               snd_cmipci_ch_reset(cm, CM_CH_CAPT);
-               snd_cmipci_write(cm, CM_REG_FUNCTRL0, 0); /* disable channels */
-               snd_cmipci_write(cm, CM_REG_FUNCTRL1, 0);
+       struct cmipci *cm = card->private_data;
 
-               /* reset mixer */
-               snd_cmipci_mixer_write(cm, 0, 0);
+       snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN);
+       snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT);
+       snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0);  /* disable ints */
+       snd_cmipci_ch_reset(cm, CM_CH_PLAY);
+       snd_cmipci_ch_reset(cm, CM_CH_CAPT);
+       snd_cmipci_write(cm, CM_REG_FUNCTRL0, 0); /* disable channels */
+       snd_cmipci_write(cm, CM_REG_FUNCTRL1, 0);
 
-               free_irq(cm->irq, cm);
-       }
+       /* reset mixer */
+       snd_cmipci_mixer_write(cm, 0, 0);
 
        snd_cmipci_free_gameport(cm);
-       pci_release_regions(cm->pci);
-       pci_disable_device(cm->pci);
-       kfree(cm);
-       return 0;
-}
-
-static int snd_cmipci_dev_free(struct snd_device *device)
-{
-       struct cmipci *cm = device->device_data;
-       return snd_cmipci_free(cm);
 }
 
 static int snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
@@ -2988,13 +2973,10 @@ static int snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
 }
 
 static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
-                            int dev, struct cmipci **rcmipci)
+                            int dev)
 {
-       struct cmipci *cm;
+       struct cmipci *cm = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_cmipci_dev_free,
-       };
        unsigned int val;
        long iomidi = 0;
        int integrated_midi = 0;
@@ -3005,18 +2987,10 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
                { },
        };
 
-       *rcmipci = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       cm = kzalloc(sizeof(*cm), GFP_KERNEL);
-       if (cm == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&cm->reg_lock);
        mutex_init(&cm->open_mutex);
        cm->device = pci->device;
@@ -3028,21 +3002,18 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
        cm->channel[0].is_dac = cm->channel[1].is_dac = 1; /* dual DAC mode */
 
        err = pci_request_regions(pci, card->driver);
-       if (err < 0) {
-               kfree(cm);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        cm->iobase = pci_resource_start(pci, 0);
 
-       if (request_irq(pci->irq, snd_cmipci_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, cm)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_cmipci_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, cm)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_cmipci_free(cm);
                return -EBUSY;
        }
        cm->irq = pci->irq;
        card->sync_irq = cm->irq;
+       card->private_free = snd_cmipci_free;
 
        pci_set_master(cm->pci);
 
@@ -3142,12 +3113,6 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
        sprintf(card->longname, "%s%s at %#lx, irq %i",
                card->shortname, modelstr, cm->iobase, cm->irq);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cm, &ops);
-       if (err < 0) {
-               snd_cmipci_free(cm);
-               return err;
-       }
-
        if (cm->chip_version >= 39) {
                val = snd_cmipci_read_b(cm, CM_REG_MPU_PCI + 1);
                if (val != 0x00 && val != 0xff) {
@@ -3240,7 +3205,6 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
        if (snd_cmipci_create_gameport(cm, dev) < 0)
                snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
 
-       *rcmipci = cm;
        return 0;
 }
 
@@ -3264,10 +3228,11 @@ static int snd_cmipci_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*cm), &card);
        if (err < 0)
                return err;
+       cm = card->private_data;
        
        switch (pci->device) {
        case PCI_DEVICE_ID_CMEDIA_CM8738:
@@ -3283,31 +3248,19 @@ static int snd_cmipci_probe(struct pci_dev *pci,
                break;
        }
 
-       err = snd_cmipci_create(card, pci, dev, &cm);
+       err = snd_cmipci_create(card, pci, dev);
        if (err < 0)
-               goto free_card;
-
-       card->private_data = cm;
+               return err;
 
        err = snd_card_register(card);
        if (err < 0)
-               goto free_card;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
-free_card:
-       snd_card_free(card);
-       return err;
 }
 
-static void snd_cmipci_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
-
 #ifdef CONFIG_PM_SLEEP
 /*
  * power management
@@ -3382,7 +3335,6 @@ static struct pci_driver cmipci_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cmipci_ids,
        .probe = snd_cmipci_probe,
-       .remove = snd_cmipci_remove,
        .driver = {
                .pm = SND_CMIPCI_PM_OPS,
        },
index e122a16..e736740 100644 (file)
@@ -1268,8 +1268,10 @@ static inline int snd_cs4281_create_gameport(struct cs4281 *chip) { return -ENOS
 static inline void snd_cs4281_free_gameport(struct cs4281 *chip) { }
 #endif /* IS_REACHABLE(CONFIG_GAMEPORT) */
 
-static int snd_cs4281_free(struct cs4281 *chip)
+static void snd_cs4281_free(struct snd_card *card)
 {
+       struct cs4281 *chip = card->private_data;
+
        snd_cs4281_free_gameport(chip);
 
        /* Mask interrupts */
@@ -1278,49 +1280,20 @@ static int snd_cs4281_free(struct cs4281 *chip)
        snd_cs4281_pokeBA0(chip, BA0_CLKCR1, 0);
        /* Sound System Power Management - Turn Everything OFF */
        snd_cs4281_pokeBA0(chip, BA0_SSPM, 0);
-       /* PCI interface - D3 state */
-       pci_set_power_state(chip->pci, PCI_D3hot);
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       iounmap(chip->ba0);
-       iounmap(chip->ba1);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-
-       kfree(chip);
-       return 0;
-}
-
-static int snd_cs4281_dev_free(struct snd_device *device)
-{
-       struct cs4281 *chip = device->device_data;
-       return snd_cs4281_free(chip);
 }
 
 static int snd_cs4281_chip_init(struct cs4281 *chip); /* defined below */
 
 static int snd_cs4281_create(struct snd_card *card,
                             struct pci_dev *pci,
-                            struct cs4281 **rchip,
                             int dual_codec)
 {
-       struct cs4281 *chip;
-       unsigned int tmp;
+       struct cs4281 *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_cs4281_dev_free,
-       };
 
-       *rchip = NULL;
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&chip->reg_lock);
        chip->card = card;
        chip->pci = pci;
@@ -1332,46 +1305,29 @@ static int snd_cs4281_create(struct snd_card *card,
        }
        chip->dual_codec = dual_codec;
 
-       err = pci_request_regions(pci, "CS4281");
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       err = pcim_iomap_regions(pci, 0x03, "CS4281"); /* 2 BARs */
+       if (err < 0)
                return err;
-       }
        chip->ba0_addr = pci_resource_start(pci, 0);
        chip->ba1_addr = pci_resource_start(pci, 1);
 
-       chip->ba0 = pci_ioremap_bar(pci, 0);
-       chip->ba1 = pci_ioremap_bar(pci, 1);
-       if (!chip->ba0 || !chip->ba1) {
-               snd_cs4281_free(chip);
-               return -ENOMEM;
-       }
+       chip->ba0 = pcim_iomap_table(pci)[0];
+       chip->ba1 = pcim_iomap_table(pci)[1];
        
-       if (request_irq(pci->irq, snd_cs4281_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_cs4281_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_cs4281_free(chip);
                return -ENOMEM;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_cs4281_free;
 
-       tmp = snd_cs4281_chip_init(chip);
-       if (tmp) {
-               snd_cs4281_free(chip);
-               return tmp;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_cs4281_free(chip);
+       err = snd_cs4281_chip_init(chip);
+       if (err)
                return err;
-       }
 
        snd_cs4281_proc_init(chip);
-
-       *rchip = chip;
        return 0;
 }
 
@@ -1887,46 +1843,34 @@ static int snd_cs4281_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       err = snd_cs4281_create(card, pci, &chip, dual_codec[dev]);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_cs4281_create(card, pci, dual_codec[dev]);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        err = snd_cs4281_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_cs4281_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_cs4281_midi(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_opl3_new(card, OPL3_HW_OPL3_CS4281, &opl3);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        opl3->private_data = chip;
        opl3->command = snd_cs4281_opl3_command;
        snd_opl3_init(opl3);
        err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        snd_cs4281_create_gameport(chip);
        strcpy(card->driver, "CS4281");
        strcpy(card->shortname, "Cirrus Logic CS4281");
@@ -1936,21 +1880,14 @@ static int snd_cs4281_probe(struct pci_dev *pci,
                chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_cs4281_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 /*
  * Power Management
  */
@@ -2054,7 +1991,6 @@ static struct pci_driver cs4281_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cs4281_ids,
        .probe = snd_cs4281_probe,
-       .remove = snd_cs4281_remove,
        .driver = {
                .pm = CS4281_PM_OPS,
        },
index 358ca84..bd60308 100644 (file)
@@ -66,61 +66,44 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
        err = snd_cs46xx_create(card, pci,
-                               external_amp[dev], thinkpad[dev],
-                               &chip);
-       if (err < 0) {
-               snd_card_free(card);
+                               external_amp[dev], thinkpad[dev]);
+       if (err < 0)
                return err;
-       }
        card->private_data = chip;
        chip->accept_valid = mmap_valid[dev];
        err = snd_cs46xx_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        err = snd_cs46xx_pcm_rear(chip, 1);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_cs46xx_pcm_iec958(chip, 2);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #endif
        err = snd_cs46xx_mixer(chip, 2);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        if (chip->nr_ac97_codecs ==2) {
                err = snd_cs46xx_pcm_center_lfe(chip, 3);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 #endif
        err = snd_cs46xx_midi(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_cs46xx_start_dsp(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
-
 
        snd_cs46xx_gameport(chip);
 
@@ -133,26 +116,18 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci,
                chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_card_cs46xx_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver cs46xx_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cs46xx_ids,
        .probe = snd_card_cs46xx_probe,
-       .remove = snd_card_cs46xx_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &snd_cs46xx_pm,
index b275df8..c4f0a0b 100644 (file)
@@ -1635,7 +1635,6 @@ struct snd_cs46xx_region {
        unsigned long base;
        void __iomem *remap_addr;
        unsigned long size;
-       struct resource *resource;
 };
 
 struct snd_cs46xx {
@@ -1718,8 +1717,7 @@ struct snd_cs46xx {
 
 int snd_cs46xx_create(struct snd_card *card,
                      struct pci_dev *pci,
-                     int external_amp, int thinkpad,
-                     struct snd_cs46xx **rcodec);
+                     int external_amp, int thinkpad);
 extern const struct dev_pm_ops snd_cs46xx_pm;
 
 int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device);
index 1e1eb17..62f4584 100644 (file)
@@ -1121,9 +1121,7 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream,
        if (params_periods(hw_params) == CS46XX_FRAGS) {
                if (runtime->dma_area != cpcm->hw_buf.area)
                        snd_pcm_lib_free_pages(substream);
-               runtime->dma_area = cpcm->hw_buf.area;
-               runtime->dma_addr = cpcm->hw_buf.addr;
-               runtime->dma_bytes = cpcm->hw_buf.bytes;
+               snd_pcm_set_runtime_buffer(substream, &cpcm->hw_buf);
 
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -1143,11 +1141,8 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream,
 #endif
 
        } else {
-               if (runtime->dma_area == cpcm->hw_buf.area) {
-                       runtime->dma_area = NULL;
-                       runtime->dma_addr = 0;
-                       runtime->dma_bytes = 0;
-               }
+               if (runtime->dma_area == cpcm->hw_buf.area)
+                       snd_pcm_set_runtime_buffer(substream, NULL);
                err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
                if (err < 0) {
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -1196,9 +1191,7 @@ static int snd_cs46xx_playback_hw_free(struct snd_pcm_substream *substream)
        if (runtime->dma_area != cpcm->hw_buf.area)
                snd_pcm_lib_free_pages(substream);
     
-       runtime->dma_area = NULL;
-       runtime->dma_addr = 0;
-       runtime->dma_bytes = 0;
+       snd_pcm_set_runtime_buffer(substream, NULL);
 
        return 0;
 }
@@ -1287,16 +1280,11 @@ static int snd_cs46xx_capture_hw_params(struct snd_pcm_substream *substream,
        if (runtime->periods == CS46XX_FRAGS) {
                if (runtime->dma_area != chip->capt.hw_buf.area)
                        snd_pcm_lib_free_pages(substream);
-               runtime->dma_area = chip->capt.hw_buf.area;
-               runtime->dma_addr = chip->capt.hw_buf.addr;
-               runtime->dma_bytes = chip->capt.hw_buf.bytes;
+               snd_pcm_set_runtime_buffer(substream, &chip->capt.hw_buf);
                substream->ops = &snd_cs46xx_capture_ops;
        } else {
-               if (runtime->dma_area == chip->capt.hw_buf.area) {
-                       runtime->dma_area = NULL;
-                       runtime->dma_addr = 0;
-                       runtime->dma_bytes = 0;
-               }
+               if (runtime->dma_area == chip->capt.hw_buf.area)
+                       snd_pcm_set_runtime_buffer(substream, NULL);
                err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
                if (err < 0)
                        return err;
@@ -1313,9 +1301,7 @@ static int snd_cs46xx_capture_hw_free(struct snd_pcm_substream *substream)
 
        if (runtime->dma_area != chip->capt.hw_buf.area)
                snd_pcm_lib_free_pages(substream);
-       runtime->dma_area = NULL;
-       runtime->dma_addr = 0;
-       runtime->dma_bytes = 0;
+       snd_pcm_set_runtime_buffer(substream, NULL);
 
        return 0;
 }
@@ -1865,13 +1851,6 @@ int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device)
 /*
  *  Mixer routines
  */
-static void snd_cs46xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
-{
-       struct snd_cs46xx *chip = bus->private_data;
-
-       chip->ac97_bus = NULL;
-}
-
 static void snd_cs46xx_mixer_free_ac97(struct snd_ac97 *ac97)
 {
        struct snd_cs46xx *chip = ac97->private_data;
@@ -2487,7 +2466,6 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
        err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus);
        if (err < 0)
                return err;
-       chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;
 
        if (cs46xx_detect_codec(chip, CS46XX_PRIMARY_CODEC_INDEX) < 0)
                return -ENXIO;
@@ -2913,12 +2891,12 @@ static void snd_cs46xx_hw_stop(struct snd_cs46xx *chip)
 }
 
 
-static int snd_cs46xx_free(struct snd_cs46xx *chip)
+static void snd_cs46xx_free(struct snd_card *card)
 {
+       struct snd_cs46xx *chip = card->private_data;
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
        int idx;
-
-       if (snd_BUG_ON(!chip))
-               return -EINVAL;
+#endif
 
        if (chip->active_ctrl)
                chip->active_ctrl(chip, 1);
@@ -2930,22 +2908,11 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
        
        snd_cs46xx_proc_done(chip);
 
-       if (chip->region.idx[0].resource)
-               snd_cs46xx_hw_stop(chip);
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
+       snd_cs46xx_hw_stop(chip);
 
        if (chip->active_ctrl)
                chip->active_ctrl(chip, -chip->amplifier);
 
-       for (idx = 0; idx < 5; idx++) {
-               struct snd_cs46xx_region *region = &chip->region.idx[idx];
-
-               iounmap(region->remap_addr);
-               release_and_free_resource(region->resource);
-       }
-
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        if (chip->dsp_spos_instance) {
                cs46xx_dsp_spos_destroy(chip);
@@ -2956,20 +2923,6 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
 #else
        vfree(chip->ba1);
 #endif
-       
-#ifdef CONFIG_PM_SLEEP
-       kfree(chip->saved_regs);
-#endif
-
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_cs46xx_dev_free(struct snd_device *device)
-{
-       struct snd_cs46xx *chip = device->device_data;
-       return snd_cs46xx_free(chip);
 }
 
 /*
@@ -3868,30 +3821,19 @@ SIMPLE_DEV_PM_OPS(snd_cs46xx_pm, snd_cs46xx_suspend, snd_cs46xx_resume);
 
 int snd_cs46xx_create(struct snd_card *card,
                      struct pci_dev *pci,
-                     int external_amp, int thinkpad,
-                     struct snd_cs46xx **rchip)
+                     int external_amp, int thinkpad)
 {
-       struct snd_cs46xx *chip;
+       struct snd_cs46xx *chip = card->private_data;
        int err, idx;
        struct snd_cs46xx_region *region;
        struct cs_card_type *cp;
        u16 ss_card, ss_vendor;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_cs46xx_dev_free,
-       };
        
-       *rchip = NULL;
-
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&chip->reg_lock);
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        mutex_init(&chip->spos_mutex);
@@ -3899,6 +3841,10 @@ int snd_cs46xx_create(struct snd_card *card,
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
+
+       err = pci_request_regions(pci, "CS46xx");
+       if (err < 0)
+               return err;
        chip->ba0_addr = pci_resource_start(pci, 0);
        chip->ba1_addr = pci_resource_start(pci, 1);
        if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 ||
@@ -3906,7 +3852,6 @@ int snd_cs46xx_create(struct snd_card *card,
                dev_err(chip->card->dev,
                        "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n",
                           chip->ba0_addr, chip->ba1_addr);
-               snd_cs46xx_free(chip);
                return -ENOMEM;
        }
 
@@ -3978,67 +3923,45 @@ int snd_cs46xx_create(struct snd_card *card,
 
        for (idx = 0; idx < 5; idx++) {
                region = &chip->region.idx[idx];
-               region->resource = request_mem_region(region->base, region->size,
-                                                     region->name);
-               if (!region->resource) {
-                       dev_err(chip->card->dev,
-                               "unable to request memory region 0x%lx-0x%lx\n",
-                                  region->base, region->base + region->size - 1);
-                       snd_cs46xx_free(chip);
-                       return -EBUSY;
-               }
-               region->remap_addr = ioremap(region->base, region->size);
+               region->remap_addr = devm_ioremap(&pci->dev, region->base,
+                                                 region->size);
                if (region->remap_addr == NULL) {
                        dev_err(chip->card->dev,
                                "%s ioremap problem\n", region->name);
-                       snd_cs46xx_free(chip);
                        return -ENOMEM;
                }
        }
 
-       if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_cs46xx_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_cs46xx_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_cs46xx_free;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        chip->dsp_spos_instance = cs46xx_dsp_spos_create(chip);
-       if (chip->dsp_spos_instance == NULL) {
-               snd_cs46xx_free(chip);
+       if (!chip->dsp_spos_instance)
                return -ENOMEM;
-       }
 #endif
 
        err = snd_cs46xx_chip_init(chip);
-       if (err < 0) {
-               snd_cs46xx_free(chip);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_cs46xx_free(chip);
+       if (err < 0)
                return err;
-       }
        
        snd_cs46xx_proc_init(card, chip);
 
 #ifdef CONFIG_PM_SLEEP
-       chip->saved_regs = kmalloc_array(ARRAY_SIZE(saved_regs),
-                                        sizeof(*chip->saved_regs),
-                                        GFP_KERNEL);
-       if (!chip->saved_regs) {
-               snd_cs46xx_free(chip);
+       chip->saved_regs = devm_kmalloc_array(&pci->dev,
+                                             ARRAY_SIZE(saved_regs),
+                                             sizeof(*chip->saved_regs),
+                                             GFP_KERNEL);
+       if (!chip->saved_regs)
                return -ENOMEM;
-       }
 #endif
 
        chip->active_ctrl(chip, -1); /* disable CLKRUN */
-
-       *rchip = chip;
        return 0;
 }
index 20b4fae..93ff029 100644 (file)
@@ -65,25 +65,6 @@ static const struct pci_device_id snd_cs5530_ids[] = {
 
 MODULE_DEVICE_TABLE(pci, snd_cs5530_ids);
 
-static int snd_cs5530_free(struct snd_cs5530 *chip)
-{
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_cs5530_dev_free(struct snd_device *device)
-{
-       struct snd_cs5530 *chip = device->device_data;
-       return snd_cs5530_free(chip);
-}
-
-static void snd_cs5530_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static u8 snd_cs5530_mixer_read(unsigned long io, u8 reg)
 {
        outb(reg, io + 4);
@@ -94,50 +75,28 @@ static u8 snd_cs5530_mixer_read(unsigned long io, u8 reg)
 }
 
 static int snd_cs5530_create(struct snd_card *card,
-                            struct pci_dev *pci,
-                            struct snd_cs5530 **rchip)
+                            struct pci_dev *pci)
 {
-       struct snd_cs5530 *chip;
+       struct snd_cs5530 *chip = card->private_data;
        unsigned long sb_base;
        u8 irq, dma8, dma16 = 0;
        u16 map;
        void __iomem *mem;
        int err;
 
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_cs5530_dev_free,
-       };
-       *rchip = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
        chip->pci = pci;
 
-       err = pci_request_regions(pci, "CS5530");
-       if (err < 0) {
-               kfree(chip); 
-               pci_disable_device(pci);
+       err = pcim_iomap_regions(pci, 1 << 0, "CS5530");
+       if (err < 0)
                return err;
-       }
        chip->pci_base = pci_resource_start(pci, 0);
-
-       mem = pci_ioremap_bar(pci, 0);
-       if (mem == NULL) {
-               snd_cs5530_free(chip);
-               return -EBUSY;
-       }
-
+       mem = pcim_iomap_table(pci)[0];
        map = readw(mem + 0x18);
-       iounmap(mem);
 
        /* Map bits
                0:1     * 0x20 + 0x200 = sb base
@@ -154,7 +113,6 @@ static int snd_cs5530_create(struct snd_card *card,
                dev_info(card->dev, "XpressAudio at 0x%lx\n", sb_base);
        else {
                dev_err(card->dev, "Could not find XpressAudio!\n");
-               snd_cs5530_free(chip);
                return -ENODEV;
        }
 
@@ -174,7 +132,6 @@ static int snd_cs5530_create(struct snd_card *card,
                dma16 = 7;
        else {
                dev_err(card->dev, "No 16bit DMA enabled\n");
-               snd_cs5530_free(chip);
                return -ENODEV;
        }
 
@@ -186,7 +143,6 @@ static int snd_cs5530_create(struct snd_card *card,
                dma8 = 3;
        else {
                dev_err(card->dev, "No 8bit DMA enabled\n");
-               snd_cs5530_free(chip);
                return -ENODEV;
        }
 
@@ -200,7 +156,6 @@ static int snd_cs5530_create(struct snd_card *card,
                irq = 10;
        else {
                dev_err(card->dev, "SoundBlaster IRQ not set\n");
-               snd_cs5530_free(chip);
                return -ENODEV;
        }
 
@@ -210,31 +165,21 @@ static int snd_cs5530_create(struct snd_card *card,
                                                dma16, SB_HW_CS5530, &chip->sb);
        if (err < 0) {
                dev_err(card->dev, "Could not create SoundBlaster\n");
-               snd_cs5530_free(chip);
                return err;
        }
 
        err = snd_sb16dsp_pcm(chip->sb, 0);
        if (err < 0) {
                dev_err(card->dev, "Could not create PCM\n");
-               snd_cs5530_free(chip);
                return err;
        }
 
        err = snd_sbmixer_new(chip->sb);
        if (err < 0) {
                dev_err(card->dev, "Could not create Mixer\n");
-               snd_cs5530_free(chip);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_cs5530_free(chip);
                return err;
        }
 
-       *rchip = chip;
        return 0;
 }
 
@@ -243,7 +188,7 @@ static int snd_cs5530_probe(struct pci_dev *pci,
 {
        static int dev;
        struct snd_card *card;
-       struct snd_cs5530 *chip = NULL;
+       struct snd_cs5530 *chip;
        int err;
 
        if (dev >= SNDRV_CARDS)
@@ -253,27 +198,23 @@ static int snd_cs5530_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
-
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       err = snd_cs5530_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_cs5530_create(card, pci);
+       if (err < 0)
                return err;
-       }
 
        strcpy(card->driver, "CS5530");
        strcpy(card->shortname, "CS5530 Audio");
        sprintf(card->longname, "%s at 0x%lx", card->shortname, chip->pci_base);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
@@ -283,7 +224,6 @@ static struct pci_driver cs5530_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cs5530_ids,
        .probe = snd_cs5530_probe,
-       .remove = snd_cs5530_remove,
 };
 
 module_pci_driver(cs5530_driver);
index e048b45..499fa01 100644 (file)
@@ -237,51 +237,24 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int snd_cs5535audio_free(struct cs5535audio *cs5535au)
+static void snd_cs5535audio_free(struct snd_card *card)
 {
-       pci_set_power_state(cs5535au->pci, PCI_D3hot);
-
-       if (cs5535au->irq >= 0)
-               free_irq(cs5535au->irq, cs5535au);
-
-       pci_release_regions(cs5535au->pci);
-       pci_disable_device(cs5535au->pci);
-       kfree(cs5535au);
-       return 0;
-}
-
-static int snd_cs5535audio_dev_free(struct snd_device *device)
-{
-       struct cs5535audio *cs5535au = device->device_data;
-       return snd_cs5535audio_free(cs5535au);
+       olpc_quirks_cleanup();
 }
 
 static int snd_cs5535audio_create(struct snd_card *card,
-                                 struct pci_dev *pci,
-                                 struct cs5535audio **rcs5535au)
+                                 struct pci_dev *pci)
 {
-       struct cs5535audio *cs5535au;
-
+       struct cs5535audio *cs5535au = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_cs5535audio_dev_free,
-       };
 
-       *rcs5535au = NULL;
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_warn(card->dev, "unable to get 32bit dma\n");
-               err = -ENXIO;
-               goto pcifail;
-       }
-
-       cs5535au = kzalloc(sizeof(*cs5535au), GFP_KERNEL);
-       if (cs5535au == NULL) {
-               err = -ENOMEM;
-               goto pcifail;
+               return -ENXIO;
        }
 
        spin_lock_init(&cs5535au->reg_lock);
@@ -290,38 +263,22 @@ static int snd_cs5535audio_create(struct snd_card *card,
        cs5535au->irq = -1;
 
        err = pci_request_regions(pci, "CS5535 Audio");
-       if (err < 0) {
-               kfree(cs5535au);
-               goto pcifail;
-       }
+       if (err < 0)
+               return err;
 
        cs5535au->port = pci_resource_start(pci, 0);
 
-       if (request_irq(pci->irq, snd_cs5535audio_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, cs5535au)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_cs5535audio_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, cs5535au)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               err = -EBUSY;
-               goto sndfail;
+               return -EBUSY;
        }
 
        cs5535au->irq = pci->irq;
        card->sync_irq = cs5535au->irq;
        pci_set_master(pci);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cs5535au, &ops);
-       if (err < 0)
-               goto sndfail;
-
-       *rcs5535au = cs5535au;
        return 0;
-
-sndfail: /* leave the device alive, just kill the snd */
-       snd_cs5535audio_free(cs5535au);
-       return err;
-
-pcifail:
-       pci_disable_device(pci);
-       return err;
 }
 
 static int snd_cs5535audio_probe(struct pci_dev *pci,
@@ -339,24 +296,24 @@ static int snd_cs5535audio_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*cs5535au), &card);
        if (err < 0)
                return err;
+       cs5535au = card->private_data;
+       card->private_free = snd_cs5535audio_free;
 
-       err = snd_cs5535audio_create(card, pci, &cs5535au);
+       err = snd_cs5535audio_create(card, pci);
        if (err < 0)
-               goto probefail_out;
-
-       card->private_data = cs5535au;
+               return err;
 
        err = snd_cs5535audio_mixer(cs5535au);
        if (err < 0)
-               goto probefail_out;
+               return err;
 
        err = snd_cs5535audio_pcm(cs5535au);
        if (err < 0)
-               goto probefail_out;
+               return err;
 
        strcpy(card->driver, DRIVER_NAME);
 
@@ -367,28 +324,17 @@ static int snd_cs5535audio_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto probefail_out;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
-probefail_out:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_cs5535audio_remove(struct pci_dev *pci)
-{
-       olpc_quirks_cleanup();
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver cs5535audio_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cs5535audio_ids,
        .probe = snd_cs5535audio_probe,
-       .remove = snd_cs5535audio_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &snd_cs5535audio_pm,
index 110d320..122170a 100644 (file)
@@ -171,10 +171,8 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
        for (i = 0; i < ARRAY_SIZE(olpc_cs5535audio_ctls); i++) {
                err = snd_ctl_add(card, snd_ctl_new1(&olpc_cs5535audio_ctls[i],
                                ac97->private_data));
-               if (err < 0) {
-                       gpio_free(OLPC_GPIO_MIC_AC);
+               if (err < 0)
                        return err;
-               }
        }
 
        /* turn off the mic by default */
@@ -184,5 +182,6 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
 
 void olpc_quirks_cleanup(void)
 {
-       gpio_free(OLPC_GPIO_MIC_AC);
+       if (machine_is_olpc())
+               gpio_free(OLPC_GPIO_MIC_AC);
 }
index a62e558..25b012e 100644 (file)
@@ -1882,105 +1882,63 @@ static irqreturn_t snd_echo_interrupt(int irq, void *dev_id)
        Module construction / destruction
 ******************************************************************************/
 
-static int snd_echo_free(struct echoaudio *chip)
+static void snd_echo_free(struct snd_card *card)
 {
+       struct echoaudio *chip = card->private_data;
+
        if (chip->comm_page)
                rest_in_peace(chip);
 
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
 
-       if (chip->comm_page)
-               snd_dma_free_pages(&chip->commpage_dma_buf);
-
-       iounmap(chip->dsp_registers);
-       release_and_free_resource(chip->iores);
-       pci_disable_device(chip->pci);
-
        /* release chip data */
        free_firmware_cache(chip);
-       kfree(chip);
-       return 0;
-}
-
-
-
-static int snd_echo_dev_free(struct snd_device *device)
-{
-       struct echoaudio *chip = device->device_data;
-
-       return snd_echo_free(chip);
 }
 
-
-
 /* <--snd_echo_probe() */
 static int snd_echo_create(struct snd_card *card,
-                          struct pci_dev *pci,
-                          struct echoaudio **rchip)
+                          struct pci_dev *pci)
 {
-       struct echoaudio *chip;
+       struct echoaudio *chip = card->private_data;
        int err;
        size_t sz;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_echo_dev_free,
-       };
-
-       *rchip = NULL;
 
        pci_write_config_byte(pci, PCI_LATENCY_TIMER, 0xC0);
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        pci_set_master(pci);
 
        /* Allocate chip if needed */
-       if (!*rchip) {
-               chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-               if (!chip) {
-                       pci_disable_device(pci);
-                       return -ENOMEM;
-               }
-               dev_dbg(card->dev, "chip=%p\n", chip);
-               spin_lock_init(&chip->lock);
-               chip->card = card;
-               chip->pci = pci;
-               chip->irq = -1;
-               chip->opencount = 0;
-               mutex_init(&chip->mode_mutex);
-               chip->can_set_rate = 1;
-       } else {
-               /* If this was called from the resume function, chip is
-                * already allocated and it contains current card settings.
-                */
-               chip = *rchip;
-       }
+       spin_lock_init(&chip->lock);
+       chip->card = card;
+       chip->pci = pci;
+       chip->irq = -1;
+       chip->opencount = 0;
+       mutex_init(&chip->mode_mutex);
+       chip->can_set_rate = 1;
 
        /* PCI resource allocation */
+       err = pci_request_regions(pci, ECHOCARD_NAME);
+       if (err < 0)
+               return err;
+
        chip->dsp_registers_phys = pci_resource_start(pci, 0);
        sz = pci_resource_len(pci, 0);
        if (sz > PAGE_SIZE)
                sz = PAGE_SIZE;         /* We map only the required part */
 
-       chip->iores = request_mem_region(chip->dsp_registers_phys, sz,
-                                        ECHOCARD_NAME);
-       if (!chip->iores) {
-               dev_err(chip->card->dev, "cannot get memory region\n");
-               snd_echo_free(chip);
-               return -EBUSY;
-       }
-       chip->dsp_registers = ioremap(chip->dsp_registers_phys, sz);
+       chip->dsp_registers = devm_ioremap(&pci->dev, chip->dsp_registers_phys, sz);
        if (!chip->dsp_registers) {
                dev_err(chip->card->dev, "ioremap failed\n");
-               snd_echo_free(chip);
                return -ENOMEM;
        }
 
        if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED,
                        KBUILD_MODNAME, chip)) {
                dev_err(chip->card->dev, "cannot grab irq\n");
-               snd_echo_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
@@ -1988,39 +1946,29 @@ static int snd_echo_create(struct snd_card *card,
        dev_dbg(card->dev, "pci=%p irq=%d subdev=%04x Init hardware...\n",
                chip->pci, chip->irq, chip->pci->subsystem_device);
 
+       card->private_free = snd_echo_free;
+
        /* Create the DSP comm page - this is the area of memory used for most
        of the communication with the DSP, which accesses it via bus mastering */
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
-                               sizeof(struct comm_page),
-                               &chip->commpage_dma_buf) < 0) {
-               dev_err(chip->card->dev, "cannot allocate the comm page\n");
-               snd_echo_free(chip);
+       chip->commpage_dma_buf =
+               snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+                                    sizeof(struct comm_page));
+       if (!chip->commpage_dma_buf)
                return -ENOMEM;
-       }
-       chip->comm_page_phys = chip->commpage_dma_buf.addr;
-       chip->comm_page = (struct comm_page *)chip->commpage_dma_buf.area;
+       chip->comm_page_phys = chip->commpage_dma_buf->addr;
+       chip->comm_page = (struct comm_page *)chip->commpage_dma_buf->area;
 
        err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device);
        if (err >= 0)
                err = set_mixer_defaults(chip);
        if (err < 0) {
                dev_err(card->dev, "init_hw err=%d\n", err);
-               snd_echo_free(chip);
                return err;
        }
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_echo_free(chip);
-               return err;
-       }
-       *rchip = chip;
-       /* Init done ! */
        return 0;
 }
 
-
-
 /* constructor */
 static int snd_echo_probe(struct pci_dev *pci,
                          const struct pci_device_id *pci_id)
@@ -2040,17 +1988,15 @@ static int snd_echo_probe(struct pci_dev *pci,
        }
 
        i = 0;
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       chip = NULL;    /* Tells snd_echo_create to allocate chip */
-       err = snd_echo_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_echo_create(card, pci);
+       if (err < 0)
                return err;
-       }
 
        strcpy(card->driver, "Echo_" ECHOCARD_NAME);
        strcpy(card->shortname, chip->card_name);
@@ -2066,7 +2012,6 @@ static int snd_echo_probe(struct pci_dev *pci,
        err = snd_echo_new_pcm(chip);
        if (err < 0) {
                dev_err(chip->card->dev, "new pcm error %d\n", err);
-               snd_card_free(card);
                return err;
        }
 
@@ -2075,7 +2020,6 @@ static int snd_echo_probe(struct pci_dev *pci,
                err = snd_echo_midi_create(card, chip);
                if (err < 0) {
                        dev_err(chip->card->dev, "new midi error %d\n", err);
-                       snd_card_free(card);
                        return err;
                }
        }
@@ -2085,64 +2029,64 @@ static int snd_echo_probe(struct pci_dev *pci,
        snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip);
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #ifdef ECHOCARD_HAS_LINE_OUT_GAIN
        err = snd_ctl_add(chip->card,
                          snd_ctl_new1(&snd_echo_line_output_gain, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif
 #else /* ECHOCARD_HAS_VMIXER */
        err = snd_ctl_add(chip->card,
                          snd_ctl_new1(&snd_echo_pcm_output_gain, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif /* ECHOCARD_HAS_VMIXER */
 
 #ifdef ECHOCARD_HAS_INPUT_GAIN
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_input_gain, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif
 
 #ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
        if (!chip->hasnt_input_nominal_level) {
                err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_intput_nominal_level, chip));
                if (err < 0)
-                       goto ctl_error;
+                       return err;
        }
 #endif
 
 #ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_output_nominal_level, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif
 
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters_switch, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 
 #ifdef ECHOCARD_HAS_MONITOR
        snd_echo_monitor_mixer.count = num_busses_in(chip) * num_busses_out(chip);
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_monitor_mixer, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif
 
 #ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_automute_switch, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif
 
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_channels_info, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 
 #ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH
        /* Creates a list of available digital modes */
@@ -2153,7 +2097,7 @@ static int snd_echo_probe(struct pci_dev *pci,
 
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_digital_mode_switch, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */
 
 #ifdef ECHOCARD_HAS_EXTERNAL_CLOCK
@@ -2167,37 +2111,32 @@ static int snd_echo_probe(struct pci_dev *pci,
                chip->clock_src_ctl = snd_ctl_new1(&snd_echo_clock_source_switch, chip);
                err = snd_ctl_add(chip->card, chip->clock_src_ctl);
                if (err < 0)
-                       goto ctl_error;
+                       return err;
        }
 #endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */
 
 #ifdef ECHOCARD_HAS_DIGITAL_IO
        err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_spdif_mode_switch, chip));
        if (err < 0)
-               goto ctl_error;
+               return err;
 #endif
 
 #ifdef ECHOCARD_HAS_PHANTOM_POWER
        if (chip->has_phantom_power) {
                err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_phantom_power_switch, chip));
                if (err < 0)
-                       goto ctl_error;
+                       return err;
        }
 #endif
 
        err = snd_card_register(card);
        if (err < 0)
-               goto ctl_error;
+               return err;
        dev_info(card->dev, "Card registered: %s\n", card->longname);
 
        pci_set_drvdata(pci, chip);
        dev++;
        return 0;
-
-ctl_error:
-       dev_err(card->dev, "new control error %d\n", err);
-       snd_card_free(card);
-       return err;
 }
 
 
@@ -2299,18 +2238,6 @@ static SIMPLE_DEV_PM_OPS(snd_echo_pm, snd_echo_suspend, snd_echo_resume);
 #define SND_ECHO_PM_OPS        NULL
 #endif /* CONFIG_PM_SLEEP */
 
-
-static void snd_echo_remove(struct pci_dev *pci)
-{
-       struct echoaudio *chip;
-
-       chip = pci_get_drvdata(pci);
-       if (chip)
-               snd_card_free(chip->card);
-}
-
-
-
 /******************************************************************************
        Everything starts and ends here
 ******************************************************************************/
@@ -2320,7 +2247,6 @@ static struct pci_driver echo_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_echo_ids,
        .probe = snd_echo_probe,
-       .remove = snd_echo_remove,
        .driver = {
                .pm = SND_ECHO_PM_OPS,
        },
index 0afe13f..d51de3e 100644 (file)
@@ -348,7 +348,7 @@ struct echoaudio {
        struct pci_dev *pci;
        unsigned long dsp_registers_phys;
        struct resource *iores;
-       struct snd_dma_buffer commpage_dma_buf;
+       struct snd_dma_buffer *commpage_dma_buf;
        int irq;
 #ifdef ECHOCARD_HAS_MIDI
        struct snd_rawmidi *rmidi;
index 887bfb3..672af4b 100644 (file)
@@ -99,67 +99,67 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*emu), &card);
        if (err < 0)
                return err;
+       emu = card->private_data;
+
        if (max_buffer_size[dev] < 32)
                max_buffer_size[dev] = 32;
        else if (max_buffer_size[dev] > 1024)
                max_buffer_size[dev] = 1024;
        err = snd_emu10k1_create(card, pci, extin[dev], extout[dev],
                                 (long)max_buffer_size[dev] * 1024 * 1024,
-                                enable_ir[dev], subsystem[dev],
-                                &emu);
+                                enable_ir[dev], subsystem[dev]);
        if (err < 0)
-               goto error;
-       card->private_data = emu;
+               return err;
        emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f;
        err = snd_emu10k1_pcm(emu, 0);
        if (err < 0)
-               goto error;
+               return err;
        err = snd_emu10k1_pcm_mic(emu, 1);
        if (err < 0)
-               goto error;
+               return err;
        err = snd_emu10k1_pcm_efx(emu, 2);
        if (err < 0)
-               goto error;
+               return err;
        /* This stores the periods table. */
        if (emu->card_capabilities->ca0151_chip) { /* P16V */   
-               err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                                         1024, &emu->p16v_buffer);
-               if (err < 0)
-                       goto error;
+               emu->p16v_buffer =
+                       snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 1024);
+               if (!emu->p16v_buffer)
+                       return -ENOMEM;
        }
 
        err = snd_emu10k1_mixer(emu, 0, 3);
        if (err < 0)
-               goto error;
+               return err;
        
        err = snd_emu10k1_timer(emu, 0);
        if (err < 0)
-               goto error;
+               return err;
 
        err = snd_emu10k1_pcm_multi(emu, 3);
        if (err < 0)
-               goto error;
+               return err;
        if (emu->card_capabilities->ca0151_chip) { /* P16V */
                err = snd_p16v_pcm(emu, 4);
                if (err < 0)
-                       goto error;
+                       return err;
        }
        if (emu->audigy) {
                err = snd_emu10k1_audigy_midi(emu);
                if (err < 0)
-                       goto error;
+                       return err;
        } else {
                err = snd_emu10k1_midi(emu);
                if (err < 0)
-                       goto error;
+                       return err;
        }
        err = snd_emu10k1_fx8010_new(emu, 0);
        if (err < 0)
-               goto error;
+               return err;
 #ifdef ENABLE_SYNTH
        if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH,
                               sizeof(struct snd_emu10k1_synth_arg), &wave) < 0 ||
@@ -187,7 +187,7 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto error;
+               return err;
 
        if (emu->card_capabilities->emu_model)
                schedule_delayed_work(&emu->emu1010.firmware_work, 0);
@@ -195,18 +195,8 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
- error:
-       snd_card_free(card);
-       return err;
 }
 
-static void snd_card_emu10k1_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
-
 #ifdef CONFIG_PM_SLEEP
 static int snd_emu10k1_suspend(struct device *dev)
 {
@@ -263,7 +253,6 @@ static struct pci_driver emu10k1_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_emu10k1_ids,
        .probe = snd_card_emu10k1_probe,
-       .remove = snd_card_emu10k1_remove,
        .driver = {
                .pm = SND_EMU10K1_PM_OPS,
        },
index 24a2fd7..86cc1ca 100644 (file)
@@ -1242,8 +1242,10 @@ static int alloc_pm_buffer(struct snd_emu10k1 *emu);
 static void free_pm_buffer(struct snd_emu10k1 *emu);
 #endif
 
-static int snd_emu10k1_free(struct snd_emu10k1 *emu)
+static void snd_emu10k1_free(struct snd_card *card)
 {
+       struct snd_emu10k1 *emu = card->private_data;
+
        if (emu->port) {        /* avoid access to already used hardware */
                snd_emu10k1_fx8010_tram_setup(emu, 0);
                snd_emu10k1_done(emu);
@@ -1256,8 +1258,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
        cancel_delayed_work_sync(&emu->emu1010.firmware_work);
        release_firmware(emu->firmware);
        release_firmware(emu->dock_fw);
-       if (emu->irq >= 0)
-               free_irq(emu->irq, emu);
        snd_util_memhdr_free(emu->memhdr);
        if (emu->silent_page.area)
                snd_dma_free_pages(&emu->silent_page);
@@ -1268,19 +1268,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
 #ifdef CONFIG_PM_SLEEP
        free_pm_buffer(emu);
 #endif
-       if (emu->port)
-               pci_release_regions(emu->pci);
-       if (emu->card_capabilities->ca0151_chip) /* P16V */
-               snd_p16v_free(emu);
-       pci_disable_device(emu->pci);
-       kfree(emu);
-       return 0;
-}
-
-static int snd_emu10k1_dev_free(struct snd_device *device)
-{
-       struct snd_emu10k1 *emu = device->device_data;
-       return snd_emu10k1_free(emu);
 }
 
 static const struct snd_emu_chip_details emu_chip_details[] = {
@@ -1782,32 +1769,22 @@ int snd_emu10k1_create(struct snd_card *card,
                       unsigned short extout_mask,
                       long max_cache_bytes,
                       int enable_ir,
-                      uint subsystem,
-                      struct snd_emu10k1 **remu)
+                      uint subsystem)
 {
-       struct snd_emu10k1 *emu;
+       struct snd_emu10k1 *emu = card->private_data;
        int idx, err;
        int is_audigy;
        size_t page_table_size;
        __le32 *pgtbl;
        unsigned int silent_page;
        const struct snd_emu_chip_details *c;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_emu10k1_dev_free,
-       };
-
-       *remu = NULL;
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       emu = kzalloc(sizeof(*emu), GFP_KERNEL);
-       if (emu == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
+       card->private_free = snd_emu10k1_free;
        emu->card = card;
        spin_lock_init(&emu->reg_lock);
        spin_lock_init(&emu->emu_lock);
@@ -1850,8 +1827,6 @@ int snd_emu10k1_create(struct snd_card *card,
        }
        if (c->vendor == 0) {
                dev_err(card->dev, "emu10k1: Card not recognised\n");
-               kfree(emu);
-               pci_disable_device(pci);
                return -ENOENT;
        }
        emu->card_capabilities = c;
@@ -1883,8 +1858,6 @@ int snd_emu10k1_create(struct snd_card *card,
                dev_err(card->dev,
                        "architecture does not support PCI busmaster DMA with mask 0x%lx\n",
                        emu->dma_mask);
-               kfree(emu);
-               pci_disable_device(pci);
                return -ENXIO;
        }
        if (is_audigy)
@@ -1893,11 +1866,8 @@ int snd_emu10k1_create(struct snd_card *card,
                emu->gpr_base = FXGPREGBASE;
 
        err = pci_request_regions(pci, "EMU10K1");
-       if (err < 0) {
-               kfree(emu);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        emu->port = pci_resource_start(pci, 0);
 
        emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
@@ -1905,10 +1875,8 @@ int snd_emu10k1_create(struct snd_card *card,
        page_table_size = sizeof(u32) * (emu->address_mode ? MAXPAGES1 :
                                         MAXPAGES0);
        if (snd_emu10k1_alloc_pages_maybe_wider(emu, page_table_size,
-                                               &emu->ptb_pages) < 0) {
-               err = -ENOMEM;
-               goto error;
-       }
+                                               &emu->ptb_pages) < 0)
+               return -ENOMEM;
        dev_dbg(card->dev, "page table address range is %.8lx:%.8lx\n",
                (unsigned long)emu->ptb_pages.addr,
                (unsigned long)(emu->ptb_pages.addr + emu->ptb_pages.bytes));
@@ -1917,26 +1885,20 @@ int snd_emu10k1_create(struct snd_card *card,
                                                 emu->max_cache_pages));
        emu->page_addr_table = vmalloc(array_size(sizeof(unsigned long),
                                                  emu->max_cache_pages));
-       if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) {
-               err = -ENOMEM;
-               goto error;
-       }
+       if (!emu->page_ptr_table || !emu->page_addr_table)
+               return -ENOMEM;
 
        if (snd_emu10k1_alloc_pages_maybe_wider(emu, EMUPAGESIZE,
-                                               &emu->silent_page) < 0) {
-               err = -ENOMEM;
-               goto error;
-       }
+                                               &emu->silent_page) < 0)
+               return -ENOMEM;
        dev_dbg(card->dev, "silent page range is %.8lx:%.8lx\n",
                (unsigned long)emu->silent_page.addr,
                (unsigned long)(emu->silent_page.addr +
                                emu->silent_page.bytes));
 
        emu->memhdr = snd_util_memhdr_new(emu->max_cache_pages * PAGE_SIZE);
-       if (emu->memhdr == NULL) {
-               err = -ENOMEM;
-               goto error;
-       }
+       if (!emu->memhdr)
+               return -ENOMEM;
        emu->memhdr->block_extra_size = sizeof(struct snd_emu10k1_memblk) -
                sizeof(struct snd_util_memblk);
 
@@ -1954,18 +1916,16 @@ int snd_emu10k1_create(struct snd_card *card,
        if (emu->card_capabilities->ca_cardbus_chip) {
                err = snd_emu10k1_cardbus_init(emu);
                if (err < 0)
-                       goto error;
+                       return err;
        }
        if (emu->card_capabilities->ecard) {
                err = snd_emu10k1_ecard_init(emu);
                if (err < 0)
-                       goto error;
+                       return err;
        } else if (emu->card_capabilities->emu_model) {
                err = snd_emu10k1_emu1010_init(emu);
-               if (err < 0) {
-                       snd_emu10k1_free(emu);
+               if (err < 0)
                        return err;
-               }
        } else {
                /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
                        does not support this, it shouldn't do any harm */
@@ -1979,11 +1939,9 @@ int snd_emu10k1_create(struct snd_card *card,
        emu->fx8010.etram_pages.bytes = 0;
 
        /* irq handler must be registered after I/O ports are activated */
-       if (request_irq(pci->irq, snd_emu10k1_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, emu)) {
-               err = -EBUSY;
-               goto error;
-       }
+       if (devm_request_irq(&pci->dev, pci->irq, snd_emu10k1_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, emu))
+               return -EBUSY;
        emu->irq = pci->irq;
        card->sync_irq = emu->irq;
 
@@ -2022,33 +1980,23 @@ int snd_emu10k1_create(struct snd_card *card,
 
        err = snd_emu10k1_init(emu, enable_ir, 0);
        if (err < 0)
-               goto error;
+               return err;
 #ifdef CONFIG_PM_SLEEP
        err = alloc_pm_buffer(emu);
        if (err < 0)
-               goto error;
+               return err;
 #endif
 
        /*  Initialize the effect engine */
        err = snd_emu10k1_init_efx(emu);
        if (err < 0)
-               goto error;
+               return err;
        snd_emu10k1_audio_enable(emu);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops);
-       if (err < 0)
-               goto error;
-
 #ifdef CONFIG_SND_PROC_FS
        snd_emu10k1_proc_init(emu);
 #endif
-
-       *remu = emu;
        return 0;
-
- error:
-       snd_emu10k1_free(emu);
-       return err;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 89b0f38..c49c44d 100644 (file)
@@ -216,7 +216,6 @@ struct emu10k1x {
        struct pci_dev *pci;
 
        unsigned long port;
-       struct resource *res_port;
        int irq;
 
        unsigned char revision;         /* chip revision */
@@ -233,7 +232,7 @@ struct emu10k1x {
        struct emu10k1x_voice capture_voice;
        u32 spdif_bits[3]; // SPDIF out setup
 
-       struct snd_dma_buffer dma_buffer;
+       struct snd_dma_buffer *dma_buffer;
 
        struct emu10k1x_midi midi;
 };
@@ -442,7 +441,7 @@ static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct emu10k1x_pcm *epcm = runtime->private_data;
        int voice = epcm->voice->number;
-       u32 *table_base = (u32 *)(emu->dma_buffer.area+1024*voice);
+       u32 *table_base = (u32 *)(emu->dma_buffer->area+1024*voice);
        u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
        int i;
        
@@ -451,7 +450,7 @@ static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream)
                *table_base++=period_size_bytes<<16;
        }
 
-       snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_ADDR, voice, emu->dma_buffer.addr+1024*voice);
+       snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_ADDR, voice, emu->dma_buffer->addr+1024*voice);
        snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_SIZE, voice, (runtime->periods - 1) << 19);
        snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_PTR, voice, 0);
        snd_emu10k1x_ptr_write(emu, PLAYBACK_POINTER, voice, 0);
@@ -737,37 +736,15 @@ static int snd_emu10k1x_ac97(struct emu10k1x *chip)
        return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
 }
 
-static int snd_emu10k1x_free(struct emu10k1x *chip)
+static void snd_emu10k1x_free(struct snd_card *card)
 {
+       struct emu10k1x *chip = card->private_data;
+
        snd_emu10k1x_ptr_write(chip, TRIGGER_CHANNEL, 0, 0);
        // disable interrupts
        outl(0, chip->port + INTE);
        // disable audio
        outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
-
-       /* release the irq */
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-
-       // release the i/o port
-       release_and_free_resource(chip->res_port);
-
-       // release the DMA
-       if (chip->dma_buffer.area) {
-               snd_dma_free_pages(&chip->dma_buffer);
-       }
-
-       pci_disable_device(chip->pci);
-
-       // release the data
-       kfree(chip);
-       return 0;
-}
-
-static int snd_emu10k1x_dev_free(struct snd_device *device)
-{
-       struct emu10k1x *chip = device->device_data;
-       return snd_emu10k1x_free(chip);
 }
 
 static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id)
@@ -885,34 +862,21 @@ static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device)
 }
 
 static int snd_emu10k1x_create(struct snd_card *card,
-                              struct pci_dev *pci,
-                              struct emu10k1x **rchip)
+                              struct pci_dev *pci)
 {
-       struct emu10k1x *chip;
+       struct emu10k1x *chip = card->private_data;
        int err;
        int ch;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_emu10k1x_dev_free,
-       };
-
-       *rchip = NULL;
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28)) < 0) {
                dev_err(card->dev, "error to set 28bit mask DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
@@ -920,29 +884,24 @@ static int snd_emu10k1x_create(struct snd_card *card,
        spin_lock_init(&chip->emu_lock);
        spin_lock_init(&chip->voice_lock);
   
+       err = pci_request_regions(pci, "EMU10K1X");
+       if (err < 0)
+               return err;
        chip->port = pci_resource_start(pci, 0);
-       chip->res_port = request_region(chip->port, 8, "EMU10K1X");
-       if (!chip->res_port) {
-               dev_err(card->dev, "cannot allocate the port 0x%lx\n",
-                       chip->port);
-               snd_emu10k1x_free(chip);
-               return -EBUSY;
-       }
 
-       if (request_irq(pci->irq, snd_emu10k1x_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_emu10k1x_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "cannot grab irq %d\n", pci->irq);
-               snd_emu10k1x_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_emu10k1x_free;
   
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               4 * 1024, &chip->dma_buffer) < 0) {
-               snd_emu10k1x_free(chip);
+       chip->dma_buffer = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+                                               4 * 1024);
+       if (!chip->dma_buffer)
                return -ENOMEM;
-       }
 
        pci_set_master(pci);
        /* read revision & serial */
@@ -998,12 +957,6 @@ static int snd_emu10k1x_create(struct snd_card *card,
 
        outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_emu10k1x_free(chip);
-               return err;
-       }
-       *rchip = chip;
        return 0;
 }
 
@@ -1553,50 +1506,37 @@ static int snd_emu10k1x_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       err = snd_emu10k1x_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_emu10k1x_create(card, pci);
+       if (err < 0)
                return err;
-       }
 
        err = snd_emu10k1x_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_emu10k1x_pcm(chip, 1);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_emu10k1x_pcm(chip, 2);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_emu10k1x_ac97(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_emu10k1x_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        
        err = snd_emu10k1x_midi(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        snd_emu10k1x_proc_init(chip);
 
@@ -1606,21 +1546,14 @@ static int snd_emu10k1x_probe(struct pci_dev *pci,
                card->shortname, chip->port, chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_emu10k1x_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 // PCI IDs
 static const struct pci_device_id snd_emu10k1x_ids[] = {
        { PCI_VDEVICE(CREATIVE, 0x0006), 0 },   /* Dell OEM version (EMU10K1) */
@@ -1633,7 +1566,6 @@ static struct pci_driver emu10k1x_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_emu10k1x_ids,
        .probe = snd_emu10k1x_probe,
-       .remove = snd_emu10k1x_remove,
 };
 
 module_pci_driver(emu10k1x_driver);
index ff2a397..18a1b07 100644 (file)
@@ -290,7 +290,7 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
        struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
        int channel = substream->pcm->device - emu->p16v_device_offset;
-       u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
+       u32 *table_base = (u32 *)(emu->p16v_buffer->area+(8*16*channel));
        u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
        int i;
        u32 tmp;
@@ -308,8 +308,8 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
                   runtime->dma_addr, runtime->dma_area, table_base);
        dev_dbg(emu->card->dev,
                "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
-                  emu->p16v_buffer.addr, emu->p16v_buffer.area,
-                  emu->p16v_buffer.bytes);
+                  emu->p16v_buffer->addr, emu->p16v_buffer->area,
+                  emu->p16v_buffer->bytes);
 #endif /* debug */
        tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
         switch (runtime->rate) {
@@ -333,7 +333,7 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
                table_base[(i*2)+1]=period_size_bytes<<16;
        }
  
-       snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel));
+       snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer->addr+(8*16*channel));
        snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
        snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
        snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
@@ -567,20 +567,6 @@ static const struct snd_pcm_ops snd_p16v_capture_ops = {
        .pointer =     snd_p16v_pcm_pointer_capture,
 };
 
-
-int snd_p16v_free(struct snd_emu10k1 *chip)
-{
-       // release the data
-       if (chip->p16v_buffer.area) {
-               snd_dma_free_pages(&chip->p16v_buffer);
-               /*
-               dev_dbg(chip->card->dev, "period lables free: %p\n",
-                          &chip->p16v_buffer);
-               */
-       }
-       return 0;
-}
-
 int snd_p16v_pcm(struct snd_emu10k1 *emu, int device)
 {
        struct snd_pcm *pcm;
index 728b69d..2651f0c 100644 (file)
@@ -414,7 +414,7 @@ struct ensoniq {
        unsigned int spdif_stream;
 
 #ifdef CHIP1370
-       struct snd_dma_buffer dma_bug;
+       struct snd_dma_buffer *dma_bug;
 #endif
 
 #ifdef SUPPORT_JOYSTICK
@@ -1872,11 +1872,11 @@ static void snd_ensoniq_proc_init(struct ensoniq *ensoniq)
 
  */
 
-static int snd_ensoniq_free(struct ensoniq *ensoniq)
+static void snd_ensoniq_free(struct snd_card *card)
 {
+       struct ensoniq *ensoniq = card->private_data;
+
        snd_ensoniq_free_gameport(ensoniq);
-       if (ensoniq->irq < 0)
-               goto __hw_end;
 #ifdef CHIP1370
        outl(ES_1370_SERR_DISABLE, ES_REG(ensoniq, CONTROL));   /* switch everything off */
        outl(0, ES_REG(ensoniq, SERIAL));       /* clear serial interface */
@@ -1884,24 +1884,6 @@ static int snd_ensoniq_free(struct ensoniq *ensoniq)
        outl(0, ES_REG(ensoniq, CONTROL));      /* switch everything off */
        outl(0, ES_REG(ensoniq, SERIAL));       /* clear serial interface */
 #endif
-       pci_set_power_state(ensoniq->pci, PCI_D3hot);
-      __hw_end:
-#ifdef CHIP1370
-       if (ensoniq->dma_bug.area)
-               snd_dma_free_pages(&ensoniq->dma_bug);
-#endif
-       if (ensoniq->irq >= 0)
-               free_irq(ensoniq->irq, ensoniq);
-       pci_release_regions(ensoniq->pci);
-       pci_disable_device(ensoniq->pci);
-       kfree(ensoniq);
-       return 0;
-}
-
-static int snd_ensoniq_dev_free(struct snd_device *device)
-{
-       struct ensoniq *ensoniq = device->device_data;
-       return snd_ensoniq_free(ensoniq);
 }
 
 #ifdef CHIP1371
@@ -1935,7 +1917,7 @@ static void snd_ensoniq_chip_init(struct ensoniq *ensoniq)
        outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
        outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
        outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE));
-       outl(ensoniq->dma_bug.addr, ES_REG(ensoniq, PHANTOM_FRAME));
+       outl(ensoniq->dma_bug->addr, ES_REG(ensoniq, PHANTOM_FRAME));
        outl(0, ES_REG(ensoniq, PHANTOM_COUNT));
 #else
        outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
@@ -2032,51 +2014,35 @@ static SIMPLE_DEV_PM_OPS(snd_ensoniq_pm, snd_ensoniq_suspend, snd_ensoniq_resume
 #endif /* CONFIG_PM_SLEEP */
 
 static int snd_ensoniq_create(struct snd_card *card,
-                             struct pci_dev *pci,
-                             struct ensoniq **rensoniq)
+                             struct pci_dev *pci)
 {
-       struct ensoniq *ensoniq;
+       struct ensoniq *ensoniq = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_ensoniq_dev_free,
-       };
 
-       *rensoniq = NULL;
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
-       ensoniq = kzalloc(sizeof(*ensoniq), GFP_KERNEL);
-       if (ensoniq == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&ensoniq->reg_lock);
        mutex_init(&ensoniq->src_mutex);
        ensoniq->card = card;
        ensoniq->pci = pci;
        ensoniq->irq = -1;
        err = pci_request_regions(pci, "Ensoniq AudioPCI");
-       if (err < 0) {
-               kfree(ensoniq);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        ensoniq->port = pci_resource_start(pci, 0);
-       if (request_irq(pci->irq, snd_audiopci_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, ensoniq)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_audiopci_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, ensoniq)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_ensoniq_free(ensoniq);
                return -EBUSY;
        }
        ensoniq->irq = pci->irq;
        card->sync_irq = ensoniq->irq;
 #ifdef CHIP1370
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               16, &ensoniq->dma_bug) < 0) {
-               dev_err(card->dev, "unable to allocate space for phantom area - dma_bug\n");
-               snd_ensoniq_free(ensoniq);
-               return -EBUSY;
-       }
+       ensoniq->dma_bug =
+               snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 16);
+       if (!ensoniq->dma_bug)
+               return -ENOMEM;
 #endif
        pci_set_master(pci);
        ensoniq->rev = pci->revision;
@@ -2099,17 +2065,10 @@ static int snd_ensoniq_create(struct snd_card *card,
                ensoniq->cssr |= ES_1371_ST_AC97_RST;
 #endif
 
+       card->private_free = snd_ensoniq_free;
        snd_ensoniq_chip_init(ensoniq);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ensoniq, &ops);
-       if (err < 0) {
-               snd_ensoniq_free(ensoniq);
-               return err;
-       }
-
        snd_ensoniq_proc_init(ensoniq);
-
-       *rensoniq = ensoniq;
        return 0;
 }
 
@@ -2360,47 +2319,35 @@ static int snd_audiopci_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*ensoniq), &card);
        if (err < 0)
                return err;
+       ensoniq = card->private_data;
 
-       err = snd_ensoniq_create(card, pci, &ensoniq);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_ensoniq_create(card, pci);
+       if (err < 0)
                return err;
-       }
-       card->private_data = ensoniq;
 
 #ifdef CHIP1370
        err = snd_ensoniq_1370_mixer(ensoniq);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #endif
 #ifdef CHIP1371
        err = snd_ensoniq_1371_mixer(ensoniq, spdif[dev], lineio[dev]);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 #endif
        err = snd_ensoniq_pcm(ensoniq, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_ensoniq_pcm2(ensoniq, 1);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_ensoniq_midi(ensoniq, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        snd_ensoniq_create_gameport(ensoniq, dev);
 
@@ -2414,26 +2361,18 @@ static int snd_audiopci_probe(struct pci_dev *pci,
                ensoniq->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_audiopci_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver ens137x_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_audiopci_ids,
        .probe = snd_audiopci_probe,
-       .remove = snd_audiopci_remove,
        .driver = {
                .pm = SND_ENSONIQ_PM_OPS,
        },
index 33b1eb3..00b976f 100644 (file)
@@ -1521,8 +1521,10 @@ static inline int snd_es1938_create_gameport(struct es1938 *chip) { return -ENOS
 static inline void snd_es1938_free_gameport(struct es1938 *chip) { }
 #endif /* SUPPORT_JOYSTICK */
 
-static int snd_es1938_free(struct es1938 *chip)
+static void snd_es1938_free(struct snd_card *card)
 {
+       struct es1938 *chip = card->private_data;
+
        /* disable irqs */
        outb(0x00, SLIO_REG(chip, IRQCONTROL));
        if (chip->rmidi)
@@ -1532,71 +1534,47 @@ static int snd_es1938_free(struct es1938 *chip)
 
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_es1938_dev_free(struct snd_device *device)
-{
-       struct es1938 *chip = device->device_data;
-       return snd_es1938_free(chip);
 }
 
 static int snd_es1938_create(struct snd_card *card,
-                            struct pci_dev *pci,
-                            struct es1938 **rchip)
+                            struct pci_dev *pci)
 {
-       struct es1938 *chip;
+       struct es1938 *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_es1938_dev_free,
-       };
-
-       *rchip = NULL;
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
         /* check, if we can restrict PCI DMA transfers to 24 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
                dev_err(card->dev,
                        "architecture does not support 24bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                 return -ENXIO;
         }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&chip->reg_lock);
        spin_lock_init(&chip->mixer_lock);
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
        err = pci_request_regions(pci, "ESS Solo-1");
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        chip->io_port = pci_resource_start(pci, 0);
        chip->sb_port = pci_resource_start(pci, 1);
        chip->vc_port = pci_resource_start(pci, 2);
        chip->mpu_port = pci_resource_start(pci, 3);
        chip->game_port = pci_resource_start(pci, 4);
+       /* still use non-managed irq handler as it's re-acquired at PM resume */
        if (request_irq(pci->irq, snd_es1938_interrupt, IRQF_SHARED,
                        KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_es1938_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_es1938_free;
        dev_dbg(card->dev,
                "create: io: 0x%lx, sb: 0x%lx, vc: 0x%lx, mpu: 0x%lx, game: 0x%lx\n",
                   chip->io_port, chip->sb_port, chip->vc_port, chip->mpu_port, chip->game_port);
@@ -1604,14 +1582,6 @@ static int snd_es1938_create(struct snd_card *card,
        chip->ddma_port = chip->vc_port + 0x00;         /* fix from Thomas Sailer */
 
        snd_es1938_chip_init(chip);
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_es1938_free(chip);
-               return err;
-       }
-
-       *rchip = chip;
        return 0;
 }
 
@@ -1762,23 +1732,20 @@ static int snd_es1938_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
-       for (idx = 0; idx < 5; idx++) {
+       chip = card->private_data;
+
+       for (idx = 0; idx < 5; idx++)
                if (pci_resource_start(pci, idx) == 0 ||
-                   !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) {
-                       snd_card_free(card);
-                       return -ENODEV;
-               }
-       }
-       err = snd_es1938_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+                   !(pci_resource_flags(pci, idx) & IORESOURCE_IO))
+                       return -ENODEV;
+
+       err = snd_es1938_create(card, pci);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        strcpy(card->driver, "ES1938");
        strcpy(card->shortname, "ESS ES1938 (Solo-1)");
@@ -1788,15 +1755,11 @@ static int snd_es1938_probe(struct pci_dev *pci,
                chip->irq);
 
        err = snd_es1938_new_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_es1938_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        if (snd_opl3_create(card,
                            SLSB_REG(chip, FMLOWADDR),
                            SLSB_REG(chip, FMHIGHADDR),
@@ -1805,15 +1768,11 @@ static int snd_es1938_probe(struct pci_dev *pci,
                           SLSB_REG(chip, FMLOWADDR));
        } else {
                err = snd_opl3_timer_new(opl3, 0, 1);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
                err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
        if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
                                chip->mpu_port,
@@ -1829,26 +1788,18 @@ static int snd_es1938_probe(struct pci_dev *pci,
        snd_es1938_create_gameport(chip);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_es1938_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver es1938_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_es1938_ids,
        .probe = snd_es1938_probe,
-       .remove = snd_es1938_remove,
        .driver = {
                .pm = ES1938_PM_OPS,
        },
index c038c10..6a8a02a 100644 (file)
@@ -2442,7 +2442,8 @@ static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
        if (!joystick[dev])
                return -ENODEV;
 
-       r = request_region(JOYSTICK_ADDR, 8, "ES1968 gameport");
+       r = devm_request_region(&chip->pci->dev, JOYSTICK_ADDR, 8,
+                               "ES1968 gameport");
        if (!r)
                return -EBUSY;
 
@@ -2450,7 +2451,6 @@ static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
        if (!gp) {
                dev_err(chip->card->dev,
                        "cannot allocate memory for gameport\n");
-               release_and_free_resource(r);
                return -ENOMEM;
        }
 
@@ -2461,7 +2461,6 @@ static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
        gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
        gameport_set_dev_parent(gp, &chip->pci->dev);
        gp->io = JOYSTICK_ADDR;
-       gameport_set_port_data(gp, r);
 
        gameport_register_port(gp);
 
@@ -2471,12 +2470,8 @@ static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
 static void snd_es1968_free_gameport(struct es1968 *chip)
 {
        if (chip->gameport) {
-               struct resource *r = gameport_get_port_data(chip->gameport);
-
                gameport_unregister_port(chip->gameport);
                chip->gameport = NULL;
-
-               release_and_free_resource(r);
        }
 }
 #else
@@ -2490,7 +2485,7 @@ static int snd_es1968_input_register(struct es1968 *chip)
        struct input_dev *input_dev;
        int err;
 
-       input_dev = input_allocate_device();
+       input_dev = devm_input_allocate_device(&chip->pci->dev);
        if (!input_dev)
                return -ENOMEM;
 
@@ -2510,10 +2505,8 @@ static int snd_es1968_input_register(struct es1968 *chip)
        __set_bit(KEY_VOLUMEUP, input_dev->keybit);
 
        err = input_register_device(input_dev);
-       if (err) {
-               input_free_device(input_dev);
+       if (err)
                return err;
-       }
 
        chip->input_dev = input_dev;
        return 0;
@@ -2597,13 +2590,11 @@ static const struct snd_tea575x_ops snd_es1968_tea_ops = {
 };
 #endif
 
-static int snd_es1968_free(struct es1968 *chip)
+static void snd_es1968_free(struct snd_card *card)
 {
+       struct es1968 *chip = card->private_data;
+
        cancel_work_sync(&chip->hwvol_work);
-#ifdef CONFIG_SND_ES1968_INPUT
-       if (chip->input_dev)
-               input_unregister_device(chip->input_dev);
-#endif
 
        if (chip->io_port) {
                outw(1, chip->io_port + 0x04); /* clear WP interrupts */
@@ -2615,19 +2606,7 @@ static int snd_es1968_free(struct es1968 *chip)
        v4l2_device_unregister(&chip->v4l2_dev);
 #endif
 
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
        snd_es1968_free_gameport(chip);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_es1968_dev_free(struct snd_device *device)
-{
-       struct es1968 *chip = device->device_data;
-       return snd_es1968_free(chip);
 }
 
 struct ess_device_list {
@@ -2657,35 +2636,22 @@ static int snd_es1968_create(struct snd_card *card,
                             int capt_streams,
                             int chip_type,
                             int do_pm,
-                            int radio_nr,
-                            struct es1968 **chip_ret)
+                            int radio_nr)
 {
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_es1968_dev_free,
-       };
-       struct es1968 *chip;
+       struct es1968 *chip = card->private_data;
        int i, err;
 
-       *chip_ret = NULL;
-
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 28 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
                dev_err(card->dev,
                        "architecture does not support 28bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (! chip) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        /* Set Vars */
        chip->type = chip_type;
        spin_lock_init(&chip->reg_lock);
@@ -2702,20 +2668,17 @@ static int snd_es1968_create(struct snd_card *card,
        chip->capture_streams = capt_streams;
 
        err = pci_request_regions(pci, "ESS Maestro");
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        chip->io_port = pci_resource_start(pci, 0);
-       if (request_irq(pci->irq, snd_es1968_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_es1968_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_es1968_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_es1968_free;
                
        /* Clear Maestro_map */
        for (i = 0; i < 32; i++)
@@ -2749,21 +2712,13 @@ static int snd_es1968_create(struct snd_card *card,
 
        snd_es1968_chip_init(chip);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_es1968_free(chip);
-               return err;
-       }
-
 #ifdef CONFIG_SND_ES1968_RADIO
        /* don't play with GPIOs on laptops */
        if (chip->pci->subsystem_vendor != 0x125d)
-               goto no_radio;
+               return 0;
        err = v4l2_device_register(&pci->dev, &chip->v4l2_dev);
-       if (err < 0) {
-               snd_es1968_free(chip);
+       if (err < 0)
                return err;
-       }
        chip->tea.v4l2_dev = &chip->v4l2_dev;
        chip->tea.private_data = chip;
        chip->tea.radio_nr = radio_nr;
@@ -2779,11 +2734,7 @@ static int snd_es1968_create(struct snd_card *card,
                        break;
                }
        }
-no_radio:
 #endif
-
-       *chip_ret = chip;
-
        return 0;
 }
 
@@ -2806,10 +2757,11 @@ static int snd_es1968_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
                 
        if (total_bufsize[dev] < 128)
                total_bufsize[dev] = 128;
@@ -2821,13 +2773,9 @@ static int snd_es1968_probe(struct pci_dev *pci,
                                pcm_substreams_c[dev],
                                pci_id->driver_data,
                                use_pm[dev],
-                               radio_nr[dev],
-                               &chip);
-       if (err < 0) {
-               snd_card_free(card);
+                               radio_nr[dev]);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        switch (chip->type) {
        case TYPE_MAESTRO2E:
@@ -2845,16 +2793,12 @@ static int snd_es1968_probe(struct pci_dev *pci,
        }
 
        err = snd_es1968_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_es1968_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        if (enable_mpu[dev] == 2) {
                /* check the deny list */
@@ -2897,25 +2841,17 @@ static int snd_es1968_probe(struct pci_dev *pci,
                card->shortname, chip->io_port, chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_es1968_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver es1968_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_es1968_ids,
        .probe = snd_es1968_probe,
-       .remove = snd_es1968_remove,
        .driver = {
                .pm = ES1968_PM_OPS,
        },
index ed9dae8..9c22ff1 100644 (file)
@@ -1028,22 +1028,6 @@ FM801_SINGLE(SNDRV_CTL_NAME_IEC958("Raw Data ",CAPTURE,SWITCH), FM801_I2S_MODE,
 FM801_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), FM801_GEN_CTRL, 2, 1, 0),
 };
 
-static void snd_fm801_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
-{
-       struct fm801 *chip = bus->private_data;
-       chip->ac97_bus = NULL;
-}
-
-static void snd_fm801_mixer_free_ac97(struct snd_ac97 *ac97)
-{
-       struct fm801 *chip = ac97->private_data;
-       if (ac97->num == 0) {
-               chip->ac97 = NULL;
-       } else {
-               chip->ac97_sec = NULL;
-       }
-}
-
 static int snd_fm801_mixer(struct fm801 *chip)
 {
        struct snd_ac97_template ac97;
@@ -1057,11 +1041,9 @@ static int snd_fm801_mixer(struct fm801 *chip)
        err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus);
        if (err < 0)
                return err;
-       chip->ac97_bus->private_free = snd_fm801_mixer_free_ac97_bus;
 
        memset(&ac97, 0, sizeof(ac97));
        ac97.private_data = chip;
-       ac97.private_free = snd_fm801_mixer_free_ac97;
        err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97);
        if (err < 0)
                return err;
@@ -1177,55 +1159,35 @@ static void snd_fm801_chip_init(struct fm801 *chip)
                     FM801_IRQ_PLAYBACK | FM801_IRQ_CAPTURE | FM801_IRQ_MPU);
 }
 
-static int snd_fm801_free(struct fm801 *chip)
+static void snd_fm801_free(struct snd_card *card)
 {
+       struct fm801 *chip = card->private_data;
        unsigned short cmdw;
 
-       if (chip->irq < 0)
-               goto __end_hw;
-
        /* interrupt setup - mask everything */
        cmdw = fm801_readw(chip, IRQ_MASK);
        cmdw |= 0x00c3;
        fm801_writew(chip, IRQ_MASK, cmdw);
 
-       devm_free_irq(chip->dev, chip->irq, chip);
-
-      __end_hw:
 #ifdef CONFIG_SND_FM801_TEA575X_BOOL
        if (!(chip->tea575x_tuner & TUNER_DISABLED)) {
                snd_tea575x_exit(&chip->tea);
                v4l2_device_unregister(&chip->v4l2_dev);
        }
 #endif
-       return 0;
-}
-
-static int snd_fm801_dev_free(struct snd_device *device)
-{
-       struct fm801 *chip = device->device_data;
-       return snd_fm801_free(chip);
 }
 
 static int snd_fm801_create(struct snd_card *card,
                            struct pci_dev *pci,
                            int tea575x_tuner,
-                           int radio_nr,
-                           struct fm801 **rchip)
+                           int radio_nr)
 {
-       struct fm801 *chip;
+       struct fm801 *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_fm801_dev_free,
-       };
 
-       *rchip = NULL;
        err = pcim_enable_device(pci);
        if (err < 0)
                return err;
-       chip = devm_kzalloc(&pci->dev, sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL)
-               return -ENOMEM;
        spin_lock_init(&chip->reg_lock);
        chip->card = card;
        chip->dev = &pci->dev;
@@ -1253,7 +1215,6 @@ static int snd_fm801_create(struct snd_card *card,
                if (devm_request_irq(&pci->dev, pci->irq, snd_fm801_interrupt,
                                IRQF_SHARED, KBUILD_MODNAME, chip)) {
                        dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-                       snd_fm801_free(chip);
                        return -EBUSY;
                }
                chip->irq = pci->irq;
@@ -1261,20 +1222,13 @@ static int snd_fm801_create(struct snd_card *card,
                pci_set_master(pci);
        }
 
+       card->private_free = snd_fm801_free;
        snd_fm801_chip_init(chip);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_fm801_free(chip);
-               return err;
-       }
-
 #ifdef CONFIG_SND_FM801_TEA575X_BOOL
        err = v4l2_device_register(&pci->dev, &chip->v4l2_dev);
-       if (err < 0) {
-               snd_fm801_free(chip);
+       if (err < 0)
                return err;
-       }
        chip->tea.v4l2_dev = &chip->v4l2_dev;
        chip->tea.radio_nr = radio_nr;
        chip->tea.private_data = chip;
@@ -1284,7 +1238,6 @@ static int snd_fm801_create(struct snd_card *card,
            (chip->tea575x_tuner & TUNER_TYPE_MASK) < 4) {
                if (snd_tea575x_init(&chip->tea, THIS_MODULE)) {
                        dev_err(card->dev, "TEA575x radio not found\n");
-                       snd_fm801_free(chip);
                        return -ENODEV;
                }
        } else if ((chip->tea575x_tuner & TUNER_TYPE_MASK) == 0) {
@@ -1312,8 +1265,6 @@ static int snd_fm801_create(struct snd_card *card,
                        sizeof(chip->tea.card));
        }
 #endif
-
-       *rchip = chip;
        return 0;
 }
 
@@ -1333,16 +1284,14 @@ static int snd_card_fm801_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
-       err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev], &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       chip = card->private_data;
+       err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev]);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        strcpy(card->driver, "FM801");
        strcpy(card->shortname, "ForteMedia FM801-");
@@ -1354,53 +1303,36 @@ static int snd_card_fm801_probe(struct pci_dev *pci,
                goto __fm801_tuner_only;
 
        err = snd_fm801_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_fm801_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801,
                                  chip->port + FM801_MPU401_DATA,
                                  MPU401_INFO_INTEGRATED |
                                  MPU401_INFO_IRQ_HOOK,
                                  -1, &chip->rmidi);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_opl3_create(card, chip->port + FM801_OPL3_BANK0,
                              chip->port + FM801_OPL3_BANK1,
                              OPL3_HW_OPL3_FM801, 1, &opl3);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
       __fm801_tuner_only:
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_card_fm801_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 #ifdef CONFIG_PM_SLEEP
 static const unsigned char saved_regs[] = {
        FM801_PCM_VOL, FM801_I2S_VOL, FM801_FM_VOL, FM801_REC_SRC,
@@ -1468,7 +1400,6 @@ static struct pci_driver fm801_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_fm801_ids,
        .probe = snd_card_fm801_probe,
-       .remove = snd_card_fm801_remove,
        .driver = {
                .pm = SND_FM801_PM_OPS,
        },
index c4360cd..ab9d274 100644 (file)
@@ -157,6 +157,16 @@ config SND_HDA_CODEC_CIRRUS
 comment "Set to Y if you want auto-loading the codec driver"
        depends on SND_HDA=y && SND_HDA_CODEC_CIRRUS=m
 
+config SND_HDA_CODEC_CS8409
+       tristate "Build Cirrus Logic HDA bridge support"
+       select SND_HDA_GENERIC
+       help
+         Say Y or M here to include Cirrus Logic HDA bridge support in
+         snd-hda-intel driver, such as CS8409.
+
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA=y && SND_HDA_CODEC_CS8409=m
+
 config SND_HDA_CODEC_CONEXANT
        tristate "Build Conexant HD-audio codec support"
        select SND_HDA_GENERIC
index b57432f..b8fa682 100644 (file)
@@ -20,6 +20,7 @@ snd-hda-codec-analog-objs :=  patch_analog.o
 snd-hda-codec-idt-objs :=      patch_sigmatel.o
 snd-hda-codec-si3054-objs :=   patch_si3054.o
 snd-hda-codec-cirrus-objs :=   patch_cirrus.o
+snd-hda-codec-cs8409-objs :=   patch_cs8409.o patch_cs8409-tables.o
 snd-hda-codec-ca0110-objs :=   patch_ca0110.o
 snd-hda-codec-ca0132-objs :=   patch_ca0132.o
 snd-hda-codec-conexant-objs := patch_conexant.o
@@ -37,6 +38,7 @@ obj-$(CONFIG_SND_HDA_CODEC_ANALOG) += snd-hda-codec-analog.o
 obj-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += snd-hda-codec-idt.o
 obj-$(CONFIG_SND_HDA_CODEC_SI3054) += snd-hda-codec-si3054.o
 obj-$(CONFIG_SND_HDA_CODEC_CIRRUS) += snd-hda-codec-cirrus.o
+obj-$(CONFIG_SND_HDA_CODEC_CS8409) += snd-hda-codec-cs8409.o
 obj-$(CONFIG_SND_HDA_CODEC_CA0110) += snd-hda-codec-ca0110.o
 obj-$(CONFIG_SND_HDA_CODEC_CA0132) += snd-hda-codec-ca0132.o
 obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o
index 1a001ec..4a85447 100644 (file)
@@ -971,6 +971,8 @@ EXPORT_SYMBOL_GPL(snd_hda_pick_pin_fixup);
  * When a special model string "nofixup" is given, also no fixup is applied.
  *
  * The function tries to find the matching model name at first, if given.
+ * If the model string contains the SSID alias, try to look up with the given
+ * alias ID.
  * If nothing matched, try to look up the PCI SSID.
  * If still nothing matched, try to look up the codec SSID.
  */
@@ -982,65 +984,77 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
        const struct snd_pci_quirk *q;
        int id = HDA_FIXUP_ID_NOT_SET;
        const char *name = NULL;
+       const char *type = NULL;
+       int vendor, device;
 
        if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
                return;
 
        /* when model=nofixup is given, don't pick up any fixups */
        if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
-               codec->fixup_list = NULL;
-               codec->fixup_name = NULL;
-               codec->fixup_id = HDA_FIXUP_ID_NO_FIXUP;
+               id = HDA_FIXUP_ID_NO_FIXUP;
+               fixlist = NULL;
                codec_dbg(codec, "%s: picked no fixup (nofixup specified)\n",
                          codec->core.chip_name);
-               return;
+               goto found;
        }
 
+       /* match with the model name string */
        if (codec->modelname && models) {
                while (models->name) {
                        if (!strcmp(codec->modelname, models->name)) {
-                               codec->fixup_id = models->id;
-                               codec->fixup_name = models->name;
-                               codec->fixup_list = fixlist;
+                               id = models->id;
+                               name = models->name;
                                codec_dbg(codec, "%s: picked fixup %s (model specified)\n",
                                          codec->core.chip_name, codec->fixup_name);
-                               return;
+                               goto found;
                        }
                        models++;
                }
        }
-       if (quirk) {
-               q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
+
+       if (!quirk)
+               return;
+
+       /* match with the SSID alias given by the model string "XXXX:YYYY" */
+       if (codec->modelname &&
+           sscanf(codec->modelname, "%04x:%04x", &vendor, &device) == 2) {
+               q = snd_pci_quirk_lookup_id(vendor, device, quirk);
                if (q) {
-                       id = q->value;
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-                       name = q->name;
-                       codec_dbg(codec, "%s: picked fixup %s (PCI SSID%s)\n",
-                                 codec->core.chip_name, name, q->subdevice_mask ? "" : " - vendor generic");
-#endif
+                       type = "alias SSID";
+                       goto found_device;
                }
        }
-       if (id < 0 && quirk) {
-               for (q = quirk; q->subvendor || q->subdevice; q++) {
-                       unsigned int vendorid =
-                               q->subdevice | (q->subvendor << 16);
-                       unsigned int mask = 0xffff0000 | q->subdevice_mask;
-                       if ((codec->core.subsystem_id & mask) == (vendorid & mask)) {
-                               id = q->value;
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-                               name = q->name;
-                               codec_dbg(codec, "%s: picked fixup %s (codec SSID)\n",
-                                         codec->core.chip_name, name);
-#endif
-                               break;
-                       }
-               }
+
+       /* match with the PCI SSID */
+       q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
+       if (q) {
+               type = "PCI SSID";
+               goto found_device;
        }
 
-       codec->fixup_id = id;
-       if (id >= 0) {
-               codec->fixup_list = fixlist;
-               codec->fixup_name = name;
+       /* match with the codec SSID */
+       q = snd_pci_quirk_lookup_id(codec->core.subsystem_id >> 16,
+                                   codec->core.subsystem_id & 0xffff,
+                                   quirk);
+       if (q) {
+               type = "codec SSID";
+               goto found_device;
        }
+
+       return; /* no matching */
+
+ found_device:
+       id = q->value;
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+       name = q->name;
+#endif
+       codec_dbg(codec, "%s: picked fixup %s for %s %04x:%04x\n",
+                 codec->core.chip_name, name ? name : "",
+                 type, q->subvendor, q->subdevice);
+ found:
+       codec->fixup_id = id;
+       codec->fixup_list = fixlist;
+       codec->fixup_name = name;
 }
 EXPORT_SYMBOL_GPL(snd_hda_pick_fixup);
index e8dee24..2523b23 100644 (file)
@@ -165,13 +165,7 @@ static int hda_codec_driver_remove(struct device *dev)
 
 static void hda_codec_driver_shutdown(struct device *dev)
 {
-       struct hda_codec *codec = dev_to_hda_codec(dev);
-
-       if (!pm_runtime_suspended(dev)) {
-               if (codec->patch_ops.reboot_notify)
-                       codec->patch_ops.reboot_notify(codec);
-               snd_hda_codec_display_power(codec, false);
-       }
+       snd_hda_codec_shutdown(dev_to_hda_codec(dev));
 }
 
 int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name,
index 7a717e1..a9ebefd 100644 (file)
@@ -2981,6 +2981,18 @@ const struct dev_pm_ops hda_codec_driver_pm = {
                           NULL)
 };
 
+/* suspend the codec at shutdown; called from driver's shutdown callback */
+void snd_hda_codec_shutdown(struct hda_codec *codec)
+{
+       struct hda_pcm *cpcm;
+
+       list_for_each_entry(cpcm, &codec->pcm_list_head, list)
+               snd_pcm_suspend_all(cpcm->pcm);
+
+       pm_runtime_force_suspend(hda_codec_dev(codec));
+       pm_runtime_disable(hda_codec_dev(codec));
+}
+
 /*
  * add standard channel maps if not specified
  */
index ca2f2ec..7cd4528 100644 (file)
@@ -669,16 +669,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        return err;
 }
 
-static int azx_pcm_mmap(struct snd_pcm_substream *substream,
-                       struct vm_area_struct *area)
-{
-       struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
-       struct azx *chip = apcm->chip;
-       if (chip->ops->pcm_mmap_prepare)
-               chip->ops->pcm_mmap_prepare(substream, area);
-       return snd_pcm_lib_default_mmap(substream, area);
-}
-
 static const struct snd_pcm_ops azx_pcm_ops = {
        .open = azx_pcm_open,
        .close = azx_pcm_close,
@@ -688,7 +678,6 @@ static const struct snd_pcm_ops azx_pcm_ops = {
        .trigger = azx_pcm_trigger,
        .pointer = azx_pcm_pointer,
        .get_time_info =  azx_get_time_info,
-       .mmap = azx_pcm_mmap,
 };
 
 static void azx_pcm_free(struct snd_pcm *pcm)
@@ -753,7 +742,7 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec,
        if (size > MAX_PREALLOC_SIZE)
                size = MAX_PREALLOC_SIZE;
        if (chip->uc_buffer)
-               type = SNDRV_DMA_TYPE_DEV_UC_SG;
+               type = SNDRV_DMA_TYPE_DEV_WC_SG;
        snd_pcm_set_managed_buffer_all(pcm, type, chip->card->dev,
                                       size, MAX_PREALLOC_SIZE);
        return 0;
index 68f9668..3062f87 100644 (file)
@@ -74,8 +74,6 @@ struct azx;
 struct hda_controller_ops {
        /* Disable msi if supported, PCI only */
        int (*disable_msi_reset_irq)(struct azx *);
-       void (*pcm_mmap_prepare)(struct snd_pcm_substream *substream,
-                                struct vm_area_struct *area);
        /* Check if current position is acceptable */
        int (*position_check)(struct azx *chip, struct azx_dev *azx_dev);
        /* enable/disable the link power */
@@ -141,7 +139,6 @@ struct azx {
        unsigned int snoop:1;
        unsigned int uc_buffer:1; /* non-cached pages for stream buffers */
        unsigned int align_buffer_size:1;
-       unsigned int region_requested:1;
        unsigned int disabled:1; /* disabled by vga_switcheroo */
        unsigned int pm_prepared:1;
 
index 481d8f8..3bf5e34 100644 (file)
@@ -6004,24 +6004,6 @@ void snd_hda_gen_free(struct hda_codec *codec)
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_free);
 
-/**
- * snd_hda_gen_reboot_notify - Make codec enter D3 before rebooting
- * @codec: the HDA codec
- *
- * This can be put as patch_ops reboot_notify function.
- */
-void snd_hda_gen_reboot_notify(struct hda_codec *codec)
-{
-       /* Make the codec enter D3 to avoid spurious noises from the internal
-        * speaker during (and after) reboot
-        */
-       snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
-       snd_hda_codec_write(codec, codec->core.afg, 0,
-                           AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-       msleep(10);
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_reboot_notify);
-
 #ifdef CONFIG_PM
 /**
  * snd_hda_gen_check_power_status - check the loopback power save state
@@ -6049,7 +6031,6 @@ static const struct hda_codec_ops generic_patch_ops = {
        .init = snd_hda_gen_init,
        .free = snd_hda_gen_free,
        .unsol_event = snd_hda_jack_unsol_event,
-       .reboot_notify = snd_hda_gen_reboot_notify,
 #ifdef CONFIG_PM
        .check_power_status = snd_hda_gen_check_power_status,
 #endif
index d4dd1b8..c43bd0f 100644 (file)
@@ -324,7 +324,6 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
                                  struct auto_pin_cfg *cfg);
 int snd_hda_gen_build_controls(struct hda_codec *codec);
 int snd_hda_gen_build_pcms(struct hda_codec *codec);
-void snd_hda_gen_reboot_notify(struct hda_codec *codec);
 
 /* standard jack event callbacks */
 void snd_hda_gen_hp_automute(struct hda_codec *codec,
index 0062c18..3aa432d 100644 (file)
@@ -883,11 +883,10 @@ static unsigned int azx_get_pos_skl(struct azx *chip, struct azx_dev *azx_dev)
        return azx_get_pos_posbuf(chip, azx_dev);
 }
 
-static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset)
+static void azx_shutdown_chip(struct azx *chip)
 {
        azx_stop_chip(chip);
-       if (!skip_link_reset)
-               azx_enter_link_reset(chip);
+       azx_enter_link_reset(chip);
        azx_clear_irq_pending(chip);
        display_power(chip, false);
 }
@@ -896,11 +895,6 @@ static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset)
 static DEFINE_MUTEX(card_list_lock);
 static LIST_HEAD(card_list);
 
-static void azx_shutdown_chip(struct azx *chip)
-{
-       __azx_shutdown_chip(chip, false);
-}
-
 static void azx_add_card_list(struct azx *chip)
 {
        struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
@@ -1373,18 +1367,11 @@ static void azx_free(struct azx *chip)
 
        if (bus->irq >= 0)
                free_irq(bus->irq, (void*)chip);
-       if (chip->msi)
-               pci_disable_msi(chip->pci);
-       iounmap(bus->remap_addr);
 
        azx_free_stream_pages(chip);
        azx_free_streams(chip);
        snd_hdac_bus_exit(bus);
 
-       if (chip->region_requested)
-               pci_release_regions(chip->pci);
-
-       pci_disable_device(chip->pci);
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
        release_firmware(chip->fw);
 #endif
@@ -1773,15 +1760,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
 
        *rchip = NULL;
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        hda = devm_kzalloc(&pci->dev, sizeof(*hda), GFP_KERNEL);
-       if (!hda) {
-               pci_disable_device(pci);
+       if (!hda)
                return -ENOMEM;
-       }
 
        chip = &hda->chip;
        mutex_init(&chip->open_mutex);
@@ -1817,14 +1802,12 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
                chip->bdl_pos_adj = bdl_pos_adj[dev];
 
        err = azx_bus_init(chip, model[dev]);
-       if (err < 0) {
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
 
        /* use the non-cached pages in non-snoop mode */
        if (!azx_snoop(chip))
-               azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_UC;
+               azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_WC;
 
        if (chip->driver_type == AZX_DRIVER_NVIDIA) {
                dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
@@ -1866,17 +1849,12 @@ static int azx_first_init(struct azx *chip)
        }
 #endif
 
-       err = pci_request_regions(pci, "ICH HD audio");
+       err = pcim_iomap_regions(pci, 1 << 0, "ICH HD audio");
        if (err < 0)
                return err;
-       chip->region_requested = 1;
 
        bus->addr = pci_resource_start(pci, 0);
-       bus->remap_addr = pci_ioremap_bar(pci, 0);
-       if (bus->remap_addr == NULL) {
-               dev_err(card->dev, "ioremap error\n");
-               return -ENXIO;
-       }
+       bus->remap_addr = pcim_iomap_table(pci)[0];
 
        if (chip->driver_type == AZX_DRIVER_SKL)
                snd_hdac_bus_parse_capabilities(bus);
@@ -2059,17 +2037,6 @@ static int disable_msi_reset_irq(struct azx *chip)
        return 0;
 }
 
-static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
-                            struct vm_area_struct *area)
-{
-#ifdef CONFIG_X86
-       struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
-       struct azx *chip = apcm->chip;
-       if (chip->uc_buffer)
-               area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
-#endif
-}
-
 /* Denylist for skipping the whole probe:
  * some HD-audio PCI entries are exposed without any codecs, and such devices
  * should be ignored from the beginning.
@@ -2083,7 +2050,6 @@ static const struct pci_device_id driver_denylist[] = {
 
 static const struct hda_controller_ops pci_hda_ops = {
        .disable_msi_reset_irq = disable_msi_reset_irq,
-       .pcm_mmap_prepare = pcm_mmap_prepare,
        .position_check = azx_position_check,
 };
 
@@ -2391,7 +2357,7 @@ static void azx_shutdown(struct pci_dev *pci)
                return;
        chip = card->private_data;
        if (chip && chip->running)
-               __azx_shutdown_chip(chip, true);
+               azx_shutdown_chip(chip);
 }
 
 /* PCI IDs */
index 8d2503e..ea8ab8b 100644 (file)
@@ -615,6 +615,8 @@ unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
                                             hda_nid_t nid,
                                             unsigned int power_state);
 
+void snd_hda_codec_shutdown(struct hda_codec *codec);
+
 /*
  * AMP control callbacks
  */
index 2132b2a..8afe600 100644 (file)
@@ -72,7 +72,7 @@ static int create_beep_ctls(struct hda_codec *codec)
 #define create_beep_ctls(codec)                0
 #endif
 
-
+#ifdef CONFIG_PM
 static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
                                hda_nid_t hp)
 {
@@ -112,16 +112,10 @@ static void ad198x_power_eapd(struct hda_codec *codec)
        }
 }
 
-static void ad198x_shutup(struct hda_codec *codec)
+static int ad198x_suspend(struct hda_codec *codec)
 {
        snd_hda_shutup_pins(codec);
        ad198x_power_eapd(codec);
-}
-
-#ifdef CONFIG_PM
-static int ad198x_suspend(struct hda_codec *codec)
-{
-       ad198x_shutup(codec);
        return 0;
 }
 #endif
@@ -168,7 +162,6 @@ static const struct hda_codec_ops ad198x_auto_patch_ops = {
        .check_power_status = snd_hda_gen_check_power_status,
        .suspend = ad198x_suspend,
 #endif
-       .reboot_notify = ad198x_shutup,
 };
 
 
index b66e7bd..2089337 100644 (file)
@@ -2270,7 +2270,7 @@ static int dspio_send_scp_message(struct hda_codec *codec,
                                  unsigned int *bytes_returned)
 {
        struct ca0132_spec *spec = codec->spec;
-       int status = -1;
+       int status;
        unsigned int scp_send_size = 0;
        unsigned int total_size;
        bool waiting_for_resp = false;
@@ -9682,11 +9682,6 @@ static void dbpro_free(struct hda_codec *codec)
        kfree(codec->spec);
 }
 
-static void ca0132_reboot_notify(struct hda_codec *codec)
-{
-       codec->patch_ops.free(codec);
-}
-
 #ifdef CONFIG_PM
 static int ca0132_suspend(struct hda_codec *codec)
 {
@@ -9706,7 +9701,6 @@ static const struct hda_codec_ops ca0132_patch_ops = {
 #ifdef CONFIG_PM
        .suspend = ca0132_suspend,
 #endif
-       .reboot_notify = ca0132_reboot_notify,
 };
 
 static const struct hda_codec_ops dbpro_patch_ops = {
index 8629e84..678fbca 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <sound/core.h>
-#include <linux/mutex.h>
 #include <linux/pci.h>
 #include <sound/tlv.h>
 #include <sound/hda_codec.h>
@@ -21,9 +20,6 @@
 /*
  */
 
-#define CS42L42_HP_CH     (2U)
-#define CS42L42_HS_MIC_CH (1U)
-
 struct cs_spec {
        struct hda_gen_spec gen;
 
@@ -42,18 +38,6 @@ struct cs_spec {
        /* for MBP SPDIF control */
        int (*spdif_sw_put)(struct snd_kcontrol *kcontrol,
                            struct snd_ctl_elem_value *ucontrol);
-
-       unsigned int cs42l42_hp_jack_in:1;
-       unsigned int cs42l42_mic_jack_in:1;
-       unsigned int cs42l42_volume_init:1;
-       char cs42l42_hp_volume[CS42L42_HP_CH];
-       char cs42l42_hs_mic_volume[CS42L42_HS_MIC_CH];
-
-       struct mutex cs8409_i2c_mux;
-
-       /* verb exec op override */
-       int (*exec_verb)(struct hdac_device *dev, unsigned int cmd,
-                                unsigned int flags, unsigned int *res);
 };
 
 /* available models with CS420x */
@@ -1239,1063 +1223,6 @@ static int patch_cs4213(struct hda_codec *codec)
        return err;
 }
 
-/* Cirrus Logic CS8409 HDA bridge with
- * companion codec CS42L42
- */
-#define CS8409_VENDOR_NID 0x47
-
-#define CS8409_CS42L42_HP_PIN_NID      0x24
-#define CS8409_CS42L42_SPK_PIN_NID     0x2c
-#define CS8409_CS42L42_AMIC_PIN_NID    0x34
-#define CS8409_CS42L42_DMIC_PIN_NID    0x44
-#define CS8409_CS42L42_DMIC_ADC_PIN_NID        0x22
-
-#define CS42L42_HSDET_AUTO_DONE        0x02
-#define CS42L42_HSTYPE_MASK            0x03
-
-#define CS42L42_JACK_INSERTED  0x0C
-#define CS42L42_JACK_REMOVED   0x00
-
-#define GPIO3_INT (1 << 3)
-#define GPIO4_INT (1 << 4)
-#define GPIO5_INT (1 << 5)
-
-#define CS42L42_I2C_ADDR       (0x48 << 1)
-
-#define CIR_I2C_ADDR   0x0059
-#define CIR_I2C_DATA   0x005A
-#define CIR_I2C_CTRL   0x005B
-#define CIR_I2C_STATUS 0x005C
-#define CIR_I2C_QWRITE 0x005D
-#define CIR_I2C_QREAD  0x005E
-
-#define CS8409_CS42L42_HP_VOL_REAL_MIN   (-63)
-#define CS8409_CS42L42_HP_VOL_REAL_MAX   (0)
-#define CS8409_CS42L42_AMIC_VOL_REAL_MIN (-97)
-#define CS8409_CS42L42_AMIC_VOL_REAL_MAX (12)
-#define CS8409_CS42L42_REG_HS_VOLUME_CHA (0x2301)
-#define CS8409_CS42L42_REG_HS_VOLUME_CHB (0x2303)
-#define CS8409_CS42L42_REG_AMIC_VOLUME   (0x1D03)
-
-struct cs8409_i2c_param {
-       unsigned int addr;
-       unsigned int reg;
-};
-
-struct cs8409_cir_param {
-       unsigned int nid;
-       unsigned int cir;
-       unsigned int coeff;
-};
-
-enum {
-       CS8409_BULLSEYE,
-       CS8409_WARLOCK,
-       CS8409_CYBORG,
-       CS8409_FIXUPS,
-};
-
-static void cs8409_cs42l42_fixups(struct hda_codec *codec,
-                                   const struct hda_fixup *fix, int action);
-static int cs8409_cs42l42_exec_verb(struct hdac_device *dev,
-               unsigned int cmd, unsigned int flags, unsigned int *res);
-
-/* Dell Inspiron models with cs8409/cs42l42 */
-static const struct hda_model_fixup cs8409_models[] = {
-       { .id = CS8409_BULLSEYE, .name = "bullseye" },
-       { .id = CS8409_WARLOCK, .name = "warlock" },
-       { .id = CS8409_CYBORG, .name = "cyborg" },
-       {}
-};
-
-/* Dell Inspiron platforms
- * with cs8409 bridge and cs42l42 codec
- */
-static const struct snd_pci_quirk cs8409_fixup_tbl[] = {
-       SND_PCI_QUIRK(0x1028, 0x0A11, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A12, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A23, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A24, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A25, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A29, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A2A, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0A2B, "Bullseye", CS8409_BULLSEYE),
-       SND_PCI_QUIRK(0x1028, 0x0AB0, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AB2, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AB1, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AB3, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AB4, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AB5, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AD9, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0ADA, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0ADB, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0ADC, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AF4, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0AF5, "Warlock", CS8409_WARLOCK),
-       SND_PCI_QUIRK(0x1028, 0x0A77, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A78, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A79, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A7A, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A7D, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A7E, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A7F, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0A80, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0ADF, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AE0, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AE1, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AE2, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AE9, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AEA, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AEB, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AEC, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AED, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AEE, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AEF, "Cyborg", CS8409_CYBORG),
-       SND_PCI_QUIRK(0x1028, 0x0AF0, "Cyborg", CS8409_CYBORG),
-       {} /* terminator */
-};
-
-static const struct hda_verb cs8409_cs42l42_init_verbs[] = {
-       { 0x01, AC_VERB_SET_GPIO_WAKE_MASK, 0x0018 }, /* WAKE from GPIO 3,4 */
-       { 0x47, AC_VERB_SET_PROC_STATE, 0x0001 },     /* Enable VPW processing  */
-       { 0x47, AC_VERB_SET_COEF_INDEX, 0x0002 },     /* Configure GPIO 6,7 */
-       { 0x47, AC_VERB_SET_PROC_COEF,  0x0080 },     /* I2C mode */
-       { 0x47, AC_VERB_SET_COEF_INDEX, 0x005b },     /* Set I2C bus speed */
-       { 0x47, AC_VERB_SET_PROC_COEF,  0x0200 },     /* 100kHz I2C_STO = 2 */
-       {} /* terminator */
-};
-
-static const struct hda_pintbl cs8409_cs42l42_pincfgs[] = {
-       { 0x24, 0x042120f0 }, /* ASP-1-TX */
-       { 0x34, 0x04a12050 }, /* ASP-1-RX */
-       { 0x2c, 0x901000f0 }, /* ASP-2-TX */
-       { 0x44, 0x90a00090 }, /* DMIC-1 */
-       {} /* terminator */
-};
-
-static const struct hda_fixup cs8409_fixups[] = {
-       [CS8409_BULLSEYE] = {
-               .type = HDA_FIXUP_PINS,
-               .v.pins = cs8409_cs42l42_pincfgs,
-               .chained = true,
-               .chain_id = CS8409_FIXUPS,
-       },
-       [CS8409_WARLOCK] = {
-               .type = HDA_FIXUP_PINS,
-               .v.pins = cs8409_cs42l42_pincfgs,
-               .chained = true,
-               .chain_id = CS8409_FIXUPS,
-       },
-       [CS8409_CYBORG] = {
-               .type = HDA_FIXUP_PINS,
-               .v.pins = cs8409_cs42l42_pincfgs,
-               .chained = true,
-               .chain_id = CS8409_FIXUPS,
-       },
-       [CS8409_FIXUPS] = {
-               .type = HDA_FIXUP_FUNC,
-               .v.func = cs8409_cs42l42_fixups,
-       },
-};
-
-/* Vendor specific HW configuration for CS42L42 */
-static const struct cs8409_i2c_param cs42l42_init_reg_seq[] = {
-       { 0x1010, 0xB0 },
-       { 0x1D01, 0x00 },
-       { 0x1D02, 0x06 },
-       { 0x1D03, 0x00 },
-       { 0x1107, 0x01 },
-       { 0x1009, 0x02 },
-       { 0x1007, 0x03 },
-       { 0x1201, 0x00 },
-       { 0x1208, 0x13 },
-       { 0x1205, 0xFF },
-       { 0x1206, 0x00 },
-       { 0x1207, 0x20 },
-       { 0x1202, 0x0D },
-       { 0x2A02, 0x02 },
-       { 0x2A03, 0x00 },
-       { 0x2A04, 0x00 },
-       { 0x2A05, 0x02 },
-       { 0x2A06, 0x00 },
-       { 0x2A07, 0x20 },
-       { 0x2A08, 0x02 },
-       { 0x2A09, 0x00 },
-       { 0x2A0A, 0x80 },
-       { 0x2A0B, 0x02 },
-       { 0x2A0C, 0x00 },
-       { 0x2A0D, 0xA0 },
-       { 0x2A01, 0x0C },
-       { 0x2902, 0x01 },
-       { 0x2903, 0x02 },
-       { 0x2904, 0x00 },
-       { 0x2905, 0x00 },
-       { 0x2901, 0x01 },
-       { 0x1101, 0x0A },
-       { 0x1102, 0x84 },
-       { 0x2301, 0x00 },
-       { 0x2303, 0x00 },
-       { 0x2302, 0x3f },
-       { 0x2001, 0x03 },
-       { 0x1B75, 0xB6 },
-       { 0x1B73, 0xC2 },
-       { 0x1129, 0x01 },
-       { 0x1121, 0xF3 },
-       { 0x1103, 0x20 },
-       { 0x1105, 0x00 },
-       { 0x1112, 0xC0 },
-       { 0x1113, 0x80 },
-       { 0x1C03, 0xC0 },
-       { 0x1105, 0x00 },
-       { 0x1112, 0xC0 },
-       { 0x1101, 0x02 },
-       {} /* Terminator */
-};
-
-/* Vendor specific hw configuration for CS8409 */
-static const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[] = {
-       { 0x47, 0x00, 0xb008 }, /* +PLL1/2_EN, +I2C_EN */
-       { 0x47, 0x01, 0x0002 }, /* ASP1/2_EN=0, ASP1_STP=1 */
-       { 0x47, 0x02, 0x0a80 }, /* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
-       { 0x47, 0x19, 0x0800 }, /* ASP1.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
-       { 0x47, 0x1a, 0x0820 }, /* ASP1.A: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=32 */
-       { 0x47, 0x29, 0x0800 }, /* ASP2.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
-       { 0x47, 0x2a, 0x2800 }, /* ASP2.A: TX.RAP=1, TX.RSZ=24 bits, TX.RCS=0 */
-       { 0x47, 0x39, 0x0800 }, /* ASP1.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
-       { 0x47, 0x3a, 0x0800 }, /* ASP1.A: RX.RAP=0, RX.RSZ=24 bits, RX.RCS=0 */
-       { 0x47, 0x03, 0x8000 }, /* ASP1: LCHI = 00h */
-       { 0x47, 0x04, 0x28ff }, /* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
-       { 0x47, 0x05, 0x0062 }, /* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
-       { 0x47, 0x06, 0x801f }, /* ASP2: LCHI=1Fh */
-       { 0x47, 0x07, 0x283f }, /* ASP2: MC/SC_SRCSEL=PLL1, LCPR=3Fh */
-       { 0x47, 0x08, 0x805c }, /* ASP2: 5050=1, MCEN=0, FSD=010, SCPOL_IN/OUT=1, SCDIV=1:16 */
-       { 0x47, 0x09, 0x0023 }, /* DMIC1_MO=10b, DMIC1/2_SR=1 */
-       { 0x47, 0x0a, 0x0000 }, /* ASP1/2_BEEP=0 */
-       { 0x47, 0x01, 0x0062 }, /* ASP1/2_EN=1, ASP1_STP=1 */
-       { 0x47, 0x00, 0x9008 }, /* -PLL2_EN */
-       { 0x47, 0x68, 0x0000 }, /* TX2.A: pre-scale att.=0 dB */
-       { 0x47, 0x82, 0xfc03 }, /* ASP1/2_xxx_EN=1, ASP1/2_MCLK_EN=0, DMIC1_SCL_EN=1 */
-       { 0x47, 0xc0, 0x9999 }, /* test mode on */
-       { 0x47, 0xc5, 0x0000 }, /* GPIO hysteresis = 30 us */
-       { 0x47, 0xc0, 0x0000 }, /* test mode off */
-       {} /* Terminator */
-};
-
-static const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[] = {
-       { 0x47, 0x65, 0x4000 }, /* EQ_SEL=1, EQ1/2_EN=0 */
-       { 0x47, 0x64, 0x4000 }, /* +EQ_ACC */
-       { 0x47, 0x65, 0x4010 }, /* +EQ2_EN */
-       { 0x47, 0x63, 0x0647 }, /* EQ_DATA_HI=0x0647 */
-       { 0x47, 0x64, 0xc0c7 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=0, EQ_DATA_LO=0x67 */
-       { 0x47, 0x63, 0x0647 }, /* EQ_DATA_HI=0x0647 */
-       { 0x47, 0x64, 0xc1c7 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=1, EQ_DATA_LO=0x67 */
-       { 0x47, 0x63, 0xf370 }, /* EQ_DATA_HI=0xf370 */
-       { 0x47, 0x64, 0xc271 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=2, EQ_DATA_LO=0x71 */
-       { 0x47, 0x63, 0x1ef8 }, /* EQ_DATA_HI=0x1ef8 */
-       { 0x47, 0x64, 0xc348 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=3, EQ_DATA_LO=0x48 */
-       { 0x47, 0x63, 0xc110 }, /* EQ_DATA_HI=0xc110 */
-       { 0x47, 0x64, 0xc45a }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=4, EQ_DATA_LO=0x5a */
-       { 0x47, 0x63, 0x1f29 }, /* EQ_DATA_HI=0x1f29 */
-       { 0x47, 0x64, 0xc574 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=5, EQ_DATA_LO=0x74 */
-       { 0x47, 0x63, 0x1d7a }, /* EQ_DATA_HI=0x1d7a */
-       { 0x47, 0x64, 0xc653 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=6, EQ_DATA_LO=0x53 */
-       { 0x47, 0x63, 0xc38c }, /* EQ_DATA_HI=0xc38c */
-       { 0x47, 0x64, 0xc714 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=7, EQ_DATA_LO=0x14 */
-       { 0x47, 0x63, 0x1ca3 }, /* EQ_DATA_HI=0x1ca3 */
-       { 0x47, 0x64, 0xc8c7 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=8, EQ_DATA_LO=0xc7 */
-       { 0x47, 0x63, 0xc38c }, /* EQ_DATA_HI=0xc38c */
-       { 0x47, 0x64, 0xc914 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=9, EQ_DATA_LO=0x14 */
-       { 0x47, 0x64, 0x0000 }, /* -EQ_ACC, -EQ_WRT */
-       {} /* Terminator */
-};
-
-/**
- * cs8409_enable_i2c_clock - Enable I2C clocks
- * @codec: the codec instance
- * @enable: Enable or disable I2C clocks
- *
- * Enable or Disable I2C clocks.
- */
-static void cs8409_enable_i2c_clock(struct hda_codec *codec, unsigned int enable)
-{
-       unsigned int retval;
-       unsigned int newval;
-
-       retval = cs_vendor_coef_get(codec, 0x0);
-       newval = (enable) ? (retval | 0x8) : (retval & 0xfffffff7);
-       cs_vendor_coef_set(codec, 0x0, newval);
-}
-
-/**
- * cs8409_i2c_wait_complete - Wait for I2C transaction
- * @codec: the codec instance
- *
- * Wait for I2C transaction to complete.
- * Return -1 if transaction wait times out.
- */
-static int cs8409_i2c_wait_complete(struct hda_codec *codec)
-{
-       int repeat = 5;
-       unsigned int retval;
-
-       do {
-               retval = cs_vendor_coef_get(codec, CIR_I2C_STATUS);
-               if ((retval & 0x18) != 0x18) {
-                       usleep_range(2000, 4000);
-                       --repeat;
-               } else
-                       return 0;
-
-       } while (repeat);
-
-       return -1;
-}
-
-/**
- * cs8409_i2c_read - CS8409 I2C Read.
- * @codec: the codec instance
- * @i2c_address: I2C Address
- * @i2c_reg: Register to read
- * @paged: Is a paged transaction
- *
- * CS8409 I2C Read.
- * Returns negative on error, otherwise returns read value in bits 0-7.
- */
-static int cs8409_i2c_read(struct hda_codec *codec,
-               unsigned int i2c_address,
-               unsigned int i2c_reg,
-               unsigned int paged)
-{
-       unsigned int i2c_reg_data;
-       unsigned int read_data;
-
-       cs8409_enable_i2c_clock(codec, 1);
-       cs_vendor_coef_set(codec, CIR_I2C_ADDR, i2c_address);
-
-       if (paged) {
-               cs_vendor_coef_set(codec, CIR_I2C_QWRITE, i2c_reg >> 8);
-               if (cs8409_i2c_wait_complete(codec) < 0) {
-                       codec_err(codec,
-                               "%s() Paged Transaction Failed 0x%02x : 0x%04x\n",
-                               __func__, i2c_address, i2c_reg);
-                       return -EIO;
-               }
-       }
-
-       i2c_reg_data = (i2c_reg << 8) & 0x0ffff;
-       cs_vendor_coef_set(codec, CIR_I2C_QREAD, i2c_reg_data);
-       if (cs8409_i2c_wait_complete(codec) < 0) {
-               codec_err(codec, "%s() Transaction Failed 0x%02x : 0x%04x\n",
-                       __func__, i2c_address, i2c_reg);
-               return -EIO;
-       }
-
-       /* Register in bits 15-8 and the data in 7-0 */
-       read_data = cs_vendor_coef_get(codec, CIR_I2C_QREAD);
-
-       cs8409_enable_i2c_clock(codec, 0);
-
-       return read_data & 0x0ff;
-}
-
-/**
- * cs8409_i2c_write - CS8409 I2C Write.
- * @codec: the codec instance
- * @i2c_address: I2C Address
- * @i2c_reg: Register to write to
- * @i2c_data: Data to write
- * @paged: Is a paged transaction
- *
- * CS8409 I2C Write.
- * Returns negative on error, otherwise returns 0.
- */
-static int cs8409_i2c_write(struct hda_codec *codec,
-               unsigned int i2c_address, unsigned int i2c_reg,
-               unsigned int i2c_data,
-               unsigned int paged)
-{
-       unsigned int i2c_reg_data;
-
-       cs8409_enable_i2c_clock(codec, 1);
-       cs_vendor_coef_set(codec, CIR_I2C_ADDR, i2c_address);
-
-       if (paged) {
-               cs_vendor_coef_set(codec, CIR_I2C_QWRITE, i2c_reg >> 8);
-               if (cs8409_i2c_wait_complete(codec) < 0) {
-                       codec_err(codec,
-                               "%s() Paged Transaction Failed 0x%02x : 0x%04x\n",
-                               __func__, i2c_address, i2c_reg);
-                       return -EIO;
-               }
-       }
-
-       i2c_reg_data = ((i2c_reg << 8) & 0x0ff00) | (i2c_data & 0x0ff);
-       cs_vendor_coef_set(codec, CIR_I2C_QWRITE, i2c_reg_data);
-
-       if (cs8409_i2c_wait_complete(codec) < 0) {
-               codec_err(codec, "%s() Transaction Failed 0x%02x : 0x%04x\n",
-                       __func__, i2c_address, i2c_reg);
-               return -EIO;
-       }
-
-       cs8409_enable_i2c_clock(codec, 0);
-
-       return 0;
-}
-
-static int cs8409_cs42l42_volume_info(struct snd_kcontrol *kcontrol,
-                                 struct snd_ctl_elem_info *uinfo)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       u16 nid = get_amp_nid(kcontrol);
-       u8 chs = get_amp_channels(kcontrol);
-
-       codec_dbg(codec, "%s() nid: %d\n", __func__, nid);
-       switch (nid) {
-       case CS8409_CS42L42_HP_PIN_NID:
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-               uinfo->count = chs == 3 ? 2 : 1;
-               uinfo->value.integer.min = CS8409_CS42L42_HP_VOL_REAL_MIN;
-               uinfo->value.integer.max = CS8409_CS42L42_HP_VOL_REAL_MAX;
-               break;
-       case CS8409_CS42L42_AMIC_PIN_NID:
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-               uinfo->count = chs == 3 ? 2 : 1;
-               uinfo->value.integer.min = CS8409_CS42L42_AMIC_VOL_REAL_MIN;
-               uinfo->value.integer.max = CS8409_CS42L42_AMIC_VOL_REAL_MAX;
-               break;
-       default:
-               break;
-       }
-       return 0;
-}
-
-static void cs8409_cs42l42_update_volume(struct hda_codec *codec)
-{
-       struct cs_spec *spec = codec->spec;
-       int data;
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-       data = cs8409_i2c_read(codec, CS42L42_I2C_ADDR,
-                               CS8409_CS42L42_REG_HS_VOLUME_CHA, 1);
-       if (data >= 0)
-               spec->cs42l42_hp_volume[0] = -data;
-       else
-               spec->cs42l42_hp_volume[0] = CS8409_CS42L42_HP_VOL_REAL_MIN;
-       data = cs8409_i2c_read(codec, CS42L42_I2C_ADDR,
-                               CS8409_CS42L42_REG_HS_VOLUME_CHB, 1);
-       if (data >= 0)
-               spec->cs42l42_hp_volume[1] = -data;
-       else
-               spec->cs42l42_hp_volume[1] = CS8409_CS42L42_HP_VOL_REAL_MIN;
-       data = cs8409_i2c_read(codec, CS42L42_I2C_ADDR,
-                               CS8409_CS42L42_REG_AMIC_VOLUME, 1);
-       if (data >= 0)
-               spec->cs42l42_hs_mic_volume[0] = -data;
-       else
-               spec->cs42l42_hs_mic_volume[0] = CS8409_CS42L42_AMIC_VOL_REAL_MIN;
-       mutex_unlock(&spec->cs8409_i2c_mux);
-       spec->cs42l42_volume_init = 1;
-}
-
-static int cs8409_cs42l42_volume_get(struct snd_kcontrol *kcontrol,
-                                struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct cs_spec *spec = codec->spec;
-       hda_nid_t nid = get_amp_nid(kcontrol);
-       int chs = get_amp_channels(kcontrol);
-       long *valp = ucontrol->value.integer.value;
-
-       if (!spec->cs42l42_volume_init) {
-               snd_hda_power_up(codec);
-               cs8409_cs42l42_update_volume(codec);
-               snd_hda_power_down(codec);
-       }
-       switch (nid) {
-       case CS8409_CS42L42_HP_PIN_NID:
-               if (chs & BIT(0))
-                       *valp++ = spec->cs42l42_hp_volume[0];
-               if (chs & BIT(1))
-                       *valp++ = spec->cs42l42_hp_volume[1];
-               break;
-       case CS8409_CS42L42_AMIC_PIN_NID:
-               if (chs & BIT(0))
-                       *valp++ = spec->cs42l42_hs_mic_volume[0];
-               break;
-       default:
-               break;
-       }
-       return 0;
-}
-
-static int cs8409_cs42l42_volume_put(struct snd_kcontrol *kcontrol,
-                                struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct cs_spec *spec = codec->spec;
-       hda_nid_t nid = get_amp_nid(kcontrol);
-       int chs = get_amp_channels(kcontrol);
-       long *valp = ucontrol->value.integer.value;
-       int change = 0;
-       char vol;
-
-       snd_hda_power_up(codec);
-       switch (nid) {
-       case CS8409_CS42L42_HP_PIN_NID:
-               mutex_lock(&spec->cs8409_i2c_mux);
-               if (chs & BIT(0)) {
-                       vol = -(*valp);
-                       change = cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
-                               CS8409_CS42L42_REG_HS_VOLUME_CHA, vol, 1);
-                       valp++;
-               }
-               if (chs & BIT(1)) {
-                       vol = -(*valp);
-                       change |= cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
-                               CS8409_CS42L42_REG_HS_VOLUME_CHB, vol, 1);
-               }
-               mutex_unlock(&spec->cs8409_i2c_mux);
-               break;
-       case CS8409_CS42L42_AMIC_PIN_NID:
-               mutex_lock(&spec->cs8409_i2c_mux);
-               if (chs & BIT(0)) {
-                       change = cs8409_i2c_write(
-                               codec, CS42L42_I2C_ADDR,
-                               CS8409_CS42L42_REG_AMIC_VOLUME, (char)*valp, 1);
-                       valp++;
-               }
-               mutex_unlock(&spec->cs8409_i2c_mux);
-               break;
-       default:
-               break;
-       }
-       cs8409_cs42l42_update_volume(codec);
-       snd_hda_power_down(codec);
-       return change;
-}
-
-static const DECLARE_TLV_DB_SCALE(
-       cs8409_cs42l42_hp_db_scale,
-       CS8409_CS42L42_HP_VOL_REAL_MIN * 100, 100, 1);
-
-static const DECLARE_TLV_DB_SCALE(
-       cs8409_cs42l42_amic_db_scale,
-       CS8409_CS42L42_AMIC_VOL_REAL_MIN * 100, 100, 1);
-
-static const struct snd_kcontrol_new cs8409_cs42l42_hp_volume_mixer = {
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .index = 0,
-       .name = "Headphone Playback Volume",
-       .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
-       .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE
-                        | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
-       .info = cs8409_cs42l42_volume_info,
-       .get = cs8409_cs42l42_volume_get,
-       .put = cs8409_cs42l42_volume_put,
-       .tlv = { .p = cs8409_cs42l42_hp_db_scale },
-       .private_value = HDA_COMPOSE_AMP_VAL(
-               CS8409_CS42L42_HP_PIN_NID, 3, 0, HDA_OUTPUT)
-               | HDA_AMP_VAL_MIN_MUTE
-};
-
-static const struct snd_kcontrol_new cs8409_cs42l42_amic_volume_mixer = {
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .index = 0,
-       .name = "Mic Capture Volume",
-       .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
-       .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE
-                        | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
-       .info = cs8409_cs42l42_volume_info,
-       .get = cs8409_cs42l42_volume_get,
-       .put = cs8409_cs42l42_volume_put,
-       .tlv = { .p = cs8409_cs42l42_amic_db_scale },
-       .private_value = HDA_COMPOSE_AMP_VAL(
-               CS8409_CS42L42_AMIC_PIN_NID, 1, 0, HDA_INPUT)
-               | HDA_AMP_VAL_MIN_MUTE
-};
-
-/* Assert/release RTS# line to CS42L42 */
-static void cs8409_cs42l42_reset(struct hda_codec *codec)
-{
-       struct cs_spec *spec = codec->spec;
-
-       /* Assert RTS# line */
-       snd_hda_codec_write(codec,
-                       codec->core.afg, 0, AC_VERB_SET_GPIO_DATA, 0);
-       /* wait ~10ms */
-       usleep_range(10000, 15000);
-       /* Release RTS# line */
-       snd_hda_codec_write(codec,
-                       codec->core.afg, 0, AC_VERB_SET_GPIO_DATA, GPIO5_INT);
-       /* wait ~10ms */
-       usleep_range(10000, 15000);
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-
-       /* Clear interrupts, by reading interrupt status registers */
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308, 1);
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1309, 1);
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130A, 1);
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130F, 1);
-
-       mutex_unlock(&spec->cs8409_i2c_mux);
-
-}
-
-/* Configure CS42L42 slave codec for jack autodetect */
-static void cs8409_cs42l42_enable_jack_detect(struct hda_codec *codec)
-{
-       struct cs_spec *spec = codec->spec;
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-
-       /* Set TIP_SENSE_EN for analog front-end of tip sense. */
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b70, 0x0020, 1);
-       /* Clear WAKE# */
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b71, 0x0001, 1);
-       /* Wait ~2.5ms */
-       usleep_range(2500, 3000);
-       /* Set mode WAKE# output follows the combination logic directly */
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b71, 0x0020, 1);
-       /* Clear interrupts status */
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f, 1);
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1b7b, 1);
-       /* Enable interrupt */
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0x03, 1);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b79, 0x00, 1);
-
-       mutex_unlock(&spec->cs8409_i2c_mux);
-}
-
-/* Enable and run CS42L42 slave codec jack auto detect */
-static void cs8409_cs42l42_run_jack_detect(struct hda_codec *codec)
-{
-       struct cs_spec *spec = codec->spec;
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-
-       /* Clear interrupts */
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308, 1);
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1b77, 1);
-
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1102, 0x87, 1);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1f06, 0x86, 1);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b74, 0x07, 1);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x131b, 0x01, 1);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1120, 0x80, 1);
-       /* Wait ~110ms*/
-       usleep_range(110000, 200000);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x111f, 0x77, 1);
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1120, 0xc0, 1);
-       /* Wait ~10ms */
-       usleep_range(10000, 25000);
-
-       mutex_unlock(&spec->cs8409_i2c_mux);
-
-}
-
-static void cs8409_cs42l42_reg_setup(struct hda_codec *codec)
-{
-       const struct cs8409_i2c_param *seq = cs42l42_init_reg_seq;
-       struct cs_spec *spec = codec->spec;
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-
-       for (; seq->addr; seq++)
-               cs8409_i2c_write(codec, CS42L42_I2C_ADDR, seq->addr, seq->reg, 1);
-
-       mutex_unlock(&spec->cs8409_i2c_mux);
-
-}
-
-/*
- * In the case of CS8409 we do not have unsolicited events from NID's 0x24
- * and 0x34 where hs mic and hp are connected. Companion codec CS42L42 will
- * generate interrupt via gpio 4 to notify jack events. We have to overwrite
- * generic snd_hda_jack_unsol_event(), read CS42L42 jack detect status registers
- * and then notify status via generic snd_hda_jack_unsol_event() call.
- */
-static void cs8409_jack_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-       struct cs_spec *spec = codec->spec;
-       int status_changed = 0;
-       int reg_cdc_status;
-       int reg_hs_status;
-       int reg_ts_status;
-       int type;
-       struct hda_jack_tbl *jk;
-
-       /* jack_unsol_event() will be called every time gpio line changing state.
-        * In this case gpio4 line goes up as a result of reading interrupt status
-        * registers in previous cs8409_jack_unsol_event() call.
-        * We don't need to handle this event, ignoring...
-        */
-       if ((res & (1 << 4)))
-               return;
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-
-       /* Read jack detect status registers */
-       reg_cdc_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308, 1);
-       reg_hs_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1124, 1);
-       reg_ts_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f, 1);
-
-       /* Clear interrupts, by reading interrupt status registers */
-       cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1b7b, 1);
-
-       mutex_unlock(&spec->cs8409_i2c_mux);
-
-       /* If status values are < 0, read error has occurred. */
-       if (reg_cdc_status < 0 || reg_hs_status < 0 || reg_ts_status < 0)
-               return;
-
-       /* HSDET_AUTO_DONE */
-       if (reg_cdc_status & CS42L42_HSDET_AUTO_DONE) {
-
-               type = ((reg_hs_status & CS42L42_HSTYPE_MASK) + 1);
-               /* CS42L42 reports optical jack as type 4
-                * We don't handle optical jack
-                */
-               if (type != 4) {
-                       if (!spec->cs42l42_hp_jack_in) {
-                               status_changed = 1;
-                               spec->cs42l42_hp_jack_in = 1;
-                       }
-                       /* type = 3 has no mic */
-                       if ((!spec->cs42l42_mic_jack_in) && (type != 3)) {
-                               status_changed = 1;
-                               spec->cs42l42_mic_jack_in = 1;
-                       }
-               } else {
-                       if (spec->cs42l42_hp_jack_in || spec->cs42l42_mic_jack_in) {
-                               status_changed = 1;
-                               spec->cs42l42_hp_jack_in = 0;
-                               spec->cs42l42_mic_jack_in = 0;
-                       }
-               }
-
-       } else {
-               /* TIP_SENSE INSERT/REMOVE */
-               switch (reg_ts_status) {
-               case CS42L42_JACK_INSERTED:
-                       cs8409_cs42l42_run_jack_detect(codec);
-                       break;
-
-               case CS42L42_JACK_REMOVED:
-                       if (spec->cs42l42_hp_jack_in || spec->cs42l42_mic_jack_in) {
-                               status_changed = 1;
-                               spec->cs42l42_hp_jack_in = 0;
-                               spec->cs42l42_mic_jack_in = 0;
-                       }
-                       break;
-
-               default:
-                       /* jack in transition */
-                       status_changed = 0;
-                       break;
-               }
-       }
-
-       if (status_changed) {
-
-               snd_hda_set_pin_ctl(codec, CS8409_CS42L42_SPK_PIN_NID,
-                               spec->cs42l42_hp_jack_in ? 0 : PIN_OUT);
-
-               /* Report jack*/
-               jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_HP_PIN_NID, 0);
-               if (jk) {
-                       snd_hda_jack_unsol_event(codec,
-                               (jk->tag << AC_UNSOL_RES_TAG_SHIFT) & AC_UNSOL_RES_TAG);
-               }
-               /* Report jack*/
-               jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_AMIC_PIN_NID, 0);
-               if (jk) {
-                       snd_hda_jack_unsol_event(codec,
-                               (jk->tag << AC_UNSOL_RES_TAG_SHIFT) & AC_UNSOL_RES_TAG);
-               }
-       }
-}
-
-#ifdef CONFIG_PM
-/* Manage PDREF, when transition to D3hot */
-static int cs8409_suspend(struct hda_codec *codec)
-{
-       struct cs_spec *spec = codec->spec;
-
-       mutex_lock(&spec->cs8409_i2c_mux);
-       /* Power down CS42L42 ASP/EQ/MIX/HP */
-       cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1101, 0xfe, 1);
-       mutex_unlock(&spec->cs8409_i2c_mux);
-       /* Assert CS42L42 RTS# line */
-       snd_hda_codec_write(codec,
-                       codec->core.afg, 0, AC_VERB_SET_GPIO_DATA, 0);
-
-       snd_hda_shutup_pins(codec);
-
-       return 0;
-}
-#endif
-
-/* Enable/Disable Unsolicited Response for gpio(s) 3,4 */
-static void cs8409_enable_ur(struct hda_codec *codec, int flag)
-{
-       /* GPIO4 INT# and GPIO3 WAKE# */
-       snd_hda_codec_write(codec, codec->core.afg,
-                       0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK,
-                       flag ? (GPIO3_INT | GPIO4_INT) : 0);
-
-       snd_hda_codec_write(codec, codec->core.afg,
-                       0, AC_VERB_SET_UNSOLICITED_ENABLE,
-                       flag ? AC_UNSOL_ENABLED : 0);
-
-}
-
-/* Vendor specific HW configuration
- * PLL, ASP, I2C, SPI, GPIOs, DMIC etc...
- */
-static void cs8409_cs42l42_hw_init(struct hda_codec *codec)
-{
-       const struct cs8409_cir_param *seq = cs8409_cs42l42_hw_cfg;
-       const struct cs8409_cir_param *seq_bullseye = cs8409_cs42l42_bullseye_atn;
-       struct cs_spec *spec = codec->spec;
-
-       if (spec->gpio_mask) {
-               snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
-                                   spec->gpio_mask);
-               snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
-                                   spec->gpio_dir);
-               snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
-                                   spec->gpio_data);
-       }
-
-       for (; seq->nid; seq++)
-               cs_vendor_coef_set(codec, seq->cir, seq->coeff);
-
-       if (codec->fixup_id == CS8409_BULLSEYE)
-               for (; seq_bullseye->nid; seq_bullseye++)
-                       cs_vendor_coef_set(codec, seq_bullseye->cir, seq_bullseye->coeff);
-
-       /* Disable Unsolicited Response during boot */
-       cs8409_enable_ur(codec, 0);
-
-       /* Reset CS42L42 */
-       cs8409_cs42l42_reset(codec);
-
-       /* Initialise CS42L42 companion codec */
-       cs8409_cs42l42_reg_setup(codec);
-
-       if (codec->fixup_id == CS8409_WARLOCK ||
-                       codec->fixup_id == CS8409_CYBORG) {
-               /* FULL_SCALE_VOL = 0 for Warlock / Cyborg */
-               mutex_lock(&spec->cs8409_i2c_mux);
-               cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x2001, 0x01, 1);
-               mutex_unlock(&spec->cs8409_i2c_mux);
-               /* DMIC1_MO=00b, DMIC1/2_SR=1 */
-               cs_vendor_coef_set(codec, 0x09, 0x0003);
-       }
-
-       /* Restore Volumes after Resume */
-       if (spec->cs42l42_volume_init) {
-               mutex_lock(&spec->cs8409_i2c_mux);
-               cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
-                                       CS8409_CS42L42_REG_HS_VOLUME_CHA,
-                                       -spec->cs42l42_hp_volume[0],
-                                       1);
-               cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
-                                       CS8409_CS42L42_REG_HS_VOLUME_CHB,
-                                       -spec->cs42l42_hp_volume[1],
-                                       1);
-               cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
-                                       CS8409_CS42L42_REG_AMIC_VOLUME,
-                                       spec->cs42l42_hs_mic_volume[0],
-                                       1);
-               mutex_unlock(&spec->cs8409_i2c_mux);
-       }
-
-       cs8409_cs42l42_update_volume(codec);
-
-       cs8409_cs42l42_enable_jack_detect(codec);
-
-       /* Enable Unsolicited Response */
-       cs8409_enable_ur(codec, 1);
-}
-
-static int cs8409_cs42l42_init(struct hda_codec *codec)
-{
-       int ret = snd_hda_gen_init(codec);
-
-       if (!ret)
-               snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
-
-       return ret;
-}
-
-static const struct hda_codec_ops cs8409_cs42l42_patch_ops = {
-       .build_controls = cs_build_controls,
-       .build_pcms = snd_hda_gen_build_pcms,
-       .init = cs8409_cs42l42_init,
-       .free = cs_free,
-       .unsol_event = cs8409_jack_unsol_event,
-#ifdef CONFIG_PM
-       .suspend = cs8409_suspend,
-#endif
-};
-
-static void cs8409_cs42l42_fixups(struct hda_codec *codec,
-                                   const struct hda_fixup *fix, int action)
-{
-       struct cs_spec *spec = codec->spec;
-       int caps;
-
-       switch (action) {
-       case HDA_FIXUP_ACT_PRE_PROBE:
-               snd_hda_add_verbs(codec, cs8409_cs42l42_init_verbs);
-               /* verb exec op override */
-               spec->exec_verb = codec->core.exec_verb;
-               codec->core.exec_verb = cs8409_cs42l42_exec_verb;
-
-               mutex_init(&spec->cs8409_i2c_mux);
-
-               codec->patch_ops = cs8409_cs42l42_patch_ops;
-
-               spec->gen.suppress_auto_mute = 1;
-               spec->gen.no_primary_hp = 1;
-               spec->gen.suppress_vmaster = 1;
-
-               /* GPIO 5 out, 3,4 in */
-               spec->gpio_dir = GPIO5_INT;
-               spec->gpio_data = 0;
-               spec->gpio_mask = 0x03f;
-
-               spec->cs42l42_hp_jack_in = 0;
-               spec->cs42l42_mic_jack_in = 0;
-
-               /* Basic initial sequence for specific hw configuration */
-               snd_hda_sequence_write(codec, cs8409_cs42l42_init_verbs);
-
-               /* CS8409 is simple HDA bridge and intended to be used with a remote
-                * companion codec. Most of input/output PIN(s) have only basic
-                * capabilities. NID(s) 0x24 and 0x34 have only OUTC and INC
-                * capabilities and no presence detect capable (PDC) and call to
-                * snd_hda_gen_build_controls() will mark them as non detectable
-                * phantom jacks. However, in this configuration companion codec
-                * CS42L42 is connected to these pins and it has jack detect
-                * capabilities. We have to override pin capabilities,
-                * otherwise they will not be created as input devices.
-                */
-               caps = snd_hdac_read_parm(&codec->core, CS8409_CS42L42_HP_PIN_NID,
-                               AC_PAR_PIN_CAP);
-               if (caps >= 0)
-                       snd_hdac_override_parm(&codec->core,
-                               CS8409_CS42L42_HP_PIN_NID, AC_PAR_PIN_CAP,
-                               (caps | (AC_PINCAP_IMP_SENSE | AC_PINCAP_PRES_DETECT)));
-
-               caps = snd_hdac_read_parm(&codec->core, CS8409_CS42L42_AMIC_PIN_NID,
-                               AC_PAR_PIN_CAP);
-               if (caps >= 0)
-                       snd_hdac_override_parm(&codec->core,
-                               CS8409_CS42L42_AMIC_PIN_NID, AC_PAR_PIN_CAP,
-                               (caps | (AC_PINCAP_IMP_SENSE | AC_PINCAP_PRES_DETECT)));
-
-               snd_hda_override_wcaps(codec, CS8409_CS42L42_HP_PIN_NID,
-                       (get_wcaps(codec, CS8409_CS42L42_HP_PIN_NID) | AC_WCAP_UNSOL_CAP));
-
-               snd_hda_override_wcaps(codec, CS8409_CS42L42_AMIC_PIN_NID,
-                       (get_wcaps(codec, CS8409_CS42L42_AMIC_PIN_NID) | AC_WCAP_UNSOL_CAP));
-               break;
-       case HDA_FIXUP_ACT_PROBE:
-
-               /* Set initial DMIC volume to -26 dB */
-               snd_hda_codec_amp_init_stereo(codec, CS8409_CS42L42_DMIC_ADC_PIN_NID,
-                               HDA_INPUT, 0, 0xff, 0x19);
-               snd_hda_gen_add_kctl(&spec->gen,
-                       NULL, &cs8409_cs42l42_hp_volume_mixer);
-               snd_hda_gen_add_kctl(&spec->gen,
-                       NULL, &cs8409_cs42l42_amic_volume_mixer);
-               cs8409_cs42l42_hw_init(codec);
-               snd_hda_codec_set_name(codec, "CS8409/CS42L42");
-               break;
-       case HDA_FIXUP_ACT_INIT:
-               cs8409_cs42l42_hw_init(codec);
-               fallthrough;
-       case HDA_FIXUP_ACT_BUILD:
-               /* Run jack auto detect first time on boot
-                * after controls have been added, to check if jack has
-                * been already plugged in.
-                * Run immediately after init.
-                */
-               cs8409_cs42l42_run_jack_detect(codec);
-               usleep_range(100000, 150000);
-               break;
-       default:
-               break;
-       }
-}
-
-static int cs8409_cs42l42_exec_verb(struct hdac_device *dev,
-               unsigned int cmd, unsigned int flags, unsigned int *res)
-{
-       struct hda_codec *codec = container_of(dev, struct hda_codec, core);
-       struct cs_spec *spec = codec->spec;
-
-       unsigned int nid = ((cmd >> 20) & 0x07f);
-       unsigned int verb = ((cmd >> 8) & 0x0fff);
-
-       /* CS8409 pins have no AC_PINSENSE_PRESENCE
-        * capabilities. We have to intercept 2 calls for pins 0x24 and 0x34
-        * and return correct pin sense values for read_pin_sense() call from
-        * hda_jack based on CS42L42 jack detect status.
-        */
-       switch (nid) {
-       case CS8409_CS42L42_HP_PIN_NID:
-               if (verb == AC_VERB_GET_PIN_SENSE) {
-                       *res = (spec->cs42l42_hp_jack_in) ? AC_PINSENSE_PRESENCE : 0;
-                       return 0;
-               }
-               break;
-
-       case CS8409_CS42L42_AMIC_PIN_NID:
-               if (verb == AC_VERB_GET_PIN_SENSE) {
-                       *res = (spec->cs42l42_mic_jack_in) ? AC_PINSENSE_PRESENCE : 0;
-                       return 0;
-               }
-               break;
-
-       default:
-               break;
-       }
-
-       return spec->exec_verb(dev, cmd, flags, res);
-}
-
-static int patch_cs8409(struct hda_codec *codec)
-{
-       int err;
-
-       if (!cs_alloc_spec(codec, CS8409_VENDOR_NID))
-               return -ENOMEM;
-
-       snd_hda_pick_fixup(codec,
-                       cs8409_models, cs8409_fixup_tbl, cs8409_fixups);
-
-       codec_dbg(codec, "Picked ID=%d, VID=%08x, DEV=%08x\n",
-                       codec->fixup_id,
-                       codec->bus->pci->subsystem_vendor,
-                       codec->bus->pci->subsystem_device);
-
-       snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
-       err = cs_parse_auto_config(codec);
-       if (err < 0) {
-               cs_free(codec);
-               return err;
-       }
-
-       snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-       return 0;
-}
-
 /*
  * patch entries
  */
@@ -2305,7 +1232,6 @@ static const struct hda_device_id snd_hda_id_cirrus[] = {
        HDA_CODEC_ENTRY(0x10134208, "CS4208", patch_cs4208),
        HDA_CODEC_ENTRY(0x10134210, "CS4210", patch_cs4210),
        HDA_CODEC_ENTRY(0x10134213, "CS4213", patch_cs4213),
-       HDA_CODEC_ENTRY(0x10138409, "CS8409", patch_cs8409),
        {} /* terminator */
 };
 MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cirrus);
index d111258..0515137 100644 (file)
@@ -177,30 +177,37 @@ static int cx_auto_init(struct hda_codec *codec)
        return 0;
 }
 
-static void cx_auto_reboot_notify(struct hda_codec *codec)
+static void cx_auto_shutdown(struct hda_codec *codec)
 {
        struct conexant_spec *spec = codec->spec;
 
        /* Turn the problematic codec into D3 to avoid spurious noises
           from the internal speaker during (and after) reboot */
        cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false);
-       snd_hda_gen_reboot_notify(codec);
 }
 
 static void cx_auto_free(struct hda_codec *codec)
 {
-       cx_auto_reboot_notify(codec);
+       cx_auto_shutdown(codec);
        snd_hda_gen_free(codec);
 }
 
+#ifdef CONFIG_PM
+static int cx_auto_suspend(struct hda_codec *codec)
+{
+       cx_auto_shutdown(codec);
+       return 0;
+}
+#endif
+
 static const struct hda_codec_ops cx_auto_patch_ops = {
        .build_controls = snd_hda_gen_build_controls,
        .build_pcms = snd_hda_gen_build_pcms,
        .init = cx_auto_init,
-       .reboot_notify = cx_auto_reboot_notify,
        .free = cx_auto_free,
        .unsol_event = snd_hda_jack_unsol_event,
 #ifdef CONFIG_PM
+       .suspend = cx_auto_suspend,
        .check_power_status = snd_hda_gen_check_power_status,
 #endif
 };
diff --git a/sound/pci/hda/patch_cs8409-tables.c b/sound/pci/hda/patch_cs8409-tables.c
new file mode 100644 (file)
index 0000000..0fb0a42
--- /dev/null
@@ -0,0 +1,560 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * patch_cs8409-tables.c  --  HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
+ *
+ * Copyright (C) 2021 Cirrus Logic, Inc. and
+ *                    Cirrus Logic International Semiconductor Ltd.
+ *
+ * Author: Lucas Tanure <tanureal@opensource.cirrus.com>
+ */
+
+#include "patch_cs8409.h"
+
+/******************************************************************************
+ *                          CS42L42 Specific Data
+ *
+ ******************************************************************************/
+
+static const DECLARE_TLV_DB_SCALE(cs42l42_dac_db_scale, CS42L42_HP_VOL_REAL_MIN * 100, 100, 1);
+
+static const DECLARE_TLV_DB_SCALE(cs42l42_adc_db_scale, CS42L42_AMIC_VOL_REAL_MIN * 100, 100, 1);
+
+const struct snd_kcontrol_new cs42l42_dac_volume_mixer = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .index = 0,
+       .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
+       .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+       .info = cs42l42_volume_info,
+       .get = cs42l42_volume_get,
+       .put = cs42l42_volume_put,
+       .tlv = { .p = cs42l42_dac_db_scale },
+       .private_value = HDA_COMPOSE_AMP_VAL_OFS(CS8409_PIN_ASP1_TRANSMITTER_A, 3, CS8409_CODEC0,
+                        HDA_OUTPUT, CS42L42_VOL_DAC) | HDA_AMP_VAL_MIN_MUTE
+};
+
+const struct snd_kcontrol_new cs42l42_adc_volume_mixer = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .index = 0,
+       .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
+       .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+       .info = cs42l42_volume_info,
+       .get = cs42l42_volume_get,
+       .put = cs42l42_volume_put,
+       .tlv = { .p = cs42l42_adc_db_scale },
+       .private_value = HDA_COMPOSE_AMP_VAL_OFS(CS8409_PIN_ASP1_RECEIVER_A, 1, CS8409_CODEC0,
+                        HDA_INPUT, CS42L42_VOL_ADC) | HDA_AMP_VAL_MIN_MUTE
+};
+
+const struct hda_pcm_stream cs42l42_48k_pcm_analog_playback = {
+       .rates = SNDRV_PCM_RATE_48000, /* fixed rate */
+};
+
+const struct hda_pcm_stream cs42l42_48k_pcm_analog_capture = {
+       .rates = SNDRV_PCM_RATE_48000, /* fixed rate */
+};
+
+/******************************************************************************
+ *                   BULLSEYE / WARLOCK / CYBORG Specific Arrays
+ *                               CS8409/CS42L42
+ ******************************************************************************/
+
+const struct hda_verb cs8409_cs42l42_init_verbs[] = {
+       { CS8409_PIN_AFG, AC_VERB_SET_GPIO_WAKE_MASK, 0x0018 },         /* WAKE from GPIO 3,4 */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_STATE, 0x0001 },   /* Enable VPW processing */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x0002 },   /* Configure GPIO 6,7 */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF,  0x0080 },   /* I2C mode */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x005b },   /* Set I2C bus speed */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF,  0x0200 },   /* 100kHz I2C_STO = 2 */
+       {} /* terminator */
+};
+
+const struct hda_pintbl cs8409_cs42l42_pincfgs[] = {
+       { CS8409_PIN_ASP1_TRANSMITTER_A, 0x042120f0 },  /* ASP-1-TX */
+       { CS8409_PIN_ASP1_RECEIVER_A, 0x04a12050 },     /* ASP-1-RX */
+       { CS8409_PIN_ASP2_TRANSMITTER_A, 0x901000f0 },  /* ASP-2-TX */
+       { CS8409_PIN_DMIC1_IN, 0x90a00090 },            /* DMIC-1 */
+       {} /* terminator */
+};
+
+/* Vendor specific HW configuration for CS42L42 */
+static const struct cs8409_i2c_param cs42l42_init_reg_seq[] = {
+       { 0x1010, 0xB0 },
+       { 0x1D01, 0x00 },
+       { 0x1D02, 0x06 },
+       { 0x1D03, 0x9F },
+       { 0x1107, 0x01 },
+       { 0x1009, 0x02 },
+       { 0x1007, 0x03 },
+       { 0x1201, 0x00 },
+       { 0x1208, 0x13 },
+       { 0x1205, 0xFF },
+       { 0x1206, 0x00 },
+       { 0x1207, 0x20 },
+       { 0x1202, 0x0D },
+       { 0x2A02, 0x02 },
+       { 0x2A03, 0x00 },
+       { 0x2A04, 0x00 },
+       { 0x2A05, 0x02 },
+       { 0x2A06, 0x00 },
+       { 0x2A07, 0x20 },
+       { 0x2A08, 0x02 },
+       { 0x2A09, 0x00 },
+       { 0x2A0A, 0x80 },
+       { 0x2A0B, 0x02 },
+       { 0x2A0C, 0x00 },
+       { 0x2A0D, 0xA0 },
+       { 0x2A01, 0x0C },
+       { 0x2902, 0x01 },
+       { 0x2903, 0x02 },
+       { 0x2904, 0x00 },
+       { 0x2905, 0x00 },
+       { 0x2901, 0x01 },
+       { 0x1101, 0x0A },
+       { 0x1102, 0x84 },
+       { 0x2301, 0x3F },
+       { 0x2303, 0x3F },
+       { 0x2302, 0x3f },
+       { 0x2001, 0x03 },
+       { 0x1B75, 0xB6 },
+       { 0x1B73, 0xC2 },
+       { 0x1129, 0x01 },
+       { 0x1121, 0xF3 },
+       { 0x1103, 0x20 },
+       { 0x1105, 0x00 },
+       { 0x1112, 0x00 },
+       { 0x1113, 0x80 },
+       { 0x1C03, 0xC0 },
+       { 0x1101, 0x02 },
+       { 0x1316, 0xff },
+       { 0x1317, 0xff },
+       { 0x1318, 0xff },
+       { 0x1319, 0xff },
+       { 0x131a, 0xff },
+       { 0x131b, 0xff },
+       { 0x131c, 0xff },
+       { 0x131e, 0xff },
+       { 0x131f, 0xff },
+       { 0x1320, 0xff },
+       { 0x1b79, 0xff },
+       { 0x1b7a, 0xff },
+};
+
+/* Vendor specific hw configuration for CS8409 */
+const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[] = {
+       /* +PLL1/2_EN, +I2C_EN */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0xb008 },
+       /* ASP1/2_EN=0, ASP1_STP=1 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0002 },
+       /* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG3, 0x0a80 },
+       /* ASP1.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL1, 0x0800 },
+       /* ASP1.A: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=32 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL2, 0x0820 },
+       /* ASP2.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP2_A_TX_CTRL1, 0x0800 },
+       /* ASP2.A: TX.RAP=1, TX.RSZ=24 bits, TX.RCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP2_A_TX_CTRL2, 0x2800 },
+       /* ASP1.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL1, 0x0800 },
+       /* ASP1.A: RX.RAP=0, RX.RSZ=24 bits, RX.RCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL2, 0x0800 },
+       /* ASP1: LCHI = 00h */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL1, 0x8000 },
+       /* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL2, 0x28ff },
+       /* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL3, 0x0062 },
+       /* ASP2: LCHI=1Fh */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL1, 0x801f },
+       /* ASP2: MC/SC_SRCSEL=PLL1, LCPR=3Fh */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL2, 0x283f },
+       /* ASP2: 5050=1, MCEN=0, FSD=010, SCPOL_IN/OUT=1, SCDIV=1:16 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL3, 0x805c },
+       /* DMIC1_MO=10b, DMIC1/2_SR=1 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DMIC_CFG, 0x0023 },
+       /* ASP1/2_BEEP=0 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_BEEP_CFG, 0x0000 },
+       /* ASP1/2_EN=1, ASP1_STP=1 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0062 },
+       /* -PLL2_EN */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0x9008 },
+       /* TX2.A: pre-scale att.=0 dB */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PRE_SCALE_ATTN2, 0x0000 },
+       /* ASP1/2_xxx_EN=1, ASP1/2_MCLK_EN=0, DMIC1_SCL_EN=1 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PAD_CFG_SLW_RATE_CTRL, 0xfc03 },
+       /* test mode on */
+       { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x9999 },
+       /* GPIO hysteresis = 30 us */
+       { CS8409_PIN_VENDOR_WIDGET, 0xc5, 0x0000 },
+       /* test mode off */
+       { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x0000 },
+       {} /* Terminator */
+};
+
+const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[] = {
+       /* EQ_SEL=1, EQ1/2_EN=0 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_CTRL1, 0x4000 },
+       /* +EQ_ACC */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0x4000 },
+       /* +EQ2_EN */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_CTRL1, 0x4010 },
+       /* EQ_DATA_HI=0x0647 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x0647 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=0, EQ_DATA_LO=0x67 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc0c7 },
+       /* EQ_DATA_HI=0x0647 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x0647 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=1, EQ_DATA_LO=0x67 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc1c7 },
+       /* EQ_DATA_HI=0xf370 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xf370 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=2, EQ_DATA_LO=0x71 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc271 },
+       /* EQ_DATA_HI=0x1ef8 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1ef8 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=3, EQ_DATA_LO=0x48 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc348 },
+       /* EQ_DATA_HI=0xc110 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc110 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=4, EQ_DATA_LO=0x5a */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc45a },
+       /* EQ_DATA_HI=0x1f29 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1f29 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=5, EQ_DATA_LO=0x74 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc574 },
+       /* EQ_DATA_HI=0x1d7a */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1d7a },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=6, EQ_DATA_LO=0x53 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc653 },
+       /* EQ_DATA_HI=0xc38c */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc38c },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=7, EQ_DATA_LO=0x14 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc714 },
+       /* EQ_DATA_HI=0x1ca3 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1ca3 },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=8, EQ_DATA_LO=0xc7 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc8c7 },
+       /* EQ_DATA_HI=0xc38c */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc38c },
+       /* +EQ_WRT, +EQ_ACC, EQ_ADR=9, EQ_DATA_LO=0x14 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc914 },
+       /* -EQ_ACC, -EQ_WRT */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0x0000 },
+       {} /* Terminator */
+};
+
+struct sub_codec cs8409_cs42l42_codec = {
+       .addr = CS42L42_I2C_ADDR,
+       .reset_gpio = CS8409_CS42L42_RESET,
+       .irq_mask = CS8409_CS42L42_INT,
+       .init_seq = cs42l42_init_reg_seq,
+       .init_seq_num = ARRAY_SIZE(cs42l42_init_reg_seq),
+       .hp_jack_in = 0,
+       .mic_jack_in = 0,
+       .paged = 1,
+       .suspended = 1,
+       .no_type_dect = 0,
+};
+
+/******************************************************************************
+ *                          Dolphin Specific Arrays
+ *                            CS8409/ 2 X CS42L42
+ ******************************************************************************/
+
+const struct hda_verb dolphin_init_verbs[] = {
+       { 0x01, AC_VERB_SET_GPIO_WAKE_MASK, DOLPHIN_WAKE }, /* WAKE from GPIO 0,4 */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_STATE, 0x0001 }, /* Enable VPW processing  */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x0002 }, /* Configure GPIO 6,7 */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF,  0x0080 }, /* I2C mode */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x005b }, /* Set I2C bus speed */
+       { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF,  0x0200 }, /* 100kHz I2C_STO = 2 */
+       {} /* terminator */
+};
+
+const struct hda_pintbl dolphin_pincfgs[] = {
+       { 0x24, 0x022210f0 }, /* ASP-1-TX-A */
+       { 0x25, 0x010240f0 }, /* ASP-1-TX-B */
+       { 0x34, 0x02a21050 }, /* ASP-1-RX */
+       {} /* terminator */
+};
+
+/* Vendor specific HW configuration for CS42L42 */
+static const struct cs8409_i2c_param dolphin_c0_init_reg_seq[] = {
+       { 0x1010, 0xB0 },
+       { 0x1D01, 0x00 },
+       { 0x1D02, 0x06 },
+       { 0x1D03, 0x9F },
+       { 0x1107, 0x01 },
+       { 0x1009, 0x02 },
+       { 0x1007, 0x03 },
+       { 0x1201, 0x00 },
+       { 0x1208, 0x13 },
+       { 0x1205, 0xFF },
+       { 0x1206, 0x00 },
+       { 0x1207, 0x20 },
+       { 0x1202, 0x0D },
+       { 0x2A02, 0x02 },
+       { 0x2A03, 0x00 },
+       { 0x2A04, 0x00 },
+       { 0x2A05, 0x02 },
+       { 0x2A06, 0x00 },
+       { 0x2A07, 0x20 },
+       { 0x2A01, 0x0C },
+       { 0x2902, 0x01 },
+       { 0x2903, 0x02 },
+       { 0x2904, 0x00 },
+       { 0x2905, 0x00 },
+       { 0x2901, 0x01 },
+       { 0x1101, 0x0A },
+       { 0x1102, 0x84 },
+       { 0x2001, 0x03 },
+       { 0x2301, 0x3F },
+       { 0x2303, 0x3F },
+       { 0x2302, 0x3f },
+       { 0x1B75, 0xB6 },
+       { 0x1B73, 0xC2 },
+       { 0x1129, 0x01 },
+       { 0x1121, 0xF3 },
+       { 0x1103, 0x20 },
+       { 0x1105, 0x00 },
+       { 0x1112, 0x00 },
+       { 0x1113, 0x80 },
+       { 0x1C03, 0xC0 },
+       { 0x1101, 0x02 },
+       { 0x1316, 0xff },
+       { 0x1317, 0xff },
+       { 0x1318, 0xff },
+       { 0x1319, 0xff },
+       { 0x131a, 0xff },
+       { 0x131b, 0xff },
+       { 0x131c, 0xff },
+       { 0x131e, 0xff },
+       { 0x131f, 0xff },
+       { 0x1320, 0xff },
+       { 0x1b79, 0xff },
+       { 0x1b7a, 0xff }
+};
+
+static const struct cs8409_i2c_param dolphin_c1_init_reg_seq[] = {
+       { 0x1010, 0xB0 },
+       { 0x1D01, 0x00 },
+       { 0x1D02, 0x06 },
+       { 0x1D03, 0x9F },
+       { 0x1107, 0x01 },
+       { 0x1009, 0x02 },
+       { 0x1007, 0x03 },
+       { 0x1201, 0x00 },
+       { 0x1208, 0x13 },
+       { 0x1205, 0xFF },
+       { 0x1206, 0x00 },
+       { 0x1207, 0x20 },
+       { 0x1202, 0x0D },
+       { 0x2A02, 0x02 },
+       { 0x2A03, 0x00 },
+       { 0x2A04, 0x80 },
+       { 0x2A05, 0x02 },
+       { 0x2A06, 0x00 },
+       { 0x2A07, 0xA0 },
+       { 0x2A01, 0x0C },
+       { 0x2902, 0x00 },
+       { 0x2903, 0x02 },
+       { 0x2904, 0x00 },
+       { 0x2905, 0x00 },
+       { 0x2901, 0x00 },
+       { 0x1101, 0x0E },
+       { 0x1102, 0x84 },
+       { 0x2001, 0x01 },
+       { 0x2301, 0x3F },
+       { 0x2303, 0x3F },
+       { 0x2302, 0x3f },
+       { 0x1B75, 0xB6 },
+       { 0x1B73, 0xC2 },
+       { 0x1129, 0x01 },
+       { 0x1121, 0xF3 },
+       { 0x1103, 0x20 },
+       { 0x1105, 0x00 },
+       { 0x1112, 0x00 },
+       { 0x1113, 0x80 },
+       { 0x1C03, 0xC0 },
+       { 0x1101, 0x06 },
+       { 0x1316, 0xff },
+       { 0x1317, 0xff },
+       { 0x1318, 0xff },
+       { 0x1319, 0xff },
+       { 0x131a, 0xff },
+       { 0x131b, 0xff },
+       { 0x131c, 0xff },
+       { 0x131e, 0xff },
+       { 0x131f, 0xff },
+       { 0x1320, 0xff },
+       { 0x1b79, 0xff },
+       { 0x1b7a, 0xff }
+};
+
+/* Vendor specific hw configuration for CS8409 */
+const struct cs8409_cir_param dolphin_hw_cfg[] = {
+       /* +PLL1/2_EN, +I2C_EN */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0xb008 },
+       /* ASP1_EN=0, ASP1_STP=1 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0002 },
+       /* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG3, 0x0a80 },
+       /* ASP1.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL1, 0x0800 },
+       /* ASP1.A: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=32 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL2, 0x0820 },
+       /* ASP1.B: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=128 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_B_TX_CTRL1, 0x0880 },
+       /* ASP1.B: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=160 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_B_TX_CTRL2, 0x08a0 },
+       /* ASP1.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL1, 0x0800 },
+       /* ASP1.A: RX.RAP=0, RX.RSZ=24 bits, RX.RCS=0 */
+       { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL2, 0x0800 },
+       /* ASP1: LCHI = 00h */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL1, 0x8000 },
+       /* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL2, 0x28ff },
+       /* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL3, 0x0062 },
+       /* ASP1/2_BEEP=0 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_BEEP_CFG, 0x0000 },
+       /* ASP1_EN=1, ASP1_STP=1 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0022 },
+       /* -PLL2_EN */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0x9008 },
+       /* ASP1_xxx_EN=1, ASP1_MCLK_EN=0 */
+       { CS8409_PIN_VENDOR_WIDGET, CS8409_PAD_CFG_SLW_RATE_CTRL, 0x5400 },
+       /* test mode on */
+       { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x9999 },
+       /* GPIO hysteresis = 30 us */
+       { CS8409_PIN_VENDOR_WIDGET, 0xc5, 0x0000 },
+       /* test mode off */
+       { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x0000 },
+       {} /* Terminator */
+};
+
+struct sub_codec dolphin_cs42l42_0 = {
+       .addr = DOLPHIN_C0_I2C_ADDR,
+       .reset_gpio = DOLPHIN_C0_RESET,
+       .irq_mask = DOLPHIN_C0_INT,
+       .init_seq = dolphin_c0_init_reg_seq,
+       .init_seq_num = ARRAY_SIZE(dolphin_c0_init_reg_seq),
+       .hp_jack_in = 0,
+       .mic_jack_in = 0,
+       .paged = 1,
+       .suspended = 1,
+       .no_type_dect = 0,
+};
+
+struct sub_codec dolphin_cs42l42_1 = {
+       .addr = DOLPHIN_C1_I2C_ADDR,
+       .reset_gpio = DOLPHIN_C1_RESET,
+       .irq_mask = DOLPHIN_C1_INT,
+       .init_seq = dolphin_c1_init_reg_seq,
+       .init_seq_num = ARRAY_SIZE(dolphin_c1_init_reg_seq),
+       .hp_jack_in = 0,
+       .mic_jack_in = 0,
+       .paged = 1,
+       .suspended = 1,
+       .no_type_dect = 1,
+};
+
+/******************************************************************************
+ *                         CS8409 Patch Driver Structs
+ *                    Arrays Used for all projects using CS8409
+ ******************************************************************************/
+
+const struct snd_pci_quirk cs8409_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x1028, 0x0A11, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A12, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A23, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A24, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A25, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A29, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A2A, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0A2B, "Bullseye", CS8409_BULLSEYE),
+       SND_PCI_QUIRK(0x1028, 0x0AB0, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AB2, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AB1, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AB3, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AB4, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AB5, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AD9, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0ADA, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0ADB, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0ADC, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AF4, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0AF5, "Warlock", CS8409_WARLOCK),
+       SND_PCI_QUIRK(0x1028, 0x0A77, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A78, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A79, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A7A, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A7D, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A7E, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A7F, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0A80, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0ADF, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AE0, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AE1, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AE2, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AE9, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AEA, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AEB, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AEC, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AED, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AEE, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AEF, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AF0, "Cyborg", CS8409_CYBORG),
+       SND_PCI_QUIRK(0x1028, 0x0AD0, "Dolphin", CS8409_DOLPHIN),
+       SND_PCI_QUIRK(0x1028, 0x0AD1, "Dolphin", CS8409_DOLPHIN),
+       SND_PCI_QUIRK(0x1028, 0x0AD2, "Dolphin", CS8409_DOLPHIN),
+       SND_PCI_QUIRK(0x1028, 0x0AD3, "Dolphin", CS8409_DOLPHIN),
+       SND_PCI_QUIRK(0x1028, 0x0ACF, "Dolphin", CS8409_DOLPHIN),
+       {} /* terminator */
+};
+
+/* Dell Inspiron models with cs8409/cs42l42 */
+const struct hda_model_fixup cs8409_models[] = {
+       { .id = CS8409_BULLSEYE, .name = "bullseye" },
+       { .id = CS8409_WARLOCK, .name = "warlock" },
+       { .id = CS8409_CYBORG, .name = "cyborg" },
+       { .id = CS8409_DOLPHIN, .name = "dolphin" },
+       {}
+};
+
+const struct hda_fixup cs8409_fixups[] = {
+       [CS8409_BULLSEYE] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = cs8409_cs42l42_pincfgs,
+               .chained = true,
+               .chain_id = CS8409_FIXUPS,
+       },
+       [CS8409_WARLOCK] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = cs8409_cs42l42_pincfgs,
+               .chained = true,
+               .chain_id = CS8409_FIXUPS,
+       },
+       [CS8409_CYBORG] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = cs8409_cs42l42_pincfgs,
+               .chained = true,
+               .chain_id = CS8409_FIXUPS,
+       },
+       [CS8409_FIXUPS] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = cs8409_cs42l42_fixups,
+       },
+       [CS8409_DOLPHIN] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = dolphin_pincfgs,
+               .chained = true,
+               .chain_id = CS8409_DOLPHIN_FIXUPS,
+       },
+       [CS8409_DOLPHIN_FIXUPS] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = dolphin_fixups,
+       },
+};
diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c
new file mode 100644 (file)
index 0000000..3c7ef55
--- /dev/null
@@ -0,0 +1,1299 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
+ *
+ * Copyright (C) 2021 Cirrus Logic, Inc. and
+ *                    Cirrus Logic International Semiconductor Ltd.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <linux/mutex.h>
+#include <linux/iopoll.h>
+
+#include "patch_cs8409.h"
+
+/******************************************************************************
+ *                        CS8409 Specific Functions
+ ******************************************************************************/
+
+static int cs8409_parse_auto_config(struct hda_codec *codec)
+{
+       struct cs8409_spec *spec = codec->spec;
+       int err;
+       int i;
+
+       err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
+       if (err < 0)
+               return err;
+
+       err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
+       if (err < 0)
+               return err;
+
+       /* keep the ADCs powered up when it's dynamically switchable */
+       if (spec->gen.dyn_adc_switch) {
+               unsigned int done = 0;
+
+               for (i = 0; i < spec->gen.input_mux.num_items; i++) {
+                       int idx = spec->gen.dyn_adc_idx[i];
+
+                       if (done & (1 << idx))
+                               continue;
+                       snd_hda_gen_fix_pin_power(codec, spec->gen.adc_nids[idx]);
+                       done |= 1 << idx;
+               }
+       }
+
+       return 0;
+}
+
+static void cs8409_disable_i2c_clock_worker(struct work_struct *work);
+
+static struct cs8409_spec *cs8409_alloc_spec(struct hda_codec *codec)
+{
+       struct cs8409_spec *spec;
+
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return NULL;
+       codec->spec = spec;
+       spec->codec = codec;
+       codec->power_save_node = 1;
+       mutex_init(&spec->i2c_mux);
+       INIT_DELAYED_WORK(&spec->i2c_clk_work, cs8409_disable_i2c_clock_worker);
+       snd_hda_gen_spec_init(&spec->gen);
+
+       return spec;
+}
+
+static inline int cs8409_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
+{
+       snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_COEF_INDEX, idx);
+       return snd_hda_codec_read(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_GET_PROC_COEF, 0);
+}
+
+static inline void cs8409_vendor_coef_set(struct hda_codec *codec, unsigned int idx,
+                                         unsigned int coef)
+{
+       snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_COEF_INDEX, idx);
+       snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_PROC_COEF, coef);
+}
+
+/*
+ * cs8409_enable_i2c_clock - Disable I2C clocks
+ * @codec: the codec instance
+ * Disable I2C clocks.
+ * This must be called when the i2c mutex is unlocked.
+ */
+static void cs8409_disable_i2c_clock(struct hda_codec *codec)
+{
+       struct cs8409_spec *spec = codec->spec;
+
+       mutex_lock(&spec->i2c_mux);
+       if (spec->i2c_clck_enabled) {
+               cs8409_vendor_coef_set(spec->codec, 0x0,
+                              cs8409_vendor_coef_get(spec->codec, 0x0) & 0xfffffff7);
+               spec->i2c_clck_enabled = 0;
+       }
+       mutex_unlock(&spec->i2c_mux);
+}
+
+/*
+ * cs8409_disable_i2c_clock_worker - Worker that disable the I2C Clock after 25ms without use
+ */
+static void cs8409_disable_i2c_clock_worker(struct work_struct *work)
+{
+       struct cs8409_spec *spec = container_of(work, struct cs8409_spec, i2c_clk_work.work);
+
+       cs8409_disable_i2c_clock(spec->codec);
+}
+
+/*
+ * cs8409_enable_i2c_clock - Enable I2C clocks
+ * @codec: the codec instance
+ * Enable I2C clocks.
+ * This must be called when the i2c mutex is locked.
+ */
+static void cs8409_enable_i2c_clock(struct hda_codec *codec)
+{
+       struct cs8409_spec *spec = codec->spec;
+
+       /* Cancel the disable timer, but do not wait for any running disable functions to finish.
+        * If the disable timer runs out before cancel, the delayed work thread will be blocked,
+        * waiting for the mutex to become unlocked. This mutex will be locked for the duration of
+        * any i2c transaction, so the disable function will run to completion immediately
+        * afterwards in the scenario. The next enable call will re-enable the clock, regardless.
+        */
+       cancel_delayed_work(&spec->i2c_clk_work);
+
+       if (!spec->i2c_clck_enabled) {
+               cs8409_vendor_coef_set(codec, 0x0, cs8409_vendor_coef_get(codec, 0x0) | 0x8);
+               spec->i2c_clck_enabled = 1;
+       }
+       queue_delayed_work(system_power_efficient_wq, &spec->i2c_clk_work, msecs_to_jiffies(25));
+}
+
+/**
+ * cs8409_i2c_wait_complete - Wait for I2C transaction
+ * @codec: the codec instance
+ *
+ * Wait for I2C transaction to complete.
+ * Return -ETIMEDOUT if transaction wait times out.
+ */
+static int cs8409_i2c_wait_complete(struct hda_codec *codec)
+{
+       unsigned int retval;
+
+       return read_poll_timeout(cs8409_vendor_coef_get, retval, retval & 0x18,
+               CS42L42_I2C_SLEEP_US, CS42L42_I2C_TIMEOUT_US, false, codec, CS8409_I2C_STS);
+}
+
+/**
+ * cs8409_set_i2c_dev_addr - Set i2c address for transaction
+ * @codec: the codec instance
+ * @addr: I2C Address
+ */
+static void cs8409_set_i2c_dev_addr(struct hda_codec *codec, unsigned int addr)
+{
+       struct cs8409_spec *spec = codec->spec;
+
+       if (spec->dev_addr != addr) {
+               cs8409_vendor_coef_set(codec, CS8409_I2C_ADDR, addr);
+               spec->dev_addr = addr;
+       }
+}
+
+/**
+ * cs8409_i2c_set_page - CS8409 I2C set page register.
+ * @scodec: the codec instance
+ * @i2c_reg: Page register
+ *
+ * Returns negative on error.
+ */
+static int cs8409_i2c_set_page(struct sub_codec *scodec, unsigned int i2c_reg)
+{
+       struct hda_codec *codec = scodec->codec;
+
+       if (scodec->paged && (scodec->last_page != (i2c_reg >> 8))) {
+               cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg >> 8);
+               if (cs8409_i2c_wait_complete(codec) < 0)
+                       return -EIO;
+               scodec->last_page = i2c_reg >> 8;
+       }
+
+       return 0;
+}
+
+/**
+ * cs8409_i2c_read - CS8409 I2C Read.
+ * @scodec: the codec instance
+ * @addr: Register to read
+ *
+ * Returns negative on error, otherwise returns read value in bits 0-7.
+ */
+static int cs8409_i2c_read(struct sub_codec *scodec, unsigned int addr)
+{
+       struct hda_codec *codec = scodec->codec;
+       struct cs8409_spec *spec = codec->spec;
+       unsigned int i2c_reg_data;
+       unsigned int read_data;
+
+       if (scodec->suspended)
+               return -EPERM;
+
+       mutex_lock(&spec->i2c_mux);
+       cs8409_enable_i2c_clock(codec);
+       cs8409_set_i2c_dev_addr(codec, scodec->addr);
+
+       if (cs8409_i2c_set_page(scodec, addr))
+               goto error;
+
+       i2c_reg_data = (addr << 8) & 0x0ffff;
+       cs8409_vendor_coef_set(codec, CS8409_I2C_QREAD, i2c_reg_data);
+       if (cs8409_i2c_wait_complete(codec) < 0)
+               goto error;
+
+       /* Register in bits 15-8 and the data in 7-0 */
+       read_data = cs8409_vendor_coef_get(codec, CS8409_I2C_QREAD);
+
+       mutex_unlock(&spec->i2c_mux);
+
+       return read_data & 0x0ff;
+
+error:
+       mutex_unlock(&spec->i2c_mux);
+       codec_err(codec, "%s() Failed 0x%02x : 0x%04x\n", __func__, scodec->addr, addr);
+       return -EIO;
+}
+
+/**
+ * cs8409_i2c_bulk_read - CS8409 I2C Read Sequence.
+ * @scodec: the codec instance
+ * @seq: Register Sequence to read
+ * @count: Number of registeres to read
+ *
+ * Returns negative on error, values are read into value element of cs8409_i2c_param sequence.
+ */
+static int cs8409_i2c_bulk_read(struct sub_codec *scodec, struct cs8409_i2c_param *seq, int count)
+{
+       struct hda_codec *codec = scodec->codec;
+       struct cs8409_spec *spec = codec->spec;
+       unsigned int i2c_reg_data;
+       int i;
+
+       if (scodec->suspended)
+               return -EPERM;
+
+       mutex_lock(&spec->i2c_mux);
+       cs8409_set_i2c_dev_addr(codec, scodec->addr);
+
+       for (i = 0; i < count; i++) {
+               cs8409_enable_i2c_clock(codec);
+               if (cs8409_i2c_set_page(scodec, seq[i].addr))
+                       goto error;
+
+               i2c_reg_data = (seq[i].addr << 8) & 0x0ffff;
+               cs8409_vendor_coef_set(codec, CS8409_I2C_QREAD, i2c_reg_data);
+
+               if (cs8409_i2c_wait_complete(codec) < 0)
+                       goto error;
+
+               seq[i].value = cs8409_vendor_coef_get(codec, CS8409_I2C_QREAD) & 0xff;
+       }
+
+       mutex_unlock(&spec->i2c_mux);
+
+       return 0;
+
+error:
+       mutex_unlock(&spec->i2c_mux);
+       codec_err(codec, "I2C Bulk Write Failed 0x%02x\n", scodec->addr);
+       return -EIO;
+}
+
+/**
+ * cs8409_i2c_write - CS8409 I2C Write.
+ * @scodec: the codec instance
+ * @addr: Register to write to
+ * @value: Data to write
+ *
+ * Returns negative on error, otherwise returns 0.
+ */
+static int cs8409_i2c_write(struct sub_codec *scodec, unsigned int addr, unsigned int value)
+{
+       struct hda_codec *codec = scodec->codec;
+       struct cs8409_spec *spec = codec->spec;
+       unsigned int i2c_reg_data;
+
+       if (scodec->suspended)
+               return -EPERM;
+
+       mutex_lock(&spec->i2c_mux);
+
+       cs8409_enable_i2c_clock(codec);
+       cs8409_set_i2c_dev_addr(codec, scodec->addr);
+
+       if (cs8409_i2c_set_page(scodec, addr))
+               goto error;
+
+       i2c_reg_data = ((addr << 8) & 0x0ff00) | (value & 0x0ff);
+       cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg_data);
+
+       if (cs8409_i2c_wait_complete(codec) < 0)
+               goto error;
+
+       mutex_unlock(&spec->i2c_mux);
+       return 0;
+
+error:
+       mutex_unlock(&spec->i2c_mux);
+       codec_err(codec, "%s() Failed 0x%02x : 0x%04x\n", __func__, scodec->addr, addr);
+       return -EIO;
+}
+
+/**
+ * cs8409_i2c_bulk_write - CS8409 I2C Write Sequence.
+ * @scodec: the codec instance
+ * @seq: Register Sequence to write
+ * @count: Number of registeres to write
+ *
+ * Returns negative on error.
+ */
+static int cs8409_i2c_bulk_write(struct sub_codec *scodec, const struct cs8409_i2c_param *seq,
+                                int count)
+{
+       struct hda_codec *codec = scodec->codec;
+       struct cs8409_spec *spec = codec->spec;
+       unsigned int i2c_reg_data;
+       int i;
+
+       if (scodec->suspended)
+               return -EPERM;
+
+       mutex_lock(&spec->i2c_mux);
+       cs8409_set_i2c_dev_addr(codec, scodec->addr);
+
+       for (i = 0; i < count; i++) {
+               cs8409_enable_i2c_clock(codec);
+               if (cs8409_i2c_set_page(scodec, seq[i].addr))
+                       goto error;
+
+               i2c_reg_data = ((seq[i].addr << 8) & 0x0ff00) | (seq[i].value & 0x0ff);
+               cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg_data);
+
+               if (cs8409_i2c_wait_complete(codec) < 0)
+                       goto error;
+       }
+
+       mutex_unlock(&spec->i2c_mux);
+
+       return 0;
+
+error:
+       mutex_unlock(&spec->i2c_mux);
+       codec_err(codec, "I2C Bulk Write Failed 0x%02x\n", scodec->addr);
+       return -EIO;
+}
+
+static int cs8409_init(struct hda_codec *codec)
+{
+       int ret = snd_hda_gen_init(codec);
+
+       if (!ret)
+               snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
+
+       return ret;
+}
+
+static int cs8409_build_controls(struct hda_codec *codec)
+{
+       int err;
+
+       err = snd_hda_gen_build_controls(codec);
+       if (err < 0)
+               return err;
+       snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
+
+       return 0;
+}
+
+/* Enable/Disable Unsolicited Response */
+static void cs8409_enable_ur(struct hda_codec *codec, int flag)
+{
+       struct cs8409_spec *spec = codec->spec;
+       unsigned int ur_gpios = 0;
+       int i;
+
+       for (i = 0; i < spec->num_scodecs; i++)
+               ur_gpios |= spec->scodecs[i]->irq_mask;
+
+       snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK,
+                           flag ? ur_gpios : 0);
+
+       snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_UNSOLICITED_ENABLE,
+                           flag ? AC_UNSOL_ENABLED : 0);
+}
+
+static void cs8409_fix_caps(struct hda_codec *codec, unsigned int nid)
+{
+       int caps;
+
+       /* CS8409 is simple HDA bridge and intended to be used with a remote
+        * companion codec. Most of input/output PIN(s) have only basic
+        * capabilities. Receive and Transmit NID(s) have only OUTC and INC
+        * capabilities and no presence detect capable (PDC) and call to
+        * snd_hda_gen_build_controls() will mark them as non detectable
+        * phantom jacks. However, a companion codec may be
+        * connected to these pins which supports jack detect
+        * capabilities. We have to override pin capabilities,
+        * otherwise they will not be created as input devices.
+        */
+       caps = snd_hdac_read_parm(&codec->core, nid, AC_PAR_PIN_CAP);
+       if (caps >= 0)
+               snd_hdac_override_parm(&codec->core, nid, AC_PAR_PIN_CAP,
+                                      (caps | (AC_PINCAP_IMP_SENSE | AC_PINCAP_PRES_DETECT)));
+
+       snd_hda_override_wcaps(codec, nid, (get_wcaps(codec, nid) | AC_WCAP_UNSOL_CAP));
+}
+
+/******************************************************************************
+ *                        CS42L42 Specific Functions
+ ******************************************************************************/
+
+int cs42l42_volume_info(struct snd_kcontrol *kctrl, struct snd_ctl_elem_info *uinfo)
+{
+       unsigned int ofs = get_amp_offset(kctrl);
+       u8 chs = get_amp_channels(kctrl);
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->value.integer.step = 1;
+       uinfo->count = chs == 3 ? 2 : 1;
+
+       switch (ofs) {
+       case CS42L42_VOL_DAC:
+               uinfo->value.integer.min = CS42L42_HP_VOL_REAL_MIN;
+               uinfo->value.integer.max = CS42L42_HP_VOL_REAL_MAX;
+               break;
+       case CS42L42_VOL_ADC:
+               uinfo->value.integer.min = CS42L42_AMIC_VOL_REAL_MIN;
+               uinfo->value.integer.max = CS42L42_AMIC_VOL_REAL_MAX;
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+int cs42l42_volume_get(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kctrl);
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42 = spec->scodecs[get_amp_index(kctrl)];
+       int chs = get_amp_channels(kctrl);
+       unsigned int ofs = get_amp_offset(kctrl);
+       long *valp = uctrl->value.integer.value;
+
+       switch (ofs) {
+       case CS42L42_VOL_DAC:
+               if (chs & BIT(0))
+                       *valp++ = cs42l42->vol[ofs];
+               if (chs & BIT(1))
+                       *valp = cs42l42->vol[ofs+1];
+               break;
+       case CS42L42_VOL_ADC:
+               if (chs & BIT(0))
+                       *valp = cs42l42->vol[ofs];
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static void cs42l42_mute(struct sub_codec *cs42l42, int vol_type,
+       unsigned int chs, bool mute)
+{
+       if (mute) {
+               if (vol_type == CS42L42_VOL_DAC) {
+                       if (chs & BIT(0))
+                               cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHA, 0x3f);
+                       if (chs & BIT(1))
+                               cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHB, 0x3f);
+               } else if (vol_type == CS42L42_VOL_ADC) {
+                       if (chs & BIT(0))
+                               cs8409_i2c_write(cs42l42, CS42L42_REG_AMIC_VOL, 0x9f);
+               }
+       } else {
+               if (vol_type == CS42L42_VOL_DAC) {
+                       if (chs & BIT(0))
+                               cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHA,
+                                       -(cs42l42->vol[CS42L42_DAC_CH0_VOL_OFFSET])
+                                       & CS42L42_REG_HS_VOL_MASK);
+                       if (chs & BIT(1))
+                               cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHB,
+                                       -(cs42l42->vol[CS42L42_DAC_CH1_VOL_OFFSET])
+                                       & CS42L42_REG_HS_VOL_MASK);
+               } else if (vol_type == CS42L42_VOL_ADC) {
+                       if (chs & BIT(0))
+                               cs8409_i2c_write(cs42l42, CS42L42_REG_AMIC_VOL,
+                                       cs42l42->vol[CS42L42_ADC_VOL_OFFSET]
+                                       & CS42L42_REG_AMIC_VOL_MASK);
+               }
+       }
+}
+
+int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kctrl);
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42 = spec->scodecs[get_amp_index(kctrl)];
+       int chs = get_amp_channels(kctrl);
+       unsigned int ofs = get_amp_offset(kctrl);
+       long *valp = uctrl->value.integer.value;
+
+       switch (ofs) {
+       case CS42L42_VOL_DAC:
+               if (chs & BIT(0))
+                       cs42l42->vol[ofs] = *valp;
+               if (chs & BIT(1)) {
+                       valp++;
+                       cs42l42->vol[ofs + 1] = *valp;
+               }
+               if (spec->playback_started)
+                       cs42l42_mute(cs42l42, CS42L42_VOL_DAC, chs, false);
+               break;
+       case CS42L42_VOL_ADC:
+               if (chs & BIT(0))
+                       cs42l42->vol[ofs] = *valp;
+               if (spec->capture_started)
+                       cs42l42_mute(cs42l42, CS42L42_VOL_ADC, chs, false);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static void cs42l42_playback_pcm_hook(struct hda_pcm_stream *hinfo,
+                                  struct hda_codec *codec,
+                                  struct snd_pcm_substream *substream,
+                                  int action)
+{
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42;
+       int i;
+       bool mute;
+
+       switch (action) {
+       case HDA_GEN_PCM_ACT_PREPARE:
+               mute = false;
+               spec->playback_started = 1;
+               break;
+       case HDA_GEN_PCM_ACT_CLEANUP:
+               mute = true;
+               spec->playback_started = 0;
+               break;
+       default:
+               return;
+       }
+
+       for (i = 0; i < spec->num_scodecs; i++) {
+               cs42l42 = spec->scodecs[i];
+               cs42l42_mute(cs42l42, CS42L42_VOL_DAC, 0x3, mute);
+       }
+}
+
+static void cs42l42_capture_pcm_hook(struct hda_pcm_stream *hinfo,
+                                  struct hda_codec *codec,
+                                  struct snd_pcm_substream *substream,
+                                  int action)
+{
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42;
+       int i;
+       bool mute;
+
+       switch (action) {
+       case HDA_GEN_PCM_ACT_PREPARE:
+               mute = false;
+               spec->capture_started = 1;
+               break;
+       case HDA_GEN_PCM_ACT_CLEANUP:
+               mute = true;
+               spec->capture_started = 0;
+               break;
+       default:
+               return;
+       }
+
+       for (i = 0; i < spec->num_scodecs; i++) {
+               cs42l42 = spec->scodecs[i];
+               cs42l42_mute(cs42l42, CS42L42_VOL_ADC, 0x3, mute);
+       }
+}
+
+/* Configure CS42L42 slave codec for jack autodetect */
+static void cs42l42_enable_jack_detect(struct sub_codec *cs42l42)
+{
+       cs8409_i2c_write(cs42l42, 0x1b70, cs42l42->hsbias_hiz);
+       /* Clear WAKE# */
+       cs8409_i2c_write(cs42l42, 0x1b71, 0x00C1);
+       /* Wait ~2.5ms */
+       usleep_range(2500, 3000);
+       /* Set mode WAKE# output follows the combination logic directly */
+       cs8409_i2c_write(cs42l42, 0x1b71, 0x00C0);
+       /* Clear interrupts status */
+       cs8409_i2c_read(cs42l42, 0x130f);
+       /* Enable interrupt */
+       cs8409_i2c_write(cs42l42, 0x1320, 0xF3);
+}
+
+/* Enable and run CS42L42 slave codec jack auto detect */
+static void cs42l42_run_jack_detect(struct sub_codec *cs42l42)
+{
+       /* Clear interrupts */
+       cs8409_i2c_read(cs42l42, 0x1308);
+       cs8409_i2c_read(cs42l42, 0x1b77);
+       cs8409_i2c_write(cs42l42, 0x1320, 0xFF);
+       cs8409_i2c_read(cs42l42, 0x130f);
+
+       cs8409_i2c_write(cs42l42, 0x1102, 0x87);
+       cs8409_i2c_write(cs42l42, 0x1f06, 0x86);
+       cs8409_i2c_write(cs42l42, 0x1b74, 0x07);
+       cs8409_i2c_write(cs42l42, 0x131b, 0xFD);
+       cs8409_i2c_write(cs42l42, 0x1120, 0x80);
+       /* Wait ~100us*/
+       usleep_range(100, 200);
+       cs8409_i2c_write(cs42l42, 0x111f, 0x77);
+       cs8409_i2c_write(cs42l42, 0x1120, 0xc0);
+}
+
+static int cs42l42_handle_tip_sense(struct sub_codec *cs42l42, unsigned int reg_ts_status)
+{
+       int status_changed = 0;
+
+       /* TIP_SENSE INSERT/REMOVE */
+       switch (reg_ts_status) {
+       case CS42L42_JACK_INSERTED:
+               if (!cs42l42->hp_jack_in) {
+                       if (cs42l42->no_type_dect) {
+                               status_changed = 1;
+                               cs42l42->hp_jack_in = 1;
+                               cs42l42->mic_jack_in = 0;
+                       } else {
+                               cs42l42_run_jack_detect(cs42l42);
+                       }
+               }
+               break;
+
+       case CS42L42_JACK_REMOVED:
+               if (cs42l42->hp_jack_in || cs42l42->mic_jack_in) {
+                       status_changed = 1;
+                       cs42l42->hp_jack_in = 0;
+                       cs42l42->mic_jack_in = 0;
+               }
+               break;
+       default:
+               /* jack in transition */
+               break;
+       }
+
+       return status_changed;
+}
+
+static int cs42l42_jack_unsol_event(struct sub_codec *cs42l42)
+{
+       int status_changed = 0;
+       int reg_cdc_status;
+       int reg_hs_status;
+       int reg_ts_status;
+       int type;
+
+       /* Read jack detect status registers */
+       reg_cdc_status = cs8409_i2c_read(cs42l42, 0x1308);
+       reg_hs_status = cs8409_i2c_read(cs42l42, 0x1124);
+       reg_ts_status = cs8409_i2c_read(cs42l42, 0x130f);
+
+       /* If status values are < 0, read error has occurred. */
+       if (reg_cdc_status < 0 || reg_hs_status < 0 || reg_ts_status < 0)
+               return -EIO;
+
+       /* HSDET_AUTO_DONE */
+       if (reg_cdc_status & CS42L42_HSDET_AUTO_DONE) {
+
+               /* Disable HSDET_AUTO_DONE */
+               cs8409_i2c_write(cs42l42, 0x131b, 0xFF);
+
+               type = ((reg_hs_status & CS42L42_HSTYPE_MASK) + 1);
+
+               if (cs42l42->no_type_dect) {
+                       status_changed = cs42l42_handle_tip_sense(cs42l42, reg_ts_status);
+               } else if (type == 4) {
+                       /* Type 4 not supported */
+                       status_changed = cs42l42_handle_tip_sense(cs42l42, CS42L42_JACK_REMOVED);
+               } else {
+                       if (!cs42l42->hp_jack_in) {
+                               status_changed = 1;
+                               cs42l42->hp_jack_in = 1;
+                       }
+                       /* type = 3 has no mic */
+                       if ((!cs42l42->mic_jack_in) && (type != 3)) {
+                               status_changed = 1;
+                               cs42l42->mic_jack_in = 1;
+                       }
+               }
+               /* Configure the HSDET mode. */
+               cs8409_i2c_write(cs42l42, 0x1120, 0x80);
+               /* Enable the HPOUT ground clamp and configure the HP pull-down */
+               cs8409_i2c_write(cs42l42, 0x1F06, 0x02);
+               /* Re-Enable Tip Sense Interrupt */
+               cs8409_i2c_write(cs42l42, 0x1320, 0xF3);
+       } else {
+               status_changed = cs42l42_handle_tip_sense(cs42l42, reg_ts_status);
+       }
+
+       return status_changed;
+}
+
+static void cs42l42_resume(struct sub_codec *cs42l42)
+{
+       struct hda_codec *codec = cs42l42->codec;
+       unsigned int gpio_data;
+       struct cs8409_i2c_param irq_regs[] = {
+               { 0x1308, 0x00 },
+               { 0x1309, 0x00 },
+               { 0x130A, 0x00 },
+               { 0x130F, 0x00 },
+       };
+
+       /* Bring CS42L42 out of Reset */
+       gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
+       gpio_data |= cs42l42->reset_gpio;
+       snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
+       usleep_range(10000, 15000);
+
+       cs42l42->suspended = 0;
+
+       /* Initialize CS42L42 companion codec */
+       cs8409_i2c_bulk_write(cs42l42, cs42l42->init_seq, cs42l42->init_seq_num);
+       usleep_range(20000, 25000);
+
+       /* Clear interrupts, by reading interrupt status registers */
+       cs8409_i2c_bulk_read(cs42l42, irq_regs, ARRAY_SIZE(irq_regs));
+
+       if (cs42l42->full_scale_vol)
+               cs8409_i2c_write(cs42l42, 0x2001, 0x01);
+
+       cs42l42_enable_jack_detect(cs42l42);
+}
+
+#ifdef CONFIG_PM
+static void cs42l42_suspend(struct sub_codec *cs42l42)
+{
+       struct hda_codec *codec = cs42l42->codec;
+       unsigned int gpio_data;
+       int reg_cdc_status = 0;
+       const struct cs8409_i2c_param cs42l42_pwr_down_seq[] = {
+               { 0x1F06, 0x02 },
+               { 0x1129, 0x00 },
+               { 0x2301, 0x3F },
+               { 0x2302, 0x3F },
+               { 0x2303, 0x3F },
+               { 0x2001, 0x0F },
+               { 0x2A01, 0x00 },
+               { 0x1207, 0x00 },
+               { 0x1101, 0xFE },
+               { 0x1102, 0x8C },
+               { 0x1101, 0xFF },
+       };
+
+       cs8409_i2c_bulk_write(cs42l42, cs42l42_pwr_down_seq, ARRAY_SIZE(cs42l42_pwr_down_seq));
+
+       if (read_poll_timeout(cs8409_i2c_read, reg_cdc_status,
+                       (reg_cdc_status & 0x1), CS42L42_PDN_SLEEP_US, CS42L42_PDN_TIMEOUT_US,
+                       true, cs42l42, 0x1308) < 0)
+               codec_warn(codec, "Timeout waiting for PDN_DONE for CS42L42\n");
+
+       /* Power down CS42L42 ASP/EQ/MIX/HP */
+       cs8409_i2c_write(cs42l42, 0x1102, 0x9C);
+       cs42l42->suspended = 1;
+       cs42l42->last_page = 0;
+       cs42l42->hp_jack_in = 0;
+       cs42l42->mic_jack_in = 0;
+
+       /* Put CS42L42 into Reset */
+       gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
+       gpio_data &= ~cs42l42->reset_gpio;
+       snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
+}
+#endif
+
+static void cs8409_free(struct hda_codec *codec)
+{
+       struct cs8409_spec *spec = codec->spec;
+
+       /* Cancel i2c clock disable timer, and disable clock if left enabled */
+       cancel_delayed_work_sync(&spec->i2c_clk_work);
+       cs8409_disable_i2c_clock(codec);
+
+       snd_hda_gen_free(codec);
+}
+
+/******************************************************************************
+ *                   BULLSEYE / WARLOCK / CYBORG Specific Functions
+ *                               CS8409/CS42L42
+ ******************************************************************************/
+
+/*
+ * In the case of CS8409 we do not have unsolicited events from NID's 0x24
+ * and 0x34 where hs mic and hp are connected. Companion codec CS42L42 will
+ * generate interrupt via gpio 4 to notify jack events. We have to overwrite
+ * generic snd_hda_jack_unsol_event(), read CS42L42 jack detect status registers
+ * and then notify status via generic snd_hda_jack_unsol_event() call.
+ */
+static void cs8409_cs42l42_jack_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
+       struct hda_jack_tbl *jk;
+
+       /* jack_unsol_event() will be called every time gpio line changing state.
+        * In this case gpio4 line goes up as a result of reading interrupt status
+        * registers in previous cs8409_jack_unsol_event() call.
+        * We don't need to handle this event, ignoring...
+        */
+       if (res & cs42l42->irq_mask)
+               return;
+
+       if (cs42l42_jack_unsol_event(cs42l42)) {
+               snd_hda_set_pin_ctl(codec, CS8409_CS42L42_SPK_PIN_NID,
+                                   cs42l42->hp_jack_in ? 0 : PIN_OUT);
+               /* Report jack*/
+               jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_HP_PIN_NID, 0);
+               if (jk)
+                       snd_hda_jack_unsol_event(codec, (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+                                                       AC_UNSOL_RES_TAG);
+               /* Report jack*/
+               jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_AMIC_PIN_NID, 0);
+               if (jk)
+                       snd_hda_jack_unsol_event(codec, (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+                                                        AC_UNSOL_RES_TAG);
+       }
+}
+
+#ifdef CONFIG_PM
+/* Manage PDREF, when transition to D3hot */
+static int cs8409_cs42l42_suspend(struct hda_codec *codec)
+{
+       struct cs8409_spec *spec = codec->spec;
+       int i;
+
+       spec->init_done = 0;
+
+       cs8409_enable_ur(codec, 0);
+
+       for (i = 0; i < spec->num_scodecs; i++)
+               cs42l42_suspend(spec->scodecs[i]);
+
+       /* Cancel i2c clock disable timer, and disable clock if left enabled */
+       cancel_delayed_work_sync(&spec->i2c_clk_work);
+       cs8409_disable_i2c_clock(codec);
+
+       snd_hda_shutup_pins(codec);
+
+       return 0;
+}
+#endif
+
+/* Vendor specific HW configuration
+ * PLL, ASP, I2C, SPI, GPIOs, DMIC etc...
+ */
+static void cs8409_cs42l42_hw_init(struct hda_codec *codec)
+{
+       const struct cs8409_cir_param *seq = cs8409_cs42l42_hw_cfg;
+       const struct cs8409_cir_param *seq_bullseye = cs8409_cs42l42_bullseye_atn;
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
+
+       if (spec->gpio_mask) {
+               snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_MASK,
+                       spec->gpio_mask);
+               snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DIRECTION,
+                       spec->gpio_dir);
+               snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA,
+                       spec->gpio_data);
+       }
+
+       for (; seq->nid; seq++)
+               cs8409_vendor_coef_set(codec, seq->cir, seq->coeff);
+
+       if (codec->fixup_id == CS8409_BULLSEYE) {
+               for (; seq_bullseye->nid; seq_bullseye++)
+                       cs8409_vendor_coef_set(codec, seq_bullseye->cir, seq_bullseye->coeff);
+       }
+
+       /* DMIC1_MO=00b, DMIC1/2_SR=1 */
+       if (codec->fixup_id == CS8409_WARLOCK || codec->fixup_id == CS8409_CYBORG)
+               cs8409_vendor_coef_set(codec, 0x09, 0x0003);
+
+       cs42l42_resume(cs42l42);
+
+       /* Enable Unsolicited Response */
+       cs8409_enable_ur(codec, 1);
+}
+
+static const struct hda_codec_ops cs8409_cs42l42_patch_ops = {
+       .build_controls = cs8409_build_controls,
+       .build_pcms = snd_hda_gen_build_pcms,
+       .init = cs8409_init,
+       .free = cs8409_free,
+       .unsol_event = cs8409_cs42l42_jack_unsol_event,
+#ifdef CONFIG_PM
+       .suspend = cs8409_cs42l42_suspend,
+#endif
+};
+
+static int cs8409_cs42l42_exec_verb(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
+                                   unsigned int *res)
+{
+       struct hda_codec *codec = container_of(dev, struct hda_codec, core);
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
+
+       unsigned int nid = ((cmd >> 20) & 0x07f);
+       unsigned int verb = ((cmd >> 8) & 0x0fff);
+
+       /* CS8409 pins have no AC_PINSENSE_PRESENCE
+        * capabilities. We have to intercept 2 calls for pins 0x24 and 0x34
+        * and return correct pin sense values for read_pin_sense() call from
+        * hda_jack based on CS42L42 jack detect status.
+        */
+       switch (nid) {
+       case CS8409_CS42L42_HP_PIN_NID:
+               if (verb == AC_VERB_GET_PIN_SENSE) {
+                       *res = (cs42l42->hp_jack_in) ? AC_PINSENSE_PRESENCE : 0;
+                       return 0;
+               }
+               break;
+       case CS8409_CS42L42_AMIC_PIN_NID:
+               if (verb == AC_VERB_GET_PIN_SENSE) {
+                       *res = (cs42l42->mic_jack_in) ? AC_PINSENSE_PRESENCE : 0;
+                       return 0;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return spec->exec_verb(dev, cmd, flags, res);
+}
+
+void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action)
+{
+       struct cs8409_spec *spec = codec->spec;
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
+               snd_hda_add_verbs(codec, cs8409_cs42l42_init_verbs);
+               /* verb exec op override */
+               spec->exec_verb = codec->core.exec_verb;
+               codec->core.exec_verb = cs8409_cs42l42_exec_verb;
+
+               spec->scodecs[CS8409_CODEC0] = &cs8409_cs42l42_codec;
+               spec->num_scodecs = 1;
+               spec->scodecs[CS8409_CODEC0]->codec = codec;
+               codec->patch_ops = cs8409_cs42l42_patch_ops;
+
+               spec->gen.suppress_auto_mute = 1;
+               spec->gen.no_primary_hp = 1;
+               spec->gen.suppress_vmaster = 1;
+
+               /* GPIO 5 out, 3,4 in */
+               spec->gpio_dir = spec->scodecs[CS8409_CODEC0]->reset_gpio;
+               spec->gpio_data = 0;
+               spec->gpio_mask = 0x03f;
+
+               /* Basic initial sequence for specific hw configuration */
+               snd_hda_sequence_write(codec, cs8409_cs42l42_init_verbs);
+
+               cs8409_fix_caps(codec, CS8409_CS42L42_HP_PIN_NID);
+               cs8409_fix_caps(codec, CS8409_CS42L42_AMIC_PIN_NID);
+
+               /* Set TIP_SENSE_EN for analog front-end of tip sense.
+                * Additionally set HSBIAS_SENSE_EN and Full Scale volume for some variants.
+                */
+               switch (codec->fixup_id) {
+               case CS8409_WARLOCK:
+                       spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x0020;
+                       spec->scodecs[CS8409_CODEC0]->full_scale_vol = 1;
+                       break;
+               case CS8409_BULLSEYE:
+                       spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x0020;
+                       spec->scodecs[CS8409_CODEC0]->full_scale_vol = 0;
+                       break;
+               case CS8409_CYBORG:
+                       spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x00a0;
+                       spec->scodecs[CS8409_CODEC0]->full_scale_vol = 1;
+                       break;
+               default:
+                       spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x0003;
+                       spec->scodecs[CS8409_CODEC0]->full_scale_vol = 1;
+                       break;
+               }
+
+               break;
+       case HDA_FIXUP_ACT_PROBE:
+               /* Fix Sample Rate to 48kHz */
+               spec->gen.stream_analog_playback = &cs42l42_48k_pcm_analog_playback;
+               spec->gen.stream_analog_capture = &cs42l42_48k_pcm_analog_capture;
+               /* add hooks */
+               spec->gen.pcm_playback_hook = cs42l42_playback_pcm_hook;
+               spec->gen.pcm_capture_hook = cs42l42_capture_pcm_hook;
+               /* Set initial DMIC volume to -26 dB */
+               snd_hda_codec_amp_init_stereo(codec, CS8409_CS42L42_DMIC_ADC_PIN_NID,
+                                             HDA_INPUT, 0, 0xff, 0x19);
+               snd_hda_gen_add_kctl(&spec->gen, "Headphone Playback Volume",
+                               &cs42l42_dac_volume_mixer);
+               snd_hda_gen_add_kctl(&spec->gen, "Mic Capture Volume",
+                               &cs42l42_adc_volume_mixer);
+               /* Disable Unsolicited Response during boot */
+               cs8409_enable_ur(codec, 0);
+               snd_hda_codec_set_name(codec, "CS8409/CS42L42");
+               break;
+       case HDA_FIXUP_ACT_INIT:
+               cs8409_cs42l42_hw_init(codec);
+               spec->init_done = 1;
+               if (spec->init_done && spec->build_ctrl_done
+                       && !spec->scodecs[CS8409_CODEC0]->hp_jack_in)
+                       cs42l42_run_jack_detect(spec->scodecs[CS8409_CODEC0]);
+               break;
+       case HDA_FIXUP_ACT_BUILD:
+               spec->build_ctrl_done = 1;
+               /* Run jack auto detect first time on boot
+                * after controls have been added, to check if jack has
+                * been already plugged in.
+                * Run immediately after init.
+                */
+               if (spec->init_done && spec->build_ctrl_done
+                       && !spec->scodecs[CS8409_CODEC0]->hp_jack_in)
+                       cs42l42_run_jack_detect(spec->scodecs[CS8409_CODEC0]);
+               break;
+       default:
+               break;
+       }
+}
+
+/******************************************************************************
+ *                          Dolphin Specific Functions
+ *                               CS8409/ 2 X CS42L42
+ ******************************************************************************/
+
+/*
+ * In the case of CS8409 we do not have unsolicited events when
+ * hs mic and hp are connected. Companion codec CS42L42 will
+ * generate interrupt via irq_mask to notify jack events. We have to overwrite
+ * generic snd_hda_jack_unsol_event(), read CS42L42 jack detect status registers
+ * and then notify status via generic snd_hda_jack_unsol_event() call.
+ */
+static void dolphin_jack_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42;
+       struct hda_jack_tbl *jk;
+
+       cs42l42 = spec->scodecs[CS8409_CODEC0];
+       if (!cs42l42->suspended && (~res & cs42l42->irq_mask) &&
+           cs42l42_jack_unsol_event(cs42l42)) {
+               jk = snd_hda_jack_tbl_get_mst(codec, DOLPHIN_HP_PIN_NID, 0);
+               if (jk)
+                       snd_hda_jack_unsol_event(codec,
+                                                (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+                                                 AC_UNSOL_RES_TAG);
+
+               jk = snd_hda_jack_tbl_get_mst(codec, DOLPHIN_AMIC_PIN_NID, 0);
+               if (jk)
+                       snd_hda_jack_unsol_event(codec,
+                                                (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+                                                 AC_UNSOL_RES_TAG);
+       }
+
+       cs42l42 = spec->scodecs[CS8409_CODEC1];
+       if (!cs42l42->suspended && (~res & cs42l42->irq_mask) &&
+           cs42l42_jack_unsol_event(cs42l42)) {
+               jk = snd_hda_jack_tbl_get_mst(codec, DOLPHIN_LO_PIN_NID, 0);
+               if (jk)
+                       snd_hda_jack_unsol_event(codec,
+                                                (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+                                                 AC_UNSOL_RES_TAG);
+       }
+}
+
+/* Vendor specific HW configuration
+ * PLL, ASP, I2C, SPI, GPIOs, DMIC etc...
+ */
+static void dolphin_hw_init(struct hda_codec *codec)
+{
+       const struct cs8409_cir_param *seq = dolphin_hw_cfg;
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42;
+       int i;
+
+       if (spec->gpio_mask) {
+               snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_MASK,
+                                   spec->gpio_mask);
+               snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DIRECTION,
+                                   spec->gpio_dir);
+               snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA,
+                                   spec->gpio_data);
+       }
+
+       for (; seq->nid; seq++)
+               cs8409_vendor_coef_set(codec, seq->cir, seq->coeff);
+
+       for (i = 0; i < spec->num_scodecs; i++) {
+               cs42l42 = spec->scodecs[i];
+               cs42l42_resume(cs42l42);
+       }
+
+       /* Enable Unsolicited Response */
+       cs8409_enable_ur(codec, 1);
+}
+
+static const struct hda_codec_ops cs8409_dolphin_patch_ops = {
+       .build_controls = cs8409_build_controls,
+       .build_pcms = snd_hda_gen_build_pcms,
+       .init = cs8409_init,
+       .free = cs8409_free,
+       .unsol_event = dolphin_jack_unsol_event,
+#ifdef CONFIG_PM
+       .suspend = cs8409_cs42l42_suspend,
+#endif
+};
+
+static int dolphin_exec_verb(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
+                            unsigned int *res)
+{
+       struct hda_codec *codec = container_of(dev, struct hda_codec, core);
+       struct cs8409_spec *spec = codec->spec;
+       struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
+
+       unsigned int nid = ((cmd >> 20) & 0x07f);
+       unsigned int verb = ((cmd >> 8) & 0x0fff);
+
+       /* CS8409 pins have no AC_PINSENSE_PRESENCE
+        * capabilities. We have to intercept calls for CS42L42 pins
+        * and return correct pin sense values for read_pin_sense() call from
+        * hda_jack based on CS42L42 jack detect status.
+        */
+       switch (nid) {
+       case DOLPHIN_HP_PIN_NID:
+       case DOLPHIN_LO_PIN_NID:
+               if (nid == DOLPHIN_LO_PIN_NID)
+                       cs42l42 = spec->scodecs[CS8409_CODEC1];
+               if (verb == AC_VERB_GET_PIN_SENSE) {
+                       *res = (cs42l42->hp_jack_in) ? AC_PINSENSE_PRESENCE : 0;
+                       return 0;
+               }
+               break;
+       case DOLPHIN_AMIC_PIN_NID:
+               if (verb == AC_VERB_GET_PIN_SENSE) {
+                       *res = (cs42l42->mic_jack_in) ? AC_PINSENSE_PRESENCE : 0;
+                       return 0;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return spec->exec_verb(dev, cmd, flags, res);
+}
+
+void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action)
+{
+       struct cs8409_spec *spec = codec->spec;
+       struct snd_kcontrol_new *kctrl;
+       int i;
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
+               snd_hda_add_verbs(codec, dolphin_init_verbs);
+               /* verb exec op override */
+               spec->exec_verb = codec->core.exec_verb;
+               codec->core.exec_verb = dolphin_exec_verb;
+
+               spec->scodecs[CS8409_CODEC0] = &dolphin_cs42l42_0;
+               spec->scodecs[CS8409_CODEC0]->codec = codec;
+               spec->scodecs[CS8409_CODEC1] = &dolphin_cs42l42_1;
+               spec->scodecs[CS8409_CODEC1]->codec = codec;
+               spec->num_scodecs = 2;
+
+               codec->patch_ops = cs8409_dolphin_patch_ops;
+
+               /* GPIO 1,5 out, 0,4 in */
+               spec->gpio_dir = spec->scodecs[CS8409_CODEC0]->reset_gpio |
+                                spec->scodecs[CS8409_CODEC1]->reset_gpio;
+               spec->gpio_data = 0;
+               spec->gpio_mask = 0x03f;
+
+               /* Basic initial sequence for specific hw configuration */
+               snd_hda_sequence_write(codec, dolphin_init_verbs);
+
+               snd_hda_jack_add_kctl(codec, DOLPHIN_LO_PIN_NID, "Line Out", true,
+                                     SND_JACK_HEADPHONE, NULL);
+
+               cs8409_fix_caps(codec, DOLPHIN_HP_PIN_NID);
+               cs8409_fix_caps(codec, DOLPHIN_LO_PIN_NID);
+               cs8409_fix_caps(codec, DOLPHIN_AMIC_PIN_NID);
+
+               break;
+       case HDA_FIXUP_ACT_PROBE:
+               /* Fix Sample Rate to 48kHz */
+               spec->gen.stream_analog_playback = &cs42l42_48k_pcm_analog_playback;
+               spec->gen.stream_analog_capture = &cs42l42_48k_pcm_analog_capture;
+               /* add hooks */
+               spec->gen.pcm_playback_hook = cs42l42_playback_pcm_hook;
+               spec->gen.pcm_capture_hook = cs42l42_capture_pcm_hook;
+               snd_hda_gen_add_kctl(&spec->gen, "Headphone Playback Volume",
+                                    &cs42l42_dac_volume_mixer);
+               snd_hda_gen_add_kctl(&spec->gen, "Mic Capture Volume", &cs42l42_adc_volume_mixer);
+               kctrl = snd_hda_gen_add_kctl(&spec->gen, "Line Out Playback Volume",
+                                            &cs42l42_dac_volume_mixer);
+               /* Update Line Out kcontrol template */
+               kctrl->private_value = HDA_COMPOSE_AMP_VAL_OFS(DOLPHIN_HP_PIN_NID, 3, CS8409_CODEC1,
+                                      HDA_OUTPUT, CS42L42_VOL_DAC) | HDA_AMP_VAL_MIN_MUTE;
+               cs8409_enable_ur(codec, 0);
+               snd_hda_codec_set_name(codec, "CS8409/CS42L42");
+               break;
+       case HDA_FIXUP_ACT_INIT:
+               dolphin_hw_init(codec);
+               spec->init_done = 1;
+               if (spec->init_done && spec->build_ctrl_done) {
+                       for (i = 0; i < spec->num_scodecs; i++) {
+                               if (!spec->scodecs[i]->hp_jack_in)
+                                       cs42l42_run_jack_detect(spec->scodecs[i]);
+                       }
+               }
+               break;
+       case HDA_FIXUP_ACT_BUILD:
+               spec->build_ctrl_done = 1;
+               /* Run jack auto detect first time on boot
+                * after controls have been added, to check if jack has
+                * been already plugged in.
+                * Run immediately after init.
+                */
+               if (spec->init_done && spec->build_ctrl_done) {
+                       for (i = 0; i < spec->num_scodecs; i++) {
+                               if (!spec->scodecs[i]->hp_jack_in)
+                                       cs42l42_run_jack_detect(spec->scodecs[i]);
+                       }
+               }
+               break;
+       default:
+               break;
+       }
+}
+
+static int patch_cs8409(struct hda_codec *codec)
+{
+       int err;
+
+       if (!cs8409_alloc_spec(codec))
+               return -ENOMEM;
+
+       snd_hda_pick_fixup(codec, cs8409_models, cs8409_fixup_tbl, cs8409_fixups);
+
+       codec_dbg(codec, "Picked ID=%d, VID=%08x, DEV=%08x\n", codec->fixup_id,
+                        codec->bus->pci->subsystem_vendor,
+                        codec->bus->pci->subsystem_device);
+
+       snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
+
+       err = cs8409_parse_auto_config(codec);
+       if (err < 0) {
+               cs8409_free(codec);
+               return err;
+       }
+
+       snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
+       return 0;
+}
+
+static const struct hda_device_id snd_hda_id_cs8409[] = {
+       HDA_CODEC_ENTRY(0x10138409, "CS8409", patch_cs8409),
+       {} /* terminator */
+};
+MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cs8409);
+
+static struct hda_codec_driver cs8409_driver = {
+       .id = snd_hda_id_cs8409,
+};
+module_hda_codec_driver(cs8409_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cirrus Logic HDA bridge");
diff --git a/sound/pci/hda/patch_cs8409.h b/sound/pci/hda/patch_cs8409.h
new file mode 100644 (file)
index 0000000..ade2b83
--- /dev/null
@@ -0,0 +1,371 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
+ *
+ * Copyright (C) 2021 Cirrus Logic, Inc. and
+ *                    Cirrus Logic International Semiconductor Ltd.
+ */
+
+#ifndef __CS8409_PATCH_H
+#define __CS8409_PATCH_H
+
+#include <linux/pci.h>
+#include <sound/tlv.h>
+#include <linux/workqueue.h>
+#include <sound/hda_codec.h>
+#include "hda_local.h"
+#include "hda_auto_parser.h"
+#include "hda_jack.h"
+#include "hda_generic.h"
+
+/* CS8409 Specific Definitions */
+
+enum cs8409_pins {
+       CS8409_PIN_ROOT,
+       CS8409_PIN_AFG,
+       CS8409_PIN_ASP1_OUT_A,
+       CS8409_PIN_ASP1_OUT_B,
+       CS8409_PIN_ASP1_OUT_C,
+       CS8409_PIN_ASP1_OUT_D,
+       CS8409_PIN_ASP1_OUT_E,
+       CS8409_PIN_ASP1_OUT_F,
+       CS8409_PIN_ASP1_OUT_G,
+       CS8409_PIN_ASP1_OUT_H,
+       CS8409_PIN_ASP2_OUT_A,
+       CS8409_PIN_ASP2_OUT_B,
+       CS8409_PIN_ASP2_OUT_C,
+       CS8409_PIN_ASP2_OUT_D,
+       CS8409_PIN_ASP2_OUT_E,
+       CS8409_PIN_ASP2_OUT_F,
+       CS8409_PIN_ASP2_OUT_G,
+       CS8409_PIN_ASP2_OUT_H,
+       CS8409_PIN_ASP1_IN_A,
+       CS8409_PIN_ASP1_IN_B,
+       CS8409_PIN_ASP1_IN_C,
+       CS8409_PIN_ASP1_IN_D,
+       CS8409_PIN_ASP1_IN_E,
+       CS8409_PIN_ASP1_IN_F,
+       CS8409_PIN_ASP1_IN_G,
+       CS8409_PIN_ASP1_IN_H,
+       CS8409_PIN_ASP2_IN_A,
+       CS8409_PIN_ASP2_IN_B,
+       CS8409_PIN_ASP2_IN_C,
+       CS8409_PIN_ASP2_IN_D,
+       CS8409_PIN_ASP2_IN_E,
+       CS8409_PIN_ASP2_IN_F,
+       CS8409_PIN_ASP2_IN_G,
+       CS8409_PIN_ASP2_IN_H,
+       CS8409_PIN_DMIC1,
+       CS8409_PIN_DMIC2,
+       CS8409_PIN_ASP1_TRANSMITTER_A,
+       CS8409_PIN_ASP1_TRANSMITTER_B,
+       CS8409_PIN_ASP1_TRANSMITTER_C,
+       CS8409_PIN_ASP1_TRANSMITTER_D,
+       CS8409_PIN_ASP1_TRANSMITTER_E,
+       CS8409_PIN_ASP1_TRANSMITTER_F,
+       CS8409_PIN_ASP1_TRANSMITTER_G,
+       CS8409_PIN_ASP1_TRANSMITTER_H,
+       CS8409_PIN_ASP2_TRANSMITTER_A,
+       CS8409_PIN_ASP2_TRANSMITTER_B,
+       CS8409_PIN_ASP2_TRANSMITTER_C,
+       CS8409_PIN_ASP2_TRANSMITTER_D,
+       CS8409_PIN_ASP2_TRANSMITTER_E,
+       CS8409_PIN_ASP2_TRANSMITTER_F,
+       CS8409_PIN_ASP2_TRANSMITTER_G,
+       CS8409_PIN_ASP2_TRANSMITTER_H,
+       CS8409_PIN_ASP1_RECEIVER_A,
+       CS8409_PIN_ASP1_RECEIVER_B,
+       CS8409_PIN_ASP1_RECEIVER_C,
+       CS8409_PIN_ASP1_RECEIVER_D,
+       CS8409_PIN_ASP1_RECEIVER_E,
+       CS8409_PIN_ASP1_RECEIVER_F,
+       CS8409_PIN_ASP1_RECEIVER_G,
+       CS8409_PIN_ASP1_RECEIVER_H,
+       CS8409_PIN_ASP2_RECEIVER_A,
+       CS8409_PIN_ASP2_RECEIVER_B,
+       CS8409_PIN_ASP2_RECEIVER_C,
+       CS8409_PIN_ASP2_RECEIVER_D,
+       CS8409_PIN_ASP2_RECEIVER_E,
+       CS8409_PIN_ASP2_RECEIVER_F,
+       CS8409_PIN_ASP2_RECEIVER_G,
+       CS8409_PIN_ASP2_RECEIVER_H,
+       CS8409_PIN_DMIC1_IN,
+       CS8409_PIN_DMIC2_IN,
+       CS8409_PIN_BEEP_GEN,
+       CS8409_PIN_VENDOR_WIDGET
+};
+
+enum cs8409_coefficient_index_registers {
+       CS8409_DEV_CFG1,
+       CS8409_DEV_CFG2,
+       CS8409_DEV_CFG3,
+       CS8409_ASP1_CLK_CTRL1,
+       CS8409_ASP1_CLK_CTRL2,
+       CS8409_ASP1_CLK_CTRL3,
+       CS8409_ASP2_CLK_CTRL1,
+       CS8409_ASP2_CLK_CTRL2,
+       CS8409_ASP2_CLK_CTRL3,
+       CS8409_DMIC_CFG,
+       CS8409_BEEP_CFG,
+       ASP1_RX_NULL_INS_RMV,
+       ASP1_Rx_RATE1,
+       ASP1_Rx_RATE2,
+       ASP1_Tx_NULL_INS_RMV,
+       ASP1_Tx_RATE1,
+       ASP1_Tx_RATE2,
+       ASP2_Rx_NULL_INS_RMV,
+       ASP2_Rx_RATE1,
+       ASP2_Rx_RATE2,
+       ASP2_Tx_NULL_INS_RMV,
+       ASP2_Tx_RATE1,
+       ASP2_Tx_RATE2,
+       ASP1_SYNC_CTRL,
+       ASP2_SYNC_CTRL,
+       ASP1_A_TX_CTRL1,
+       ASP1_A_TX_CTRL2,
+       ASP1_B_TX_CTRL1,
+       ASP1_B_TX_CTRL2,
+       ASP1_C_TX_CTRL1,
+       ASP1_C_TX_CTRL2,
+       ASP1_D_TX_CTRL1,
+       ASP1_D_TX_CTRL2,
+       ASP1_E_TX_CTRL1,
+       ASP1_E_TX_CTRL2,
+       ASP1_F_TX_CTRL1,
+       ASP1_F_TX_CTRL2,
+       ASP1_G_TX_CTRL1,
+       ASP1_G_TX_CTRL2,
+       ASP1_H_TX_CTRL1,
+       ASP1_H_TX_CTRL2,
+       ASP2_A_TX_CTRL1,
+       ASP2_A_TX_CTRL2,
+       ASP2_B_TX_CTRL1,
+       ASP2_B_TX_CTRL2,
+       ASP2_C_TX_CTRL1,
+       ASP2_C_TX_CTRL2,
+       ASP2_D_TX_CTRL1,
+       ASP2_D_TX_CTRL2,
+       ASP2_E_TX_CTRL1,
+       ASP2_E_TX_CTRL2,
+       ASP2_F_TX_CTRL1,
+       ASP2_F_TX_CTRL2,
+       ASP2_G_TX_CTRL1,
+       ASP2_G_TX_CTRL2,
+       ASP2_H_TX_CTRL1,
+       ASP2_H_TX_CTRL2,
+       ASP1_A_RX_CTRL1,
+       ASP1_A_RX_CTRL2,
+       ASP1_B_RX_CTRL1,
+       ASP1_B_RX_CTRL2,
+       ASP1_C_RX_CTRL1,
+       ASP1_C_RX_CTRL2,
+       ASP1_D_RX_CTRL1,
+       ASP1_D_RX_CTRL2,
+       ASP1_E_RX_CTRL1,
+       ASP1_E_RX_CTRL2,
+       ASP1_F_RX_CTRL1,
+       ASP1_F_RX_CTRL2,
+       ASP1_G_RX_CTRL1,
+       ASP1_G_RX_CTRL2,
+       ASP1_H_RX_CTRL1,
+       ASP1_H_RX_CTRL2,
+       ASP2_A_RX_CTRL1,
+       ASP2_A_RX_CTRL2,
+       ASP2_B_RX_CTRL1,
+       ASP2_B_RX_CTRL2,
+       ASP2_C_RX_CTRL1,
+       ASP2_C_RX_CTRL2,
+       ASP2_D_RX_CTRL1,
+       ASP2_D_RX_CTRL2,
+       ASP2_E_RX_CTRL1,
+       ASP2_E_RX_CTRL2,
+       ASP2_F_RX_CTRL1,
+       ASP2_F_RX_CTRL2,
+       ASP2_G_RX_CTRL1,
+       ASP2_G_RX_CTRL2,
+       ASP2_H_RX_CTRL1,
+       ASP2_H_RX_CTRL2,
+       CS8409_I2C_ADDR,
+       CS8409_I2C_DATA,
+       CS8409_I2C_CTRL,
+       CS8409_I2C_STS,
+       CS8409_I2C_QWRITE,
+       CS8409_I2C_QREAD,
+       CS8409_SPI_CTRL,
+       CS8409_SPI_TX_DATA,
+       CS8409_SPI_RX_DATA,
+       CS8409_SPI_STS,
+       CS8409_PFE_COEF_W1, /* Parametric filter engine coefficient write 1*/
+       CS8409_PFE_COEF_W2,
+       CS8409_PFE_CTRL1,
+       CS8409_PFE_CTRL2,
+       CS8409_PRE_SCALE_ATTN1,
+       CS8409_PRE_SCALE_ATTN2,
+       CS8409_PFE_COEF_MON1, /* Parametric filter engine coefficient monitor 1*/
+       CS8409_PFE_COEF_MON2,
+       CS8409_ASP1_INTRN_STS,
+       CS8409_ASP2_INTRN_STS,
+       CS8409_ASP1_RX_SCLK_COUNT,
+       CS8409_ASP1_TX_SCLK_COUNT,
+       CS8409_ASP2_RX_SCLK_COUNT,
+       CS8409_ASP2_TX_SCLK_COUNT,
+       CS8409_ASP_UNS_RESP_MASK,
+       CS8409_LOOPBACK_CTRL = 0x80,
+       CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */
+};
+
+/* CS42L42 Specific Definitions */
+
+#define CS8409_MAX_CODECS                      8
+#define CS42L42_VOLUMES                                (4U)
+#define CS42L42_HP_VOL_REAL_MIN                        (-63)
+#define CS42L42_HP_VOL_REAL_MAX                        (0)
+#define CS42L42_AMIC_VOL_REAL_MIN              (-97)
+#define CS42L42_AMIC_VOL_REAL_MAX              (12)
+#define CS42L42_REG_HS_VOL_CHA                 (0x2301)
+#define CS42L42_REG_HS_VOL_CHB                 (0x2303)
+#define CS42L42_REG_HS_VOL_MASK                        (0x003F)
+#define CS42L42_REG_AMIC_VOL                   (0x1D03)
+#define CS42L42_REG_AMIC_VOL_MASK              (0x00FF)
+#define CS42L42_HSDET_AUTO_DONE                        (0x02)
+#define CS42L42_HSTYPE_MASK                    (0x03)
+#define CS42L42_JACK_INSERTED                  (0x0C)
+#define CS42L42_JACK_REMOVED                   (0x00)
+#define CS42L42_I2C_TIMEOUT_US                 (20000)
+#define CS42L42_I2C_SLEEP_US                   (2000)
+#define CS42L42_PDN_TIMEOUT_US                 (250000)
+#define CS42L42_PDN_SLEEP_US                   (2000)
+
+/* Dell BULLSEYE / WARLOCK / CYBORG Specific Definitions */
+
+#define CS42L42_I2C_ADDR                       (0x48 << 1)
+#define CS8409_CS42L42_RESET                   GENMASK(5, 5) /* CS8409_GPIO5 */
+#define CS8409_CS42L42_INT                     GENMASK(4, 4) /* CS8409_GPIO4 */
+#define CS8409_CS42L42_HP_PIN_NID              CS8409_PIN_ASP1_TRANSMITTER_A
+#define CS8409_CS42L42_SPK_PIN_NID             CS8409_PIN_ASP2_TRANSMITTER_A
+#define CS8409_CS42L42_AMIC_PIN_NID            CS8409_PIN_ASP1_RECEIVER_A
+#define CS8409_CS42L42_DMIC_PIN_NID            CS8409_PIN_DMIC1_IN
+#define CS8409_CS42L42_DMIC_ADC_PIN_NID                CS8409_PIN_DMIC1
+
+/* Dolphin */
+
+#define DOLPHIN_C0_I2C_ADDR                    (0x48 << 1)
+#define DOLPHIN_C1_I2C_ADDR                    (0x49 << 1)
+#define DOLPHIN_HP_PIN_NID                     CS8409_PIN_ASP1_TRANSMITTER_A
+#define DOLPHIN_LO_PIN_NID                     CS8409_PIN_ASP1_TRANSMITTER_B
+#define DOLPHIN_AMIC_PIN_NID                   CS8409_PIN_ASP1_RECEIVER_A
+
+#define DOLPHIN_C0_INT                         GENMASK(4, 4)
+#define DOLPHIN_C1_INT                         GENMASK(0, 0)
+#define DOLPHIN_C0_RESET                       GENMASK(5, 5)
+#define DOLPHIN_C1_RESET                       GENMASK(1, 1)
+#define DOLPHIN_WAKE                           (DOLPHIN_C0_INT | DOLPHIN_C1_INT)
+
+enum {
+       CS8409_BULLSEYE,
+       CS8409_WARLOCK,
+       CS8409_CYBORG,
+       CS8409_FIXUPS,
+       CS8409_DOLPHIN,
+       CS8409_DOLPHIN_FIXUPS,
+};
+
+enum {
+       CS8409_CODEC0,
+       CS8409_CODEC1
+};
+
+enum {
+       CS42L42_VOL_ADC,
+       CS42L42_VOL_DAC,
+};
+
+#define CS42L42_ADC_VOL_OFFSET                 (CS42L42_VOL_ADC)
+#define CS42L42_DAC_CH0_VOL_OFFSET             (CS42L42_VOL_DAC)
+#define CS42L42_DAC_CH1_VOL_OFFSET             (CS42L42_VOL_DAC + 1)
+
+struct cs8409_i2c_param {
+       unsigned int addr;
+       unsigned int value;
+};
+
+struct cs8409_cir_param {
+       unsigned int nid;
+       unsigned int cir;
+       unsigned int coeff;
+};
+
+struct sub_codec {
+       struct hda_codec *codec;
+       unsigned int addr;
+       unsigned int reset_gpio;
+       unsigned int irq_mask;
+       const struct cs8409_i2c_param *init_seq;
+       unsigned int init_seq_num;
+
+       unsigned int hp_jack_in:1;
+       unsigned int mic_jack_in:1;
+       unsigned int suspended:1;
+       unsigned int paged:1;
+       unsigned int last_page;
+       unsigned int hsbias_hiz;
+       unsigned int full_scale_vol:1;
+       unsigned int no_type_dect:1;
+
+       s8 vol[CS42L42_VOLUMES];
+};
+
+struct cs8409_spec {
+       struct hda_gen_spec gen;
+       struct hda_codec *codec;
+
+       struct sub_codec *scodecs[CS8409_MAX_CODECS];
+       unsigned int num_scodecs;
+
+       unsigned int gpio_mask;
+       unsigned int gpio_dir;
+       unsigned int gpio_data;
+
+       struct mutex i2c_mux;
+       unsigned int i2c_clck_enabled;
+       unsigned int dev_addr;
+       struct delayed_work i2c_clk_work;
+
+       unsigned int playback_started:1;
+       unsigned int capture_started:1;
+       unsigned int init_done:1;
+       unsigned int build_ctrl_done:1;
+
+       /* verb exec op override */
+       int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
+                        unsigned int *res);
+};
+
+extern const struct snd_kcontrol_new cs42l42_dac_volume_mixer;
+extern const struct snd_kcontrol_new cs42l42_adc_volume_mixer;
+
+int cs42l42_volume_info(struct snd_kcontrol *kctrl, struct snd_ctl_elem_info *uinfo);
+int cs42l42_volume_get(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl);
+int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl);
+
+extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_playback;
+extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_capture;
+extern const struct snd_pci_quirk cs8409_fixup_tbl[];
+extern const struct hda_model_fixup cs8409_models[];
+extern const struct hda_fixup cs8409_fixups[];
+extern const struct hda_verb cs8409_cs42l42_init_verbs[];
+extern const struct hda_pintbl cs8409_cs42l42_pincfgs[];
+extern const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[];
+extern const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[];
+extern struct sub_codec cs8409_cs42l42_codec;
+
+extern const struct hda_verb dolphin_init_verbs[];
+extern const struct hda_pintbl dolphin_pincfgs[];
+extern const struct cs8409_cir_param dolphin_hw_cfg[];
+extern struct sub_codec dolphin_cs42l42_0;
+extern struct sub_codec dolphin_cs42l42_1;
+
+void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action);
+void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action);
+
+#endif
index e143e69..65d2c55 100644 (file)
@@ -47,6 +47,10 @@ IS_ENABLED(CONFIG_SND_HDA_INTEL_HDMI_SILENT_STREAM);
 module_param(enable_silent_stream, bool, 0644);
 MODULE_PARM_DESC(enable_silent_stream, "Enable Silent Stream for HDMI devices");
 
+static bool enable_all_pins;
+module_param(enable_all_pins, bool, 0444);
+MODULE_PARM_DESC(enable_all_pins, "Forcibly enable all pins");
+
 struct hdmi_spec_per_cvt {
        hda_nid_t cvt_nid;
        int assigned;
@@ -1959,6 +1963,9 @@ static int hdmi_parse_codec(struct hda_codec *codec)
                return -EINVAL;
        }
 
+       if (enable_all_pins)
+               spec->force_connect = true;
+
        q = snd_pci_quirk_lookup(codec->bus->pci, force_connect_list);
 
        if (q && q->value)
index 7ad689f..8b7a389 100644 (file)
@@ -109,7 +109,6 @@ struct alc_spec {
        void (*power_hook)(struct hda_codec *codec);
 #endif
        void (*shutup)(struct hda_codec *codec);
-       void (*reboot_notify)(struct hda_codec *codec);
 
        int init_amp;
        int codec_variant;      /* flag for other variants */
@@ -897,16 +896,6 @@ static inline void alc_shutup(struct hda_codec *codec)
                alc_shutup_pins(codec);
 }
 
-static void alc_reboot_notify(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-
-       if (spec && spec->reboot_notify)
-               spec->reboot_notify(codec);
-       else
-               alc_shutup(codec);
-}
-
 #define alc_free       snd_hda_gen_free
 
 #ifdef CONFIG_PM
@@ -952,7 +941,6 @@ static const struct hda_codec_ops alc_patch_ops = {
        .suspend = alc_suspend,
        .check_power_status = snd_hda_gen_check_power_status,
 #endif
-       .reboot_notify = alc_reboot_notify,
 };
 
 
@@ -5773,7 +5761,6 @@ static void alc_fixup_tpt440_dock(struct hda_codec *codec,
        struct alc_spec *spec = codec->spec;
 
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
-               spec->reboot_notify = snd_hda_gen_reboot_notify; /* reduce noise */
                spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
                codec->power_save_node = 0; /* avoid click noises */
                snd_hda_apply_pincfgs(codec, pincfgs);
@@ -8438,6 +8425,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x87f2, "HP ProBook 640 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x87f6, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
        SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
        SND_PCI_QUIRK(0x103c, 0x8805, "HP ProBook 650 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x880d, "HP EliteBook 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
@@ -9521,6 +9509,16 @@ static int patch_alc269(struct hda_codec *codec)
 
        snd_hda_pick_fixup(codec, alc269_fixup_models,
                       alc269_fixup_tbl, alc269_fixups);
+       /* FIXME: both TX300 and ROG Strix G17 have the same SSID, and
+        * the quirk breaks the latter (bko#214101).
+        * Clear the wrong entry.
+        */
+       if (codec->fixup_id == ALC282_FIXUP_ASUS_TX300 &&
+           codec->core.vendor_id == 0x10ec0294) {
+               codec_dbg(codec, "Clear wrong fixup for ASUS ROG Strix G17\n");
+               codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
+       }
+
        snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups, true);
        snd_hda_pick_pin_fixup(codec, alc269_fallback_pin_fixup_tbl, alc269_fixups, false);
        snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl,
index 3bd592e..61df4d3 100644 (file)
@@ -4380,18 +4380,6 @@ static int stac_init(struct hda_codec *codec)
        return 0;
 }
 
-static void stac_shutup(struct hda_codec *codec)
-{
-       struct sigmatel_spec *spec = codec->spec;
-
-       snd_hda_shutup_pins(codec);
-
-       if (spec->eapd_mask)
-               stac_gpio_set(codec, spec->gpio_mask,
-                               spec->gpio_dir, spec->gpio_data &
-                               ~spec->eapd_mask);
-}
-
 #define stac_free      snd_hda_gen_free
 
 #ifdef CONFIG_SND_PROC_FS
@@ -4444,7 +4432,15 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer,
 #ifdef CONFIG_PM
 static int stac_suspend(struct hda_codec *codec)
 {
-       stac_shutup(codec);
+       struct sigmatel_spec *spec = codec->spec;
+
+       snd_hda_shutup_pins(codec);
+
+       if (spec->eapd_mask)
+               stac_gpio_set(codec, spec->gpio_mask,
+                               spec->gpio_dir, spec->gpio_data &
+                               ~spec->eapd_mask);
+
        return 0;
 }
 #else
@@ -4460,7 +4456,6 @@ static const struct hda_codec_ops stac_patch_ops = {
 #ifdef CONFIG_PM
        .suspend = stac_suspend,
 #endif
-       .reboot_notify = stac_shutup,
 };
 
 static int alloc_stac_spec(struct hda_codec *codec)
index d54cd51..a5241a2 100644 (file)
@@ -2432,31 +2432,18 @@ static int snd_ice1712_build_controls(struct snd_ice1712 *ice)
                           snd_ctl_new1(&snd_ice1712_mixer_pro_peak, ice));
 }
 
-static int snd_ice1712_free(struct snd_ice1712 *ice)
+static void snd_ice1712_free(struct snd_card *card)
 {
-       if (!ice->port)
-               goto __hw_end;
+       struct snd_ice1712 *ice = card->private_data;
+
+       if (ice->card_info && ice->card_info->chip_exit)
+               ice->card_info->chip_exit(ice);
+
        /* mask all interrupts */
        outb(ICE1712_MULTI_CAPTURE | ICE1712_MULTI_PLAYBACK, ICEMT(ice, IRQ));
        outb(0xff, ICEREG(ice, IRQMASK));
-       /* --- */
-__hw_end:
-       if (ice->irq >= 0)
-               free_irq(ice->irq, ice);
 
-       if (ice->port)
-               pci_release_regions(ice->pci);
        snd_ice1712_akm4xxx_free(ice);
-       pci_disable_device(ice->pci);
-       kfree(ice->spec);
-       kfree(ice);
-       return 0;
-}
-
-static int snd_ice1712_dev_free(struct snd_device *device)
-{
-       struct snd_ice1712 *ice = device->device_data;
-       return snd_ice1712_free(ice);
 }
 
 static int snd_ice1712_create(struct snd_card *card,
@@ -2464,34 +2451,22 @@ static int snd_ice1712_create(struct snd_card *card,
                              const char *modelname,
                              int omni,
                              int cs8427_timeout,
-                             int dxr_enable,
-                             struct snd_ice1712 **r_ice1712)
+                             int dxr_enable)
 {
-       struct snd_ice1712 *ice;
+       struct snd_ice1712 *ice = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_ice1712_dev_free,
-       };
-
-       *r_ice1712 = NULL;
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 28 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
                dev_err(card->dev,
                        "architecture does not support 28bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       ice = kzalloc(sizeof(*ice), GFP_KERNEL);
-       if (ice == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        ice->omni = omni ? 1 : 0;
        if (cs8427_timeout < 1)
                cs8427_timeout = 1;
@@ -2523,45 +2498,29 @@ static int snd_ice1712_create(struct snd_card *card,
        pci_write_config_word(ice->pci, 0x42, 0x0006);
        snd_ice1712_proc_init(ice);
 
-       card->private_data = ice;
-
        err = pci_request_regions(pci, "ICE1712");
-       if (err < 0) {
-               kfree(ice);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        ice->port = pci_resource_start(pci, 0);
        ice->ddma_port = pci_resource_start(pci, 1);
        ice->dmapath_port = pci_resource_start(pci, 2);
        ice->profi_port = pci_resource_start(pci, 3);
 
-       if (request_irq(pci->irq, snd_ice1712_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, ice)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_ice1712_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, ice)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_ice1712_free(ice);
                return -EIO;
        }
 
        ice->irq = pci->irq;
        card->sync_irq = ice->irq;
+       card->private_free = snd_ice1712_free;
 
-       if (snd_ice1712_read_eeprom(ice, modelname) < 0) {
-               snd_ice1712_free(ice);
+       if (snd_ice1712_read_eeprom(ice, modelname) < 0)
                return -EIO;
-       }
-       if (snd_ice1712_chip_init(ice) < 0) {
-               snd_ice1712_free(ice);
+       if (snd_ice1712_chip_init(ice) < 0)
                return -EIO;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops);
-       if (err < 0) {
-               snd_ice1712_free(ice);
-               return err;
-       }
 
-       *r_ice1712 = ice;
        return 0;
 }
 
@@ -2591,34 +2550,31 @@ static int snd_ice1712_probe(struct pci_dev *pci,
        }
 
        err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+                          sizeof(*ice), &card);
        if (err < 0)
                return err;
+       ice = card->private_data;
 
        strcpy(card->driver, "ICE1712");
        strcpy(card->shortname, "ICEnsemble ICE1712");
 
        err = snd_ice1712_create(card, pci, model[dev], omni[dev],
-               cs8427_timeout[dev], dxr_enable[dev], &ice);
-       if (err < 0) {
-               snd_card_free(card);
+                                cs8427_timeout[dev], dxr_enable[dev]);
+       if (err < 0)
                return err;
-       }
 
        for (tbl = card_tables; *tbl; tbl++) {
                for (c = *tbl; c->subvendor; c++) {
                        if (c->subvendor == ice->eeprom.subvendor) {
-                               ice->card_info = c;
                                strcpy(card->shortname, c->name);
                                if (c->driver) /* specific driver? */
                                        strcpy(card->driver, c->driver);
                                if (c->chip_init) {
                                        err = c->chip_init(ice);
-                                       if (err < 0) {
-                                               snd_card_free(card);
+                                       if (err < 0)
                                                return err;
-                                       }
                                }
+                               ice->card_info = c;
                                goto __found;
                        }
                }
@@ -2627,45 +2583,33 @@ static int snd_ice1712_probe(struct pci_dev *pci,
  __found:
 
        err = snd_ice1712_pcm_profi(ice, pcm_dev++);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        if (ice_has_con_ac97(ice)) {
                err = snd_ice1712_pcm(ice, pcm_dev++);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 
        err = snd_ice1712_ac97_mixer(ice);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_ice1712_build_controls(ice);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        if (c->build_controls) {
                err = c->build_controls(ice);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 
        if (ice_has_con_ac97(ice)) {
                err = snd_ice1712_pcm_ds(ice, pcm_dev++);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 
        if (!c->no_mpu401) {
@@ -2674,10 +2618,8 @@ static int snd_ice1712_probe(struct pci_dev *pci,
                        c->mpu401_1_info_flags |
                        MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
                        -1, &ice->rmidi[0]);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
                if (c->mpu401_1_name)
                        /*  Preferred name available in card_info */
                        snprintf(ice->rmidi[0]->name,
@@ -2692,10 +2634,8 @@ static int snd_ice1712_probe(struct pci_dev *pci,
                                MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
                                -1, &ice->rmidi[1]);
 
-                       if (err < 0) {
-                               snd_card_free(card);
+                       if (err < 0)
                                return err;
-                       }
                        if (c->mpu401_2_name)
                                /*  Preferred name available in card_info */
                                snprintf(ice->rmidi[1]->name,
@@ -2711,25 +2651,13 @@ static int snd_ice1712_probe(struct pci_dev *pci,
                card->shortname, ice->port, ice->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_ice1712_remove(struct pci_dev *pci)
-{
-       struct snd_card *card = pci_get_drvdata(pci);
-       struct snd_ice1712 *ice = card->private_data;
-
-       if (ice->card_info && ice->card_info->chip_exit)
-               ice->card_info->chip_exit(ice);
-       snd_card_free(card);
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int snd_ice1712_suspend(struct device *dev)
 {
@@ -2810,7 +2738,6 @@ static struct pci_driver ice1712_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ice1712_ids,
        .probe = snd_ice1712_probe,
-       .remove = snd_ice1712_remove,
        .driver = {
                .pm = SND_VT1712_PM_OPS,
        },
index ef2367d..f627586 100644 (file)
@@ -2150,13 +2150,6 @@ static const struct snd_kcontrol_new snd_vt1724_mixer_pro_peak = {
        .get = snd_vt1724_pro_peak_get
 };
 
-/*
- *
- */
-
-static const struct snd_ice1712_card_info no_matched;
-
-
 /*
   ooAoo cards with no controls
 */
@@ -2454,54 +2447,29 @@ static int snd_vt1724_build_controls(struct snd_ice1712 *ice)
                           snd_ctl_new1(&snd_vt1724_mixer_pro_peak, ice));
 }
 
-static int snd_vt1724_free(struct snd_ice1712 *ice)
+static void snd_vt1724_free(struct snd_card *card)
 {
-       if (!ice->port)
-               goto __hw_end;
+       struct snd_ice1712 *ice = card->private_data;
+
        /* mask all interrupts */
        outb(0xff, ICEMT1724(ice, DMA_INT_MASK));
        outb(0xff, ICEREG1724(ice, IRQMASK));
-       /* --- */
-__hw_end:
-       if (ice->irq >= 0)
-               free_irq(ice->irq, ice);
-       pci_release_regions(ice->pci);
-       snd_ice1712_akm4xxx_free(ice);
-       pci_disable_device(ice->pci);
-       kfree(ice->spec);
-       kfree(ice);
-       return 0;
-}
 
-static int snd_vt1724_dev_free(struct snd_device *device)
-{
-       struct snd_ice1712 *ice = device->device_data;
-       return snd_vt1724_free(ice);
+       snd_ice1712_akm4xxx_free(ice);
 }
 
 static int snd_vt1724_create(struct snd_card *card,
                             struct pci_dev *pci,
-                            const char *modelname,
-                            struct snd_ice1712 **r_ice1712)
+                            const char *modelname)
 {
-       struct snd_ice1712 *ice;
+       struct snd_ice1712 *ice = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_vt1724_dev_free,
-       };
-
-       *r_ice1712 = NULL;
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       ice = kzalloc(sizeof(*ice), GFP_KERNEL);
-       if (ice == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        ice->vt1724 = 1;
        spin_lock_init(&ice->reg_lock);
        mutex_init(&ice->gpio_mutex);
@@ -2519,44 +2487,28 @@ static int snd_vt1724_create(struct snd_card *card,
        pci_set_master(pci);
        snd_vt1724_proc_init(ice);
 
-       card->private_data = ice;
-
        err = pci_request_regions(pci, "ICE1724");
-       if (err < 0) {
-               kfree(ice);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        ice->port = pci_resource_start(pci, 0);
        ice->profi_port = pci_resource_start(pci, 1);
 
-       if (request_irq(pci->irq, snd_vt1724_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, ice)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_vt1724_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, ice)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_vt1724_free(ice);
                return -EIO;
        }
 
        ice->irq = pci->irq;
        card->sync_irq = ice->irq;
+       card->private_free = snd_vt1724_free;
 
        snd_vt1724_chip_reset(ice);
-       if (snd_vt1724_read_eeprom(ice, modelname) < 0) {
-               snd_vt1724_free(ice);
+       if (snd_vt1724_read_eeprom(ice, modelname) < 0)
                return -EIO;
-       }
-       if (snd_vt1724_chip_init(ice) < 0) {
-               snd_vt1724_free(ice);
+       if (snd_vt1724_chip_init(ice) < 0)
                return -EIO;
-       }
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops);
-       if (err < 0) {
-               snd_vt1724_free(ice);
-               return err;
-       }
-
-       *r_ice1712 = ice;
        return 0;
 }
 
@@ -2574,7 +2526,7 @@ static int snd_vt1724_probe(struct pci_dev *pci,
        struct snd_card *card;
        struct snd_ice1712 *ice;
        int pcm_dev = 0, err;
-       const struct snd_ice1712_card_info * const *tbl, *c;
+       const struct snd_ice1712_card_info *c;
 
        if (dev >= SNDRV_CARDS)
                return -ENODEV;
@@ -2583,44 +2535,34 @@ static int snd_vt1724_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*ice), &card);
        if (err < 0)
                return err;
+       ice = card->private_data;
 
        strcpy(card->driver, "ICE1724");
        strcpy(card->shortname, "ICEnsemble ICE1724");
 
-       err = snd_vt1724_create(card, pci, model[dev], &ice);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_vt1724_create(card, pci, model[dev]);
+       if (err < 0)
                return err;
-       }
 
        /* field init before calling chip_init */
        ice->ext_clock_count = 0;
 
-       for (tbl = card_tables; *tbl; tbl++) {
-               for (c = *tbl; c->name; c++) {
-                       if ((model[dev] && c->model &&
-                            !strcmp(model[dev], c->model)) ||
-                           (c->subvendor == ice->eeprom.subvendor)) {
-                               strcpy(card->shortname, c->name);
-                               if (c->driver) /* specific driver? */
-                                       strcpy(card->driver, c->driver);
-                               if (c->chip_init) {
-                                       err = c->chip_init(ice);
-                                       if (err < 0) {
-                                               snd_card_free(card);
-                                               return err;
-                                       }
-                               }
-                               goto __found;
-                       }
+       c = ice->card_info;
+       if (c) {
+               strcpy(card->shortname, c->name);
+               if (c->driver) /* specific driver? */
+                       strcpy(card->driver, c->driver);
+               if (c->chip_init) {
+                       err = c->chip_init(ice);
+                       if (err < 0)
+                               return err;
                }
        }
-       c = &no_matched;
-__found:
+
        /*
        * VT1724 has separate DMAs for the analog and the SPDIF streams while
        * ICE1712 has only one for both (mixed up).
@@ -2651,60 +2593,44 @@ __found:
                set_std_hw_rates(ice);
 
        err = snd_vt1724_pcm_profi(ice, pcm_dev++);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_vt1724_pcm_spdif(ice, pcm_dev++);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_vt1724_pcm_indep(ice, pcm_dev++);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_vt1724_ac97_mixer(ice);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_vt1724_build_controls(ice);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        if (ice->pcm && ice->has_spdif) { /* has SPDIF I/O */
                err = snd_vt1724_spdif_build_controls(ice);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 
-       if (c->build_controls) {
+       if (c && c->build_controls) {
                err = c->build_controls(ice);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 
-       if (!c->no_mpu401) {
+       if (!c || !c->no_mpu401) {
                if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {
                        struct snd_rawmidi *rmidi;
 
                        err = snd_rawmidi_new(card, "MIDI", 0, 1, 1, &rmidi);
-                       if (err < 0) {
-                               snd_card_free(card);
+                       if (err < 0)
                                return err;
-                       }
                        ice->rmidi[0] = rmidi;
                        rmidi->private_data = ice;
                        strcpy(rmidi->name, "ICE1724 MIDI");
@@ -2729,25 +2655,13 @@ __found:
                card->shortname, ice->port, ice->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_vt1724_remove(struct pci_dev *pci)
-{
-       struct snd_card *card = pci_get_drvdata(pci);
-       struct snd_ice1712 *ice = card->private_data;
-
-       if (ice->card_info && ice->card_info->chip_exit)
-               ice->card_info->chip_exit(ice);
-       snd_card_free(card);
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int snd_vt1724_suspend(struct device *dev)
 {
@@ -2825,7 +2739,6 @@ static struct pci_driver vt1724_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_vt1724_ids,
        .probe = snd_vt1724_probe,
-       .remove = snd_vt1724_remove,
        .driver = {
                .pm = SND_VT1724_PM_OPS,
        },
index df3ba5c..a51032b 100644 (file)
@@ -378,7 +378,7 @@ struct intel8x0 {
        spinlock_t reg_lock;
        
        u32 bdbars_count;
-       struct snd_dma_buffer bdbars;
+       struct snd_dma_buffer *bdbars;
        u32 int_sta_reg;                /* interrupt status register */
        u32 int_sta_mask;               /* interrupt status mask */
 };
@@ -1427,7 +1427,7 @@ struct ich_pcm_table {
 };
 
 #define intel8x0_dma_type(chip) \
-       ((chip)->fix_nocache ? SNDRV_DMA_TYPE_DEV_UC : SNDRV_DMA_TYPE_DEV)
+       ((chip)->fix_nocache ? SNDRV_DMA_TYPE_DEV_WC : SNDRV_DMA_TYPE_DEV)
 
 static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
                             const struct ich_pcm_table *rec)
@@ -2528,8 +2528,9 @@ static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing)
        return 0;
 }
 
-static int snd_intel8x0_free(struct intel8x0 *chip)
+static void snd_intel8x0_free(struct snd_card *card)
 {
+       struct intel8x0 *chip = card->private_data;
        unsigned int i;
 
        if (chip->irq < 0)
@@ -2552,16 +2553,6 @@ static int snd_intel8x0_free(struct intel8x0 *chip)
       __hw_end:
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
-       if (chip->bdbars.area)
-               snd_dma_free_pages(&chip->bdbars);
-       if (chip->addr)
-               pci_iounmap(chip->pci, chip->addr);
-       if (chip->bmaddr)
-               pci_iounmap(chip->pci, chip->bmaddr);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -2656,6 +2647,8 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip)
 
        if (chip->ac97_bus->clock != 48000)
                return; /* specified in module option */
+       if (chip->inside_vm && !ac97_clock)
+               return; /* no measurement on VM */
 
       __again:
        subs = chip->pcm[0]->streams[0].substream;
@@ -2829,12 +2822,6 @@ static void snd_intel8x0_proc_init(struct intel8x0 *chip)
                             snd_intel8x0_proc_read);
 }
 
-static int snd_intel8x0_dev_free(struct snd_device *device)
-{
-       struct intel8x0 *chip = device->device_data;
-       return snd_intel8x0_free(chip);
-}
-
 struct ich_reg_info {
        unsigned int int_sta_mask;
        unsigned int offset;
@@ -2878,19 +2865,15 @@ fini:
        return result;
 }
 
-static int snd_intel8x0_create(struct snd_card *card,
-                              struct pci_dev *pci,
-                              unsigned long device_type,
-                              struct intel8x0 **r_intel8x0)
+static int snd_intel8x0_init(struct snd_card *card,
+                            struct pci_dev *pci,
+                            unsigned long device_type)
 {
-       struct intel8x0 *chip;
+       struct intel8x0 *chip = card->private_data;
        int err;
        unsigned int i;
        unsigned int int_sta_masks;
        struct ichdev *ichdev;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_intel8x0_dev_free,
-       };
 
        static const unsigned int bdbars[] = {
                3, /* DEVICE_INTEL */
@@ -2923,17 +2906,10 @@ static int snd_intel8x0_create(struct snd_card *card,
        };
        const struct ich_reg_info *tbl;
 
-       *r_intel8x0 = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&chip->reg_lock);
        chip->device_type = device_type;
        chip->card = card;
@@ -2959,38 +2935,23 @@ static int snd_intel8x0_create(struct snd_card *card,
                chip->fix_nocache = 1; /* enable workaround */
 
        err = pci_request_regions(pci, card->shortname);
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
 
        if (device_type == DEVICE_ALI) {
                /* ALI5455 has no ac97 region */
-               chip->bmaddr = pci_iomap(pci, 0, 0);
-               goto port_inited;
-       }
-
-       if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
-               chip->addr = pci_iomap(pci, 2, 0);
-       else
-               chip->addr = pci_iomap(pci, 0, 0);
-       if (!chip->addr) {
-               dev_err(card->dev, "AC'97 space ioremap problem\n");
-               snd_intel8x0_free(chip);
-               return -EIO;
+               chip->bmaddr = pcim_iomap(pci, 0, 0);
+       } else {
+               if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
+                       chip->addr = pcim_iomap(pci, 2, 0);
+               else
+                       chip->addr = pcim_iomap(pci, 0, 0);
+               if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
+                       chip->bmaddr = pcim_iomap(pci, 3, 0);
+               else
+                       chip->bmaddr = pcim_iomap(pci, 1, 0);
        }
-       if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
-               chip->bmaddr = pci_iomap(pci, 3, 0);
-       else
-               chip->bmaddr = pci_iomap(pci, 1, 0);
 
- port_inited:
-       if (!chip->bmaddr) {
-               dev_err(card->dev, "Controller space ioremap problem\n");
-               snd_intel8x0_free(chip);
-               return -EIO;
-       }
        chip->bdbars_count = bdbars[device_type];
 
        /* initialize offsets */
@@ -3026,21 +2987,20 @@ static int snd_intel8x0_create(struct snd_card *card,
 
        /* allocate buffer descriptor lists */
        /* the start of each lists must be aligned to 8 bytes */
-       if (snd_dma_alloc_pages(intel8x0_dma_type(chip), &pci->dev,
-                               chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
-                               &chip->bdbars) < 0) {
-               snd_intel8x0_free(chip);
-               dev_err(card->dev, "cannot allocate buffer descriptors\n");
+       chip->bdbars = snd_devm_alloc_pages(&pci->dev, intel8x0_dma_type(chip),
+                                           chip->bdbars_count * sizeof(u32) *
+                                           ICH_MAX_FRAGS * 2);
+       if (!chip->bdbars)
                return -ENOMEM;
-       }
+
        /* tables must be aligned to 8 bytes here, but the kernel pages
           are much bigger, so we don't care (on i386) */
        int_sta_masks = 0;
        for (i = 0; i < chip->bdbars_count; i++) {
                ichdev = &chip->ichd[i];
-               ichdev->bdbar = ((__le32 *)chip->bdbars.area) +
+               ichdev->bdbar = ((__le32 *)chip->bdbars->area) +
                        (i * ICH_MAX_FRAGS * 2);
-               ichdev->bdbar_addr = chip->bdbars.addr +
+               ichdev->bdbar_addr = chip->bdbars->addr +
                        (i * sizeof(u32) * ICH_MAX_FRAGS * 2);
                int_sta_masks |= ichdev->int_sta_mask;
        }
@@ -3074,28 +3034,24 @@ static int snd_intel8x0_create(struct snd_card *card,
                chip->codec_isr_bits |= chip->codec_bit[i];
 
        err = snd_intel8x0_chip_init(chip, 1);
-       if (err < 0) {
-               snd_intel8x0_free(chip);
+       if (err < 0)
                return err;
-       }
 
        /* request irq after initializaing int_sta_mask, etc */
+       /* NOTE: we don't use devm version here since it's released /
+        * re-acquired in PM callbacks.
+        * It's released explicitly in snd_intel8x0_free(), too.
+        */
        if (request_irq(pci->irq, snd_intel8x0_interrupt,
                        IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_intel8x0_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_intel8x0_free(chip);
-               return err;
-       }
+       card->private_free = snd_intel8x0_free;
 
-       *r_intel8x0 = chip;
        return 0;
 }
 
@@ -3161,9 +3117,11 @@ static int snd_intel8x0_probe(struct pci_dev *pci,
        int err;
        struct shortname_table *name;
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        if (spdif_aclink < 0)
                spdif_aclink = check_default_spdif_aclink(pci);
@@ -3197,23 +3155,16 @@ static int snd_intel8x0_probe(struct pci_dev *pci,
                        buggy_irq = 0;
        }
 
-       err = snd_intel8x0_create(card, pci, pci_id->driver_data, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_intel8x0_init(card, pci, pci_id->driver_data);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        err = snd_intel8x0_mixer(chip, ac97_clock, ac97_quirk);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_intel8x0_pcm(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        
        snd_intel8x0_proc_init(chip);
 
@@ -3231,24 +3182,17 @@ static int snd_intel8x0_probe(struct pci_dev *pci,
        }
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
+
        pci_set_drvdata(pci, card);
        return 0;
 }
 
-static void snd_intel8x0_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver intel8x0_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_intel8x0_ids,
        .probe = snd_intel8x0_probe,
-       .remove = snd_intel8x0_remove,
        .driver = {
                .pm = INTEL8X0_PM_OPS,
        },
index b96fce6..7de3cb2 100644 (file)
@@ -182,7 +182,7 @@ struct intel8x0m {
 
        spinlock_t reg_lock;
        
-       struct snd_dma_buffer bdbars;
+       struct snd_dma_buffer *bdbars;
        u32 bdbars_count;
        u32 int_sta_reg;                /* interrupt status register */
        u32 int_sta_mask;               /* interrupt status mask */
@@ -947,8 +947,9 @@ static int snd_intel8x0m_chip_init(struct intel8x0m *chip, int probing)
        return 0;
 }
 
-static int snd_intel8x0m_free(struct intel8x0m *chip)
+static void snd_intel8x0m_free(struct snd_card *card)
 {
+       struct intel8x0m *chip = card->private_data;
        unsigned int i;
 
        if (chip->irq < 0)
@@ -962,16 +963,6 @@ static int snd_intel8x0m_free(struct intel8x0m *chip)
  __hw_end:
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
-       if (chip->bdbars.area)
-               snd_dma_free_pages(&chip->bdbars);
-       if (chip->addr)
-               pci_iounmap(chip->pci, chip->addr);
-       if (chip->bmaddr)
-               pci_iounmap(chip->pci, chip->bmaddr);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -1047,47 +1038,30 @@ static void snd_intel8x0m_proc_init(struct intel8x0m *chip)
                             snd_intel8x0m_proc_read);
 }
 
-static int snd_intel8x0m_dev_free(struct snd_device *device)
-{
-       struct intel8x0m *chip = device->device_data;
-       return snd_intel8x0m_free(chip);
-}
-
 struct ich_reg_info {
        unsigned int int_sta_mask;
        unsigned int offset;
 };
 
-static int snd_intel8x0m_create(struct snd_card *card,
-                               struct pci_dev *pci,
-                               unsigned long device_type,
-                               struct intel8x0m **r_intel8x0m)
+static int snd_intel8x0m_init(struct snd_card *card,
+                             struct pci_dev *pci,
+                             unsigned long device_type)
 {
-       struct intel8x0m *chip;
+       struct intel8x0m *chip = card->private_data;
        int err;
        unsigned int i;
        unsigned int int_sta_masks;
        struct ichdev *ichdev;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_intel8x0m_dev_free,
-       };
        static const struct ich_reg_info intel_regs[2] = {
                { ICH_MIINT, 0 },
                { ICH_MOINT, 0x10 },
        };
        const struct ich_reg_info *tbl;
 
-       *r_intel8x0m = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&chip->reg_lock);
        chip->device_type = device_type;
        chip->card = card;
@@ -1095,37 +1069,21 @@ static int snd_intel8x0m_create(struct snd_card *card,
        chip->irq = -1;
 
        err = pci_request_regions(pci, card->shortname);
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
 
        if (device_type == DEVICE_ALI) {
                /* ALI5455 has no ac97 region */
-               chip->bmaddr = pci_iomap(pci, 0, 0);
-               goto port_inited;
-       }
-
-       if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
-               chip->addr = pci_iomap(pci, 2, 0);
-       else
-               chip->addr = pci_iomap(pci, 0, 0);
-       if (!chip->addr) {
-               dev_err(card->dev, "AC'97 space ioremap problem\n");
-               snd_intel8x0m_free(chip);
-               return -EIO;
-       }
-       if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
-               chip->bmaddr = pci_iomap(pci, 3, 0);
-       else
-               chip->bmaddr = pci_iomap(pci, 1, 0);
-
-port_inited:
-       if (!chip->bmaddr) {
-               dev_err(card->dev, "Controller space ioremap problem\n");
-               snd_intel8x0m_free(chip);
-               return -EIO;
+               chip->bmaddr = pcim_iomap(pci, 0, 0);
+       } else {
+               if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
+                       chip->addr = pcim_iomap(pci, 2, 0);
+               else
+                       chip->addr = pcim_iomap(pci, 0, 0);
+               if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
+                       chip->bmaddr = pcim_iomap(pci, 3, 0);
+               else
+                       chip->bmaddr = pcim_iomap(pci, 1, 0);
        }
 
        /* initialize offsets */
@@ -1153,19 +1111,19 @@ port_inited:
 
        /* allocate buffer descriptor lists */
        /* the start of each lists must be aligned to 8 bytes */
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
-                               &chip->bdbars) < 0) {
-               snd_intel8x0m_free(chip);
+       chip->bdbars = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+                                           chip->bdbars_count * sizeof(u32) *
+                                           ICH_MAX_FRAGS * 2);
+       if (!chip->bdbars)
                return -ENOMEM;
-       }
+
        /* tables must be aligned to 8 bytes here, but the kernel pages
           are much bigger, so we don't care (on i386) */
        int_sta_masks = 0;
        for (i = 0; i < chip->bdbars_count; i++) {
                ichdev = &chip->ichd[i];
-               ichdev->bdbar = ((__le32 *)chip->bdbars.area) + (i * ICH_MAX_FRAGS * 2);
-               ichdev->bdbar_addr = chip->bdbars.addr + (i * sizeof(u32) * ICH_MAX_FRAGS * 2);
+               ichdev->bdbar = ((__le32 *)chip->bdbars->area) + (i * ICH_MAX_FRAGS * 2);
+               ichdev->bdbar_addr = chip->bdbars->addr + (i * sizeof(u32) * ICH_MAX_FRAGS * 2);
                int_sta_masks |= ichdev->int_sta_mask;
        }
        chip->int_sta_reg = ICH_REG_GLOB_STA;
@@ -1174,27 +1132,23 @@ port_inited:
        pci_set_master(pci);
 
        err = snd_intel8x0m_chip_init(chip, 1);
-       if (err < 0) {
-               snd_intel8x0m_free(chip);
+       if (err < 0)
                return err;
-       }
 
+       /* NOTE: we don't use devm version here since it's released /
+        * re-acquired in PM callbacks.
+        * It's released explicitly in snd_intel8x0m_free(), too.
+        */
        if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED,
                        KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_intel8x0m_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_intel8x0m_free(chip);
-               return err;
-       }
+       card->private_free = snd_intel8x0m_free;
 
-       *r_intel8x0m = chip;
        return 0;
 }
 
@@ -1232,9 +1186,11 @@ static int snd_intel8x0m_probe(struct pci_dev *pci,
        int err;
        struct shortname_table *name;
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        strcpy(card->driver, "ICH-MODEM");
        strcpy(card->shortname, "Intel ICH");
@@ -1246,23 +1202,16 @@ static int snd_intel8x0m_probe(struct pci_dev *pci,
        }
        strcat(card->shortname," Modem");
 
-       err = snd_intel8x0m_create(card, pci, pci_id->driver_data, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_intel8x0m_init(card, pci, pci_id->driver_data);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        err = snd_intel8x0m_mixer(chip, ac97_clock);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_intel8x0m_pcm(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        
        snd_intel8x0m_proc_init(chip);
 
@@ -1270,24 +1219,16 @@ static int snd_intel8x0m_probe(struct pci_dev *pci,
                card->shortname, chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        return 0;
 }
 
-static void snd_intel8x0m_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver intel8x0m_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_intel8x0m_ids,
        .probe = snd_intel8x0m_probe,
-       .remove = snd_intel8x0m_remove,
        .driver = {
                .pm = INTEL8X0M_PM_OPS,
        },
index 030e01b..5c9e240 100644 (file)
@@ -320,10 +320,10 @@ struct snd_korg1212 {
         unsigned long inIRQ;
         void __iomem *iobase;
 
-       struct snd_dma_buffer dma_dsp;
-        struct snd_dma_buffer dma_play;
-        struct snd_dma_buffer dma_rec;
-       struct snd_dma_buffer dma_shared;
+       struct snd_dma_buffer *dma_dsp;
+       struct snd_dma_buffer *dma_play;
+       struct snd_dma_buffer *dma_rec;
+       struct snd_dma_buffer *dma_shared;
 
        u32 DataBufsSize;
 
@@ -1200,8 +1200,8 @@ static int snd_korg1212_downloadDSPCode(struct snd_korg1212 *korg1212)
         snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_IN_PROCESS);
 
         rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_StartDSPDownload,
-                                     UpperWordSwap(korg1212->dma_dsp.addr),
-                                     0, 0, 0);
+                                         UpperWordSwap(korg1212->dma_dsp->addr),
+                                         0, 0, 0);
        if (rc)
                K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n",
                                   rc, stateName[korg1212->cardState]);
@@ -1382,7 +1382,7 @@ static int snd_korg1212_playback_open(struct snd_pcm_substream *substream)
        snd_korg1212_OpenCard(korg1212);
 
         runtime->hw = snd_korg1212_playback_info;
-       snd_pcm_set_runtime_buffer(substream, &korg1212->dma_play);
+       snd_pcm_set_runtime_buffer(substream, korg1212->dma_play);
 
         spin_lock_irqsave(&korg1212->lock, flags);
 
@@ -1413,7 +1413,7 @@ static int snd_korg1212_capture_open(struct snd_pcm_substream *substream)
        snd_korg1212_OpenCard(korg1212);
 
         runtime->hw = snd_korg1212_capture_info;
-       snd_pcm_set_runtime_buffer(substream, &korg1212->dma_rec);
+       snd_pcm_set_runtime_buffer(substream, korg1212->dma_rec);
 
         spin_lock_irqsave(&korg1212->lock, flags);
 
@@ -2080,96 +2080,30 @@ static void snd_korg1212_proc_init(struct snd_korg1212 *korg1212)
                             snd_korg1212_proc_read);
 }
 
-static int
-snd_korg1212_free(struct snd_korg1212 *korg1212)
+static void
+snd_korg1212_free(struct snd_card *card)
 {
-        snd_korg1212_TurnOffIdleMonitor(korg1212);
-
-        if (korg1212->irq >= 0) {
-                snd_korg1212_DisableCardInterrupts(korg1212);
-                free_irq(korg1212->irq, korg1212);
-                korg1212->irq = -1;
-        }
-        
-        if (korg1212->iobase != NULL) {
-                iounmap(korg1212->iobase);
-                korg1212->iobase = NULL;
-        }
-        
-       pci_release_regions(korg1212->pci);
-
-        // ----------------------------------------------------
-        // free up memory resources used for the DSP download.
-        // ----------------------------------------------------
-        if (korg1212->dma_dsp.area) {
-               snd_dma_free_pages(&korg1212->dma_dsp);
-               korg1212->dma_dsp.area = NULL;
-        }
-
-#ifndef K1212_LARGEALLOC
-
-        // ------------------------------------------------------
-        // free up memory resources used for the Play/Rec Buffers
-        // ------------------------------------------------------
-       if (korg1212->dma_play.area) {
-               snd_dma_free_pages(&korg1212->dma_play);
-               korg1212->dma_play.area = NULL;
-        }
+       struct snd_korg1212 *korg1212 = card->private_data;
 
-       if (korg1212->dma_rec.area) {
-               snd_dma_free_pages(&korg1212->dma_rec);
-               korg1212->dma_rec.area = NULL;
-        }
-
-#endif
-
-        // ----------------------------------------------------
-        // free up memory resources used for the Shared Buffers
-        // ----------------------------------------------------
-       if (korg1212->dma_shared.area) {
-               snd_dma_free_pages(&korg1212->dma_shared);
-               korg1212->dma_shared.area = NULL;
-        }
-        
-       pci_disable_device(korg1212->pci);
-        kfree(korg1212);
-        return 0;
+       snd_korg1212_TurnOffIdleMonitor(korg1212);
+       snd_korg1212_DisableCardInterrupts(korg1212);
 }
 
-static int snd_korg1212_dev_free(struct snd_device *device)
-{
-        struct snd_korg1212 *korg1212 = device->device_data;
-        K1212_DEBUG_PRINTK("K1212_DEBUG: Freeing device\n");
-       return snd_korg1212_free(korg1212);
-}
-
-static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
-                              struct snd_korg1212 **rchip)
+static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci)
 
 {
         int err, rc;
         unsigned int i;
-       unsigned iomem_size;
+       __maybe_unused unsigned iomem_size;
        __maybe_unused unsigned ioport_size;
        __maybe_unused unsigned iomem2_size;
-        struct snd_korg1212 * korg1212;
+       struct snd_korg1212 *korg1212 = card->private_data;
        const struct firmware *dsp_code;
 
-       static const struct snd_device_ops ops = {
-                .dev_free = snd_korg1212_dev_free,
-        };
-
-        * rchip = NULL;
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                 return err;
 
-        korg1212 = kzalloc(sizeof(*korg1212), GFP_KERNEL);
-        if (korg1212 == NULL) {
-               pci_disable_device(pci);
-                return -ENOMEM;
-       }
-
        korg1212->card = card;
        korg1212->pci = pci;
 
@@ -2198,12 +2132,9 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
         for (i=0; i<kAudioChannels; i++)
                 korg1212->volumePhase[i] = 0;
 
-       err = pci_request_regions(pci, "korg1212");
-       if (err < 0) {
-               kfree(korg1212);
-               pci_disable_device(pci);
+       err = pcim_iomap_regions_request_all(pci, 1 << 0, "korg1212");
+       if (err < 0)
                return err;
-       }
 
         korg1212->iomem = pci_resource_start(korg1212->pci, 0);
         korg1212->ioport = pci_resource_start(korg1212->pci, 1);
@@ -2223,26 +2154,20 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
                   korg1212->iomem2, iomem2_size,
                   stateName[korg1212->cardState]);
 
-       korg1212->iobase = ioremap(korg1212->iomem, iomem_size);
-       if (!korg1212->iobase) {
-               snd_printk(KERN_ERR "korg1212: unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem,
-                           korg1212->iomem + iomem_size - 1);
-                snd_korg1212_free(korg1212);
-                return -EBUSY;
-        }
+       korg1212->iobase = pcim_iomap_table(pci)[0];
 
-        err = request_irq(pci->irq, snd_korg1212_interrupt,
+       err = devm_request_irq(&pci->dev, pci->irq, snd_korg1212_interrupt,
                           IRQF_SHARED,
                           KBUILD_MODNAME, korg1212);
 
         if (err) {
                snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq);
-                snd_korg1212_free(korg1212);
                 return -EBUSY;
         }
 
         korg1212->irq = pci->irq;
        card->sync_irq = korg1212->irq;
+       card->private_free = snd_korg1212_free;
 
        pci_set_master(korg1212->pci);
 
@@ -2281,41 +2206,36 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
                    korg1212->idRegPtr,
                   stateName[korg1212->cardState]);
 
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               sizeof(struct KorgSharedBuffer), &korg1212->dma_shared) < 0) {
-               snd_printk(KERN_ERR "korg1212: can not allocate shared buffer memory (%zd bytes)\n", sizeof(struct KorgSharedBuffer));
-                snd_korg1212_free(korg1212);
-                return -ENOMEM;
-        }
-        korg1212->sharedBufferPtr = (struct KorgSharedBuffer *)korg1212->dma_shared.area;
-        korg1212->sharedBufferPhy = korg1212->dma_shared.addr;
+       korg1212->dma_shared = snd_devm_alloc_pages(&pci->dev,
+                                                   SNDRV_DMA_TYPE_DEV,
+                                                   sizeof(struct KorgSharedBuffer));
+       if (!korg1212->dma_shared)
+               return -ENOMEM;
+       korg1212->sharedBufferPtr = (struct KorgSharedBuffer *)korg1212->dma_shared->area;
+       korg1212->sharedBufferPhy = korg1212->dma_shared->addr;
 
         K1212_DEBUG_PRINTK("K1212_DEBUG: Shared Buffer Area = 0x%p (0x%08lx), %d bytes\n", korg1212->sharedBufferPtr, korg1212->sharedBufferPhy, sizeof(struct KorgSharedBuffer));
 
 #ifndef K1212_LARGEALLOC
-
         korg1212->DataBufsSize = sizeof(struct KorgAudioBuffer) * kNumBuffers;
+       korg1212->dma_play = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+                                                 korg1212->DataBufsSize);
+       if (!korg1212->dma_play)
+               return -ENOMEM;
 
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               korg1212->DataBufsSize, &korg1212->dma_play) < 0) {
-               snd_printk(KERN_ERR "korg1212: can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
-                snd_korg1212_free(korg1212);
-                return -ENOMEM;
-        }
-       korg1212->playDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_play.area;
-       korg1212->PlayDataPhy = korg1212->dma_play.addr;
+       korg1212->playDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_play->area;
+       korg1212->PlayDataPhy = korg1212->dma_play->addr;
 
         K1212_DEBUG_PRINTK("K1212_DEBUG: Play Data Area = 0x%p (0x%08x), %d bytes\n",
                korg1212->playDataBufsPtr, korg1212->PlayDataPhy, korg1212->DataBufsSize);
 
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               korg1212->DataBufsSize, &korg1212->dma_rec) < 0) {
-               snd_printk(KERN_ERR "korg1212: can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
-                snd_korg1212_free(korg1212);
-                return -ENOMEM;
-        }
-        korg1212->recordDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_rec.area;
-        korg1212->RecDataPhy = korg1212->dma_rec.addr;
+       korg1212->dma_rec = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+                                                korg1212->DataBufsSize);
+       if (!korg1212->dma_rec)
+               return -ENOMEM;
+
+       korg1212->recordDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_rec->area;
+       korg1212->RecDataPhy = korg1212->dma_rec->addr;
 
         K1212_DEBUG_PRINTK("K1212_DEBUG: Record Data Area = 0x%p (0x%08x), %d bytes\n",
                korg1212->recordDataBufsPtr, korg1212->RecDataPhy, korg1212->DataBufsSize);
@@ -2339,23 +2259,21 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
        err = request_firmware(&dsp_code, "korg/k1212.dsp", &pci->dev);
        if (err < 0) {
                snd_printk(KERN_ERR "firmware not available\n");
-               snd_korg1212_free(korg1212);
                return err;
        }
 
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
-                               dsp_code->size, &korg1212->dma_dsp) < 0) {
-               snd_printk(KERN_ERR "korg1212: cannot allocate dsp code memory (%zd bytes)\n", dsp_code->size);
-                snd_korg1212_free(korg1212);
+       korg1212->dma_dsp = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+                                                dsp_code->size);
+       if (!korg1212->dma_dsp) {
                release_firmware(dsp_code);
-                return -ENOMEM;
-        }
+               return -ENOMEM;
+       }
 
         K1212_DEBUG_PRINTK("K1212_DEBUG: DSP Code area = 0x%p (0x%08x) %d bytes [%s]\n",
-                  korg1212->dma_dsp.area, korg1212->dma_dsp.addr, dsp_code->size,
+                  korg1212->dma_dsp->area, korg1212->dma_dsp->addr, dsp_code->size,
                   stateName[korg1212->cardState]);
 
-       memcpy(korg1212->dma_dsp.area, dsp_code->data, dsp_code->size);
+       memcpy(korg1212->dma_dsp->area, dsp_code->data, dsp_code->size);
 
        release_firmware(dsp_code);
 
@@ -2364,12 +2282,6 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
        if (rc)
                K1212_DEBUG_PRINTK("K1212_DEBUG: Reboot Card - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, korg1212, &ops);
-       if (err < 0) {
-                snd_korg1212_free(korg1212);
-                return err;
-        }
-        
        snd_korg1212_EnableCardInterrupts(korg1212);
 
        mdelay(CARD_BOOT_DELAY_IN_MS);
@@ -2411,10 +2323,8 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
         }
 
         snd_korg1212_proc_init(korg1212);
-        
-        * rchip = korg1212;
-       return 0;
 
+       return 0;
 }
 
 /*
@@ -2437,16 +2347,15 @@ snd_korg1212_probe(struct pci_dev *pci,
                dev++;
                return -ENOENT;
        }
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*korg1212), &card);
        if (err < 0)
                return err;
+       korg1212 = card->private_data;
 
-       err = snd_korg1212_create(card, pci, &korg1212);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_korg1212_create(card, pci);
+       if (err < 0)
                return err;
-       }
 
        strcpy(card->driver, "korg1212");
        strcpy(card->shortname, "korg1212");
@@ -2456,25 +2365,17 @@ snd_korg1212_probe(struct pci_dev *pci,
         K1212_DEBUG_PRINTK("K1212_DEBUG: %s\n", card->longname);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_korg1212_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver korg1212_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_korg1212_ids,
        .probe = snd_korg1212_probe,
-       .remove = snd_korg1212_remove,
 };
 
 module_pci_driver(korg1212_driver);
index 03b4be4..5269a1d 100644 (file)
@@ -344,20 +344,18 @@ static void lola_irq_disable(struct lola *chip)
 
 static int setup_corb_rirb(struct lola *chip)
 {
-       int err;
        unsigned char tmp;
        unsigned long end_time;
 
-       err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-                                 &chip->pci->dev,
-                                 PAGE_SIZE, &chip->rb);
-       if (err < 0)
-               return err;
+       chip->rb = snd_devm_alloc_pages(&chip->pci->dev, SNDRV_DMA_TYPE_DEV,
+                                       PAGE_SIZE);
+       if (!chip->rb)
+               return -ENOMEM;
 
-       chip->corb.addr = chip->rb.addr;
-       chip->corb.buf = (__le32 *)chip->rb.area;
-       chip->rirb.addr = chip->rb.addr + 2048;
-       chip->rirb.buf = (__le32 *)(chip->rb.area + 2048);
+       chip->corb.addr = chip->rb->addr;
+       chip->corb.buf = (__le32 *)chip->rb->area;
+       chip->rirb.addr = chip->rb->addr + 2048;
+       chip->rirb.buf = (__le32 *)(chip->rb->area + 2048);
 
        /* disable ringbuffer DMAs */
        lola_writeb(chip, BAR0, RIRBCTL, 0);
@@ -529,56 +527,31 @@ static void lola_stop_hw(struct lola *chip)
        lola_irq_disable(chip);
 }
 
-static void lola_free(struct lola *chip)
+static void lola_free(struct snd_card *card)
 {
+       struct lola *chip = card->private_data;
+
        if (chip->initialized)
                lola_stop_hw(chip);
-       lola_free_pcm(chip);
        lola_free_mixer(chip);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, (void *)chip);
-       iounmap(chip->bar[0].remap_addr);
-       iounmap(chip->bar[1].remap_addr);
-       if (chip->rb.area)
-               snd_dma_free_pages(&chip->rb);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
 }
 
-static int lola_dev_free(struct snd_device *device)
+static int lola_create(struct snd_card *card, struct pci_dev *pci, int dev)
 {
-       lola_free(device->device_data);
-       return 0;
-}
-
-static int lola_create(struct snd_card *card, struct pci_dev *pci,
-                      int dev, struct lola **rchip)
-{
-       struct lola *chip;
+       struct lola *chip = card->private_data;
        int err;
        unsigned int dever;
-       static const struct snd_device_ops ops = {
-               .dev_free = lola_dev_free,
-       };
 
-       *rchip = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (!chip) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&chip->reg_lock);
        mutex_init(&chip->open_mutex);
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
+       card->private_free = lola_free;
 
        chip->granularity = granularity[dev];
        switch (chip->granularity) {
@@ -607,34 +580,25 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
                chip->sample_rate_min = 16000;
        }
 
-       err = pci_request_regions(pci, DRVNAME);
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       err = pcim_iomap_regions(pci, (1 << 0) | (1 << 2), DRVNAME);
+       if (err < 0)
                return err;
-       }
 
        chip->bar[0].addr = pci_resource_start(pci, 0);
-       chip->bar[0].remap_addr = pci_ioremap_bar(pci, 0);
+       chip->bar[0].remap_addr = pcim_iomap_table(pci)[0];
        chip->bar[1].addr = pci_resource_start(pci, 2);
-       chip->bar[1].remap_addr = pci_ioremap_bar(pci, 2);
-       if (!chip->bar[0].remap_addr || !chip->bar[1].remap_addr) {
-               dev_err(chip->card->dev, "ioremap error\n");
-               err = -ENXIO;
-               goto errout;
-       }
+       chip->bar[1].remap_addr = pcim_iomap_table(pci)[2];
 
        pci_set_master(pci);
 
        err = reset_controller(chip);
        if (err < 0)
-               goto errout;
+               return err;
 
-       if (request_irq(pci->irq, lola_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, lola_interrupt, IRQF_SHARED,
+                            KBUILD_MODNAME, chip)) {
                dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq);
-               err = -EBUSY;
-               goto errout;
+               return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
@@ -653,19 +617,12 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
            (!chip->pcm[CAPT].num_streams &&
             !chip->pcm[PLAY].num_streams)) {
                dev_err(chip->card->dev, "invalid DEVER = %x\n", dever);
-               err = -EINVAL;
-               goto errout;
+               return -EINVAL;
        }
 
        err = setup_corb_rirb(chip);
        if (err < 0)
-               goto errout;
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               dev_err(chip->card->dev, "Error creating device [card]!\n");
-               goto errout;
-       }
+               return err;
 
        strcpy(card->driver, "Lola");
        strscpy(card->shortname, "Digigram Lola", sizeof(card->shortname));
@@ -677,12 +634,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
        lola_irq_enable(chip);
 
        chip->initialized = 1;
-       *rchip = chip;
        return 0;
-
- errout:
-       lola_free(chip);
-       return err;
 }
 
 static int lola_probe(struct pci_dev *pci,
@@ -700,47 +652,39 @@ static int lola_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0) {
                dev_err(&pci->dev, "Error creating card!\n");
                return err;
        }
+       chip = card->private_data;
 
-       err = lola_create(card, pci, dev, &chip);
+       err = lola_create(card, pci, dev);
        if (err < 0)
-               goto out_free;
-       card->private_data = chip;
+               return err;
 
        err = lola_parse_tree(chip);
        if (err < 0)
-               goto out_free;
+               return err;
 
        err = lola_create_pcm(chip);
        if (err < 0)
-               goto out_free;
+               return err;
 
        err = lola_create_mixer(chip);
        if (err < 0)
-               goto out_free;
+               return err;
 
        lola_proc_debug_new(chip);
 
        err = snd_card_register(card);
        if (err < 0)
-               goto out_free;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
-       return err;
-out_free:
-       snd_card_free(card);
-       return err;
-}
-
-static void lola_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
+       return 0;
 }
 
 /* PCI IDs */
@@ -755,7 +699,6 @@ static struct pci_driver lola_driver = {
        .name = KBUILD_MODNAME,
        .id_table = lola_ids,
        .probe = lola_probe,
-       .remove = lola_remove,
 };
 
 module_pci_driver(lola_driver);
index 8a598aa..0ff772c 100644 (file)
@@ -303,7 +303,7 @@ struct lola_stream {
 
 struct lola_pcm {
        unsigned int num_streams;
-       struct snd_dma_buffer bdl; /* BDL buffer */
+       struct snd_dma_buffer *bdl; /* BDL buffer */
        struct lola_stream streams[MAX_STREAM_COUNT];
 };
 
@@ -328,7 +328,7 @@ struct lola {
        unsigned int last_cmd_nid, last_verb, last_data, last_extdata;
 
        /* CORB/RIRB buffers */
-       struct snd_dma_buffer rb;
+       struct snd_dma_buffer *rb;
 
        /* unsolicited events */
        unsigned int last_unsol_res;
@@ -480,7 +480,6 @@ int lola_codec_flush(struct lola *chip);
 
 /* PCM */
 int lola_create_pcm(struct lola *chip);
-void lola_free_pcm(struct lola *chip);
 int lola_init_pcm(struct lola *chip, int dir, int *nidp);
 void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits);
 
index 684faaf..738ec98 100644 (file)
@@ -348,7 +348,7 @@ static int lola_setup_periods(struct lola *chip, struct lola_pcm *pcm,
        periods = str->bufsize / period_bytes;
 
        /* program the initial BDL entries */
-       bdl = (__le32 *)(pcm->bdl.area + LOLA_BDL_ENTRY_SIZE * str->index);
+       bdl = (__le32 *)(pcm->bdl->area + LOLA_BDL_ENTRY_SIZE * str->index);
        ofs = 0;
        str->frags = 0;
        for (i = 0; i < periods; i++) {
@@ -433,7 +433,7 @@ static int lola_setup_controller(struct lola *chip, struct lola_pcm *pcm,
                return -EINVAL;
 
        /* set up BDL */
-       bdl = pcm->bdl.addr + LOLA_BDL_ENTRY_SIZE * str->index;
+       bdl = pcm->bdl->addr + LOLA_BDL_ENTRY_SIZE * str->index;
        lola_dsd_write(chip, str->dsd, BDPL, (u32)bdl);
        lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(bdl));
        /* program the stream LVI (last valid index) of the BDL */
@@ -588,11 +588,11 @@ int lola_create_pcm(struct lola *chip)
        int i, err;
 
        for (i = 0; i < 2; i++) {
-               err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-                                         &chip->pci->dev,
-                                         PAGE_SIZE, &chip->pcm[i].bdl);
-               if (err < 0)
-                       return err;
+               chip->pcm[i].bdl =
+                       snd_devm_alloc_pages(&chip->pci->dev, SNDRV_DMA_TYPE_DEV,
+                                            PAGE_SIZE);
+               if (!chip->pcm[i].bdl)
+                       return -ENOMEM;
        }
 
        err = snd_pcm_new(chip->card, "Digigram Lola", 0,
@@ -614,12 +614,6 @@ int lola_create_pcm(struct lola *chip)
        return 0;
 }
 
-void lola_free_pcm(struct lola *chip)
-{
-       snd_dma_free_pages(&chip->pcm[0].bdl);
-       snd_dma_free_pages(&chip->pcm[1].bdl);
-}
-
 /*
  */
 
index 1be97c3..168a108 100644 (file)
@@ -524,29 +524,11 @@ static int lx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        return lx_pcm_trigger_dispatch(chip, stream, cmd);
 }
 
-static int snd_lx6464es_free(struct lx6464es *chip)
+static void snd_lx6464es_free(struct snd_card *card)
 {
-       dev_dbg(chip->card->dev, "->snd_lx6464es_free\n");
+       struct lx6464es *chip = card->private_data;
 
        lx_irq_disable(chip);
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-
-       iounmap(chip->port_dsp_bar);
-       ioport_unmap(chip->port_plx_remapped);
-
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-
-       kfree(chip);
-
-       return 0;
-}
-
-static int snd_lx6464es_dev_free(struct snd_device *device)
-{
-       return snd_lx6464es_free(device->device_data);
 }
 
 /* reset the dsp during initialization */
@@ -930,22 +912,15 @@ static int lx_proc_create(struct snd_card *card, struct lx6464es *chip)
 
 
 static int snd_lx6464es_create(struct snd_card *card,
-                              struct pci_dev *pci,
-                              struct lx6464es **rchip)
+                              struct pci_dev *pci)
 {
-       struct lx6464es *chip;
+       struct lx6464es *chip = card->private_data;
        int err;
 
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_lx6464es_dev_free,
-       };
-
        dev_dbg(card->dev, "->snd_lx6464es_create\n");
 
-       *rchip = NULL;
-
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
@@ -956,16 +931,9 @@ static int snd_lx6464es_create(struct snd_card *card,
        if (err < 0) {
                dev_err(card->dev,
                        "architecture does not support 32bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               err = -ENOMEM;
-               goto alloc_failed;
-       }
-
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
@@ -978,33 +946,30 @@ static int snd_lx6464es_create(struct snd_card *card,
        /* request resources */
        err = pci_request_regions(pci, card_name);
        if (err < 0)
-               goto request_regions_failed;
+               return err;
 
        /* plx port */
        chip->port_plx = pci_resource_start(pci, 1);
-       chip->port_plx_remapped = ioport_map(chip->port_plx,
-                                            pci_resource_len(pci, 1));
+       chip->port_plx_remapped = devm_ioport_map(&pci->dev, chip->port_plx,
+                                                 pci_resource_len(pci, 1));
+       if (!chip->port_plx_remapped)
+               return -ENOMEM;
 
        /* dsp port */
-       chip->port_dsp_bar = pci_ioremap_bar(pci, 2);
-       if (!chip->port_dsp_bar) {
-               dev_err(card->dev, "cannot remap PCI memory region\n");
-               err = -ENOMEM;
-               goto remap_pci_failed;
-       }
+       chip->port_dsp_bar = pcim_iomap(pci, 2, 0);
+       if (!chip->port_dsp_bar)
+               return -ENOMEM;
 
-       err = request_threaded_irq(pci->irq, lx_interrupt, lx_threaded_irq,
-                                  IRQF_SHARED, KBUILD_MODNAME, chip);
+       err = devm_request_threaded_irq(&pci->dev, pci->irq, lx_interrupt,
+                                       lx_threaded_irq, IRQF_SHARED,
+                                       KBUILD_MODNAME, chip);
        if (err) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               goto request_irq_failed;
+               return err;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto device_new_failed;
+       card->private_free = snd_lx6464es_free;
 
        err = lx_init_dsp(chip);
        if (err < 0) {
@@ -1025,25 +990,7 @@ static int snd_lx6464es_create(struct snd_card *card,
        if (err < 0)
                return err;
 
-       *rchip = chip;
        return 0;
-
-device_new_failed:
-       free_irq(pci->irq, chip);
-
-request_irq_failed:
-       iounmap(chip->port_dsp_bar);
-
-remap_pci_failed:
-       pci_release_regions(pci);
-
-request_regions_failed:
-       kfree(chip);
-
-alloc_failed:
-       pci_disable_device(pci);
-
-       return err;
 }
 
 static int snd_lx6464es_probe(struct pci_dev *pci,
@@ -1063,15 +1010,16 @@ static int snd_lx6464es_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
-       err = snd_lx6464es_create(card, pci, &chip);
+       err = snd_lx6464es_create(card, pci);
        if (err < 0) {
                dev_err(card->dev, "error during snd_lx6464es_create\n");
-               goto out_free;
+               return err;
        }
 
        strcpy(card->driver, "LX6464ES");
@@ -1088,30 +1036,18 @@ static int snd_lx6464es_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto out_free;
+               return err;
 
        dev_dbg(chip->card->dev, "initialization successful\n");
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
-out_free:
-       snd_card_free(card);
-       return err;
-
 }
 
-static void snd_lx6464es_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
-
 static struct pci_driver lx6464es_driver = {
        .name =     KBUILD_MODNAME,
        .id_table = snd_lx6464es_ids,
        .probe =    snd_lx6464es_probe,
-       .remove = snd_lx6464es_remove,
 };
 
 module_pci_driver(lx6464es_driver);
index 77a484b..056838e 100644 (file)
@@ -2339,16 +2339,13 @@ snd_m3_enable_ints(struct snd_m3 *chip)
 /*
  */
 
-static int snd_m3_free(struct snd_m3 *chip)
+static void snd_m3_free(struct snd_card *card)
 {
+       struct snd_m3 *chip = card->private_data;
        struct m3_dma *s;
        int i;
 
        cancel_work_sync(&chip->hwvol_work);
-#ifdef CONFIG_SND_MAESTRO3_INPUT
-       if (chip->input_dev)
-               input_unregister_device(chip->input_dev);
-#endif
 
        if (chip->substreams) {
                spin_lock_irq(&chip->reg_lock);
@@ -2359,7 +2356,6 @@ static int snd_m3_free(struct snd_m3 *chip)
                                snd_m3_pcm_stop(chip, s, s->substream);
                }
                spin_unlock_irq(&chip->reg_lock);
-               kfree(chip->substreams);
        }
        if (chip->iobase) {
                outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */
@@ -2368,19 +2364,8 @@ static int snd_m3_free(struct snd_m3 *chip)
 #ifdef CONFIG_PM_SLEEP
        vfree(chip->suspend_mem);
 #endif
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-
-       if (chip->iobase)
-               pci_release_regions(chip->pci);
-
        release_firmware(chip->assp_kernel_image);
        release_firmware(chip->assp_minisrc_image);
-
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
 }
 
 
@@ -2473,7 +2458,7 @@ static int snd_m3_input_register(struct snd_m3 *chip)
        struct input_dev *input_dev;
        int err;
 
-       input_dev = input_allocate_device();
+       input_dev = devm_input_allocate_device(&chip->pci->dev);
        if (!input_dev)
                return -ENOMEM;
 
@@ -2493,10 +2478,8 @@ static int snd_m3_input_register(struct snd_m3 *chip)
        __set_bit(KEY_VOLUMEUP, input_dev->keybit);
 
        err = input_register_device(input_dev);
-       if (err) {
-               input_free_device(input_dev);
+       if (err)
                return err;
-       }
 
        chip->input_dev = input_dev;
        return 0;
@@ -2506,44 +2489,25 @@ static int snd_m3_input_register(struct snd_m3 *chip)
 /*
  */
 
-static int snd_m3_dev_free(struct snd_device *device)
-{
-       struct snd_m3 *chip = device->device_data;
-       return snd_m3_free(chip);
-}
-
 static int
 snd_m3_create(struct snd_card *card, struct pci_dev *pci,
              int enable_amp,
-             int amp_gpio,
-             struct snd_m3 **chip_ret)
+             int amp_gpio)
 {
-       struct snd_m3 *chip;
+       struct snd_m3 *chip = card->private_data;
        int i, err;
        const struct snd_pci_quirk *quirk;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_m3_dev_free,
-       };
 
-       *chip_ret = NULL;
-
-       if (pci_enable_device(pci))
+       if (pcim_enable_device(pci))
                return -EIO;
 
        /* check, if we can restrict PCI DMA transfers to 28 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
                dev_err(card->dev,
                        "architecture does not support 28bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&chip->reg_lock);
 
        switch (pci->device) {
@@ -2559,6 +2523,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
        chip->pci = pci;
        chip->irq = -1;
        INIT_WORK(&chip->hwvol_work, snd_m3_update_hw_volume);
+       card->private_free = snd_m3_free;
 
        chip->external_amp = enable_amp;
        if (amp_gpio >= 0 && amp_gpio <= 0x0f)
@@ -2588,27 +2553,24 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
                chip->is_omnibook = 1;
 
        chip->num_substreams = NR_DSPS;
-       chip->substreams = kcalloc(chip->num_substreams, sizeof(struct m3_dma),
-                                  GFP_KERNEL);
-       if (chip->substreams == NULL) {
-               kfree(chip);
-               pci_disable_device(pci);
+       chip->substreams = devm_kcalloc(&pci->dev, chip->num_substreams,
+                                       sizeof(struct m3_dma), GFP_KERNEL);
+       if (!chip->substreams)
                return -ENOMEM;
-       }
 
        err = request_firmware(&chip->assp_kernel_image,
                               "ess/maestro3_assp_kernel.fw", &pci->dev);
        if (err < 0)
-               goto free_chip;
+               return err;
 
        err = request_firmware(&chip->assp_minisrc_image,
                               "ess/maestro3_assp_minisrc.fw", &pci->dev);
        if (err < 0)
-               goto free_chip;
+               return err;
 
        err = pci_request_regions(pci, card->driver);
        if (err < 0)
-               goto free_chip;
+               return err;
 
        chip->iobase = pci_resource_start(pci, 0);
        
@@ -2624,11 +2586,10 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
 
        snd_m3_hv_init(chip);
 
-       if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_m3_interrupt, IRQF_SHARED,
+                            KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               err = -ENOMEM;
-               goto free_chip;
+               return -ENOMEM;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
@@ -2642,10 +2603,6 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
                dev_warn(card->dev, "can't allocate apm buffer\n");
 #endif
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto free_chip;
-
        err = snd_m3_mixer(chip);
        if (err < 0)
                return err;
@@ -2674,13 +2631,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
        snd_m3_enable_ints(chip);
        snd_m3_assp_continue(chip);
 
-       *chip_ret = chip;
-
        return 0; 
-
-free_chip:
-       snd_m3_free(chip);
-       return err;
 }
 
 /*
@@ -2704,10 +2655,11 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        switch (pci->device) {
        case PCI_DEVICE_ID_ESS_ALLEGRO:
@@ -2723,11 +2675,9 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                break;
        }
 
-       err = snd_m3_create(card, pci, external_amp[dev], amp_gpio[dev], &chip);
+       err = snd_m3_create(card, pci, external_amp[dev], amp_gpio[dev]);
        if (err < 0)
-               goto free_card;
-
-       card->private_data = chip;
+               return err;
 
        sprintf(card->shortname, "ESS %s PCI", card->driver);
        sprintf(card->longname, "%s at 0x%lx, irq %d",
@@ -2735,7 +2685,7 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 
        err = snd_card_register(card);
        if (err < 0)
-               goto free_card;
+               return err;
 
 #if 0 /* TODO: not supported yet */
        /* TODO enable MIDI IRQ and I/O */
@@ -2750,22 +2700,12 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
-free_card:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_m3_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver m3_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_m3_ids,
        .probe = snd_m3_probe,
-       .remove = snd_m3_remove,
        .driver = {
                .pm = M3_PM_OPS,
        },
index 12d02d7..c9c1785 100644 (file)
@@ -193,11 +193,9 @@ struct nm256 {
        struct snd_card *card;
 
        void __iomem *cport;            /* control port */
-       struct resource *res_cport;     /* its resource */
        unsigned long cport_addr;       /* physical address */
 
        void __iomem *buffer;           /* buffer */
-       struct resource *res_buffer;    /* its resource */
        unsigned long buffer_addr;      /* buffer phyiscal address */
 
        u32 buffer_start;               /* start offset from pci resource 0 */
@@ -1313,8 +1311,9 @@ snd_nm256_mixer(struct nm256 *chip)
                .read = snd_nm256_ac97_read,
        };
 
-       chip->ac97_regs = kcalloc(ARRAY_SIZE(nm256_ac97_init_val),
-                                 sizeof(short), GFP_KERNEL);
+       chip->ac97_regs = devm_kcalloc(chip->card->dev,
+                                      ARRAY_SIZE(nm256_ac97_init_val),
+                                      sizeof(short), GFP_KERNEL);
        if (! chip->ac97_regs)
                return -ENOMEM;
 
@@ -1437,56 +1436,27 @@ static SIMPLE_DEV_PM_OPS(nm256_pm, nm256_suspend, nm256_resume);
 #define NM256_PM_OPS   NULL
 #endif /* CONFIG_PM_SLEEP */
 
-static int snd_nm256_free(struct nm256 *chip)
+static void snd_nm256_free(struct snd_card *card)
 {
+       struct nm256 *chip = card->private_data;
+
        if (chip->streams[SNDRV_PCM_STREAM_PLAYBACK].running)
                snd_nm256_playback_stop(chip);
        if (chip->streams[SNDRV_PCM_STREAM_CAPTURE].running)
                snd_nm256_capture_stop(chip);
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-
-       iounmap(chip->cport);
-       iounmap(chip->buffer);
-       release_and_free_resource(chip->res_cport);
-       release_and_free_resource(chip->res_buffer);
-
-       pci_disable_device(chip->pci);
-       kfree(chip->ac97_regs);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_nm256_dev_free(struct snd_device *device)
-{
-       struct nm256 *chip = device->device_data;
-       return snd_nm256_free(chip);
 }
 
 static int
-snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
-                struct nm256 **chip_ret)
+snd_nm256_create(struct snd_card *card, struct pci_dev *pci)
 {
-       struct nm256 *chip;
+       struct nm256 *chip = card->private_data;
        int err, pval;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_nm256_dev_free,
-       };
        u32 addr;
 
-       *chip_ret = NULL;
-
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->card = card;
        chip->pci = pci;
        chip->use_cache = use_cache;
@@ -1508,22 +1478,17 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
        chip->buffer_addr = pci_resource_start(pci, 0);
        chip->cport_addr = pci_resource_start(pci, 1);
 
+       err = pci_request_regions(pci, card->driver);
+       if (err < 0)
+               return err;
+
        /* Init the memory port info.  */
        /* remap control port (#2) */
-       chip->res_cport = request_mem_region(chip->cport_addr, NM_PORT2_SIZE,
-                                            card->driver);
-       if (chip->res_cport == NULL) {
-               dev_err(card->dev, "memory region 0x%lx (size 0x%x) busy\n",
-                          chip->cport_addr, NM_PORT2_SIZE);
-               err = -EBUSY;
-               goto __error;
-       }
-       chip->cport = ioremap(chip->cport_addr, NM_PORT2_SIZE);
-       if (chip->cport == NULL) {
+       chip->cport = devm_ioremap(&pci->dev, chip->cport_addr, NM_PORT2_SIZE);
+       if (!chip->cport) {
                dev_err(card->dev, "unable to map control port %lx\n",
                        chip->cport_addr);
-               err = -ENOMEM;
-               goto __error;
+               return -ENOMEM;
        }
 
        if (!strcmp(card->driver, "NM256AV")) {
@@ -1539,8 +1504,7 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
                                        " force_ac97=1\n");
                                dev_err(card->dev,
                                        "or try sb16, opl3sa2, or cs423x drivers instead.\n");
-                               err = -ENXIO;
-                               goto __error;
+                               return -ENXIO;
                        }
                }
                chip->buffer_end = 2560 * 1024;
@@ -1572,7 +1536,7 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
                /* get buffer end pointer from signature */
                err = snd_nm256_peek_for_sig(chip);
                if (err < 0)
-                       goto __error;
+                       return err;
        }
 
        chip->buffer_start = chip->buffer_end - chip->buffer_size;
@@ -1581,21 +1545,12 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
        dev_info(card->dev, "Mapping port 1 from 0x%x - 0x%x\n",
               chip->buffer_start, chip->buffer_end);
 
-       chip->res_buffer = request_mem_region(chip->buffer_addr,
-                                             chip->buffer_size,
-                                             card->driver);
-       if (chip->res_buffer == NULL) {
-               dev_err(card->dev, "buffer 0x%lx (size 0x%x) busy\n",
-                          chip->buffer_addr, chip->buffer_size);
-               err = -EBUSY;
-               goto __error;
-       }
-       chip->buffer = ioremap(chip->buffer_addr, chip->buffer_size);
-       if (chip->buffer == NULL) {
-               err = -ENOMEM;
+       chip->buffer = devm_ioremap(&pci->dev, chip->buffer_addr,
+                                   chip->buffer_size);
+       if (!chip->buffer) {
                dev_err(card->dev, "unable to map ring buffer at %lx\n",
                        chip->buffer_addr);
-               goto __error;
+               return -ENOMEM;
        }
 
        /* set offsets */
@@ -1618,19 +1573,10 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
        chip->coeffs_current = 0;
 
        snd_nm256_init_chip(chip);
+       card->private_free = snd_nm256_free;
 
        // pci_set_master(pci); /* needed? */
-       
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto __error;
-
-       *chip_ret = chip;
        return 0;
-
-__error:
-       snd_nm256_free(chip);
-       return err;
 }
 
 
@@ -1673,9 +1619,11 @@ static int snd_nm256_probe(struct pci_dev *pci,
                }
        }
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        switch (pci->device) {
        case PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO:
@@ -1689,7 +1637,6 @@ static int snd_nm256_probe(struct pci_dev *pci,
                break;
        default:
                dev_err(&pci->dev, "invalid device id 0x%x\n", pci->device);
-               snd_card_free(card);
                return -EINVAL;
        }
 
@@ -1704,12 +1651,9 @@ static int snd_nm256_probe(struct pci_dev *pci,
                capture_bufsize = 4;
        if (capture_bufsize > 128)
                capture_bufsize = 128;
-       err = snd_nm256_create(card, pci, &chip);
-       if (err < 0) {
-               snd_card_free(card);
+       err = snd_nm256_create(card, pci);
+       if (err < 0)
                return err;
-       }
-       card->private_data = chip;
 
        if (reset_workaround) {
                dev_dbg(&pci->dev, "reset_workaround activated\n");
@@ -1722,15 +1666,11 @@ static int snd_nm256_probe(struct pci_dev *pci,
        }
 
        err = snd_nm256_pcm(chip, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_nm256_mixer(chip);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        sprintf(card->shortname, "NeoMagic %s", card->driver);
        sprintf(card->longname, "%s at 0x%lx & 0x%lx, irq %d",
@@ -1738,26 +1678,17 @@ static int snd_nm256_probe(struct pci_dev *pci,
                chip->buffer_addr, chip->cport_addr, chip->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        return 0;
 }
 
-static void snd_nm256_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
-
 static struct pci_driver nm256_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_nm256_ids,
        .probe = snd_nm256_probe,
-       .remove = snd_nm256_remove,
        .driver = {
                .pm = NM256_PM_OPS,
        },
index e335c4b..c346f42 100644 (file)
@@ -854,7 +854,6 @@ static struct pci_driver oxygen_driver = {
        .name = KBUILD_MODNAME,
        .id_table = oxygen_ids,
        .probe = generic_oxygen_probe,
-       .remove = oxygen_pci_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &oxygen_pci_pm,
index 06bf7e5..0cae640 100644 (file)
@@ -161,7 +161,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
                                      const struct pci_device_id *id
                                     )
                    );
-void oxygen_pci_remove(struct pci_dev *pci);
 #ifdef CONFIG_PM_SLEEP
 extern const struct dev_pm_ops oxygen_pci_pm;
 #endif
index afc6dd3..4fb3f24 100644 (file)
@@ -570,15 +570,10 @@ static void oxygen_card_free(struct snd_card *card)
        struct oxygen *chip = card->private_data;
 
        oxygen_shutdown(chip);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
        flush_work(&chip->spdif_input_bits_work);
        flush_work(&chip->gpio_work);
        chip->model.cleanup(chip);
-       kfree(chip->model_data);
        mutex_destroy(&chip->mutex);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
 }
 
 int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
@@ -594,8 +589,8 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
        const struct pci_device_id *pci_id;
        int err;
 
-       err = snd_card_new(&pci->dev, index, id, owner,
-                          sizeof(*chip), &card);
+       err = snd_devm_card_new(&pci->dev, index, id, owner,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
 
@@ -610,41 +605,38 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
        INIT_WORK(&chip->gpio_work, oxygen_gpio_changed);
        init_waitqueue_head(&chip->ac97_waitqueue);
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
-               goto err_card;
+               return err;
 
        err = pci_request_regions(pci, DRIVER);
        if (err < 0) {
                dev_err(card->dev, "cannot reserve PCI resources\n");
-               goto err_pci_enable;
+               return err;
        }
 
        if (!(pci_resource_flags(pci, 0) & IORESOURCE_IO) ||
            pci_resource_len(pci, 0) < OXYGEN_IO_SIZE) {
                dev_err(card->dev, "invalid PCI I/O range\n");
-               err = -ENXIO;
-               goto err_pci_regions;
+               return -ENXIO;
        }
        chip->addr = pci_resource_start(pci, 0);
 
        pci_id = oxygen_search_pci_id(chip, ids);
-       if (!pci_id) {
-               err = -ENODEV;
-               goto err_pci_regions;
-       }
+       if (!pci_id)
+               return -ENODEV;
+
        oxygen_restore_eeprom(chip, pci_id);
        err = get_model(chip, pci_id);
        if (err < 0)
-               goto err_pci_regions;
+               return err;
 
        if (chip->model.model_data_size) {
-               chip->model_data = kzalloc(chip->model.model_data_size,
-                                          GFP_KERNEL);
-               if (!chip->model_data) {
-                       err = -ENOMEM;
-                       goto err_pci_regions;
-               }
+               chip->model_data = devm_kzalloc(&pci->dev,
+                                               chip->model.model_data_size,
+                                               GFP_KERNEL);
+               if (!chip->model_data)
+                       return -ENOMEM;
        }
 
        pci_set_master(pci);
@@ -654,11 +646,11 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
        oxygen_init(chip);
        chip->model.init(chip);
 
-       err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED,
-                         KBUILD_MODNAME, chip);
+       err = devm_request_irq(&pci->dev, pci->irq, oxygen_interrupt,
+                              IRQF_SHARED, KBUILD_MODNAME, chip);
        if (err < 0) {
                dev_err(card->dev, "cannot grab interrupt %d\n", pci->irq);
-               goto err_card;
+               return err;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
@@ -672,11 +664,11 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
 
        err = oxygen_pcm_init(chip);
        if (err < 0)
-               goto err_card;
+               return err;
 
        err = oxygen_mixer_init(chip);
        if (err < 0)
-               goto err_card;
+               return err;
 
        if (chip->model.device_config & (MIDI_OUTPUT | MIDI_INPUT)) {
                unsigned int info_flags =
@@ -689,7 +681,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
                                          chip->addr + OXYGEN_MPU401,
                                          info_flags, -1, &chip->midi);
                if (err < 0)
-                       goto err_card;
+                       return err;
        }
 
        oxygen_proc_init(chip);
@@ -704,27 +696,13 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto err_card;
+               return err;
 
        pci_set_drvdata(pci, card);
        return 0;
-
-err_pci_regions:
-       pci_release_regions(pci);
-err_pci_enable:
-       pci_disable_device(pci);
-err_card:
-       snd_card_free(card);
-       return err;
 }
 EXPORT_SYMBOL(oxygen_pci_probe);
 
-void oxygen_pci_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-EXPORT_SYMBOL(oxygen_pci_remove);
-
 #ifdef CONFIG_PM_SLEEP
 static int oxygen_pci_suspend(struct device *dev)
 {
index 434f885..17650a5 100644 (file)
@@ -137,7 +137,6 @@ static struct pci_driver se6x_driver = {
        .name = KBUILD_MODNAME,
        .id_table = se6x_ids,
        .probe = se6x_probe,
-       .remove = oxygen_pci_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &oxygen_pci_pm,
index baa3244..2e40513 100644 (file)
@@ -82,7 +82,6 @@ static struct pci_driver xonar_driver = {
        .name = KBUILD_MODNAME,
        .id_table = xonar_ids,
        .probe = xonar_probe,
-       .remove = oxygen_pci_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &oxygen_pci_pm,
index 96b9371..242bd7e 100644 (file)
@@ -366,7 +366,7 @@ static int pcxhr_sub_set_clock(struct pcxhr_mgr *mgr,
                mgr->codec_speed = speed;       /* save new codec speed */
        }
 
-       dev_dbg(&mgr->pci->dev, "pcxhr_sub_set_clock to %dHz (realfreq=%d)\n",
+       dev_dbg(&mgr->pci->dev, "%s to %dHz (realfreq=%d)\n", __func__,
                    rate, realfreq);
        return 0;
 }
@@ -499,7 +499,7 @@ static int pcxhr_set_stream_state(struct snd_pcxhr *chip,
        else {
                if (stream->status != PCXHR_STREAM_STATUS_SCHEDULE_STOP) {
                        dev_err(chip->card->dev,
-                               "pcxhr_set_stream_state CANNOT be stopped\n");
+                               "%s CANNOT be stopped\n", __func__);
                        return -EINVAL;
                }
                start = 0;
@@ -524,7 +524,7 @@ static int pcxhr_set_stream_state(struct snd_pcxhr *chip,
        err = pcxhr_send_msg(chip->mgr, &rmh);
        if (err)
                dev_err(chip->card->dev,
-                       "ERROR pcxhr_set_stream_state err=%x;\n", err);
+                       "ERROR %s err=%x;\n", __func__, err);
        stream->status =
          start ? PCXHR_STREAM_STATUS_STARTED : PCXHR_STREAM_STATUS_STOPPED;
        return err;
@@ -570,7 +570,7 @@ static int pcxhr_set_format(struct pcxhr_stream *stream)
                break;
        default:
                dev_err(chip->card->dev,
-                       "error pcxhr_set_format() : unknown format\n");
+                       "error %s() : unknown format\n", __func__);
                return -EINVAL;
        }
 
@@ -615,7 +615,7 @@ static int pcxhr_set_format(struct pcxhr_stream *stream)
        err = pcxhr_send_msg(chip->mgr, &rmh);
        if (err)
                dev_err(chip->card->dev,
-                       "ERROR pcxhr_set_format err=%x;\n", err);
+                       "ERROR %s err=%x;\n", __func__, err);
        return err;
 }
 
@@ -630,7 +630,7 @@ static int pcxhr_update_r_buffer(struct pcxhr_stream *stream)
        stream_num = is_capture ? 0 : subs->number;
 
        dev_dbg(chip->card->dev,
-               "pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n",
+               "%s(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n", __func__,
                is_capture ? 'c' : 'p',
                chip->chip_idx, (void *)(long)subs->runtime->dma_addr,
                subs->runtime->dma_bytes, subs->number);
@@ -721,21 +721,20 @@ static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr)
        }
        if (capture_mask == 0 && playback_mask == 0) {
                mutex_unlock(&mgr->setup_mutex);
-               dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : no pipes\n");
+               dev_err(&mgr->pci->dev, "%s : no pipes\n", __func__);
                return;
        }
 
-       dev_dbg(&mgr->pci->dev, "pcxhr_start_linked_stream : "
-                   "playback_mask=%x capture_mask=%x\n",
-                   playback_mask, capture_mask);
+       dev_dbg(&mgr->pci->dev, "%s : playback_mask=%x capture_mask=%x\n",
+                   __func__, playback_mask, capture_mask);
 
        /* synchronous stop of all the pipes concerned */
        err = pcxhr_set_pipe_state(mgr,  playback_mask, capture_mask, 0);
        if (err) {
                mutex_unlock(&mgr->setup_mutex);
-               dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
+               dev_err(&mgr->pci->dev, "%s : "
                           "error stop pipes (P%x C%x)\n",
-                          playback_mask, capture_mask);
+                          __func__, playback_mask, capture_mask);
                return;
        }
 
@@ -778,9 +777,9 @@ static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr)
        err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
        if (err) {
                mutex_unlock(&mgr->setup_mutex);
-               dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
+               dev_err(&mgr->pci->dev, "%s : "
                           "error start pipes (P%x C%x)\n",
-                          playback_mask, capture_mask);
+                          __func__, playback_mask, capture_mask);
                return;
        }
 
@@ -889,7 +888,7 @@ static int pcxhr_hardware_timer(struct pcxhr_mgr *mgr, int start)
        }
        err = pcxhr_send_msg(mgr, &rmh);
        if (err < 0)
-               dev_err(&mgr->pci->dev, "error pcxhr_hardware_timer err(%x)\n",
+               dev_err(&mgr->pci->dev, "error %s err(%x)\n", __func__,
                           err);
        return err;
 }
@@ -904,7 +903,7 @@ static int pcxhr_prepare(struct snd_pcm_substream *subs)
        int err = 0;
 
        dev_dbg(chip->card->dev,
-               "pcxhr_prepare : period_size(%lx) periods(%x) buffer_size(%lx)\n",
+               "%s : period_size(%lx) periods(%x) buffer_size(%lx)\n", __func__,
                    subs->runtime->period_size, subs->runtime->periods,
                    subs->runtime->buffer_size);
 
@@ -997,12 +996,12 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
        runtime->hw = pcxhr_caps;
 
        if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK ) {
-               dev_dbg(chip->card->dev, "pcxhr_open playback chip%d subs%d\n",
-                           chip->chip_idx, subs->number);
+               dev_dbg(chip->card->dev, "%s playback chip%d subs%d\n",
+                           __func__, chip->chip_idx, subs->number);
                stream = &chip->playback_stream[subs->number];
        } else {
-               dev_dbg(chip->card->dev, "pcxhr_open capture chip%d subs%d\n",
-                           chip->chip_idx, subs->number);
+               dev_dbg(chip->card->dev, "%s capture chip%d subs%d\n",
+                           __func__, chip->chip_idx, subs->number);
                if (mgr->mono_capture)
                        runtime->hw.channels_max = 1;
                else
@@ -1011,8 +1010,8 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
        }
        if (stream->status != PCXHR_STREAM_STATUS_FREE){
                /* streams in use */
-               dev_err(chip->card->dev, "pcxhr_open chip%d subs%d in use\n",
-                          chip->chip_idx, subs->number);
+               dev_err(chip->card->dev, "%s chip%d subs%d in use\n",
+                          __func__, chip->chip_idx, subs->number);
                mutex_unlock(&mgr->setup_mutex);
                return -EBUSY;
        }
@@ -1077,7 +1076,7 @@ static int pcxhr_close(struct snd_pcm_substream *subs)
 
        mutex_lock(&mgr->setup_mutex);
 
-       dev_dbg(chip->card->dev, "pcxhr_close chip%d subs%d\n",
+       dev_dbg(chip->card->dev, "%s chip%d subs%d\n", __func__,
                    chip->chip_idx, subs->number);
 
        /* sample rate released */
@@ -1572,7 +1571,7 @@ static int pcxhr_probe(struct pci_dev *pci,
        /* init setup mutex*/
        mutex_init(&mgr->setup_mutex);
 
-       mgr->prmh = kmalloc(sizeof(*mgr->prmh) + 
+       mgr->prmh = kmalloc(sizeof(*mgr->prmh) +
                            sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS -
                                           PCXHR_SIZE_MAX_STATUS),
                            GFP_KERNEL);
index 709a1a2..5a987c6 100644 (file)
@@ -1798,13 +1798,11 @@ static int snd_riptide_initialize(struct snd_riptide *chip)
        return err;
 }
 
-static int snd_riptide_free(struct snd_riptide *chip)
+static void snd_riptide_free(struct snd_card *card)
 {
+       struct snd_riptide *chip = card->private_data;
        struct cmdif *cif;
 
-       if (!chip)
-               return 0;
-
        cif = chip->cif;
        if (cif) {
                SET_GRESET(cif->hwport);
@@ -1812,39 +1810,19 @@ static int snd_riptide_free(struct snd_riptide *chip)
                UNSET_GRESET(cif->hwport);
                kfree(chip->cif);
        }
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
        release_firmware(chip->fw_entry);
-       release_and_free_resource(chip->res_port);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_riptide_dev_free(struct snd_device *device)
-{
-       struct snd_riptide *chip = device->device_data;
-
-       return snd_riptide_free(chip);
 }
 
 static int
-snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
-                  struct snd_riptide **rchip)
+snd_riptide_create(struct snd_card *card, struct pci_dev *pci)
 {
-       struct snd_riptide *chip;
+       struct snd_riptide *chip = card->private_data;
        struct riptideport *hwport;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free = snd_riptide_dev_free,
-       };
 
-       *rchip = NULL;
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
-       chip = kzalloc(sizeof(struct snd_riptide), GFP_KERNEL);
-       if (!chip)
-               return -ENOMEM;
 
        spin_lock_init(&chip->lock);
        chip->card = card;
@@ -1855,24 +1833,20 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
        chip->received_irqs = 0;
        chip->handled_irqs = 0;
        chip->cif = NULL;
+       card->private_free = snd_riptide_free;
 
-       chip->res_port = request_region(chip->port, 64, "RIPTIDE");
-       if (!chip->res_port) {
-               snd_printk(KERN_ERR
-                          "Riptide: unable to grab region 0x%lx-0x%lx\n",
-                          chip->port, chip->port + 64 - 1);
-               snd_riptide_free(chip);
-               return -EBUSY;
-       }
+       err = pci_request_regions(pci, "RIPTIDE");
+       if (err < 0)
+               return err;
        hwport = (struct riptideport *)chip->port;
        UNSET_AIE(hwport);
 
-       if (request_threaded_irq(pci->irq, snd_riptide_interrupt,
-                                riptide_handleirq, IRQF_SHARED,
-                                KBUILD_MODNAME, chip)) {
+       if (devm_request_threaded_irq(&pci->dev, pci->irq,
+                                     snd_riptide_interrupt,
+                                     riptide_handleirq, IRQF_SHARED,
+                                     KBUILD_MODNAME, chip)) {
                snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n",
                           pci->irq);
-               snd_riptide_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
@@ -1880,18 +1854,9 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
        chip->device_id = pci->device;
        pci_set_master(pci);
        err = snd_riptide_initialize(chip);
-       if (err < 0) {
-               snd_riptide_free(chip);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_riptide_free(chip);
+       if (err < 0)
                return err;
-       }
 
-       *rchip = chip;
        return 0;
 }
 
@@ -2073,20 +2038,20 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
-       err = snd_riptide_create(card, pci, &chip);
+       chip = card->private_data;
+       err = snd_riptide_create(card, pci);
        if (err < 0)
-               goto error;
-       card->private_data = chip;
+               return err;
        err = snd_riptide_pcm(chip, 0);
        if (err < 0)
-               goto error;
+               return err;
        err = snd_riptide_mixer(chip);
        if (err < 0)
-               goto error;
+               return err;
 
        val = LEGACY_ENABLE_ALL;
        if (opl3_port[dev])
@@ -2153,26 +2118,16 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        snd_riptide_proc_init(chip);
        err = snd_card_register(card);
        if (err < 0)
-               goto error;
+               return err;
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
- error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_card_riptide_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_riptide_ids,
        .probe = snd_card_riptide_probe,
-       .remove = snd_card_riptide_remove,
        .driver = {
                .pm = RIPTIDE_PM_OPS,
        },
index b5b3578..5b6bd9f 100644 (file)
@@ -1278,27 +1278,10 @@ static const struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = {
        .ack =          snd_rme32_capture_fd_ack,
 };
 
-static void snd_rme32_free(void *private_data)
+static void snd_rme32_free(struct rme32 *rme32)
 {
-       struct rme32 *rme32 = (struct rme32 *) private_data;
-
-       if (rme32 == NULL) {
-               return;
-       }
-       if (rme32->irq >= 0) {
+       if (rme32->irq >= 0)
                snd_rme32_pcm_stop(rme32, 0);
-               free_irq(rme32->irq, (void *) rme32);
-               rme32->irq = -1;
-       }
-       if (rme32->iobase) {
-               iounmap(rme32->iobase);
-               rme32->iobase = NULL;
-       }
-       if (rme32->port) {
-               pci_release_regions(rme32->pci);
-               rme32->port = 0;
-       }
-       pci_disable_device(rme32->pci);
 }
 
 static void snd_rme32_free_spdif_pcm(struct snd_pcm *pcm)
@@ -1322,7 +1305,7 @@ static int snd_rme32_create(struct rme32 *rme32)
        rme32->irq = -1;
        spin_lock_init(&rme32->lock);
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
@@ -1331,16 +1314,16 @@ static int snd_rme32_create(struct rme32 *rme32)
                return err;
        rme32->port = pci_resource_start(rme32->pci, 0);
 
-       rme32->iobase = ioremap(rme32->port, RME32_IO_SIZE);
+       rme32->iobase = devm_ioremap(&pci->dev, rme32->port, RME32_IO_SIZE);
        if (!rme32->iobase) {
                dev_err(rme32->card->dev,
                        "unable to remap memory region 0x%lx-0x%lx\n",
-                          rme32->port, rme32->port + RME32_IO_SIZE - 1);
+                       rme32->port, rme32->port + RME32_IO_SIZE - 1);
                return -ENOMEM;
        }
 
-       if (request_irq(pci->irq, snd_rme32_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, rme32)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_rme32_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, rme32)) {
                dev_err(rme32->card->dev, "unable to grab IRQ %d\n", pci->irq);
                return -EBUSY;
        }
@@ -1907,8 +1890,8 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct rme32), &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*rme32), &card);
        if (err < 0)
                return err;
        card->private_free = snd_rme32_card_free;
@@ -1918,10 +1901,8 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
         if (fullduplex[dev])
                rme32->fullduplex_mode = 1;
        err = snd_rme32_create(rme32);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        strcpy(card->driver, "Digi32");
        switch (rme32->pci->device) {
@@ -1939,25 +1920,17 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                card->shortname, rme32->rev, rme32->port, rme32->irq);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_rme32_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver rme32_driver = {
        .name =         KBUILD_MODNAME,
        .id_table =     snd_rme32_ids,
        .probe =        snd_rme32_probe,
-       .remove =       snd_rme32_remove,
 };
 
 module_pci_driver(rme32_driver);
index fc7ac07..8fc8115 100644 (file)
@@ -1562,33 +1562,17 @@ static const struct snd_pcm_ops snd_rme96_capture_adat_ops = {
 };
 
 static void
-snd_rme96_free(void *private_data)
+snd_rme96_free(struct rme96 *rme96)
 {
-       struct rme96 *rme96 = (struct rme96 *)private_data;
-
-       if (!rme96)
-               return;
-
        if (rme96->irq >= 0) {
                snd_rme96_trigger(rme96, RME96_STOP_BOTH);
                rme96->areg &= ~RME96_AR_DAC_EN;
                writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);
-               free_irq(rme96->irq, (void *)rme96);
-               rme96->irq = -1;
-       }
-       if (rme96->iobase) {
-               iounmap(rme96->iobase);
-               rme96->iobase = NULL;
-       }
-       if (rme96->port) {
-               pci_release_regions(rme96->pci);
-               rme96->port = 0;
        }
 #ifdef CONFIG_PM_SLEEP
        vfree(rme96->playback_suspend_buffer);
        vfree(rme96->capture_suspend_buffer);
 #endif
-       pci_disable_device(rme96->pci);
 }
 
 static void
@@ -1614,7 +1598,7 @@ snd_rme96_create(struct rme96 *rme96)
        rme96->irq = -1;
        spin_lock_init(&rme96->lock);
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
@@ -1623,16 +1607,16 @@ snd_rme96_create(struct rme96 *rme96)
                return err;
        rme96->port = pci_resource_start(rme96->pci, 0);
 
-       rme96->iobase = ioremap(rme96->port, RME96_IO_SIZE);
+       rme96->iobase = devm_ioremap(&pci->dev, rme96->port, RME96_IO_SIZE);
        if (!rme96->iobase) {
                dev_err(rme96->card->dev,
                        "unable to remap memory region 0x%lx-0x%lx\n",
                        rme96->port, rme96->port + RME96_IO_SIZE - 1);
-               return -ENOMEM;
+               return -EBUSY;
        }
 
-       if (request_irq(pci->irq, snd_rme96_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, rme96)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_rme96_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, rme96)) {
                dev_err(rme96->card->dev, "unable to grab IRQ %d\n", pci->irq);
                return -EBUSY;
        }
@@ -2462,8 +2446,8 @@ snd_rme96_probe(struct pci_dev *pci,
                dev++;
                return -ENOENT;
        }
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct rme96), &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*rme96), &card);
        if (err < 0)
                return err;
        card->private_free = snd_rme96_card_free;
@@ -2472,19 +2456,15 @@ snd_rme96_probe(struct pci_dev *pci,
        rme96->pci = pci;
        err = snd_rme96_create(rme96);
        if (err)
-               goto free_card;
+               return err;
        
 #ifdef CONFIG_PM_SLEEP
        rme96->playback_suspend_buffer = vmalloc(RME96_BUFFER_SIZE);
-       if (!rme96->playback_suspend_buffer) {
-               err = -ENOMEM;
-               goto free_card;
-       }
+       if (!rme96->playback_suspend_buffer)
+               return -ENOMEM;
        rme96->capture_suspend_buffer = vmalloc(RME96_BUFFER_SIZE);
-       if (!rme96->capture_suspend_buffer) {
-               err = -ENOMEM;
-               goto free_card;
-       }
+       if (!rme96->capture_suspend_buffer)
+               return -ENOMEM;
 #endif
 
        strcpy(card->driver, "Digi96");
@@ -2511,26 +2491,17 @@ snd_rme96_probe(struct pci_dev *pci,
                rme96->port, rme96->irq);
        err = snd_card_register(card);
        if (err)
-               goto free_card;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-free_card:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_rme96_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver rme96_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_rme96_ids,
        .probe = snd_rme96_probe,
-       .remove = snd_rme96_remove,
        .driver = {
                .pm = RME96_PM_OPS,
        },
index 8457a4b..75aa2ea 100644 (file)
@@ -468,8 +468,8 @@ struct hdsp {
        unsigned char         ss_out_channels;
        u32                   io_loopback;          /* output loopback channel states*/
 
-       struct snd_dma_buffer capture_dma_buf;
-       struct snd_dma_buffer playback_dma_buf;
+       struct snd_dma_buffer *capture_dma_buf;
+       struct snd_dma_buffer *playback_dma_buf;
        unsigned char        *capture_buffer;       /* suitably aligned address */
        unsigned char        *playback_buffer;      /* suitably aligned address */
 
@@ -565,18 +565,12 @@ static const char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = {
        -1, -1
 };
 
-static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
+static struct snd_dma_buffer *
+snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size)
 {
-       return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, size, dmab);
+       return snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, size);
 }
 
-static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
-{
-       if (dmab->area)
-               snd_dma_free_pages(dmab);
-}
-
-
 static const struct pci_device_id snd_hdsp_ids[] = {
        {
                .vendor = PCI_VENDOR_ID_XILINX,
@@ -3768,20 +3762,15 @@ static void snd_hdsp_proc_init(struct hdsp *hdsp)
        snd_card_ro_proc_new(hdsp->card, "hdsp", hdsp, snd_hdsp_proc_read);
 }
 
-static void snd_hdsp_free_buffers(struct hdsp *hdsp)
-{
-       snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
-       snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
-}
-
 static int snd_hdsp_initialize_memory(struct hdsp *hdsp)
 {
        unsigned long pb_bus, cb_bus;
 
-       if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 ||
-           snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) {
-               if (hdsp->capture_dma_buf.area)
-                       snd_dma_free_pages(&hdsp->capture_dma_buf);
+       hdsp->capture_dma_buf =
+               snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES);
+       hdsp->playback_dma_buf =
+               snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES);
+       if (!hdsp->capture_dma_buf || !hdsp->playback_dma_buf) {
                dev_err(hdsp->card->dev,
                        "%s: no buffers available\n", hdsp->card_name);
                return -ENOMEM;
@@ -3789,16 +3778,16 @@ static int snd_hdsp_initialize_memory(struct hdsp *hdsp)
 
        /* Align to bus-space 64K boundary */
 
-       cb_bus = ALIGN(hdsp->capture_dma_buf.addr, 0x10000ul);
-       pb_bus = ALIGN(hdsp->playback_dma_buf.addr, 0x10000ul);
+       cb_bus = ALIGN(hdsp->capture_dma_buf->addr, 0x10000ul);
+       pb_bus = ALIGN(hdsp->playback_dma_buf->addr, 0x10000ul);
 
        /* Tell the card where it is */
 
        hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus);
        hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus);
 
-       hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr);
-       hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr);
+       hdsp->capture_buffer = hdsp->capture_dma_buf->area + (cb_bus - hdsp->capture_dma_buf->addr);
+       hdsp->playback_buffer = hdsp->playback_dma_buf->area + (pb_bus - hdsp->playback_dma_buf->addr);
 
        return 0;
 }
@@ -4518,8 +4507,7 @@ static int snd_hdsp_playback_open(struct snd_pcm_substream *substream)
        snd_pcm_set_sync(substream);
 
         runtime->hw = snd_hdsp_playback_subinfo;
-       runtime->dma_area = hdsp->playback_buffer;
-       runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
+       snd_pcm_set_runtime_buffer(substream, hdsp->playback_dma_buf);
 
        hdsp->playback_pid = current->pid;
        hdsp->playback_substream = substream;
@@ -4595,8 +4583,7 @@ static int snd_hdsp_capture_open(struct snd_pcm_substream *substream)
        snd_pcm_set_sync(substream);
 
        runtime->hw = snd_hdsp_capture_subinfo;
-       runtime->dma_area = hdsp->capture_buffer;
-       runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
+       snd_pcm_set_runtime_buffer(substream, hdsp->capture_dma_buf);
 
        hdsp->capture_pid = current->pid;
        hdsp->capture_substream = substream;
@@ -5313,7 +5300,7 @@ static int snd_hdsp_create(struct snd_card *card,
                is_9632 = 1;
        }
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
@@ -5323,15 +5310,15 @@ static int snd_hdsp_create(struct snd_card *card,
        if (err < 0)
                return err;
        hdsp->port = pci_resource_start(pci, 0);
-       hdsp->iobase = ioremap(hdsp->port, HDSP_IO_EXTENT);
+       hdsp->iobase = devm_ioremap(&pci->dev, hdsp->port, HDSP_IO_EXTENT);
        if (!hdsp->iobase) {
                dev_err(hdsp->card->dev, "unable to remap region 0x%lx-0x%lx\n",
                        hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
                return -EBUSY;
        }
 
-       if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, hdsp)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_hdsp_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, hdsp)) {
                dev_err(hdsp->card->dev, "unable to use IRQ %d\n", pci->irq);
                return -EBUSY;
        }
@@ -5411,8 +5398,10 @@ static int snd_hdsp_create(struct snd_card *card,
        return 0;
 }
 
-static int snd_hdsp_free(struct hdsp *hdsp)
+static void snd_hdsp_card_free(struct snd_card *card)
 {
+       struct hdsp *hdsp = card->private_data;
+
        if (hdsp->port) {
                /* stop the audio, and cancel all interrupts */
                cancel_work_sync(&hdsp->midi_work);
@@ -5420,29 +5409,8 @@ static int snd_hdsp_free(struct hdsp *hdsp)
                hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
        }
 
-       if (hdsp->irq >= 0)
-               free_irq(hdsp->irq, (void *)hdsp);
-
-       snd_hdsp_free_buffers(hdsp);
-
        release_firmware(hdsp->firmware);
        vfree(hdsp->fw_uploaded);
-       iounmap(hdsp->iobase);
-
-       if (hdsp->port)
-               pci_release_regions(hdsp->pci);
-
-       if (pci_is_enabled(hdsp->pci))
-               pci_disable_device(hdsp->pci);
-       return 0;
-}
-
-static void snd_hdsp_card_free(struct snd_card *card)
-{
-       struct hdsp *hdsp = card->private_data;
-
-       if (hdsp)
-               snd_hdsp_free(hdsp);
 }
 
 static int snd_hdsp_probe(struct pci_dev *pci,
@@ -5460,8 +5428,8 @@ static int snd_hdsp_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct hdsp), &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct hdsp), &card);
        if (err < 0)
                return err;
 
@@ -5471,32 +5439,23 @@ static int snd_hdsp_probe(struct pci_dev *pci,
        hdsp->pci = pci;
        err = snd_hdsp_create(card, hdsp);
        if (err)
-               goto free_card;
+               return err;
 
        strcpy(card->shortname, "Hammerfall DSP");
        sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
                hdsp->port, hdsp->irq);
        err = snd_card_register(card);
-       if (err) {
-free_card:
-               snd_card_free(card);
+       if (err)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_hdsp_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver hdsp_driver = {
        .name =     KBUILD_MODNAME,
        .id_table = snd_hdsp_ids,
        .probe =    snd_hdsp_probe,
-       .remove = snd_hdsp_remove,
 };
 
 module_pci_driver(hdsp_driver);
index 97a0bff..ff06ee8 100644 (file)
@@ -6575,34 +6575,25 @@ static int snd_hdspm_create(struct snd_card *card,
                }
        }
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
        pci_set_master(hdspm->pci);
 
-       err = pci_request_regions(pci, "hdspm");
+       err = pcim_iomap_regions(pci, 1 << 0, "hdspm");
        if (err < 0)
                return err;
 
        hdspm->port = pci_resource_start(pci, 0);
        io_extent = pci_resource_len(pci, 0);
-
-       dev_dbg(card->dev, "grabbed memory region 0x%lx-0x%lx\n",
-                       hdspm->port, hdspm->port + io_extent - 1);
-
-       hdspm->iobase = ioremap(hdspm->port, io_extent);
-       if (!hdspm->iobase) {
-               dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n",
-                               hdspm->port, hdspm->port + io_extent - 1);
-               return -EBUSY;
-       }
+       hdspm->iobase = pcim_iomap_table(pci)[0];
        dev_dbg(card->dev, "remapped region (0x%lx) 0x%lx-0x%lx\n",
                        (unsigned long)hdspm->iobase, hdspm->port,
                        hdspm->port + io_extent - 1);
 
-       if (request_irq(pci->irq, snd_hdspm_interrupt,
-                       IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_hdspm_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
                dev_err(card->dev, "unable to use IRQ %d\n", pci->irq);
                return -EBUSY;
        }
@@ -6614,7 +6605,7 @@ static int snd_hdspm_create(struct snd_card *card,
 
        dev_dbg(card->dev, "kmalloc Mixer memory of %zd Bytes\n",
                sizeof(*hdspm->mixer));
-       hdspm->mixer = kzalloc(sizeof(*hdspm->mixer), GFP_KERNEL);
+       hdspm->mixer = devm_kzalloc(&pci->dev, sizeof(*hdspm->mixer), GFP_KERNEL);
        if (!hdspm->mixer)
                return -ENOMEM;
 
@@ -6859,8 +6850,9 @@ static int snd_hdspm_create(struct snd_card *card,
 }
 
 
-static int snd_hdspm_free(struct hdspm * hdspm)
+static void snd_hdspm_card_free(struct snd_card *card)
 {
+       struct hdspm *hdspm = card->private_data;
 
        if (hdspm->port) {
                cancel_work_sync(&hdspm->midi_work);
@@ -6873,28 +6865,6 @@ static int snd_hdspm_free(struct hdspm * hdspm)
                hdspm_write(hdspm, HDSPM_controlRegister,
                            hdspm->control_register);
        }
-
-       if (hdspm->irq >= 0)
-               free_irq(hdspm->irq, (void *) hdspm);
-
-       kfree(hdspm->mixer);
-       iounmap(hdspm->iobase);
-
-       if (hdspm->port)
-               pci_release_regions(hdspm->pci);
-
-       if (pci_is_enabled(hdspm->pci))
-               pci_disable_device(hdspm->pci);
-       return 0;
-}
-
-
-static void snd_hdspm_card_free(struct snd_card *card)
-{
-       struct hdspm *hdspm = card->private_data;
-
-       if (hdspm)
-               snd_hdspm_free(hdspm);
 }
 
 
@@ -6913,8 +6883,8 @@ static int snd_hdspm_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev],
-                          THIS_MODULE, sizeof(*hdspm), &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev],
+                               THIS_MODULE, sizeof(*hdspm), &card);
        if (err < 0)
                return err;
 
@@ -6925,7 +6895,7 @@ static int snd_hdspm_probe(struct pci_dev *pci,
 
        err = snd_hdspm_create(card, hdspm);
        if (err < 0)
-               goto free_card;
+               return err;
 
        if (hdspm->io_type != MADIface) {
                snprintf(card->shortname, sizeof(card->shortname), "%s_%x",
@@ -6944,28 +6914,18 @@ static int snd_hdspm_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto free_card;
+               return err;
 
        pci_set_drvdata(pci, card);
 
        dev++;
        return 0;
-
-free_card:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_hdspm_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver hdspm_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_hdspm_ids,
        .probe = snd_hdspm_probe,
-       .remove = snd_hdspm_remove,
 };
 
 module_pci_driver(hdspm_driver);
index f1aad38..e76f737 100644 (file)
@@ -208,8 +208,8 @@ struct snd_rme9652 {
        unsigned char ds_channels;
        unsigned char ss_channels;      /* different for hammerfall/hammerfall-light */
 
-       struct snd_dma_buffer playback_dma_buf;
-       struct snd_dma_buffer capture_dma_buf;
+       struct snd_dma_buffer *playback_dma_buf;
+       struct snd_dma_buffer *capture_dma_buf;
 
        unsigned char *capture_buffer;  /* suitably aligned address */
        unsigned char *playback_buffer; /* suitably aligned address */
@@ -275,18 +275,12 @@ static const char channel_map_9636_ds[26] = {
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 };
 
-static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
+static struct snd_dma_buffer *
+snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size)
 {
-       return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, size, dmab);
+       return snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, size);
 }
 
-static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
-{
-       if (dmab->area)
-               snd_dma_free_pages(dmab);
-}
-
-
 static const struct pci_device_id snd_rme9652_ids[] = {
        {
                .vendor    = 0x10ee,
@@ -1715,37 +1709,23 @@ static void snd_rme9652_proc_init(struct snd_rme9652 *rme9652)
                             snd_rme9652_proc_read);
 }
 
-static void snd_rme9652_free_buffers(struct snd_rme9652 *rme9652)
+static void snd_rme9652_card_free(struct snd_card *card)
 {
-       snd_hammerfall_free_buffer(&rme9652->capture_dma_buf, rme9652->pci);
-       snd_hammerfall_free_buffer(&rme9652->playback_dma_buf, rme9652->pci);
-}
+       struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) card->private_data;
 
-static int snd_rme9652_free(struct snd_rme9652 *rme9652)
-{
        if (rme9652->irq >= 0)
                rme9652_stop(rme9652);
-       snd_rme9652_free_buffers(rme9652);
-
-       if (rme9652->irq >= 0)
-               free_irq(rme9652->irq, (void *)rme9652);
-       iounmap(rme9652->iobase);
-       if (rme9652->port)
-               pci_release_regions(rme9652->pci);
-
-       if (pci_is_enabled(rme9652->pci))
-               pci_disable_device(rme9652->pci);
-       return 0;
 }
 
 static int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
 {
        unsigned long pb_bus, cb_bus;
 
-       if (snd_hammerfall_get_buffer(rme9652->pci, &rme9652->capture_dma_buf, RME9652_DMA_AREA_BYTES) < 0 ||
-           snd_hammerfall_get_buffer(rme9652->pci, &rme9652->playback_dma_buf, RME9652_DMA_AREA_BYTES) < 0) {
-               if (rme9652->capture_dma_buf.area)
-                       snd_dma_free_pages(&rme9652->capture_dma_buf);
+       rme9652->capture_dma_buf =
+               snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES);
+       rme9652->playback_dma_buf =
+               snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES);
+       if (!rme9652->capture_dma_buf || !rme9652->playback_dma_buf) {
                dev_err(rme9652->card->dev,
                        "%s: no buffers available\n", rme9652->card_name);
                return -ENOMEM;
@@ -1753,16 +1733,16 @@ static int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
 
        /* Align to bus-space 64K boundary */
 
-       cb_bus = ALIGN(rme9652->capture_dma_buf.addr, 0x10000ul);
-       pb_bus = ALIGN(rme9652->playback_dma_buf.addr, 0x10000ul);
+       cb_bus = ALIGN(rme9652->capture_dma_buf->addr, 0x10000ul);
+       pb_bus = ALIGN(rme9652->playback_dma_buf->addr, 0x10000ul);
 
        /* Tell the card where it is */
 
        rme9652_write(rme9652, RME9652_rec_buffer, cb_bus);
        rme9652_write(rme9652, RME9652_play_buffer, pb_bus);
 
-       rme9652->capture_buffer = rme9652->capture_dma_buf.area + (cb_bus - rme9652->capture_dma_buf.addr);
-       rme9652->playback_buffer = rme9652->playback_dma_buf.area + (pb_bus - rme9652->playback_dma_buf.addr);
+       rme9652->capture_buffer = rme9652->capture_dma_buf->area + (cb_bus - rme9652->capture_dma_buf->addr);
+       rme9652->playback_buffer = rme9652->playback_dma_buf->area + (pb_bus - rme9652->playback_dma_buf->addr);
 
        return 0;
 }
@@ -2279,8 +2259,7 @@ static int snd_rme9652_playback_open(struct snd_pcm_substream *substream)
        snd_pcm_set_sync(substream);
 
         runtime->hw = snd_rme9652_playback_subinfo;
-       runtime->dma_area = rme9652->playback_buffer;
-       runtime->dma_bytes = RME9652_DMA_AREA_BYTES;
+       snd_pcm_set_runtime_buffer(substream, rme9652->playback_dma_buf);
 
        if (rme9652->capture_substream == NULL) {
                rme9652_stop(rme9652);
@@ -2339,8 +2318,7 @@ static int snd_rme9652_capture_open(struct snd_pcm_substream *substream)
        snd_pcm_set_sync(substream);
 
        runtime->hw = snd_rme9652_capture_subinfo;
-       runtime->dma_area = rme9652->capture_buffer;
-       runtime->dma_bytes = RME9652_DMA_AREA_BYTES;
+       snd_pcm_set_runtime_buffer(substream, rme9652->capture_dma_buf);
 
        if (rme9652->playback_substream == NULL) {
                rme9652_stop(rme9652);
@@ -2452,7 +2430,7 @@ static int snd_rme9652_create(struct snd_card *card,
                return -ENODEV;
        }
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
@@ -2462,15 +2440,15 @@ static int snd_rme9652_create(struct snd_card *card,
        if (err < 0)
                return err;
        rme9652->port = pci_resource_start(pci, 0);
-       rme9652->iobase = ioremap(rme9652->port, RME9652_IO_EXTENT);
+       rme9652->iobase = devm_ioremap(&pci->dev, rme9652->port, RME9652_IO_EXTENT);
        if (rme9652->iobase == NULL) {
                dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n",
                        rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1);
                return -EBUSY;
        }
        
-       if (request_irq(pci->irq, snd_rme9652_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, rme9652)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_rme9652_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, rme9652)) {
                dev_err(card->dev, "unable to request IRQ %d\n", pci->irq);
                return -EBUSY;
        }
@@ -2562,14 +2540,6 @@ static int snd_rme9652_create(struct snd_card *card,
        return 0;
 }
 
-static void snd_rme9652_card_free(struct snd_card *card)
-{
-       struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) card->private_data;
-
-       if (rme9652)
-               snd_rme9652_free(rme9652);
-}
-
 static int snd_rme9652_probe(struct pci_dev *pci,
                             const struct pci_device_id *pci_id)
 {
@@ -2585,8 +2555,8 @@ static int snd_rme9652_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          sizeof(struct snd_rme9652), &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(struct snd_rme9652), &card);
 
        if (err < 0)
                return err;
@@ -2597,33 +2567,24 @@ static int snd_rme9652_probe(struct pci_dev *pci,
        rme9652->pci = pci;
        err = snd_rme9652_create(card, rme9652, precise_ptr[dev]);
        if (err)
-               goto free_card;
+               return err;
 
        strcpy(card->shortname, rme9652->card_name);
 
        sprintf(card->longname, "%s at 0x%lx, irq %d",
                card->shortname, rme9652->port, rme9652->irq);
        err = snd_card_register(card);
-       if (err) {
-free_card:
-               snd_card_free(card);
+       if (err)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_rme9652_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver rme9652_driver = {
        .name     = KBUILD_MODNAME,
        .id_table = snd_rme9652_ids,
        .probe    = snd_rme9652_probe,
-       .remove   = snd_rme9652_remove,
 };
 
 module_pci_driver(rme9652_driver);
index 00ab51c..0b722b0 100644 (file)
@@ -1007,16 +1007,10 @@ static int sis_mixer_create(struct sis7019 *sis)
        return rc;
 }
 
-static void sis_free_suspend(struct sis7019 *sis)
+static void sis_chip_free(struct snd_card *card)
 {
-       int i;
-
-       for (i = 0; i < SIS_SUSPEND_PAGES; i++)
-               kfree(sis->suspend_state[i]);
-}
+       struct sis7019 *sis = card->private_data;
 
-static int sis_chip_free(struct sis7019 *sis)
-{
        /* Reset the chip, and disable all interrputs.
         */
        outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR);
@@ -1028,18 +1022,6 @@ static int sis_chip_free(struct sis7019 *sis)
         */
        if (sis->irq >= 0)
                free_irq(sis->irq, sis);
-
-       iounmap(sis->ioaddr);
-       pci_release_regions(sis->pci);
-       pci_disable_device(sis->pci);
-       sis_free_suspend(sis);
-       return 0;
-}
-
-static int sis_dev_free(struct snd_device *dev)
-{
-       struct sis7019 *sis = dev->device_data;
-       return sis_chip_free(sis);
 }
 
 static int sis_chip_init(struct sis7019 *sis)
@@ -1265,7 +1247,8 @@ static int sis_alloc_suspend(struct sis7019 *sis)
         * buffer.
         */
        for (i = 0; i < SIS_SUSPEND_PAGES; i++) {
-               sis->suspend_state[i] = kmalloc(4096, GFP_KERNEL);
+               sis->suspend_state[i] = devm_kmalloc(&sis->pci->dev, 4096,
+                                                    GFP_KERNEL);
                if (!sis->suspend_state[i])
                        return -ENOMEM;
        }
@@ -1279,23 +1262,19 @@ static int sis_chip_create(struct snd_card *card,
 {
        struct sis7019 *sis = card->private_data;
        struct voice *voice;
-       static const struct snd_device_ops ops = {
-               .dev_free = sis_dev_free,
-       };
        int rc;
        int i;
 
-       rc = pci_enable_device(pci);
+       rc = pcim_enable_device(pci);
        if (rc)
-               goto error_out;
+               return rc;
 
        rc = dma_set_mask(&pci->dev, DMA_BIT_MASK(30));
        if (rc < 0) {
                dev_err(&pci->dev, "architecture does not support 30-bit PCI busmaster DMA");
-               goto error_out_enabled;
+               return -ENXIO;
        }
 
-       memset(sis, 0, sizeof(*sis));
        mutex_init(&sis->ac97_mutex);
        spin_lock_init(&sis->voice_lock);
        sis->card = card;
@@ -1306,31 +1285,31 @@ static int sis_chip_create(struct snd_card *card,
        rc = pci_request_regions(pci, "SiS7019");
        if (rc) {
                dev_err(&pci->dev, "unable request regions\n");
-               goto error_out_enabled;
+               return rc;
        }
 
-       rc = -EIO;
-       sis->ioaddr = ioremap(pci_resource_start(pci, 1), 0x4000);
+       sis->ioaddr = devm_ioremap(&pci->dev, pci_resource_start(pci, 1), 0x4000);
        if (!sis->ioaddr) {
                dev_err(&pci->dev, "unable to remap MMIO, aborting\n");
-               goto error_out_cleanup;
+               return -EIO;
        }
 
        rc = sis_alloc_suspend(sis);
        if (rc < 0) {
                dev_err(&pci->dev, "unable to allocate state storage\n");
-               goto error_out_cleanup;
+               return rc;
        }
 
        rc = sis_chip_init(sis);
        if (rc)
-               goto error_out_cleanup;
+               return rc;
+       card->private_free = sis_chip_free;
 
        rc = request_irq(pci->irq, sis_interrupt, IRQF_SHARED, KBUILD_MODNAME,
                         sis);
        if (rc) {
                dev_err(&pci->dev, "unable to allocate irq %d\n", sis->irq);
-               goto error_out_cleanup;
+               return rc;
        }
 
        sis->irq = pci->irq;
@@ -1349,20 +1328,7 @@ static int sis_chip_create(struct snd_card *card,
        voice->num = SIS_CAPTURE_CHAN_AC97_PCM_IN;
        voice->ctrl_base = SIS_CAPTURE_DMA_ADDR(sis->ioaddr, voice->num);
 
-       rc = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sis, &ops);
-       if (rc)
-               goto error_out_cleanup;
-
        return 0;
-
-error_out_cleanup:
-       sis_chip_free(sis);
-
-error_out_enabled:
-       pci_disable_device(pci);
-
-error_out:
-       return rc;
 }
 
 static int snd_sis7019_probe(struct pci_dev *pci,
@@ -1372,9 +1338,8 @@ static int snd_sis7019_probe(struct pci_dev *pci,
        struct sis7019 *sis;
        int rc;
 
-       rc = -ENOENT;
        if (!enable)
-               goto error_out;
+               return -ENOENT;
 
        /* The user can specify which codecs should be present so that we
         * can wait for them to show up if they are slow to recover from
@@ -1390,23 +1355,23 @@ static int snd_sis7019_probe(struct pci_dev *pci,
        rc = snd_card_new(&pci->dev, index, id, THIS_MODULE,
                          sizeof(*sis), &card);
        if (rc < 0)
-               goto error_out;
+               return rc;
 
        strcpy(card->driver, "SiS7019");
        strcpy(card->shortname, "SiS7019");
        rc = sis_chip_create(card, pci);
        if (rc)
-               goto card_error_out;
+               return rc;
 
        sis = card->private_data;
 
        rc = sis_mixer_create(sis);
        if (rc)
-               goto card_error_out;
+               return rc;
 
        rc = sis_pcm_create(sis);
        if (rc)
-               goto card_error_out;
+               return rc;
 
        snprintf(card->longname, sizeof(card->longname),
                        "%s Audio Accelerator with %s at 0x%lx, irq %d",
@@ -1415,28 +1380,16 @@ static int snd_sis7019_probe(struct pci_dev *pci,
 
        rc = snd_card_register(card);
        if (rc)
-               goto card_error_out;
+               return rc;
 
        pci_set_drvdata(pci, card);
        return 0;
-
-card_error_out:
-       snd_card_free(card);
-
-error_out:
-       return rc;
-}
-
-static void snd_sis7019_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver sis7019_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_sis7019_ids,
        .probe = snd_sis7019_probe,
-       .remove = snd_sis7019_remove,
        .driver = {
                .pm = SIS_PM_OPS,
        },
index 03a48da..c8c4988 100644 (file)
@@ -1193,69 +1193,43 @@ static inline int snd_sonicvibes_create_gameport(struct sonicvibes *sonic) { ret
 static inline void snd_sonicvibes_free_gameport(struct sonicvibes *sonic) { }
 #endif
 
-static int snd_sonicvibes_free(struct sonicvibes *sonic)
+static void snd_sonicvibes_free(struct snd_card *card)
 {
+       struct sonicvibes *sonic = card->private_data;
+
        snd_sonicvibes_free_gameport(sonic);
        pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port);
        pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port);
-       if (sonic->irq >= 0)
-               free_irq(sonic->irq, sonic);
-       release_and_free_resource(sonic->res_dmaa);
-       release_and_free_resource(sonic->res_dmac);
-       pci_release_regions(sonic->pci);
-       pci_disable_device(sonic->pci);
-       kfree(sonic);
-       return 0;
-}
-
-static int snd_sonicvibes_dev_free(struct snd_device *device)
-{
-       struct sonicvibes *sonic = device->device_data;
-       return snd_sonicvibes_free(sonic);
 }
 
 static int snd_sonicvibes_create(struct snd_card *card,
                                 struct pci_dev *pci,
                                 int reverb,
-                                int mge,
-                                struct sonicvibes **rsonic)
+                                int mge)
 {
-       struct sonicvibes *sonic;
+       struct sonicvibes *sonic = card->private_data;
        unsigned int dmaa, dmac;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_sonicvibes_dev_free,
-       };
 
-       *rsonic = NULL;
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 24 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
                dev_err(card->dev,
                        "architecture does not support 24bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                 return -ENXIO;
         }
 
-       sonic = kzalloc(sizeof(*sonic), GFP_KERNEL);
-       if (sonic == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        spin_lock_init(&sonic->reg_lock);
        sonic->card = card;
        sonic->pci = pci;
        sonic->irq = -1;
 
        err = pci_request_regions(pci, "S3 SonicVibes");
-       if (err < 0) {
-               kfree(sonic);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
 
        sonic->sb_port = pci_resource_start(pci, 0);
        sonic->enh_port = pci_resource_start(pci, 1);
@@ -1263,14 +1237,14 @@ static int snd_sonicvibes_create(struct snd_card *card,
        sonic->midi_port = pci_resource_start(pci, 3);
        sonic->game_port = pci_resource_start(pci, 4);
 
-       if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, sonic)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_sonicvibes_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, sonic)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_sonicvibes_free(sonic);
                return -EBUSY;
        }
        sonic->irq = pci->irq;
        card->sync_irq = sonic->irq;
+       card->private_free = snd_sonicvibes_free;
 
        pci_read_config_dword(pci, 0x40, &dmaa);
        pci_read_config_dword(pci, 0x48, &dmac);
@@ -1294,17 +1268,17 @@ static int snd_sonicvibes_create(struct snd_card *card,
        pci_write_config_dword(pci, 0x40, dmaa);
        pci_write_config_dword(pci, 0x48, dmac);
 
-       sonic->res_dmaa = request_region(dmaa, 0x10, "S3 SonicVibes DDMA-A");
+       sonic->res_dmaa = devm_request_region(&pci->dev, dmaa, 0x10,
+                                             "S3 SonicVibes DDMA-A");
        if (!sonic->res_dmaa) {
-               snd_sonicvibes_free(sonic);
                dev_err(card->dev,
                        "unable to grab DDMA-A port at 0x%x-0x%x\n",
                        dmaa, dmaa + 0x10 - 1);
                return -EBUSY;
        }
-       sonic->res_dmac = request_region(dmac, 0x10, "S3 SonicVibes DDMA-C");
+       sonic->res_dmac = devm_request_region(&pci->dev, dmac, 0x10,
+                                             "S3 SonicVibes DDMA-C");
        if (!sonic->res_dmac) {
-               snd_sonicvibes_free(sonic);
                dev_err(card->dev,
                        "unable to grab DDMA-C port at 0x%x-0x%x\n",
                        dmac, dmac + 0x10 - 1);
@@ -1365,15 +1339,7 @@ static int snd_sonicvibes_create(struct snd_card *card,
 #endif
        sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION);
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops);
-       if (err < 0) {
-               snd_sonicvibes_free(sonic);
-               return err;
-       }
-
        snd_sonicvibes_proc_init(sonic);
-
-       *rsonic = sonic;
        return 0;
 }
 
@@ -1429,7 +1395,7 @@ static int snd_sonic_probe(struct pci_dev *pci,
        struct sonicvibes *sonic;
        struct snd_rawmidi *midi_uart;
        struct snd_opl3 *opl3;
-       int idx, err;
+       int err;
 
        if (dev >= SNDRV_CARDS)
                return -ENODEV;
@@ -1438,25 +1404,16 @@ static int snd_sonic_probe(struct pci_dev *pci,
                return -ENOENT;
        }
  
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*sonic), &card);
        if (err < 0)
                return err;
-       for (idx = 0; idx < 5; idx++) {
-               if (pci_resource_start(pci, idx) == 0 ||
-                   !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) {
-                       snd_card_free(card);
-                       return -ENODEV;
-               }
-       }
+       sonic = card->private_data;
        err = snd_sonicvibes_create(card, pci,
                                    reverb[dev] ? 1 : 0,
-                                   mge[dev] ? 1 : 0,
-                                   &sonic);
-       if (err < 0) {
-               snd_card_free(card);
+                                   mge[dev] ? 1 : 0);
+       if (err < 0)
                return err;
-       }
 
        strcpy(card->driver, "SonicVibes");
        strcpy(card->shortname, "S3 SonicVibes");
@@ -1467,65 +1424,45 @@ static int snd_sonic_probe(struct pci_dev *pci,
                sonic->irq);
 
        err = snd_sonicvibes_pcm(sonic, 0);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_sonicvibes_mixer(sonic);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES,
                                  sonic->midi_port,
                                  MPU401_INFO_INTEGRATED |
                                  MPU401_INFO_IRQ_HOOK,
                                  -1, &midi_uart);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        snd_sonicvibes_midi(sonic, midi_uart);
        err = snd_opl3_create(card, sonic->synth_port,
                              sonic->synth_port + 2,
                              OPL3_HW_OPL3_SV, 1, &opl3);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_sonicvibes_create_gameport(sonic);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_sonic_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver sonicvibes_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_sonic_ids,
        .probe = snd_sonic_probe,
-       .remove = snd_sonic_remove,
 };
 
 module_pci_driver(sonicvibes_driver);
index 60e4dca..9922ab4 100644 (file)
@@ -62,21 +62,18 @@ static int snd_trident_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               sizeof(*trident), &card);
        if (err < 0)
                return err;
+       trident = card->private_data;
 
        err = snd_trident_create(card, pci,
                                 pcm_channels[dev],
                                 ((pci->vendor << 16) | pci->device) == TRIDENT_DEVICE_ID_SI7018 ? 1 : 2,
-                                wavetable_size[dev],
-                                &trident);
-       if (err < 0) {
-               snd_card_free(card);
+                                wavetable_size[dev]);
+       if (err < 0)
                return err;
-       }
-       card->private_data = trident;
 
        switch (trident->device) {
        case TRIDENT_DEVICE_ID_DX:
@@ -102,26 +99,20 @@ static int snd_trident_probe(struct pci_dev *pci,
                card->shortname, trident->port, trident->irq);
 
        err = snd_trident_pcm(trident, pcm_dev++);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        switch (trident->device) {
        case TRIDENT_DEVICE_ID_DX:
        case TRIDENT_DEVICE_ID_NX:
                err = snd_trident_foldback_pcm(trident, pcm_dev++);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
                break;
        }
        if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) {
                err = snd_trident_spdif_pcm(trident, pcm_dev++);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
        if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
                err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
@@ -129,34 +120,24 @@ static int snd_trident_probe(struct pci_dev *pci,
                                          MPU401_INFO_INTEGRATED |
                                          MPU401_INFO_IRQ_HOOK,
                                          -1, &trident->rmidi);
-               if (err < 0) {
-                       snd_card_free(card);
+               if (err < 0)
                        return err;
-               }
        }
 
        snd_trident_create_gameport(trident);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_trident_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 static struct pci_driver trident_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_trident_ids,
        .probe = snd_trident_probe,
-       .remove = snd_trident_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &snd_trident_pm,
index c579a44..9768a7f 100644 (file)
@@ -251,9 +251,9 @@ struct snd_trident_memblk_arg {
 struct snd_trident_tlb {
        __le32 *entries;                /* 16k-aligned TLB table */
        dma_addr_t entries_dmaaddr;     /* 16k-aligned PCI address to TLB table */
-       struct snd_dma_buffer buffer;
+       struct snd_dma_buffer *buffer;
        struct snd_util_memhdr * memhdr;        /* page allocation list */
-       struct snd_dma_buffer silent_page;
+       struct snd_dma_buffer *silent_page;
 };
 
 struct snd_trident_voice {
@@ -400,8 +400,7 @@ int snd_trident_create(struct snd_card *card,
                       struct pci_dev *pci,
                       int pcm_streams,
                       int pcm_spdif_device,
-                      int max_wavetable_size,
-                      struct snd_trident ** rtrident);
+                      int max_wavetable_size);
 int snd_trident_create_gameport(struct snd_trident *trident);
 
 int snd_trident_pcm(struct snd_trident *trident, int device);
index cfbca3b..e98eea1 100644 (file)
@@ -42,7 +42,7 @@ static int snd_trident_sis_reset(struct snd_trident *trident);
 
 static void snd_trident_clear_voices(struct snd_trident * trident,
                                     unsigned short v_min, unsigned short v_max);
-static int snd_trident_free(struct snd_trident *trident);
+static void snd_trident_free(struct snd_card *card);
 
 /*
  *  common I/O routines
@@ -3299,12 +3299,6 @@ static void snd_trident_proc_init(struct snd_trident *trident)
        snd_card_ro_proc_new(trident->card, s, trident, snd_trident_proc_read);
 }
 
-static int snd_trident_dev_free(struct snd_device *device)
-{
-       struct snd_trident *trident = device->device_data;
-       return snd_trident_free(trident);
-}
-
 /*---------------------------------------------------------------------------
    snd_trident_tlb_alloc
   
@@ -3324,23 +3318,27 @@ static int snd_trident_tlb_alloc(struct snd_trident *trident)
        /* TLB array must be aligned to 16kB !!! so we allocate
           32kB region and correct offset when necessary */
 
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev,
-                               2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) {
+       trident->tlb.buffer =
+               snd_devm_alloc_pages(&trident->pci->dev, SNDRV_DMA_TYPE_DEV,
+                                    2 * SNDRV_TRIDENT_MAX_PAGES * 4);
+       if (!trident->tlb.buffer) {
                dev_err(trident->card->dev, "unable to allocate TLB buffer\n");
                return -ENOMEM;
        }
-       trident->tlb.entries = (__le32 *)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4);
-       trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer.addr, SNDRV_TRIDENT_MAX_PAGES * 4);
+       trident->tlb.entries = (__le32 *)ALIGN((unsigned long)trident->tlb.buffer->area, SNDRV_TRIDENT_MAX_PAGES * 4);
+       trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer->addr, SNDRV_TRIDENT_MAX_PAGES * 4);
 
        /* allocate and setup silent page and initialise TLB entries */
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev,
-                               SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) {
+       trident->tlb.silent_page =
+               snd_devm_alloc_pages(&trident->pci->dev, SNDRV_DMA_TYPE_DEV,
+                                    SNDRV_TRIDENT_PAGE_SIZE);
+       if (!trident->tlb.silent_page) {
                dev_err(trident->card->dev, "unable to allocate silent page\n");
                return -ENOMEM;
        }
-       memset(trident->tlb.silent_page.area, 0, SNDRV_TRIDENT_PAGE_SIZE);
+       memset(trident->tlb.silent_page->area, 0, SNDRV_TRIDENT_PAGE_SIZE);
        for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++)
-               trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page.addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));
+               trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page->addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));
 
        /* use emu memory block manager code to manage tlb page allocation */
        trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE * SNDRV_TRIDENT_MAX_PAGES);
@@ -3497,36 +3495,24 @@ int snd_trident_create(struct snd_card *card,
                       struct pci_dev *pci,
                       int pcm_streams,
                       int pcm_spdif_device,
-                      int max_wavetable_size,
-                      struct snd_trident ** rtrident)
+                      int max_wavetable_size)
 {
-       struct snd_trident *trident;
+       struct snd_trident *trident = card->private_data;
        int i, err;
        struct snd_trident_voice *voice;
        struct snd_trident_pcm_mixer *tmix;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_trident_dev_free,
-       };
-
-       *rtrident = NULL;
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 30 bits */
        if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(30))) {
                dev_err(card->dev,
                        "architecture does not support 30bit PCI busmaster DMA\n");
-               pci_disable_device(pci);
                return -ENXIO;
        }
        
-       trident = kzalloc(sizeof(*trident), GFP_KERNEL);
-       if (trident == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        trident->device = (pci->vendor << 16) | pci->device;
        trident->card = card;
        trident->pci = pci;
@@ -3542,22 +3528,19 @@ int snd_trident_create(struct snd_card *card,
                max_wavetable_size = 0;
        trident->synth.max_size = max_wavetable_size * 1024;
        trident->irq = -1;
+       card->private_free = snd_trident_free;
 
        trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE);
        pci_set_master(pci);
 
        err = pci_request_regions(pci, "Trident Audio");
-       if (err < 0) {
-               kfree(trident);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        trident->port = pci_resource_start(pci, 0);
 
-       if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, trident)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_trident_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, trident)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_trident_free(trident);
                return -EBUSY;
        }
        trident->irq = pci->irq;
@@ -3565,13 +3548,10 @@ int snd_trident_create(struct snd_card *card,
 
        /* allocate 16k-aligned TLB for NX cards */
        trident->tlb.entries = NULL;
-       trident->tlb.buffer.area = NULL;
        if (trident->device == TRIDENT_DEVICE_ID_NX) {
                err = snd_trident_tlb_alloc(trident);
-               if (err < 0) {
-                       snd_trident_free(trident);
+               if (err < 0)
                        return err;
-               }
        }
 
        trident->spdif_bits = trident->spdif_pcm_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
@@ -3591,16 +3571,8 @@ int snd_trident_create(struct snd_card *card,
                snd_BUG();
                break;
        }
-       if (err < 0) {
-               snd_trident_free(trident);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, trident, &ops);
-       if (err < 0) {
-               snd_trident_free(trident);
+       if (err < 0)
                return err;
-       }
 
        err = snd_trident_mixer(trident, pcm_spdif_device);
        if (err < 0)
@@ -3624,7 +3596,6 @@ int snd_trident_create(struct snd_card *card,
        snd_trident_enable_eso(trident);
 
        snd_trident_proc_init(trident);
-       *rtrident = trident;
        return 0;
 }
 
@@ -3634,14 +3605,16 @@ int snd_trident_create(struct snd_card *card,
    Description: This routine will free the device specific class for
                 the 4DWave card. 
                 
-   Parameters:  trident  - device specific private data for 4DWave card
+   Parameters:  card - card to release
 
    Returns:     None.
   
   ---------------------------------------------------------------------------*/
 
-static int snd_trident_free(struct snd_trident *trident)
+static void snd_trident_free(struct snd_card *card)
 {
+       struct snd_trident *trident = card->private_data;
+
        snd_trident_free_gameport(trident);
        snd_trident_disable_eso(trident);
        // Disable S/PDIF out
@@ -3650,19 +3623,10 @@ static int snd_trident_free(struct snd_trident *trident)
        else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
                outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
        }
-       if (trident->irq >= 0)
-               free_irq(trident->irq, trident);
-       if (trident->tlb.buffer.area) {
+       if (trident->tlb.buffer) {
                outl(0, TRID_REG(trident, NX_TLBC));
                snd_util_memhdr_free(trident->tlb.memhdr);
-               if (trident->tlb.silent_page.area)
-                       snd_dma_free_pages(&trident->tlb.silent_page);
-               snd_dma_free_pages(&trident->tlb.buffer);
        }
-       pci_release_regions(trident->pci);
-       pci_disable_device(trident->pci);
-       kfree(trident);
-       return 0;
 }
 
 /*---------------------------------------------------------------------------
index 4ad3855..05de2b9 100644 (file)
@@ -31,7 +31,7 @@
 /* fill TLB entrie(s) corresponding to page with ptr */
 #define set_tlb_bus(trident,page,addr) __set_tlb_bus(trident,page,addr)
 /* fill TLB entrie(s) corresponding to page with silence pointer */
-#define set_silent_tlb(trident,page)   __set_tlb_bus(trident, page, trident->tlb.silent_page.addr)
+#define set_silent_tlb(trident,page)   __set_tlb_bus(trident, page, trident->tlb.silent_page->addr)
 /* get aligned page from offset address */
 #define get_aligned_page(offset)       ((offset) >> 12)
 /* get offset address from aligned page */
@@ -58,8 +58,8 @@ static inline void set_tlb_bus(struct snd_trident *trident, int page,
 static inline void set_silent_tlb(struct snd_trident *trident, int page)
 {
        page <<= 1;
-       __set_tlb_bus(trident, page, trident->tlb.silent_page.addr);
-       __set_tlb_bus(trident, page+1, trident->tlb.silent_page.addr);
+       __set_tlb_bus(trident, page, trident->tlb.silent_page->addr);
+       __set_tlb_bus(trident, page+1, trident->tlb.silent_page->addr);
 }
 
 #else
@@ -92,7 +92,7 @@ static inline void set_silent_tlb(struct snd_trident *trident, int page)
        int i;
        page *= UNIT_PAGES;
        for (i = 0; i < UNIT_PAGES; i++, page++)
-               __set_tlb_bus(trident, page, trident->tlb.silent_page.addr);
+               __set_tlb_bus(trident, page, trident->tlb.silent_page->addr);
 }
 
 #endif /* PAGE_SIZE */
index 943813a..65514f7 100644 (file)
@@ -1911,13 +1911,12 @@ static int snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_overrid
 static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy)
 {
        struct gameport *gp;
-       struct resource *r;
 
        if (!joystick)
                return -ENODEV;
 
-       r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport");
-       if (!r) {
+       if (!devm_request_region(chip->card->dev, JOYSTICK_ADDR, 8,
+                                "VIA686 gameport")) {
                dev_warn(chip->card->dev, "cannot reserve joystick port %#x\n",
                       JOYSTICK_ADDR);
                return -EBUSY;
@@ -1927,7 +1926,6 @@ static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legac
        if (!gp) {
                dev_err(chip->card->dev,
                        "cannot allocate memory for gameport\n");
-               release_and_free_resource(r);
                return -ENOMEM;
        }
 
@@ -1935,7 +1933,6 @@ static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legac
        gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
        gameport_set_dev_parent(gp, &chip->pci->dev);
        gp->io = JOYSTICK_ADDR;
-       gameport_set_port_data(gp, r);
 
        /* Enable legacy joystick port */
        *legacy |= VIA_FUNC_ENABLE_GAME;
@@ -1949,11 +1946,8 @@ static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legac
 static void snd_via686_free_gameport(struct via82xx *chip)
 {
        if (chip->gameport) {
-               struct resource *r = gameport_get_port_data(chip->gameport);
-
                gameport_unregister_port(chip->gameport);
                chip->gameport = NULL;
-               release_and_free_resource(r);
        }
 }
 #else
@@ -2063,7 +2057,8 @@ static int snd_via686_init_misc(struct via82xx *chip)
                }
        }
        if (mpu_port >= 0x200)
-               chip->mpu_res = request_region(mpu_port, 2, "VIA82xx MPU401");
+               chip->mpu_res = devm_request_region(&chip->pci->dev, mpu_port,
+                                                   2, "VIA82xx MPU401");
        if (chip->mpu_res) {
                if (rev_h)
                        legacy |= VIA_FUNC_MIDI_PNP;    /* enable PCI I/O 2 */
@@ -2302,61 +2297,35 @@ static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume
 #define SND_VIA82XX_PM_OPS     NULL
 #endif /* CONFIG_PM_SLEEP */
 
-static int snd_via82xx_free(struct via82xx *chip)
+static void snd_via82xx_free(struct snd_card *card)
 {
+       struct via82xx *chip = card->private_data;
        unsigned int i;
 
-       if (chip->irq < 0)
-               goto __end_hw;
        /* disable interrupts */
        for (i = 0; i < chip->num_devs; i++)
                snd_via82xx_channel_reset(chip, &chip->devs[i]);
 
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
- __end_hw:
-       release_and_free_resource(chip->mpu_res);
-       pci_release_regions(chip->pci);
-
        if (chip->chip_type == TYPE_VIA686) {
                snd_via686_free_gameport(chip);
                pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, chip->old_legacy);
                pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, chip->old_legacy_cfg);
        }
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_via82xx_dev_free(struct snd_device *device)
-{
-       struct via82xx *chip = device->device_data;
-       return snd_via82xx_free(chip);
 }
 
 static int snd_via82xx_create(struct snd_card *card,
                              struct pci_dev *pci,
                              int chip_type,
                              int revision,
-                             unsigned int ac97_clock,
-                             struct via82xx **r_via)
+                             unsigned int ac97_clock)
 {
-       struct via82xx *chip;
+       struct via82xx *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_via82xx_dev_free,
-        };
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (!chip) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        chip->chip_type = chip_type;
        chip->revision = revision;
 
@@ -2373,44 +2342,31 @@ static int snd_via82xx_create(struct snd_card *card,
                              chip->old_legacy & ~(VIA_FUNC_ENABLE_SB|VIA_FUNC_ENABLE_FM));
 
        err = pci_request_regions(pci, card->driver);
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        chip->port = pci_resource_start(pci, 0);
-       if (request_irq(pci->irq,
-                       chip_type == TYPE_VIA8233 ?
-                       snd_via8233_interrupt : snd_via686_interrupt,
-                       IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq,
+                            chip_type == TYPE_VIA8233 ?
+                            snd_via8233_interrupt : snd_via686_interrupt,
+                            IRQF_SHARED,
+                            KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_via82xx_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_via82xx_free;
        if (ac97_clock >= 8000 && ac97_clock <= 48000)
                chip->ac97_clock = ac97_clock;
 
        err = snd_via82xx_chip_init(chip);
-       if (err < 0) {
-               snd_via82xx_free(chip);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_via82xx_free(chip);
+       if (err < 0)
                return err;
-       }
 
        /* The 8233 ac97 controller does not implement the master bit
         * in the pci command register. IMHO this is a violation of the PCI spec.
         * We call pci_set_master here because it does not hurt. */
        pci_set_master(pci);
-
-       *r_via = chip;
        return 0;
 }
 
@@ -2511,9 +2467,11 @@ static int snd_via82xx_probe(struct pci_dev *pci,
        unsigned int i;
        int err;
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        card_type = pci_id->driver_data;
        switch (card_type) {
@@ -2552,36 +2510,34 @@ static int snd_via82xx_probe(struct pci_dev *pci,
                break;
        default:
                dev_err(card->dev, "invalid card type %d\n", card_type);
-               err = -EINVAL;
-               goto __error;
+               return -EINVAL;
        }
                
        err = snd_via82xx_create(card, pci, chip_type, pci->revision,
-                                ac97_clock, &chip);
+                                ac97_clock);
        if (err < 0)
-               goto __error;
-       card->private_data = chip;
+               return err;
        err = snd_via82xx_mixer_new(chip, ac97_quirk);
        if (err < 0)
-               goto __error;
+               return err;
 
        if (chip_type == TYPE_VIA686) {
                err = snd_via686_pcm_new(chip);
                if (err < 0)
-                       goto __error;
+                       return err;
                err = snd_via686_init_misc(chip);
                if (err < 0)
-                       goto __error;
+                       return err;
        } else {
                if (chip_type == TYPE_VIA8233A) {
                        err = snd_via8233a_pcm_new(chip);
                        if (err < 0)
-                               goto __error;
+                               return err;
                        // chip->dxs_fixed = 1; /* FIXME: use 48k for DXS #3? */
                } else {
                        err = snd_via8233_pcm_new(chip);
                        if (err < 0)
-                               goto __error;
+                               return err;
                        if (dxs_support == VIA_DXS_48K)
                                chip->dxs_fixed = 1;
                        else if (dxs_support == VIA_DXS_NO_VRA)
@@ -2593,7 +2549,7 @@ static int snd_via82xx_probe(struct pci_dev *pci,
                }
                err = snd_via8233_init_misc(chip);
                if (err < 0)
-                       goto __error;
+                       return err;
        }
 
        /* disable interrupts */
@@ -2607,28 +2563,16 @@ static int snd_via82xx_probe(struct pci_dev *pci,
        snd_via82xx_proc_init(chip);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        return 0;
-
- __error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_via82xx_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver via82xx_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_via82xx_ids,
        .probe = snd_via82xx_probe,
-       .remove = snd_via82xx_remove,
        .driver = {
                .pm = SND_VIA82XX_PM_OPS,
        },
index 07278a3..234f7fb 100644 (file)
@@ -1048,95 +1048,57 @@ static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume
 #define SND_VIA82XX_PM_OPS     NULL
 #endif /* CONFIG_PM_SLEEP */
 
-static int snd_via82xx_free(struct via82xx_modem *chip)
+static void snd_via82xx_free(struct snd_card *card)
 {
+       struct via82xx_modem *chip = card->private_data;
        unsigned int i;
 
-       if (chip->irq < 0)
-               goto __end_hw;
        /* disable interrupts */
        for (i = 0; i < chip->num_devs; i++)
                snd_via82xx_channel_reset(chip, &chip->devs[i]);
-
-      __end_hw:
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_via82xx_dev_free(struct snd_device *device)
-{
-       struct via82xx_modem *chip = device->device_data;
-       return snd_via82xx_free(chip);
 }
 
 static int snd_via82xx_create(struct snd_card *card,
                              struct pci_dev *pci,
                              int chip_type,
                              int revision,
-                             unsigned int ac97_clock,
-                             struct via82xx_modem **r_via)
+                             unsigned int ac97_clock)
 {
-       struct via82xx_modem *chip;
+       struct via82xx_modem *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_via82xx_dev_free,
-        };
 
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (!chip) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
-
        spin_lock_init(&chip->reg_lock);
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
 
        err = pci_request_regions(pci, card->driver);
-       if (err < 0) {
-               kfree(chip);
-               pci_disable_device(pci);
+       if (err < 0)
                return err;
-       }
        chip->port = pci_resource_start(pci, 0);
-       if (request_irq(pci->irq, snd_via82xx_interrupt, IRQF_SHARED,
-                       KBUILD_MODNAME, chip)) {
+       if (devm_request_irq(&pci->dev, pci->irq, snd_via82xx_interrupt,
+                            IRQF_SHARED, KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_via82xx_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_via82xx_free;
        if (ac97_clock >= 8000 && ac97_clock <= 48000)
                chip->ac97_clock = ac97_clock;
 
        err = snd_via82xx_chip_init(chip);
-       if (err < 0) {
-               snd_via82xx_free(chip);
-               return err;
-       }
-
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_via82xx_free(chip);
+       if (err < 0)
                return err;
-       }
 
        /* The 8233 ac97 controller does not implement the master bit
         * in the pci command register. IMHO this is a violation of the PCI spec.
         * We call pci_set_master here because it does not hurt. */
        pci_set_master(pci);
-
-       *r_via = chip;
        return 0;
 }
 
@@ -1150,9 +1112,11 @@ static int snd_via82xx_probe(struct pci_dev *pci,
        unsigned int i;
        int err;
 
-       err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+       err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+                               sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        card_type = pci_id->driver_data;
        switch (card_type) {
@@ -1162,22 +1126,20 @@ static int snd_via82xx_probe(struct pci_dev *pci,
                break;
        default:
                dev_err(card->dev, "invalid card type %d\n", card_type);
-               err = -EINVAL;
-               goto __error;
+               return -EINVAL;
        }
                
        err = snd_via82xx_create(card, pci, chip_type, pci->revision,
-                                ac97_clock, &chip);
+                                ac97_clock);
        if (err < 0)
-               goto __error;
-       card->private_data = chip;
+               return err;
        err = snd_via82xx_mixer_new(chip);
        if (err < 0)
-               goto __error;
+               return err;
 
        err = snd_via686_pcm_new(chip);
        if (err < 0)
-               goto __error;
+               return err;
 
        /* disable interrupts */
        for (i = 0; i < chip->num_devs; i++)
@@ -1189,28 +1151,16 @@ static int snd_via82xx_probe(struct pci_dev *pci,
        snd_via82xx_proc_init(chip);
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        pci_set_drvdata(pci, card);
        return 0;
-
- __error:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_via82xx_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver via82xx_modem_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_via82xx_modem_ids,
        .probe = snd_via82xx_probe,
-       .remove = snd_via82xx_remove,
        .driver = {
                .pm = SND_VIA82XX_PM_OPS,
        },
index 04c7204..f48cc20 100644 (file)
@@ -100,26 +100,6 @@ static const struct snd_vx_hardware vx222_mic_hw = {
 
 /*
  */
-static int snd_vx222_free(struct vx_core *chip)
-{
-       struct snd_vx222 *vx = to_vx222(chip);
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, (void*)chip);
-       if (vx->port[0])
-               pci_release_regions(vx->pci);
-       pci_disable_device(vx->pci);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_vx222_dev_free(struct snd_device *device)
-{
-       struct vx_core *chip = device->device_data;
-       return snd_vx222_free(chip);
-}
-
-
 static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
                            const struct snd_vx_hardware *hw,
                            struct snd_vx222 **rchip)
@@ -127,13 +107,10 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
        struct vx_core *chip;
        struct snd_vx222 *vx;
        int i, err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_vx222_dev_free,
-       };
        const struct snd_vx_ops *vx_ops;
 
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
        pci_set_master(pci);
@@ -141,38 +118,26 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
        vx_ops = hw->type == VX_TYPE_BOARD ? &vx222_old_ops : &vx222_ops;
        chip = snd_vx_create(card, hw, vx_ops,
                             sizeof(struct snd_vx222) - sizeof(struct vx_core));
-       if (! chip) {
-               pci_disable_device(pci);
+       if (!chip)
                return -ENOMEM;
-       }
        vx = to_vx222(chip);
        vx->pci = pci;
 
        err = pci_request_regions(pci, CARD_NAME);
-       if (err < 0) {
-               snd_vx222_free(chip);
+       if (err < 0)
                return err;
-       }
        for (i = 0; i < 2; i++)
                vx->port[i] = pci_resource_start(pci, i + 1);
 
-       if (request_threaded_irq(pci->irq, snd_vx_irq_handler,
-                                snd_vx_threaded_irq_handler, IRQF_SHARED,
-                                KBUILD_MODNAME, chip)) {
+       if (devm_request_threaded_irq(&pci->dev, pci->irq, snd_vx_irq_handler,
+                                     snd_vx_threaded_irq_handler, IRQF_SHARED,
+                                     KBUILD_MODNAME, chip)) {
                dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
-               snd_vx222_free(chip);
                return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               snd_vx222_free(chip);
-               return err;
-       }
-
-       *rchip = vx;
        return 0;
 }
 
@@ -193,8 +158,8 @@ static int snd_vx222_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                               0, &card);
        if (err < 0)
                return err;
 
@@ -211,10 +176,8 @@ static int snd_vx222_probe(struct pci_dev *pci,
                break;
        }
        err = snd_vx222_create(card, pci, hw, &vx);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
        card->private_data = vx;
        vx->core.ibl.size = ibl[dev];
 
@@ -228,27 +191,18 @@ static int snd_vx222_probe(struct pci_dev *pci,
 #endif
 
        err = snd_vx_setup_firmware(&vx->core);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
+       if (err < 0)
                return err;
-       }
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
 }
 
-static void snd_vx222_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int snd_vx222_suspend(struct device *dev)
 {
@@ -276,7 +230,6 @@ static struct pci_driver vx222_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_vx222_ids,
        .probe = snd_vx222_probe,
-       .remove = snd_vx222_remove,
        .driver = {
                .pm = SND_VX222_PM_OPS,
        },
index 7e32d57..1e198e4 100644 (file)
@@ -105,7 +105,8 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
        }
 
        if (!r) {
-               r = request_region(io_port, 1, "YMFPCI gameport");
+               r = devm_request_region(&chip->pci->dev, io_port, 1,
+                                       "YMFPCI gameport");
                if (!r) {
                        dev_err(chip->card->dev,
                                "joystick port %#x is in use.\n", io_port);
@@ -117,7 +118,6 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
        if (!gp) {
                dev_err(chip->card->dev,
                        "cannot allocate memory for gameport\n");
-               release_and_free_resource(r);
                return -ENOMEM;
        }
 
@@ -126,7 +126,6 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
        gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
        gameport_set_dev_parent(gp, &chip->pci->dev);
        gp->io = io_port;
-       gameport_set_port_data(gp, r);
 
        if (chip->pci->device >= 0x0010) /* YMF 744/754 */
                pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE, io_port);
@@ -142,12 +141,8 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
 void snd_ymfpci_free_gameport(struct snd_ymfpci *chip)
 {
        if (chip->gameport) {
-               struct resource *r = gameport_get_port_data(chip->gameport);
-
                gameport_unregister_port(chip->gameport);
                chip->gameport = NULL;
-
-               release_and_free_resource(r);
        }
 }
 #else
@@ -176,9 +171,10 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
        }
 
        err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                          0, &card);
+                          sizeof(*chip), &card);
        if (err < 0)
                return err;
+       chip = card->private_data;
 
        switch (pci_id->device) {
        case 0x0004: str = "YMF724";  model = "DS-1"; break;
@@ -199,7 +195,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                        fm_port[dev] = pci_resource_start(pci, 1);
                }
                if (fm_port[dev] > 0)
-                       fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3");
+                       fm_res = devm_request_region(&pci->dev, fm_port[dev],
+                                                    4, "YMFPCI OPL3");
                if (fm_res) {
                        legacy_ctrl |= YMFPCI_LEGACY_FMEN;
                        pci_write_config_word(pci, PCIR_DSXG_FMBASE, fm_port[dev]);
@@ -209,7 +206,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                        mpu_port[dev] = pci_resource_start(pci, 1) + 0x20;
                }
                if (mpu_port[dev] > 0)
-                       mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401");
+                       mpu_res = devm_request_region(&pci->dev, mpu_port[dev],
+                                                     2, "YMFPCI MPU401");
                if (mpu_res) {
                        legacy_ctrl |= YMFPCI_LEGACY_MEN;
                        pci_write_config_word(pci, PCIR_DSXG_MPU401BASE, mpu_port[dev]);
@@ -223,7 +221,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                default: fm_port[dev] = 0; break;
                }
                if (fm_port[dev] > 0)
-                       fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3");
+                       fm_res = devm_request_region(&pci->dev, fm_port[dev],
+                                                    4, "YMFPCI OPL3");
                if (fm_res) {
                        legacy_ctrl |= YMFPCI_LEGACY_FMEN;
                } else {
@@ -238,7 +237,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                default: mpu_port[dev] = 0; break;
                }
                if (mpu_port[dev] > 0)
-                       mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401");
+                       mpu_res = devm_request_region(&pci->dev, mpu_port[dev],
+                                                     2, "YMFPCI MPU401");
                if (mpu_res) {
                        legacy_ctrl |= YMFPCI_LEGACY_MEN;
                } else {
@@ -253,15 +253,9 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
        pci_read_config_word(pci, PCIR_DSXG_LEGACY, &old_legacy_ctrl);
        pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
        pci_write_config_word(pci, PCIR_DSXG_ELEGACY, legacy_ctrl2);
-       err = snd_ymfpci_create(card, pci, old_legacy_ctrl, &chip);
-       if (err  < 0) {
-               release_and_free_resource(mpu_res);
-               release_and_free_resource(fm_res);
-               goto free_card;
-       }
-       chip->fm_res = fm_res;
-       chip->mpu_res = mpu_res;
-       card->private_data = chip;
+       err = snd_ymfpci_create(card, pci, old_legacy_ctrl);
+       if (err  < 0)
+               return err;
 
        strcpy(card->driver, str);
        sprintf(card->shortname, "Yamaha %s (%s)", model, str);
@@ -271,30 +265,30 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                chip->irq);
        err = snd_ymfpci_pcm(chip, 0);
        if (err < 0)
-               goto free_card;
+               return err;
 
        err = snd_ymfpci_pcm_spdif(chip, 1);
        if (err < 0)
-               goto free_card;
+               return err;
 
        err = snd_ymfpci_mixer(chip, rear_switch[dev]);
        if (err < 0)
-               goto free_card;
+               return err;
 
        if (chip->ac97->ext_id & AC97_EI_SDAC) {
                err = snd_ymfpci_pcm_4ch(chip, 2);
                if (err < 0)
-                       goto free_card;
+                       return err;
 
                err = snd_ymfpci_pcm2(chip, 3);
                if (err < 0)
-                       goto free_card;
+                       return err;
        }
        err = snd_ymfpci_timer(chip, 0);
        if (err < 0)
-               goto free_card;
+               return err;
 
-       if (chip->mpu_res) {
+       if (mpu_res) {
                err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI,
                                          mpu_port[dev],
                                          MPU401_INFO_INTEGRATED |
@@ -308,7 +302,7 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                        pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
                }
        }
-       if (chip->fm_res) {
+       if (fm_res) {
                err = snd_opl3_create(card,
                                      fm_port[dev],
                                      fm_port[dev] + 2,
@@ -323,7 +317,7 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                        err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                        if (err < 0) {
                                dev_err(card->dev, "cannot create opl3 hwdep\n");
-                               goto free_card;
+                               return err;
                        }
                }
        }
@@ -332,27 +326,17 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               goto free_card;
+               return err;
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
-
-free_card:
-       snd_card_free(card);
-       return err;
-}
-
-static void snd_card_ymfpci_remove(struct pci_dev *pci)
-{
-       snd_card_free(pci_get_drvdata(pci));
 }
 
 static struct pci_driver ymfpci_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ymfpci_ids,
        .probe = snd_card_ymfpci_probe,
-       .remove = snd_card_ymfpci_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &snd_ymfpci_pm,
index c73d8a5..6696877 100644 (file)
@@ -275,16 +275,13 @@ struct snd_ymfpci {
        unsigned char rev;      /* PCI revision */
        unsigned long reg_area_phys;
        void __iomem *reg_area_virt;
-       struct resource *res_reg_area;
-       struct resource *fm_res;
-       struct resource *mpu_res;
 
        unsigned short old_legacy_ctrl;
 #ifdef SUPPORT_JOYSTICK
        struct gameport *gameport;
 #endif
 
-       struct snd_dma_buffer work_ptr;
+       struct snd_dma_buffer *work_ptr;
 
        unsigned int bank_size_playback;
        unsigned int bank_size_capture;
@@ -358,8 +355,7 @@ struct snd_ymfpci {
 
 int snd_ymfpci_create(struct snd_card *card,
                      struct pci_dev *pci,
-                     unsigned short old_legacy_ctrl,
-                     struct snd_ymfpci ** rcodec);
+                     unsigned short old_legacy_ctrl);
 void snd_ymfpci_free_gameport(struct snd_ymfpci *chip);
 
 extern const struct dev_pm_ops snd_ymfpci_pm;
index 8fd0607..c80114c 100644 (file)
@@ -2116,11 +2116,12 @@ static int snd_ymfpci_memalloc(struct snd_ymfpci *chip)
               chip->work_size;
        /* work_ptr must be aligned to 256 bytes, but it's already
           covered with the kernel page allocation mechanism */
-       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
-                               size, &chip->work_ptr) < 0) 
+       chip->work_ptr = snd_devm_alloc_pages(&chip->pci->dev,
+                                             SNDRV_DMA_TYPE_DEV, size);
+       if (!chip->work_ptr)
                return -ENOMEM;
-       ptr = chip->work_ptr.area;
-       ptr_addr = chip->work_ptr.addr;
+       ptr = chip->work_ptr->area;
+       ptr_addr = chip->work_ptr->addr;
        memset(ptr, 0, size);   /* for sure */
 
        chip->bank_base_playback = ptr;
@@ -2165,7 +2166,7 @@ static int snd_ymfpci_memalloc(struct snd_ymfpci *chip)
        chip->work_base_addr = ptr_addr;
        
        snd_BUG_ON(ptr + chip->work_size !=
-                  chip->work_ptr.area + chip->work_ptr.bytes);
+                  chip->work_ptr->area + chip->work_ptr->bytes);
 
        snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, chip->bank_base_playback_addr);
        snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, chip->bank_base_capture_addr);
@@ -2196,65 +2197,32 @@ static int snd_ymfpci_memalloc(struct snd_ymfpci *chip)
        return 0;
 }
 
-static int snd_ymfpci_free(struct snd_ymfpci *chip)
+static void snd_ymfpci_free(struct snd_card *card)
 {
+       struct snd_ymfpci *chip = card->private_data;
        u16 ctrl;
 
-       if (snd_BUG_ON(!chip))
-               return -EINVAL;
-
-       if (chip->res_reg_area) {       /* don't touch busy hardware */
-               snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
-               snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
-               snd_ymfpci_writel(chip, YDSXGR_LEGACYOUTVOL, 0);
-               snd_ymfpci_writel(chip, YDSXGR_STATUS, ~0);
-               snd_ymfpci_disable_dsp(chip);
-               snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, 0);
-               snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, 0);
-               snd_ymfpci_writel(chip, YDSXGR_EFFCTRLBASE, 0);
-               snd_ymfpci_writel(chip, YDSXGR_WORKBASE, 0);
-               snd_ymfpci_writel(chip, YDSXGR_WORKSIZE, 0);
-               ctrl = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL);
-               snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
-       }
+       snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
+       snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
+       snd_ymfpci_writel(chip, YDSXGR_LEGACYOUTVOL, 0);
+       snd_ymfpci_writel(chip, YDSXGR_STATUS, ~0);
+       snd_ymfpci_disable_dsp(chip);
+       snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, 0);
+       snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, 0);
+       snd_ymfpci_writel(chip, YDSXGR_EFFCTRLBASE, 0);
+       snd_ymfpci_writel(chip, YDSXGR_WORKBASE, 0);
+       snd_ymfpci_writel(chip, YDSXGR_WORKSIZE, 0);
+       ctrl = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL);
+       snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
 
        snd_ymfpci_ac3_done(chip);
 
-       /* Set PCI device to D3 state */
-#if 0
-       /* FIXME: temporarily disabled, otherwise we cannot fire up
-        * the chip again unless reboot.  ACPI bug?
-        */
-       pci_set_power_state(chip->pci, PCI_D3hot);
-#endif
-
-#ifdef CONFIG_PM_SLEEP
-       kfree(chip->saved_regs);
-#endif
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       release_and_free_resource(chip->mpu_res);
-       release_and_free_resource(chip->fm_res);
        snd_ymfpci_free_gameport(chip);
-       iounmap(chip->reg_area_virt);
-       if (chip->work_ptr.area)
-               snd_dma_free_pages(&chip->work_ptr);
        
-       release_and_free_resource(chip->res_reg_area);
-
        pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
        
-       pci_disable_device(chip->pci);
        release_firmware(chip->dsp_microcode);
        release_firmware(chip->controller_microcode);
-       kfree(chip);
-       return 0;
-}
-
-static int snd_ymfpci_dev_free(struct snd_device *device)
-{
-       struct snd_ymfpci *chip = device->device_data;
-       return snd_ymfpci_free(chip);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -2346,27 +2314,16 @@ SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume);
 
 int snd_ymfpci_create(struct snd_card *card,
                      struct pci_dev *pci,
-                     unsigned short old_legacy_ctrl,
-                     struct snd_ymfpci **rchip)
+                     unsigned short old_legacy_ctrl)
 {
-       struct snd_ymfpci *chip;
+       struct snd_ymfpci *chip = card->private_data;
        int err;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_ymfpci_dev_free,
-       };
        
-       *rchip = NULL;
-
        /* enable PCI device */
-       err = pci_enable_device(pci);
+       err = pcim_enable_device(pci);
        if (err < 0)
                return err;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL) {
-               pci_disable_device(pci);
-               return -ENOMEM;
-       }
        chip->old_legacy_ctrl = old_legacy_ctrl;
        spin_lock_init(&chip->reg_lock);
        spin_lock_init(&chip->voice_lock);
@@ -2377,71 +2334,59 @@ int snd_ymfpci_create(struct snd_card *card,
        chip->irq = -1;
        chip->device_id = pci->device;
        chip->rev = pci->revision;
-       chip->reg_area_phys = pci_resource_start(pci, 0);
-       chip->reg_area_virt = ioremap(chip->reg_area_phys, 0x8000);
-       pci_set_master(pci);
-       chip->src441_used = -1;
 
-       chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI");
-       if (!chip->res_reg_area) {
+       err = pci_request_regions(pci, "YMFPCI");
+       if (err < 0)
+               return err;
+
+       chip->reg_area_phys = pci_resource_start(pci, 0);
+       chip->reg_area_virt = devm_ioremap(&pci->dev, chip->reg_area_phys, 0x8000);
+       if (!chip->reg_area_virt) {
                dev_err(chip->card->dev,
                        "unable to grab memory region 0x%lx-0x%lx\n",
                        chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1);
-               err = -EBUSY;
-               goto free_chip;
+               return -EBUSY;
        }
-       if (request_irq(pci->irq, snd_ymfpci_interrupt, IRQF_SHARED,
+       pci_set_master(pci);
+       chip->src441_used = -1;
+
+       if (devm_request_irq(&pci->dev, pci->irq, snd_ymfpci_interrupt, IRQF_SHARED,
                        KBUILD_MODNAME, chip)) {
                dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq);
-               err = -EBUSY;
-               goto free_chip;
+               return -EBUSY;
        }
        chip->irq = pci->irq;
        card->sync_irq = chip->irq;
+       card->private_free = snd_ymfpci_free;
 
        snd_ymfpci_aclink_reset(pci);
-       if (snd_ymfpci_codec_ready(chip, 0) < 0) {
-               err = -EIO;
-               goto free_chip;
-       }
+       if (snd_ymfpci_codec_ready(chip, 0) < 0)
+               return -EIO;
 
        err = snd_ymfpci_request_firmware(chip);
        if (err < 0) {
                dev_err(chip->card->dev, "firmware request failed: %d\n", err);
-               goto free_chip;
+               return err;
        }
        snd_ymfpci_download_image(chip);
 
        udelay(100); /* seems we need a delay after downloading image.. */
 
-       if (snd_ymfpci_memalloc(chip) < 0) {
-               err = -EIO;
-               goto free_chip;
-       }
+       if (snd_ymfpci_memalloc(chip) < 0)
+               return -EIO;
 
        err = snd_ymfpci_ac3_init(chip);
        if (err < 0)
-               goto free_chip;
+               return err;
 
 #ifdef CONFIG_PM_SLEEP
-       chip->saved_regs = kmalloc_array(YDSXGR_NUM_SAVED_REGS, sizeof(u32),
-                                        GFP_KERNEL);
-       if (chip->saved_regs == NULL) {
-               err = -ENOMEM;
-               goto free_chip;
-       }
+       chip->saved_regs = devm_kmalloc_array(&pci->dev, YDSXGR_NUM_SAVED_REGS,
+                                             sizeof(u32), GFP_KERNEL);
+       if (!chip->saved_regs)
+               return -ENOMEM;
 #endif
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0)
-               goto free_chip;
-
        snd_ymfpci_proc_init(card, chip);
 
-       *rchip = chip;
        return 0;
-
-free_chip:
-       snd_ymfpci_free(chip);
-       return err;
 }
index 0dfb6a9..7a0f0e7 100644 (file)
@@ -50,19 +50,6 @@ static void vxpocket_release(struct pcmcia_device *link)
        pcmcia_disable_device(link);
 }
 
-/*
- * destructor, called from snd_card_free_when_closed()
- */
-static int snd_vxpocket_dev_free(struct snd_device *device)
-{
-       struct vx_core *chip = device->device_data;
-
-       snd_vx_free_firmware(chip);
-       kfree(chip);
-       return 0;
-}
-
-
 /*
  * Hardware information
  */
@@ -122,21 +109,12 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl,
 {
        struct vx_core *chip;
        struct snd_vxpocket *vxp;
-       static const struct snd_device_ops ops = {
-               .dev_free =     snd_vxpocket_dev_free,
-       };
-       int err;
 
        chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops,
                             sizeof(struct snd_vxpocket) - sizeof(struct vx_core));
        if (!chip)
                return -ENOMEM;
 
-       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-       if (err < 0) {
-               kfree(chip);
-               return err;
-       }
        chip->ibl.size = ibl;
 
        vxp = to_vxpocket(chip);
index ba5a85b..49ff5e7 100644 (file)
@@ -52,3 +52,12 @@ config SND_SOC_AMD_RENOIR_MACH
        depends on SND_SOC_AMD_RENOIR
        help
         This option enables machine driver for DMIC
+
+config SND_SOC_AMD_ACP5x
+       tristate "AMD Audio Coprocessor-v5.x I2S support"
+       depends on X86 && PCI
+       help
+        This option enables ACP v5.x support on AMD platform
+
+        By enabling this flag build will trigger for ACP PCI driver,
+        ACP DMA driver, CPU DAI driver.
index e6df2f7..07150d2 100644 (file)
@@ -10,3 +10,4 @@ obj-$(CONFIG_SND_SOC_AMD_CZ_RT5645_MACH) += snd-soc-acp-rt5645-mach.o
 obj-$(CONFIG_SND_SOC_AMD_ACP3x) += raven/
 obj-$(CONFIG_SND_SOC_AMD_RV_RT5682_MACH) += snd-soc-acp-rt5682-mach.o
 obj-$(CONFIG_SND_SOC_AMD_RENOIR) += renoir/
+obj-$(CONFIG_SND_SOC_AMD_ACP5x) += vangogh/
index 3c60c5f..b3df98a 100644 (file)
@@ -756,15 +756,9 @@ static int cz_probe(struct platform_device *pdev)
        snd_soc_card_set_drvdata(card, machine);
        ret = devm_snd_soc_register_card(&pdev->dev, card);
        if (ret) {
-               if (ret != -EPROBE_DEFER)
-                       dev_err(&pdev->dev,
-                               "devm_snd_soc_register_card(%s) failed: %d\n",
-                               card->name, ret);
-               else
-                       dev_dbg(&pdev->dev,
-                               "devm_snd_soc_register_card(%s) probe deferred: %d\n",
-                               card->name, ret);
-               return ret;
+               return dev_err_probe(&pdev->dev, ret,
+                               "devm_snd_soc_register_card(%s) failed\n",
+                               card->name);
        }
        bt_uart_enable = !device_property_read_bool(&pdev->dev,
                                                    "bt-pad-enable");
index cc1ce6f..11b3c4f 100644 (file)
@@ -156,7 +156,7 @@ static void config_acp_dma_channel(void __iomem *acp_mmio, u8 ch_num,
        acp_reg_write(priority_level, acp_mmio, mmACP_DMA_PRIO_0 + ch_num);
 }
 
-/* Initialize a dma descriptor in SRAM based on descritor information passed */
+/* Initialize a dma descriptor in SRAM based on descriptor information passed */
 static void config_dma_descriptor_in_sram(void __iomem *acp_mmio,
                                          u16 descr_idx,
                                          acp_dma_dscr_transfer_t *descr_info)
@@ -288,7 +288,7 @@ static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size,
                                              &dmadscr[i]);
        }
        pre_config_reset(acp_mmio, ch);
-       /* Configure the DMA channel with the above descriptore */
+       /* Configure the DMA channel with the above descriptor */
        config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1,
                               NUM_DSCRS_PER_CHANNEL,
                               ACP_DMA_PRIORITY_LEVEL_NORMAL);
@@ -322,7 +322,7 @@ static void acp_pte_config(void __iomem *acp_mmio, dma_addr_t addr,
                high |= BIT(31);
                acp_reg_write(high, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
 
-               /* Move to next physically contiguos page */
+               /* Move to next physically contiguous page */
                addr += PAGE_SIZE;
        }
 }
@@ -602,11 +602,11 @@ static int acp_init(void __iomem *acp_mmio, u32 asic_type)
                acp_reg_write(val, acp_mmio, mmACP_BT_UART_PAD_SEL);
        }
 
-       /* initiailize Onion control DAGB register */
+       /* initialize Onion control DAGB register */
        acp_reg_write(ACP_ONION_CNTL_DEFAULT, acp_mmio,
                      mmACP_AXI2DAGB_ONION_CNTL);
 
-       /* initiailize Garlic control DAGB registers */
+       /* initialize Garlic control DAGB registers */
        acp_reg_write(ACP_GARLIC_CNTL_DEFAULT, acp_mmio,
                      mmACP_AXI2DAGB_GARLIC_CNTL);
 
@@ -621,7 +621,7 @@ static int acp_init(void __iomem *acp_mmio, u32 asic_type)
        acp_reg_write(ACP_SRAM_BASE_ADDRESS, acp_mmio,
                      mmACP_DMA_DESC_BASE_ADDR);
 
-       /* Num of descriptiors in SRAM 0x4, means 256 descriptors;(64 * 4) */
+       /* Num of descriptors 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);
@@ -1035,13 +1035,6 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component,
        return bytes_to_frames(runtime, pos);
 }
 
-static int acp_dma_mmap(struct snd_soc_component *component,
-                       struct snd_pcm_substream *substream,
-                       struct vm_area_struct *vma)
-{
-       return snd_pcm_lib_default_mmap(substream, vma);
-}
-
 static int acp_dma_prepare(struct snd_soc_component *component,
                           struct snd_pcm_substream *substream)
 {
@@ -1205,7 +1198,6 @@ static const struct snd_soc_component_driver acp_asoc_platform = {
        .hw_params      = acp_dma_hw_params,
        .trigger        = acp_dma_trigger,
        .pointer        = acp_dma_pointer,
-       .mmap           = acp_dma_mmap,
        .prepare        = acp_dma_prepare,
        .pcm_construct  = acp_dma_new,
 };
index d9980ab..e561464 100644 (file)
@@ -512,17 +512,11 @@ static int acp3x_probe(struct platform_device *pdev)
 
        ret = devm_snd_soc_register_card(&pdev->dev, card);
        if (ret) {
-               if (ret != -EPROBE_DEFER)
-                       dev_err(&pdev->dev,
-                               "devm_snd_soc_register_card(%s) failed: %d\n",
-                               card->name, ret);
-               else
-                       dev_dbg(&pdev->dev,
-                               "devm_snd_soc_register_card(%s) probe deferred: %d\n",
-                               card->name, ret);
+               return dev_err_probe(&pdev->dev, ret,
+                               "devm_snd_soc_register_card(%s) failed\n",
+                               card->name);
        }
-
-       return ret;
+       return 0;
 }
 
 static const struct acpi_device_id acp3x_audio_acpi_match[] = {
index 597d7c4..75c0669 100644 (file)
@@ -147,7 +147,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
                high |= BIT(31);
                rv_writel(high, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val
                                + 4);
-               /* Move to next physically contiguos page */
+               /* Move to next physically contiguous page */
                val += 8;
                addr += PAGE_SIZE;
        }
@@ -320,13 +320,6 @@ static int acp3x_dma_new(struct snd_soc_component *component,
        return 0;
 }
 
-static int acp3x_dma_mmap(struct snd_soc_component *component,
-                         struct snd_pcm_substream *substream,
-                         struct vm_area_struct *vma)
-{
-       return snd_pcm_lib_default_mmap(substream, vma);
-}
-
 static int acp3x_dma_close(struct snd_soc_component *component,
                           struct snd_pcm_substream *substream)
 {
@@ -370,7 +363,6 @@ static const struct snd_soc_component_driver acp3x_i2s_component = {
        .close          = acp3x_dma_close,
        .hw_params      = acp3x_dma_hw_params,
        .pointer        = acp3x_dma_pointer,
-       .mmap           = acp3x_dma_mmap,
        .pcm_construct  = acp3x_dma_new,
 };
 
index 0391c28..9dd22a2 100644 (file)
@@ -291,13 +291,6 @@ static int acp_pdm_dma_new(struct snd_soc_component *component,
        return 0;
 }
 
-static int acp_pdm_dma_mmap(struct snd_soc_component *component,
-                           struct snd_pcm_substream *substream,
-                           struct vm_area_struct *vma)
-{
-       return snd_pcm_lib_default_mmap(substream, vma);
-}
-
 static int acp_pdm_dma_close(struct snd_soc_component *component,
                             struct snd_pcm_substream *substream)
 {
@@ -375,7 +368,6 @@ static const struct snd_soc_component_driver acp_pdm_component = {
        .close          = acp_pdm_dma_close,
        .hw_params      = acp_pdm_dma_hw_params,
        .pointer        = acp_pdm_dma_pointer,
-       .mmap           = acp_pdm_dma_mmap,
        .pcm_construct  = acp_pdm_dma_new,
 };
 
index 306134b..5d979a7 100644 (file)
@@ -54,10 +54,9 @@ static int acp_probe(struct platform_device *pdev)
        snd_soc_card_set_drvdata(card, machine);
        ret = devm_snd_soc_register_card(&pdev->dev, card);
        if (ret) {
-               dev_err(&pdev->dev,
-                       "snd_soc_register_card(%s) failed: %d\n",
-                       acp_card.name, ret);
-               return ret;
+               return dev_err_probe(&pdev->dev, ret,
+                               "snd_soc_register_card(%s) failed\n",
+                               card->name);
        }
        return 0;
 }
diff --git a/sound/soc/amd/vangogh/Makefile b/sound/soc/amd/vangogh/Makefile
new file mode 100644 (file)
index 0000000..3353f93
--- /dev/null
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Vangogh platform Support
+snd-pci-acp5x-objs     := pci-acp5x.o
+snd-acp5x-i2s-objs     := acp5x-i2s.o
+snd-acp5x-pcm-dma-objs := acp5x-pcm-dma.o
+
+obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-pci-acp5x.o
+obj-$(CONFIG_SND_SOC_AMD_ACP5x)        += snd-acp5x-i2s.o
+obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-acp5x-pcm-dma.o
diff --git a/sound/soc/amd/vangogh/acp5x-i2s.c b/sound/soc/amd/vangogh/acp5x-i2s.c
new file mode 100644 (file)
index 0000000..2705e57
--- /dev/null
@@ -0,0 +1,427 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// AMD ALSA SoC PCM Driver
+//
+// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <linux/dma-mapping.h>
+
+#include "acp5x.h"
+
+#define DRV_NAME "acp5x_i2s_playcap"
+
+static int acp5x_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
+                            unsigned int fmt)
+{
+       struct i2s_dev_data *adata;
+       int mode;
+
+       adata = snd_soc_dai_get_drvdata(cpu_dai);
+       mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+       switch (mode) {
+       case SND_SOC_DAIFMT_I2S:
+               adata->tdm_mode = TDM_DISABLE;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               adata->tdm_mode = TDM_ENABLE;
+               break;
+       default:
+               return -EINVAL;
+       }
+       mode = fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
+       switch (mode) {
+       case SND_SOC_DAIFMT_CBC_CFC:
+               adata->master_mode = I2S_MASTER_MODE_ENABLE;
+               break;
+       case SND_SOC_DAIFMT_CBP_CFP:
+               adata->master_mode = I2S_MASTER_MODE_DISABLE;
+               break;
+       }
+       return 0;
+}
+
+static int acp5x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai,
+                                 u32 tx_mask, u32 rx_mask,
+                                 int slots, int slot_width)
+{
+       struct i2s_dev_data *adata;
+       u32 frm_len;
+       u16 slot_len;
+
+       adata = snd_soc_dai_get_drvdata(cpu_dai);
+
+       /* These values are as per Hardware Spec */
+       switch (slot_width) {
+       case SLOT_WIDTH_8:
+               slot_len = 8;
+               break;
+       case SLOT_WIDTH_16:
+               slot_len = 16;
+               break;
+       case SLOT_WIDTH_24:
+               slot_len = 24;
+               break;
+       case SLOT_WIDTH_32:
+               slot_len = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+       frm_len = FRM_LEN | (slots << 15) | (slot_len << 18);
+       adata->tdm_fmt = frm_len;
+       return 0;
+}
+
+static int acp5x_i2s_hwparams(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *params,
+                             struct snd_soc_dai *dai)
+{
+       struct i2s_stream_instance *rtd;
+       struct snd_soc_pcm_runtime *prtd;
+       struct snd_soc_card *card;
+       struct acp5x_platform_info *pinfo;
+       struct i2s_dev_data *adata;
+       union acp_i2stdm_mstrclkgen mclkgen;
+
+       u32 val;
+       u32 reg_val, frmt_reg, master_reg;
+       u32 lrclk_div_val, bclk_div_val;
+
+       lrclk_div_val = 0;
+       bclk_div_val = 0;
+       prtd = asoc_substream_to_rtd(substream);
+       rtd = substream->runtime->private_data;
+       card = prtd->card;
+       adata = snd_soc_dai_get_drvdata(dai);
+       pinfo = snd_soc_card_get_drvdata(card);
+       if (pinfo) {
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                       rtd->i2s_instance = pinfo->play_i2s_instance;
+               else
+                       rtd->i2s_instance = pinfo->cap_i2s_instance;
+       }
+
+       /* These values are as per Hardware Spec */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_U8:
+       case SNDRV_PCM_FORMAT_S8:
+               rtd->xfer_resolution = 0x0;
+               break;
+       case SNDRV_PCM_FORMAT_S16_LE:
+               rtd->xfer_resolution = 0x02;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               rtd->xfer_resolution = 0x04;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               rtd->xfer_resolution = 0x05;
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               switch (rtd->i2s_instance) {
+               case I2S_HS_INSTANCE:
+                       reg_val = ACP_HSTDM_ITER;
+                       frmt_reg = ACP_HSTDM_TXFRMT;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       reg_val = ACP_I2STDM_ITER;
+                       frmt_reg = ACP_I2STDM_TXFRMT;
+               }
+       } else {
+               switch (rtd->i2s_instance) {
+               case I2S_HS_INSTANCE:
+                       reg_val = ACP_HSTDM_IRER;
+                       frmt_reg = ACP_HSTDM_RXFRMT;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       reg_val = ACP_I2STDM_IRER;
+                       frmt_reg = ACP_I2STDM_RXFRMT;
+               }
+       }
+       if (adata->tdm_mode) {
+               val = acp_readl(rtd->acp5x_base + reg_val);
+               acp_writel(val | 0x2, rtd->acp5x_base + reg_val);
+               acp_writel(adata->tdm_fmt, rtd->acp5x_base + frmt_reg);
+       }
+       val = acp_readl(rtd->acp5x_base + reg_val);
+       val &= ~ACP5x_ITER_IRER_SAMP_LEN_MASK;
+       val = val | (rtd->xfer_resolution  << 3);
+       acp_writel(val, rtd->acp5x_base + reg_val);
+
+       if (adata->master_mode) {
+               switch (rtd->i2s_instance) {
+               case I2S_HS_INSTANCE:
+                       master_reg = ACP_I2STDM2_MSTRCLKGEN;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       master_reg = ACP_I2STDM0_MSTRCLKGEN;
+                       break;
+               }
+               mclkgen.bits.i2stdm_master_mode = 0x1;
+               if (adata->tdm_mode)
+                       mclkgen.bits.i2stdm_format_mode = 0x01;
+               else
+                       mclkgen.bits.i2stdm_format_mode = 0x0;
+               switch (params_format(params)) {
+               case SNDRV_PCM_FORMAT_S16_LE:
+                       switch (params_rate(params)) {
+                       case 8000:
+                               bclk_div_val = 768;
+                               break;
+                       case 16000:
+                               bclk_div_val = 384;
+                               break;
+                       case 24000:
+                               bclk_div_val = 256;
+                               break;
+                       case 32000:
+                               bclk_div_val = 192;
+                               break;
+                       case 44100:
+                       case 48000:
+                               bclk_div_val = 128;
+                               break;
+                       case 88200:
+                       case 96000:
+                               bclk_div_val = 64;
+                               break;
+                       case 192000:
+                               bclk_div_val = 32;
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+                       lrclk_div_val = 32;
+                       break;
+               case SNDRV_PCM_FORMAT_S32_LE:
+                       switch (params_rate(params)) {
+                       case 8000:
+                               bclk_div_val = 384;
+                               break;
+                       case 16000:
+                               bclk_div_val = 192;
+                               break;
+                       case 24000:
+                               bclk_div_val = 128;
+                               break;
+                       case 32000:
+                               bclk_div_val = 96;
+                               break;
+                       case 44100:
+                       case 48000:
+                               bclk_div_val = 64;
+                               break;
+                       case 88200:
+                       case 96000:
+                               bclk_div_val = 32;
+                               break;
+                       case 192000:
+                               bclk_div_val = 16;
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+                       lrclk_div_val = 64;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               mclkgen.bits.i2stdm_bclk_div_val = bclk_div_val;
+               mclkgen.bits.i2stdm_lrclk_div_val = lrclk_div_val;
+               acp_writel(mclkgen.u32_all, rtd->acp5x_base + master_reg);
+       }
+       return 0;
+}
+
+static int acp5x_i2s_trigger(struct snd_pcm_substream *substream,
+                            int cmd, struct snd_soc_dai *dai)
+{
+       struct i2s_stream_instance *rtd;
+       u32 ret, val, period_bytes, reg_val, ier_val, water_val;
+       u32 buf_size, buf_reg;
+
+       rtd = substream->runtime->private_data;
+       period_bytes = frames_to_bytes(substream->runtime,
+                                      substream->runtime->period_size);
+       buf_size = frames_to_bytes(substream->runtime,
+                                  substream->runtime->buffer_size);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               rtd->bytescount = acp_get_byte_count(rtd,
+                                                    substream->stream);
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       switch (rtd->i2s_instance) {
+                       case I2S_HS_INSTANCE:
+                               water_val =
+                                       ACP_HS_TX_INTR_WATERMARK_SIZE;
+                               reg_val = ACP_HSTDM_ITER;
+                               ier_val = ACP_HSTDM_IER;
+                               buf_reg = ACP_HS_TX_RINGBUFSIZE;
+                               break;
+                       case I2S_SP_INSTANCE:
+                       default:
+                               water_val =
+                                       ACP_I2S_TX_INTR_WATERMARK_SIZE;
+                               reg_val = ACP_I2STDM_ITER;
+                               ier_val = ACP_I2STDM_IER;
+                               buf_reg = ACP_I2S_TX_RINGBUFSIZE;
+                       }
+               } else {
+                       switch (rtd->i2s_instance) {
+                       case I2S_HS_INSTANCE:
+                               water_val =
+                                       ACP_HS_RX_INTR_WATERMARK_SIZE;
+                               reg_val = ACP_HSTDM_IRER;
+                               ier_val = ACP_HSTDM_IER;
+                               buf_reg = ACP_HS_RX_RINGBUFSIZE;
+                               break;
+                       case I2S_SP_INSTANCE:
+                       default:
+                               water_val =
+                                       ACP_I2S_RX_INTR_WATERMARK_SIZE;
+                               reg_val = ACP_I2STDM_IRER;
+                               ier_val = ACP_I2STDM_IER;
+                               buf_reg = ACP_I2S_RX_RINGBUFSIZE;
+                       }
+               }
+               acp_writel(period_bytes, rtd->acp5x_base + water_val);
+               acp_writel(buf_size, rtd->acp5x_base + buf_reg);
+               val = acp_readl(rtd->acp5x_base + reg_val);
+               val = val | BIT(0);
+               acp_writel(val, rtd->acp5x_base + reg_val);
+               acp_writel(1, rtd->acp5x_base + ier_val);
+               ret = 0;
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       switch (rtd->i2s_instance) {
+                       case I2S_HS_INSTANCE:
+                               reg_val = ACP_HSTDM_ITER;
+                               break;
+                       case I2S_SP_INSTANCE:
+                       default:
+                               reg_val = ACP_I2STDM_ITER;
+                       }
+
+               } else {
+                       switch (rtd->i2s_instance) {
+                       case I2S_HS_INSTANCE:
+                               reg_val = ACP_HSTDM_IRER;
+                               break;
+                       case I2S_SP_INSTANCE:
+                       default:
+                               reg_val = ACP_I2STDM_IRER;
+                       }
+               }
+               val = acp_readl(rtd->acp5x_base + reg_val);
+               val = val & ~BIT(0);
+               acp_writel(val, rtd->acp5x_base + reg_val);
+
+               if (!(acp_readl(rtd->acp5x_base + ACP_HSTDM_ITER) & BIT(0)) &&
+                   !(acp_readl(rtd->acp5x_base + ACP_HSTDM_IRER) & BIT(0)))
+                       acp_writel(0, rtd->acp5x_base + ACP_HSTDM_IER);
+               if (!(acp_readl(rtd->acp5x_base + ACP_I2STDM_ITER) & BIT(0)) &&
+                   !(acp_readl(rtd->acp5x_base + ACP_I2STDM_IRER) & BIT(0)))
+                       acp_writel(0, rtd->acp5x_base + ACP_I2STDM_IER);
+               ret = 0;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static struct snd_soc_dai_ops acp5x_i2s_dai_ops = {
+       .hw_params = acp5x_i2s_hwparams,
+       .trigger = acp5x_i2s_trigger,
+       .set_fmt = acp5x_i2s_set_fmt,
+       .set_tdm_slot = acp5x_i2s_set_tdm_slot,
+};
+
+static const struct snd_soc_component_driver acp5x_dai_component = {
+       .name = "acp5x-i2s",
+};
+
+static struct snd_soc_dai_driver acp5x_i2s_dai = {
+       .playback = {
+               .rates = SNDRV_PCM_RATE_8000_96000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+                       SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+               .channels_min = 2,
+               .channels_max = 2,
+               .rate_min = 8000,
+               .rate_max = 96000,
+       },
+       .capture = {
+               .rates = SNDRV_PCM_RATE_8000_96000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+                       SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+               .channels_min = 2,
+               .channels_max = 2,
+               .rate_min = 8000,
+               .rate_max = 96000,
+       },
+       .ops = &acp5x_i2s_dai_ops,
+};
+
+static int acp5x_dai_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct i2s_dev_data *adata;
+       int ret;
+
+       adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
+                            GFP_KERNEL);
+       if (!adata)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
+               return -ENOMEM;
+       }
+       adata->acp5x_base = devm_ioremap(&pdev->dev, res->start,
+                                        resource_size(res));
+       if (!adata->acp5x_base)
+               return -ENOMEM;
+
+       adata->master_mode = I2S_MASTER_MODE_ENABLE;
+       dev_set_drvdata(&pdev->dev, adata);
+       ret = devm_snd_soc_register_component(&pdev->dev,
+                                             &acp5x_dai_component,
+                                             &acp5x_i2s_dai, 1);
+       if (ret)
+               dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
+       return ret;
+}
+
+static struct platform_driver acp5x_dai_driver = {
+       .probe = acp5x_dai_probe,
+       .driver = {
+               .name = "acp5x_i2s_playcap",
+       },
+};
+
+module_platform_driver(acp5x_dai_driver);
+
+MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
+MODULE_DESCRIPTION("AMD ACP5.x CPU DAI Driver");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/vangogh/acp5x-pcm-dma.c b/sound/soc/amd/vangogh/acp5x-pcm-dma.c
new file mode 100644 (file)
index 0000000..f10de38
--- /dev/null
@@ -0,0 +1,517 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// AMD ALSA SoC PCM Driver
+//
+// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+
+#include "acp5x.h"
+
+#define DRV_NAME "acp5x_i2s_dma"
+
+static const struct snd_pcm_hardware acp5x_pcm_hardware_playback = {
+       .info = SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+       .formats = SNDRV_PCM_FMTBIT_S16_LE |  SNDRV_PCM_FMTBIT_S8 |
+                  SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+       .channels_min = 2,
+       .channels_max = 2,
+       .rates = SNDRV_PCM_RATE_8000_96000,
+       .rate_min = 8000,
+       .rate_max = 96000,
+       .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
+       .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
+       .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
+       .periods_min = PLAYBACK_MIN_NUM_PERIODS,
+       .periods_max = PLAYBACK_MAX_NUM_PERIODS,
+};
+
+static const struct snd_pcm_hardware acp5x_pcm_hardware_capture = {
+       .info = SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+       .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+                  SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+       .channels_min = 2,
+       .channels_max = 2,
+       .rates = SNDRV_PCM_RATE_8000_96000,
+       .rate_min = 8000,
+       .rate_max = 96000,
+       .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
+       .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
+       .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
+       .periods_min = CAPTURE_MIN_NUM_PERIODS,
+       .periods_max = CAPTURE_MAX_NUM_PERIODS,
+};
+
+static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
+{
+       struct i2s_dev_data *vg_i2s_data;
+       u16 irq_flag;
+       u32 val;
+
+       vg_i2s_data = dev_id;
+       if (!vg_i2s_data)
+               return IRQ_NONE;
+
+       irq_flag = 0;
+       val = acp_readl(vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT);
+       if ((val & BIT(HS_TX_THRESHOLD)) && vg_i2s_data->play_stream) {
+               acp_writel(BIT(HS_TX_THRESHOLD), vg_i2s_data->acp5x_base +
+                          ACP_EXTERNAL_INTR_STAT);
+               snd_pcm_period_elapsed(vg_i2s_data->play_stream);
+               irq_flag = 1;
+       }
+       if ((val & BIT(I2S_TX_THRESHOLD)) && vg_i2s_data->i2ssp_play_stream) {
+               acp_writel(BIT(I2S_TX_THRESHOLD),
+                          vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT);
+               snd_pcm_period_elapsed(vg_i2s_data->i2ssp_play_stream);
+               irq_flag = 1;
+       }
+
+       if ((val & BIT(HS_RX_THRESHOLD)) && vg_i2s_data->capture_stream) {
+               acp_writel(BIT(HS_RX_THRESHOLD), vg_i2s_data->acp5x_base +
+                          ACP_EXTERNAL_INTR_STAT);
+               snd_pcm_period_elapsed(vg_i2s_data->capture_stream);
+               irq_flag = 1;
+       }
+       if ((val & BIT(I2S_RX_THRESHOLD)) && vg_i2s_data->i2ssp_capture_stream) {
+               acp_writel(BIT(I2S_RX_THRESHOLD),
+                          vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT);
+               snd_pcm_period_elapsed(vg_i2s_data->i2ssp_capture_stream);
+               irq_flag = 1;
+       }
+
+       if (irq_flag)
+               return IRQ_HANDLED;
+       else
+               return IRQ_NONE;
+}
+
+static void config_acp5x_dma(struct i2s_stream_instance *rtd, int direction)
+{
+       u16 page_idx;
+       u32 low, high, val, acp_fifo_addr, reg_fifo_addr;
+       u32 reg_dma_size, reg_fifo_size;
+       dma_addr_t addr;
+
+       addr = rtd->dma_addr;
+       if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+               switch (rtd->i2s_instance) {
+               case I2S_HS_INSTANCE:
+                       val = ACP_SRAM_HS_PB_PTE_OFFSET;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       val = ACP_SRAM_SP_PB_PTE_OFFSET;
+               }
+       } else {
+               switch (rtd->i2s_instance) {
+               case I2S_HS_INSTANCE:
+                       val = ACP_SRAM_HS_CP_PTE_OFFSET;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       val = ACP_SRAM_SP_CP_PTE_OFFSET;
+               }
+       }
+       /* Group Enable */
+       acp_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp5x_base +
+                  ACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
+       acp_writel(PAGE_SIZE_4K_ENABLE, rtd->acp5x_base +
+                  ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
+
+       for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
+               /* Load the low address of page int ACP SRAM through SRBM */
+               low = lower_32_bits(addr);
+               high = upper_32_bits(addr);
+
+               acp_writel(low, rtd->acp5x_base + ACP_SCRATCH_REG_0 + val);
+               high |= BIT(31);
+               acp_writel(high, rtd->acp5x_base + ACP_SCRATCH_REG_0 + val + 4);
+               /* Move to next physically contiguous page */
+               val += 8;
+               addr += PAGE_SIZE;
+       }
+
+       if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+               switch (rtd->i2s_instance) {
+               case I2S_HS_INSTANCE:
+                       reg_dma_size = ACP_HS_TX_DMA_SIZE;
+                       acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+                                       HS_PB_FIFO_ADDR_OFFSET;
+                       reg_fifo_addr = ACP_HS_TX_FIFOADDR;
+                       reg_fifo_size = ACP_HS_TX_FIFOSIZE;
+                       acp_writel(I2S_HS_TX_MEM_WINDOW_START,
+                                  rtd->acp5x_base + ACP_HS_TX_RINGBUFADDR);
+                       break;
+
+               case I2S_SP_INSTANCE:
+               default:
+                       reg_dma_size = ACP_I2S_TX_DMA_SIZE;
+                       acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+                                       SP_PB_FIFO_ADDR_OFFSET;
+                       reg_fifo_addr = ACP_I2S_TX_FIFOADDR;
+                       reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
+                       acp_writel(I2S_SP_TX_MEM_WINDOW_START,
+                                  rtd->acp5x_base + ACP_I2S_TX_RINGBUFADDR);
+               }
+       } else {
+               switch (rtd->i2s_instance) {
+               case I2S_HS_INSTANCE:
+                       reg_dma_size = ACP_HS_RX_DMA_SIZE;
+                       acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+                                       HS_CAPT_FIFO_ADDR_OFFSET;
+                       reg_fifo_addr = ACP_HS_RX_FIFOADDR;
+                       reg_fifo_size = ACP_HS_RX_FIFOSIZE;
+                       acp_writel(I2S_HS_RX_MEM_WINDOW_START,
+                                  rtd->acp5x_base + ACP_HS_RX_RINGBUFADDR);
+                       break;
+
+               case I2S_SP_INSTANCE:
+               default:
+                       reg_dma_size = ACP_I2S_RX_DMA_SIZE;
+                       acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+                                       SP_CAPT_FIFO_ADDR_OFFSET;
+                       reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
+                       reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
+                       acp_writel(I2S_SP_RX_MEM_WINDOW_START,
+                                  rtd->acp5x_base + ACP_I2S_RX_RINGBUFADDR);
+               }
+       }
+       acp_writel(DMA_SIZE, rtd->acp5x_base + reg_dma_size);
+       acp_writel(acp_fifo_addr, rtd->acp5x_base + reg_fifo_addr);
+       acp_writel(FIFO_SIZE, rtd->acp5x_base + reg_fifo_size);
+       acp_writel(BIT(I2S_RX_THRESHOLD) | BIT(HS_RX_THRESHOLD)
+                  | BIT(I2S_TX_THRESHOLD) | BIT(HS_TX_THRESHOLD),
+                  rtd->acp5x_base + ACP_EXTERNAL_INTR_CNTL);
+}
+
+static int acp5x_dma_open(struct snd_soc_component *component,
+                         struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime;
+       struct snd_soc_pcm_runtime *prtd;
+       struct i2s_dev_data *adata;
+       struct i2s_stream_instance *i2s_data;
+       int ret;
+
+       runtime = substream->runtime;
+       prtd = asoc_substream_to_rtd(substream);
+       component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
+       adata = dev_get_drvdata(component->dev);
+
+       i2s_data = kzalloc(sizeof(*i2s_data), GFP_KERNEL);
+       if (!i2s_data)
+               return -ENOMEM;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               runtime->hw = acp5x_pcm_hardware_playback;
+       else
+               runtime->hw = acp5x_pcm_hardware_capture;
+
+       ret = snd_pcm_hw_constraint_integer(runtime,
+                                           SNDRV_PCM_HW_PARAM_PERIODS);
+       if (ret < 0) {
+               dev_err(component->dev, "set integer constraint failed\n");
+               kfree(i2s_data);
+               return ret;
+       }
+       i2s_data->acp5x_base = adata->acp5x_base;
+       runtime->private_data = i2s_data;
+       return ret;
+}
+
+static int acp5x_dma_hw_params(struct snd_soc_component *component,
+                              struct snd_pcm_substream *substream,
+                              struct snd_pcm_hw_params *params)
+{
+       struct i2s_stream_instance *rtd;
+       struct snd_soc_pcm_runtime *prtd;
+       struct snd_soc_card *card;
+       struct acp5x_platform_info *pinfo;
+       struct i2s_dev_data *adata;
+       u64 size;
+
+       prtd = asoc_substream_to_rtd(substream);
+       card = prtd->card;
+       pinfo = snd_soc_card_get_drvdata(card);
+       adata = dev_get_drvdata(component->dev);
+       rtd = substream->runtime->private_data;
+
+       if (!rtd)
+               return -EINVAL;
+
+       if (pinfo) {
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       rtd->i2s_instance = pinfo->play_i2s_instance;
+                       switch (rtd->i2s_instance) {
+                       case I2S_HS_INSTANCE:
+                               adata->play_stream = substream;
+                               break;
+                       case I2S_SP_INSTANCE:
+                       default:
+                               adata->i2ssp_play_stream = substream;
+                       }
+               } else {
+                       rtd->i2s_instance = pinfo->cap_i2s_instance;
+                       switch (rtd->i2s_instance) {
+                       case I2S_HS_INSTANCE:
+                               adata->capture_stream = substream;
+                               break;
+                       case I2S_SP_INSTANCE:
+                       default:
+                               adata->i2ssp_capture_stream = substream;
+                       }
+               }
+       } else {
+               dev_err(component->dev, "pinfo failed\n");
+               return -EINVAL;
+       }
+       size = params_buffer_bytes(params);
+       rtd->dma_addr = substream->dma_buffer.addr;
+       rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
+       config_acp5x_dma(rtd, substream->stream);
+       return 0;
+}
+
+static snd_pcm_uframes_t acp5x_dma_pointer(struct snd_soc_component *component,
+                                          struct snd_pcm_substream *substream)
+{
+       struct i2s_stream_instance *rtd;
+       u32 pos;
+       u32 buffersize;
+       u64 bytescount;
+
+       rtd = substream->runtime->private_data;
+       buffersize = frames_to_bytes(substream->runtime,
+                                    substream->runtime->buffer_size);
+       bytescount = acp_get_byte_count(rtd, substream->stream);
+       if (bytescount > rtd->bytescount)
+               bytescount -= rtd->bytescount;
+       pos = do_div(bytescount, buffersize);
+       return bytes_to_frames(substream->runtime, pos);
+}
+
+static int acp5x_dma_new(struct snd_soc_component *component,
+                        struct snd_soc_pcm_runtime *rtd)
+{
+       struct device *parent = component->dev->parent;
+
+       snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+                                      parent, MIN_BUFFER, MAX_BUFFER);
+       return 0;
+}
+
+static int acp5x_dma_close(struct snd_soc_component *component,
+                          struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *prtd;
+       struct i2s_dev_data *adata;
+       struct i2s_stream_instance *ins;
+
+       prtd = asoc_substream_to_rtd(substream);
+       component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
+       adata = dev_get_drvdata(component->dev);
+       ins = substream->runtime->private_data;
+       if (!ins)
+               return -EINVAL;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               switch (ins->i2s_instance) {
+               case I2S_HS_INSTANCE:
+                       adata->play_stream = NULL;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       adata->i2ssp_play_stream = NULL;
+               }
+       } else {
+               switch (ins->i2s_instance) {
+               case I2S_HS_INSTANCE:
+                       adata->capture_stream = NULL;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       adata->i2ssp_capture_stream = NULL;
+               }
+       }
+       kfree(ins);
+       return 0;
+}
+
+static const struct snd_soc_component_driver acp5x_i2s_component = {
+       .name           = DRV_NAME,
+       .open           = acp5x_dma_open,
+       .close          = acp5x_dma_close,
+       .hw_params      = acp5x_dma_hw_params,
+       .pointer        = acp5x_dma_pointer,
+       .pcm_construct  = acp5x_dma_new,
+};
+
+static int acp5x_audio_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct i2s_dev_data *adata;
+       unsigned int irqflags;
+       int status;
+
+       if (!pdev->dev.platform_data) {
+               dev_err(&pdev->dev, "platform_data not retrieved\n");
+               return -ENODEV;
+       }
+       irqflags = *((unsigned int *)(pdev->dev.platform_data));
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
+               return -ENODEV;
+       }
+
+       adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
+       if (!adata)
+               return -ENOMEM;
+
+       adata->acp5x_base = devm_ioremap(&pdev->dev, res->start,
+                                        resource_size(res));
+       if (!adata->acp5x_base)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
+               return -ENODEV;
+       }
+
+       adata->i2s_irq = res->start;
+       dev_set_drvdata(&pdev->dev, adata);
+       status = devm_snd_soc_register_component(&pdev->dev,
+                                                &acp5x_i2s_component,
+                                                NULL, 0);
+       if (status) {
+               dev_err(&pdev->dev, "Fail to register acp i2s component\n");
+               return status;
+       }
+       status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler,
+                                 irqflags, "ACP5x_I2S_IRQ", adata);
+       if (status) {
+               dev_err(&pdev->dev, "ACP5x I2S IRQ request failed\n");
+               return status;
+       }
+       pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_allow(&pdev->dev);
+
+       return 0;
+}
+
+static int acp5x_audio_remove(struct platform_device *pdev)
+{
+       pm_runtime_disable(&pdev->dev);
+       return 0;
+}
+
+static int __maybe_unused acp5x_pcm_resume(struct device *dev)
+{
+       struct i2s_dev_data *adata;
+       u32 val, reg_val, frmt_val;
+
+       reg_val = 0;
+       frmt_val = 0;
+       adata = dev_get_drvdata(dev);
+
+       if (adata->play_stream && adata->play_stream->runtime) {
+               struct i2s_stream_instance *rtd =
+                       adata->play_stream->runtime->private_data;
+               config_acp5x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK);
+               switch (rtd->i2s_instance) {
+               case I2S_HS_INSTANCE:
+                       reg_val = ACP_HSTDM_ITER;
+                       frmt_val = ACP_HSTDM_TXFRMT;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       reg_val = ACP_I2STDM_ITER;
+                       frmt_val = ACP_I2STDM_TXFRMT;
+               }
+               acp_writel((rtd->xfer_resolution  << 3),
+                          rtd->acp5x_base + reg_val);
+       }
+
+       if (adata->capture_stream && adata->capture_stream->runtime) {
+               struct i2s_stream_instance *rtd =
+                       adata->capture_stream->runtime->private_data;
+               config_acp5x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE);
+               switch (rtd->i2s_instance) {
+               case I2S_HS_INSTANCE:
+                       reg_val = ACP_HSTDM_IRER;
+                       frmt_val = ACP_HSTDM_RXFRMT;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       reg_val = ACP_I2STDM_IRER;
+                       frmt_val = ACP_I2STDM_RXFRMT;
+               }
+               acp_writel((rtd->xfer_resolution  << 3),
+                          rtd->acp5x_base + reg_val);
+       }
+       if (adata->tdm_mode == TDM_ENABLE) {
+               acp_writel(adata->tdm_fmt, adata->acp5x_base + frmt_val);
+               val = acp_readl(adata->acp5x_base + reg_val);
+               acp_writel(val | 0x2, adata->acp5x_base + reg_val);
+       }
+       acp_writel(1, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB);
+       return 0;
+}
+
+static int __maybe_unused acp5x_pcm_suspend(struct device *dev)
+{
+       struct i2s_dev_data *adata;
+
+       adata = dev_get_drvdata(dev);
+       acp_writel(0, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB);
+       return 0;
+}
+
+static int __maybe_unused acp5x_pcm_runtime_resume(struct device *dev)
+{
+       struct i2s_dev_data *adata;
+
+       adata = dev_get_drvdata(dev);
+       acp_writel(1, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB);
+       return 0;
+}
+
+static const struct dev_pm_ops acp5x_pm_ops = {
+       SET_RUNTIME_PM_OPS(acp5x_pcm_suspend,
+                          acp5x_pcm_runtime_resume, NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(acp5x_pcm_suspend, acp5x_pcm_resume)
+};
+
+static struct platform_driver acp5x_dma_driver = {
+       .probe = acp5x_audio_probe,
+       .remove = acp5x_audio_remove,
+       .driver = {
+               .name = "acp5x_i2s_dma",
+               .pm = &acp5x_pm_ops,
+       },
+};
+
+module_platform_driver(acp5x_dma_driver);
+
+MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
+MODULE_DESCRIPTION("AMD ACP 5.x PCM Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/vangogh/acp5x.h b/sound/soc/amd/vangogh/acp5x.h
new file mode 100644 (file)
index 0000000..a808635
--- /dev/null
@@ -0,0 +1,193 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * AMD ALSA SoC PCM Driver
+ *
+ * Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
+ */
+
+#include "vg_chip_offset_byte.h"
+#include <sound/pcm.h>
+
+#define ACP5x_PHY_BASE_ADDRESS 0x1240000
+#define ACP_DEVICE_ID 0x15E2
+#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK  0x00010001
+
+#define ACP_PGFSM_CNTL_POWER_ON_MASK   0x01
+#define ACP_PGFSM_CNTL_POWER_OFF_MASK  0x00
+#define ACP_PGFSM_STATUS_MASK          0x03
+#define ACP_POWERED_ON                 0x00
+#define ACP_POWER_ON_IN_PROGRESS       0x01
+#define ACP_POWERED_OFF                        0x02
+#define ACP_POWER_OFF_IN_PROGRESS      0x03
+
+#define ACP_ERR_INTR_MASK      0x20000000
+#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
+
+#define ACP5x_DEVS 3
+#define        ACP5x_REG_START 0x1240000
+#define        ACP5x_REG_END   0x1250200
+#define ACP5x_I2STDM_REG_START 0x1242400
+#define ACP5x_I2STDM_REG_END   0x1242410
+#define ACP5x_HS_TDM_REG_START 0x1242814
+#define ACP5x_HS_TDM_REG_END   0x1242824
+#define I2S_MODE 0
+#define ACP5x_I2S_MODE 1
+#define ACP5x_RES 4
+#define        I2S_RX_THRESHOLD 27
+#define        I2S_TX_THRESHOLD 28
+#define        HS_TX_THRESHOLD 24
+#define        HS_RX_THRESHOLD 23
+
+#define I2S_SP_INSTANCE                 1
+#define I2S_HS_INSTANCE                 2
+
+#define ACP_SRAM_PTE_OFFSET    0x02050000
+#define ACP_SRAM_SP_PB_PTE_OFFSET      0x0
+#define ACP_SRAM_SP_CP_PTE_OFFSET      0x100
+#define ACP_SRAM_HS_PB_PTE_OFFSET      0x200
+#define ACP_SRAM_HS_CP_PTE_OFFSET      0x300
+#define PAGE_SIZE_4K_ENABLE 0x2
+#define I2S_SP_TX_MEM_WINDOW_START     0x4000000
+#define I2S_SP_RX_MEM_WINDOW_START     0x4020000
+#define I2S_HS_TX_MEM_WINDOW_START     0x4040000
+#define I2S_HS_RX_MEM_WINDOW_START     0x4060000
+
+#define SP_PB_FIFO_ADDR_OFFSET         0x500
+#define SP_CAPT_FIFO_ADDR_OFFSET       0x700
+#define HS_PB_FIFO_ADDR_OFFSET         0x900
+#define HS_CAPT_FIFO_ADDR_OFFSET       0xB00
+#define PLAYBACK_MIN_NUM_PERIODS    2
+#define PLAYBACK_MAX_NUM_PERIODS    8
+#define PLAYBACK_MAX_PERIOD_SIZE    8192
+#define PLAYBACK_MIN_PERIOD_SIZE    1024
+#define CAPTURE_MIN_NUM_PERIODS     2
+#define CAPTURE_MAX_NUM_PERIODS     8
+#define CAPTURE_MAX_PERIOD_SIZE     8192
+#define CAPTURE_MIN_PERIOD_SIZE     1024
+
+#define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS)
+#define MIN_BUFFER MAX_BUFFER
+#define FIFO_SIZE 0x100
+#define DMA_SIZE 0x40
+#define FRM_LEN 0x100
+
+#define I2S_MASTER_MODE_ENABLE 1
+#define I2S_MASTER_MODE_DISABLE 0
+
+#define SLOT_WIDTH_8 8
+#define SLOT_WIDTH_16 16
+#define SLOT_WIDTH_24 24
+#define SLOT_WIDTH_32 32
+#define TDM_ENABLE 1
+#define TDM_DISABLE 0
+#define ACP5x_ITER_IRER_SAMP_LEN_MASK  0x38
+
+struct i2s_dev_data {
+       bool tdm_mode;
+       bool master_mode;
+       unsigned int i2s_irq;
+       u16 i2s_instance;
+       u32 tdm_fmt;
+       void __iomem *acp5x_base;
+       struct snd_pcm_substream *play_stream;
+       struct snd_pcm_substream *capture_stream;
+       struct snd_pcm_substream *i2ssp_play_stream;
+       struct snd_pcm_substream *i2ssp_capture_stream;
+};
+
+struct i2s_stream_instance {
+       u16 num_pages;
+       u16 i2s_instance;
+       u16 direction;
+       u16 channels;
+       u32 xfer_resolution;
+       u32 val;
+       dma_addr_t dma_addr;
+       u64 bytescount;
+       void __iomem *acp5x_base;
+};
+
+union acp_dma_count {
+       struct {
+               u32 low;
+               u32 high;
+       } bcount;
+       u64 bytescount;
+};
+
+struct acp5x_platform_info {
+       u16 play_i2s_instance;
+       u16 cap_i2s_instance;
+};
+
+union acp_i2stdm_mstrclkgen {
+       struct {
+               u32 i2stdm_master_mode : 1;
+               u32 i2stdm_format_mode : 1;
+               u32 i2stdm_lrclk_div_val : 9;
+               u32 i2stdm_bclk_div_val : 11;
+               u32:10;
+       } bitfields, bits;
+       u32  u32_all;
+};
+
+/* common header file uses exact offset rather than relative
+ * offset which requires subtraction logic from base_addr
+ * for accessing ACP5x MMIO space registers
+ */
+static inline u32 acp_readl(void __iomem *base_addr)
+{
+       return readl(base_addr - ACP5x_PHY_BASE_ADDRESS);
+}
+
+static inline void acp_writel(u32 val, void __iomem *base_addr)
+{
+       writel(val, base_addr - ACP5x_PHY_BASE_ADDRESS);
+}
+
+static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd,
+                                    int direction)
+{
+       union acp_dma_count byte_count;
+
+       if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+               switch (rtd->i2s_instance) {
+               case I2S_HS_INSTANCE:
+                       byte_count.bcount.high =
+                               acp_readl(rtd->acp5x_base +
+                                         ACP_HS_TX_LINEARPOSCNTR_HIGH);
+                       byte_count.bcount.low =
+                               acp_readl(rtd->acp5x_base +
+                                         ACP_HS_TX_LINEARPOSCNTR_LOW);
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       byte_count.bcount.high =
+                               acp_readl(rtd->acp5x_base +
+                                         ACP_I2S_TX_LINEARPOSCNTR_HIGH);
+                       byte_count.bcount.low =
+                               acp_readl(rtd->acp5x_base +
+                                         ACP_I2S_TX_LINEARPOSCNTR_LOW);
+               }
+       } else {
+               switch (rtd->i2s_instance) {
+               case I2S_HS_INSTANCE:
+                       byte_count.bcount.high =
+                               acp_readl(rtd->acp5x_base +
+                                         ACP_HS_RX_LINEARPOSCNTR_HIGH);
+                       byte_count.bcount.low =
+                               acp_readl(rtd->acp5x_base +
+                                         ACP_HS_RX_LINEARPOSCNTR_LOW);
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       byte_count.bcount.high =
+                               acp_readl(rtd->acp5x_base +
+                                         ACP_I2S_RX_LINEARPOSCNTR_HIGH);
+                       byte_count.bcount.low =
+                               acp_readl(rtd->acp5x_base +
+                                         ACP_I2S_RX_LINEARPOSCNTR_LOW);
+               }
+       }
+       return byte_count.bytescount;
+}
diff --git a/sound/soc/amd/vangogh/pci-acp5x.c b/sound/soc/amd/vangogh/pci-acp5x.c
new file mode 100644 (file)
index 0000000..a57b762
--- /dev/null
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// AMD Vangogh ACP PCI Driver
+//
+// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
+
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+
+#include "acp5x.h"
+
+struct acp5x_dev_data {
+       void __iomem *acp5x_base;
+       bool acp5x_audio_mode;
+       struct resource *res;
+       struct platform_device *pdev[ACP5x_DEVS];
+};
+
+static int acp5x_power_on(void __iomem *acp5x_base)
+{
+       u32 val;
+       int timeout;
+
+       val = acp_readl(acp5x_base + ACP_PGFSM_STATUS);
+
+       if (val == 0)
+               return val;
+
+       if ((val & ACP_PGFSM_STATUS_MASK) !=
+                               ACP_POWER_ON_IN_PROGRESS)
+               acp_writel(ACP_PGFSM_CNTL_POWER_ON_MASK,
+                          acp5x_base + ACP_PGFSM_CONTROL);
+       timeout = 0;
+       while (++timeout < 500) {
+               val = acp_readl(acp5x_base + ACP_PGFSM_STATUS);
+               if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_ON)
+                       return 0;
+               udelay(1);
+       }
+       return -ETIMEDOUT;
+}
+
+static int acp5x_reset(void __iomem *acp5x_base)
+{
+       u32 val;
+       int timeout;
+
+       acp_writel(1, acp5x_base + ACP_SOFT_RESET);
+       timeout = 0;
+       while (++timeout < 500) {
+               val = acp_readl(acp5x_base + ACP_SOFT_RESET);
+               if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK)
+                       break;
+               cpu_relax();
+       }
+       acp_writel(0, acp5x_base + ACP_SOFT_RESET);
+       timeout = 0;
+       while (++timeout < 500) {
+               val = acp_readl(acp5x_base + ACP_SOFT_RESET);
+               if (!val)
+                       return 0;
+               cpu_relax();
+       }
+       return -ETIMEDOUT;
+}
+
+static void acp5x_enable_interrupts(void __iomem *acp5x_base)
+{
+       acp_writel(0x01, acp5x_base + ACP_EXTERNAL_INTR_ENB);
+}
+
+static void acp5x_disable_interrupts(void __iomem *acp5x_base)
+{
+       acp_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp5x_base +
+                  ACP_EXTERNAL_INTR_STAT);
+       acp_writel(0x00, acp5x_base + ACP_EXTERNAL_INTR_CNTL);
+       acp_writel(0x00, acp5x_base + ACP_EXTERNAL_INTR_ENB);
+}
+
+static int acp5x_init(void __iomem *acp5x_base)
+{
+       int ret;
+
+       /* power on */
+       ret = acp5x_power_on(acp5x_base);
+       if (ret) {
+               pr_err("ACP5x power on failed\n");
+               return ret;
+       }
+       /* Reset */
+       ret = acp5x_reset(acp5x_base);
+       if (ret) {
+               pr_err("ACP5x reset failed\n");
+               return ret;
+       }
+       acp5x_enable_interrupts(acp5x_base);
+       return 0;
+}
+
+static int acp5x_deinit(void __iomem *acp5x_base)
+{
+       int ret;
+
+       acp5x_disable_interrupts(acp5x_base);
+       /* Reset */
+       ret = acp5x_reset(acp5x_base);
+       if (ret) {
+               pr_err("ACP5x reset failed\n");
+               return ret;
+       }
+       return 0;
+}
+
+static int snd_acp5x_probe(struct pci_dev *pci,
+                          const struct pci_device_id *pci_id)
+{
+       struct acp5x_dev_data *adata;
+       struct platform_device_info pdevinfo[ACP5x_DEVS];
+       unsigned int irqflags;
+       int ret, i;
+       u32 addr, val;
+
+       irqflags = IRQF_SHARED;
+       if (pci->revision != 0x50)
+               return -ENODEV;
+
+       if (pci_enable_device(pci)) {
+               dev_err(&pci->dev, "pci_enable_device failed\n");
+               return -ENODEV;
+       }
+
+       ret = pci_request_regions(pci, "AMD ACP5x audio");
+       if (ret < 0) {
+               dev_err(&pci->dev, "pci_request_regions failed\n");
+               goto disable_pci;
+       }
+
+       adata = devm_kzalloc(&pci->dev, sizeof(struct acp5x_dev_data),
+                            GFP_KERNEL);
+       if (!adata) {
+               ret = -ENOMEM;
+               goto release_regions;
+       }
+       addr = pci_resource_start(pci, 0);
+       adata->acp5x_base = devm_ioremap(&pci->dev, addr,
+                                        pci_resource_len(pci, 0));
+       if (!adata->acp5x_base) {
+               ret = -ENOMEM;
+               goto release_regions;
+       }
+       pci_set_master(pci);
+       pci_set_drvdata(pci, adata);
+       ret = acp5x_init(adata->acp5x_base);
+       if (ret)
+               goto release_regions;
+
+       val = acp_readl(adata->acp5x_base + ACP_PIN_CONFIG);
+       switch (val) {
+       case I2S_MODE:
+               adata->res = devm_kzalloc(&pci->dev,
+                                         sizeof(struct resource) * ACP5x_RES,
+                                         GFP_KERNEL);
+               if (!adata->res) {
+                       ret = -ENOMEM;
+                       goto de_init;
+               }
+
+               adata->res[0].name = "acp5x_i2s_iomem";
+               adata->res[0].flags = IORESOURCE_MEM;
+               adata->res[0].start = addr;
+               adata->res[0].end = addr + (ACP5x_REG_END - ACP5x_REG_START);
+
+               adata->res[1].name = "acp5x_i2s_sp";
+               adata->res[1].flags = IORESOURCE_MEM;
+               adata->res[1].start = addr + ACP5x_I2STDM_REG_START;
+               adata->res[1].end = addr + ACP5x_I2STDM_REG_END;
+
+               adata->res[2].name = "acp5x_i2s_hs";
+               adata->res[2].flags = IORESOURCE_MEM;
+               adata->res[2].start = addr + ACP5x_HS_TDM_REG_START;
+               adata->res[2].end = addr + ACP5x_HS_TDM_REG_END;
+
+               adata->res[3].name = "acp5x_i2s_irq";
+               adata->res[3].flags = IORESOURCE_IRQ;
+               adata->res[3].start = pci->irq;
+               adata->res[3].end = adata->res[3].start;
+
+               adata->acp5x_audio_mode = ACP5x_I2S_MODE;
+
+               memset(&pdevinfo, 0, sizeof(pdevinfo));
+               pdevinfo[0].name = "acp5x_i2s_dma";
+               pdevinfo[0].id = 0;
+               pdevinfo[0].parent = &pci->dev;
+               pdevinfo[0].num_res = 4;
+               pdevinfo[0].res = &adata->res[0];
+               pdevinfo[0].data = &irqflags;
+               pdevinfo[0].size_data = sizeof(irqflags);
+
+               pdevinfo[1].name = "acp5x_i2s_playcap";
+               pdevinfo[1].id = 0;
+               pdevinfo[1].parent = &pci->dev;
+               pdevinfo[1].num_res = 1;
+               pdevinfo[1].res = &adata->res[1];
+
+               pdevinfo[2].name = "acp5x_i2s_playcap";
+               pdevinfo[2].id = 1;
+               pdevinfo[2].parent = &pci->dev;
+               pdevinfo[2].num_res = 1;
+               pdevinfo[2].res = &adata->res[2];
+
+               for (i = 0; i < ACP5x_DEVS; i++) {
+                       adata->pdev[i] =
+                               platform_device_register_full(&pdevinfo[i]);
+                       if (IS_ERR(adata->pdev[i])) {
+                               dev_err(&pci->dev, "cannot register %s device\n",
+                                       pdevinfo[i].name);
+                               ret = PTR_ERR(adata->pdev[i]);
+                               goto unregister_devs;
+                       }
+               }
+               break;
+       default:
+               dev_info(&pci->dev, "ACP audio mode : %d\n", val);
+       }
+       pm_runtime_set_autosuspend_delay(&pci->dev, 2000);
+       pm_runtime_use_autosuspend(&pci->dev);
+       pm_runtime_put_noidle(&pci->dev);
+       pm_runtime_allow(&pci->dev);
+       return 0;
+
+unregister_devs:
+       for (--i; i >= 0; i--)
+               platform_device_unregister(adata->pdev[i]);
+de_init:
+       if (acp5x_deinit(adata->acp5x_base))
+               dev_err(&pci->dev, "ACP de-init failed\n");
+release_regions:
+       pci_release_regions(pci);
+disable_pci:
+       pci_disable_device(pci);
+
+       return ret;
+}
+
+static int __maybe_unused snd_acp5x_suspend(struct device *dev)
+{
+       int ret;
+       struct acp5x_dev_data *adata;
+
+       adata = dev_get_drvdata(dev);
+       ret = acp5x_deinit(adata->acp5x_base);
+       if (ret)
+               dev_err(dev, "ACP de-init failed\n");
+       else
+               dev_dbg(dev, "ACP de-initialized\n");
+
+       return ret;
+}
+
+static int __maybe_unused snd_acp5x_resume(struct device *dev)
+{
+       int ret;
+       struct acp5x_dev_data *adata;
+
+       adata = dev_get_drvdata(dev);
+       ret = acp5x_init(adata->acp5x_base);
+       if (ret) {
+               dev_err(dev, "ACP init failed\n");
+               return ret;
+       }
+       return 0;
+}
+
+static const struct dev_pm_ops acp5x_pm = {
+       SET_RUNTIME_PM_OPS(snd_acp5x_suspend,
+                          snd_acp5x_resume, NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(snd_acp5x_suspend, snd_acp5x_resume)
+};
+
+static void snd_acp5x_remove(struct pci_dev *pci)
+{
+       struct acp5x_dev_data *adata;
+       int i, ret;
+
+       adata = pci_get_drvdata(pci);
+       if (adata->acp5x_audio_mode == ACP5x_I2S_MODE) {
+               for (i = 0; i < ACP5x_DEVS; i++)
+                       platform_device_unregister(adata->pdev[i]);
+       }
+       ret = acp5x_deinit(adata->acp5x_base);
+       if (ret)
+               dev_err(&pci->dev, "ACP de-init failed\n");
+       pm_runtime_forbid(&pci->dev);
+       pm_runtime_get_noresume(&pci->dev);
+       pci_release_regions(pci);
+       pci_disable_device(pci);
+}
+
+static const struct pci_device_id snd_acp5x_ids[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID),
+       .class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
+       .class_mask = 0xffffff },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, snd_acp5x_ids);
+
+static struct pci_driver acp5x_driver  = {
+       .name = KBUILD_MODNAME,
+       .id_table = snd_acp5x_ids,
+       .probe = snd_acp5x_probe,
+       .remove = snd_acp5x_remove,
+       .driver = {
+               .pm = &acp5x_pm,
+       }
+};
+
+module_pci_driver(acp5x_driver);
+
+MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
+MODULE_DESCRIPTION("AMD Vangogh ACP PCI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/vangogh/vg_chip_offset_byte.h b/sound/soc/amd/vangogh/vg_chip_offset_byte.h
new file mode 100644 (file)
index 0000000..b1165ae
--- /dev/null
@@ -0,0 +1,337 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * AMD ACP 5.x Register Documentation
+ *
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _acp_ip_OFFSET_HEADER
+#define _acp_ip_OFFSET_HEADER
+
+/* Registers from ACP_DMA block */
+#define ACP_DMA_CNTL_0                                0x1240000
+#define ACP_DMA_CNTL_1                                0x1240004
+#define ACP_DMA_CNTL_2                                0x1240008
+#define ACP_DMA_CNTL_3                                0x124000C
+#define ACP_DMA_CNTL_4                                0x1240010
+#define ACP_DMA_CNTL_5                                0x1240014
+#define ACP_DMA_CNTL_6                                0x1240018
+#define ACP_DMA_CNTL_7                                0x124001C
+#define ACP_DMA_DSCR_STRT_IDX_0                       0x1240020
+#define ACP_DMA_DSCR_STRT_IDX_1                       0x1240024
+#define ACP_DMA_DSCR_STRT_IDX_2                       0x1240028
+#define ACP_DMA_DSCR_STRT_IDX_3                       0x124002C
+#define ACP_DMA_DSCR_STRT_IDX_4                       0x1240030
+#define ACP_DMA_DSCR_STRT_IDX_5                       0x1240034
+#define ACP_DMA_DSCR_STRT_IDX_6                       0x1240038
+#define ACP_DMA_DSCR_STRT_IDX_7                       0x124003C
+#define ACP_DMA_DSCR_CNT_0                            0x1240040
+#define ACP_DMA_DSCR_CNT_1                            0x1240044
+#define ACP_DMA_DSCR_CNT_2                            0x1240048
+#define ACP_DMA_DSCR_CNT_3                            0x124004C
+#define ACP_DMA_DSCR_CNT_4                            0x1240050
+#define ACP_DMA_DSCR_CNT_5                            0x1240054
+#define ACP_DMA_DSCR_CNT_6                            0x1240058
+#define ACP_DMA_DSCR_CNT_7                            0x124005C
+#define ACP_DMA_PRIO_0                                0x1240060
+#define ACP_DMA_PRIO_1                                0x1240064
+#define ACP_DMA_PRIO_2                                0x1240068
+#define ACP_DMA_PRIO_3                                0x124006C
+#define ACP_DMA_PRIO_4                                0x1240070
+#define ACP_DMA_PRIO_5                                0x1240074
+#define ACP_DMA_PRIO_6                                0x1240078
+#define ACP_DMA_PRIO_7                                0x124007C
+#define ACP_DMA_CUR_DSCR_0                            0x1240080
+#define ACP_DMA_CUR_DSCR_1                            0x1240084
+#define ACP_DMA_CUR_DSCR_2                            0x1240088
+#define ACP_DMA_CUR_DSCR_3                            0x124008C
+#define ACP_DMA_CUR_DSCR_4                            0x1240090
+#define ACP_DMA_CUR_DSCR_5                            0x1240094
+#define ACP_DMA_CUR_DSCR_6                            0x1240098
+#define ACP_DMA_CUR_DSCR_7                            0x124009C
+#define ACP_DMA_CUR_TRANS_CNT_0                       0x12400A0
+#define ACP_DMA_CUR_TRANS_CNT_1                       0x12400A4
+#define ACP_DMA_CUR_TRANS_CNT_2                       0x12400A8
+#define ACP_DMA_CUR_TRANS_CNT_3                       0x12400AC
+#define ACP_DMA_CUR_TRANS_CNT_4                       0x12400B0
+#define ACP_DMA_CUR_TRANS_CNT_5                       0x12400B4
+#define ACP_DMA_CUR_TRANS_CNT_6                       0x12400B8
+#define ACP_DMA_CUR_TRANS_CNT_7                       0x12400BC
+#define ACP_DMA_ERR_STS_0                             0x12400C0
+#define ACP_DMA_ERR_STS_1                             0x12400C4
+#define ACP_DMA_ERR_STS_2                             0x12400C8
+#define ACP_DMA_ERR_STS_3                             0x12400CC
+#define ACP_DMA_ERR_STS_4                             0x12400D0
+#define ACP_DMA_ERR_STS_5                             0x12400D4
+#define ACP_DMA_ERR_STS_6                             0x12400D8
+#define ACP_DMA_ERR_STS_7                             0x12400DC
+#define ACP_DMA_DESC_BASE_ADDR                        0x12400E0
+#define ACP_DMA_DESC_MAX_NUM_DSCR                     0x12400E4
+#define ACP_DMA_CH_STS                                0x12400E8
+#define ACP_DMA_CH_GROUP                              0x12400EC
+#define ACP_DMA_CH_RST_STS                            0x12400F0
+
+/* Registers from ACP_AXI2AXIATU block */
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1                0x1240C00
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1                0x1240C04
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2                0x1240C08
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2                0x1240C0C
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3                0x1240C10
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_3                0x1240C14
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4                0x1240C18
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_4                0x1240C1C
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5                0x1240C20
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5                0x1240C24
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6                0x1240C28
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_6                0x1240C2C
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7                0x1240C30
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_7                0x1240C34
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8                0x1240C38
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_8                0x1240C3C
+#define ACPAXI2AXI_ATU_CTRL                           0x1240C40
+
+/*  Registers from ACP_CLKRST block */
+#define ACP_SOFT_RESET                                0x1241000
+#define ACP_CONTROL                                   0x1241004
+#define ACP_STATUS                                    0x1241008
+#define ACP_DYNAMIC_CG_MASTER_CONTROL                 0x1241010
+
+/* Registers from ACP_MISC block */
+#define ACP_EXTERNAL_INTR_ENB                         0x1241800
+#define ACP_EXTERNAL_INTR_CNTL                        0x1241804
+#define ACP_EXTERNAL_INTR_STAT                        0x1241808
+#define ACP_ERROR_STATUS                              0x12418C4
+#define ACP_SW_I2S_ERROR_REASON                       0x12418C8
+#define ACP_MEM_PG_STS                                0x12418CC
+#define ACP_PGMEM_DEEP_SLEEP_CTRL                     0x12418D0
+#define ACP_PGMEM_SHUT_DOWN_CTRL                      0x12418D4
+
+/* Registers from ACP_PGFSM block */
+#define ACP_PIN_CONFIG                                0x1241400
+#define ACP_PAD_PULLUP_CTRL                           0x1241404
+#define ACP_PAD_PULLDOWN_CTRL                         0x1241408
+#define ACP_PAD_DRIVE_STRENGTH_CTRL                   0x124140C
+#define ACP_PAD_SCHMEN_CTRL                           0x1241410
+#define ACP_SW_PAD_KEEPER_EN                          0x1241414
+#define ACP_SW_WAKE_EN                                0x1241418
+#define ACP_I2S_WAKE_EN                               0x124141C
+#define ACP_PME_EN                                    0x1241420
+#define ACP_PGFSM_CONTROL                             0x1241424
+#define ACP_PGFSM_STATUS                              0x1241428
+#define ACP_CLKMUX_SEL                                0x124142C
+#define ACP_DEVICE_STATE                              0x1241430
+#define AZ_DEVICE_STATE                               0x1241434
+#define ACP_INTR_URGENCY_TIMER                        0x1241438
+#define AZ_INTR_URGENCY_TIMER                         0x124143C
+#define ACP_AON_SW_INTR_TRIG                          0x1241440
+
+/* Registers from ACP_SCRATCH block */
+#define ACP_SCRATCH_REG_0                             0x1250000
+#define ACP_SCRATCH_REG_1                             0x1250004
+#define ACP_SCRATCH_REG_2                             0x1250008
+#define ACP_SCRATCH_REG_3                             0x125000C
+#define ACP_SCRATCH_REG_4                             0x1250010
+#define ACP_SCRATCH_REG_5                             0x1250014
+#define ACP_SCRATCH_REG_6                             0x1250018
+#define ACP_SCRATCH_REG_7                             0x125001C
+#define ACP_SCRATCH_REG_8                             0x1250020
+#define ACP_SCRATCH_REG_9                             0x1250024
+#define ACP_SCRATCH_REG_10                            0x1250028
+#define ACP_SCRATCH_REG_11                            0x125002C
+#define ACP_SCRATCH_REG_12                            0x1250030
+#define ACP_SCRATCH_REG_13                            0x1250034
+#define ACP_SCRATCH_REG_14                            0x1250038
+#define ACP_SCRATCH_REG_15                            0x125003C
+#define ACP_SCRATCH_REG_16                            0x1250040
+#define ACP_SCRATCH_REG_17                            0x1250044
+#define ACP_SCRATCH_REG_18                            0x1250048
+#define ACP_SCRATCH_REG_19                            0x125004C
+#define ACP_SCRATCH_REG_20                            0x1250050
+#define ACP_SCRATCH_REG_21                            0x1250054
+#define ACP_SCRATCH_REG_22                            0x1250058
+#define ACP_SCRATCH_REG_23                            0x125005C
+#define ACP_SCRATCH_REG_24                            0x1250060
+#define ACP_SCRATCH_REG_25                            0x1250064
+#define ACP_SCRATCH_REG_26                            0x1250068
+#define ACP_SCRATCH_REG_27                            0x125006C
+#define ACP_SCRATCH_REG_28                            0x1250070
+#define ACP_SCRATCH_REG_29                            0x1250074
+#define ACP_SCRATCH_REG_30                            0x1250078
+#define ACP_SCRATCH_REG_31                            0x125007C
+#define ACP_SCRATCH_REG_32                            0x1250080
+#define ACP_SCRATCH_REG_33                            0x1250084
+#define ACP_SCRATCH_REG_34                            0x1250088
+#define ACP_SCRATCH_REG_35                            0x125008C
+#define ACP_SCRATCH_REG_36                            0x1250090
+#define ACP_SCRATCH_REG_37                            0x1250094
+#define ACP_SCRATCH_REG_38                            0x1250098
+#define ACP_SCRATCH_REG_39                            0x125009C
+#define ACP_SCRATCH_REG_40                            0x12500A0
+#define ACP_SCRATCH_REG_41                            0x12500A4
+#define ACP_SCRATCH_REG_42                            0x12500A8
+#define ACP_SCRATCH_REG_43                            0x12500AC
+#define ACP_SCRATCH_REG_44                            0x12500B0
+#define ACP_SCRATCH_REG_45                            0x12500B4
+#define ACP_SCRATCH_REG_46                            0x12500B8
+#define ACP_SCRATCH_REG_47                            0x12500BC
+#define ACP_SCRATCH_REG_48                            0x12500C0
+#define ACP_SCRATCH_REG_49                            0x12500C4
+#define ACP_SCRATCH_REG_50                            0x12500C8
+#define ACP_SCRATCH_REG_51                            0x12500CC
+#define ACP_SCRATCH_REG_52                            0x12500D0
+#define ACP_SCRATCH_REG_53                            0x12500D4
+#define ACP_SCRATCH_REG_54                            0x12500D8
+#define ACP_SCRATCH_REG_55                            0x12500DC
+#define ACP_SCRATCH_REG_56                            0x12500E0
+#define ACP_SCRATCH_REG_57                            0x12500E4
+#define ACP_SCRATCH_REG_58                            0x12500E8
+#define ACP_SCRATCH_REG_59                            0x12500EC
+#define ACP_SCRATCH_REG_60                            0x12500F0
+#define ACP_SCRATCH_REG_61                            0x12500F4
+#define ACP_SCRATCH_REG_62                            0x12500F8
+#define ACP_SCRATCH_REG_63                            0x12500FC
+#define ACP_SCRATCH_REG_64                            0x1250100
+#define ACP_SCRATCH_REG_65                            0x1250104
+#define ACP_SCRATCH_REG_66                            0x1250108
+#define ACP_SCRATCH_REG_67                            0x125010C
+#define ACP_SCRATCH_REG_68                            0x1250110
+#define ACP_SCRATCH_REG_69                            0x1250114
+#define ACP_SCRATCH_REG_70                            0x1250118
+#define ACP_SCRATCH_REG_71                            0x125011C
+#define ACP_SCRATCH_REG_72                            0x1250120
+#define ACP_SCRATCH_REG_73                            0x1250124
+#define ACP_SCRATCH_REG_74                            0x1250128
+#define ACP_SCRATCH_REG_75                            0x125012C
+#define ACP_SCRATCH_REG_76                            0x1250130
+#define ACP_SCRATCH_REG_77                            0x1250134
+#define ACP_SCRATCH_REG_78                            0x1250138
+#define ACP_SCRATCH_REG_79                            0x125013C
+#define ACP_SCRATCH_REG_80                            0x1250140
+#define ACP_SCRATCH_REG_81                            0x1250144
+#define ACP_SCRATCH_REG_82                            0x1250148
+#define ACP_SCRATCH_REG_83                            0x125014C
+#define ACP_SCRATCH_REG_84                            0x1250150
+#define ACP_SCRATCH_REG_85                            0x1250154
+#define ACP_SCRATCH_REG_86                            0x1250158
+#define ACP_SCRATCH_REG_87                            0x125015C
+#define ACP_SCRATCH_REG_88                            0x1250160
+#define ACP_SCRATCH_REG_89                            0x1250164
+#define ACP_SCRATCH_REG_90                            0x1250168
+#define ACP_SCRATCH_REG_91                            0x125016C
+#define ACP_SCRATCH_REG_92                            0x1250170
+#define ACP_SCRATCH_REG_93                            0x1250174
+#define ACP_SCRATCH_REG_94                            0x1250178
+#define ACP_SCRATCH_REG_95                            0x125017C
+#define ACP_SCRATCH_REG_96                            0x1250180
+#define ACP_SCRATCH_REG_97                            0x1250184
+#define ACP_SCRATCH_REG_98                            0x1250188
+#define ACP_SCRATCH_REG_99                            0x125018C
+#define ACP_SCRATCH_REG_100                           0x1250190
+#define ACP_SCRATCH_REG_101                           0x1250194
+#define ACP_SCRATCH_REG_102                           0x1250198
+#define ACP_SCRATCH_REG_103                           0x125019C
+#define ACP_SCRATCH_REG_104                           0x12501A0
+#define ACP_SCRATCH_REG_105                           0x12501A4
+#define ACP_SCRATCH_REG_106                           0x12501A8
+#define ACP_SCRATCH_REG_107                           0x12501AC
+#define ACP_SCRATCH_REG_108                           0x12501B0
+#define ACP_SCRATCH_REG_109                           0x12501B4
+#define ACP_SCRATCH_REG_110                           0x12501B8
+#define ACP_SCRATCH_REG_111                           0x12501BC
+#define ACP_SCRATCH_REG_112                           0x12501C0
+#define ACP_SCRATCH_REG_113                           0x12501C4
+#define ACP_SCRATCH_REG_114                           0x12501C8
+#define ACP_SCRATCH_REG_115                           0x12501CC
+#define ACP_SCRATCH_REG_116                           0x12501D0
+#define ACP_SCRATCH_REG_117                           0x12501D4
+#define ACP_SCRATCH_REG_118                           0x12501D8
+#define ACP_SCRATCH_REG_119                           0x12501DC
+#define ACP_SCRATCH_REG_120                           0x12501E0
+#define ACP_SCRATCH_REG_121                           0x12501E4
+#define ACP_SCRATCH_REG_122                           0x12501E8
+#define ACP_SCRATCH_REG_123                           0x12501EC
+#define ACP_SCRATCH_REG_124                           0x12501F0
+#define ACP_SCRATCH_REG_125                           0x12501F4
+#define ACP_SCRATCH_REG_126                           0x12501F8
+#define ACP_SCRATCH_REG_127                           0x12501FC
+#define ACP_SCRATCH_REG_128                           0x1250200
+
+/* Registers from ACP_AUDIO_BUFFERS block */
+#define ACP_I2S_RX_RINGBUFADDR                        0x1242000
+#define ACP_I2S_RX_RINGBUFSIZE                        0x1242004
+#define ACP_I2S_RX_LINKPOSITIONCNTR                   0x1242008
+#define ACP_I2S_RX_FIFOADDR                           0x124200C
+#define ACP_I2S_RX_FIFOSIZE                           0x1242010
+#define ACP_I2S_RX_DMA_SIZE                           0x1242014
+#define ACP_I2S_RX_LINEARPOSCNTR_HIGH                 0x1242018
+#define ACP_I2S_RX_LINEARPOSCNTR_LOW                  0x124201C
+#define ACP_I2S_RX_INTR_WATERMARK_SIZE                0x1242020
+#define ACP_I2S_TX_RINGBUFADDR                        0x1242024
+#define ACP_I2S_TX_RINGBUFSIZE                        0x1242028
+#define ACP_I2S_TX_LINKPOSITIONCNTR                   0x124202C
+#define ACP_I2S_TX_FIFOADDR                           0x1242030
+#define ACP_I2S_TX_FIFOSIZE                           0x1242034
+#define ACP_I2S_TX_DMA_SIZE                           0x1242038
+#define ACP_I2S_TX_LINEARPOSCNTR_HIGH                 0x124203C
+#define ACP_I2S_TX_LINEARPOSCNTR_LOW                  0x1242040
+#define ACP_I2S_TX_INTR_WATERMARK_SIZE                0x1242044
+#define ACP_BT_RX_RINGBUFADDR                         0x1242048
+#define ACP_BT_RX_RINGBUFSIZE                         0x124204C
+#define ACP_BT_RX_LINKPOSITIONCNTR                    0x1242050
+#define ACP_BT_RX_FIFOADDR                            0x1242054
+#define ACP_BT_RX_FIFOSIZE                            0x1242058
+#define ACP_BT_RX_DMA_SIZE                            0x124205C
+#define ACP_BT_RX_LINEARPOSCNTR_HIGH                  0x1242060
+#define ACP_BT_RX_LINEARPOSCNTR_LOW                   0x1242064
+#define ACP_BT_RX_INTR_WATERMARK_SIZE                 0x1242068
+#define ACP_BT_TX_RINGBUFADDR                         0x124206C
+#define ACP_BT_TX_RINGBUFSIZE                         0x1242070
+#define ACP_BT_TX_LINKPOSITIONCNTR                    0x1242074
+#define ACP_BT_TX_FIFOADDR                            0x1242078
+#define ACP_BT_TX_FIFOSIZE                            0x124207C
+#define ACP_BT_TX_DMA_SIZE                            0x1242080
+#define ACP_BT_TX_LINEARPOSCNTR_HIGH                  0x1242084
+#define ACP_BT_TX_LINEARPOSCNTR_LOW                   0x1242088
+#define ACP_BT_TX_INTR_WATERMARK_SIZE                 0x124208C
+#define ACP_HS_RX_RINGBUFADDR                         0x1242090
+#define ACP_HS_RX_RINGBUFSIZE                         0x1242094
+#define ACP_HS_RX_LINKPOSITIONCNTR                    0x1242098
+#define ACP_HS_RX_FIFOADDR                            0x124209C
+#define ACP_HS_RX_FIFOSIZE                            0x12420A0
+#define ACP_HS_RX_DMA_SIZE                            0x12420A4
+#define ACP_HS_RX_LINEARPOSCNTR_HIGH                 0x12420A8
+#define ACP_HS_RX_LINEARPOSCNTR_LOW                   0x12420AC
+#define ACP_HS_RX_INTR_WATERMARK_SIZE                 0x12420B0
+#define ACP_HS_TX_RINGBUFADDR                         0x12420B4
+#define ACP_HS_TX_RINGBUFSIZE                         0x12420B8
+#define ACP_HS_TX_LINKPOSITIONCNTR                    0x12420BC
+#define ACP_HS_TX_FIFOADDR                            0x12420C0
+#define ACP_HS_TX_FIFOSIZE                            0x12420C4
+#define ACP_HS_TX_DMA_SIZE                            0x12420C8
+#define ACP_HS_TX_LINEARPOSCNTR_HIGH                  0x12420CC
+#define ACP_HS_TX_LINEARPOSCNTR_LOW                   0x12420D0
+#define ACP_HS_TX_INTR_WATERMARK_SIZE                 0x12420D4
+
+/* Registers from ACP_I2S_TDM block */
+#define ACP_I2STDM_IER                                0x1242400
+#define ACP_I2STDM_IRER                               0x1242404
+#define ACP_I2STDM_RXFRMT                             0x1242408
+#define ACP_I2STDM_ITER                               0x124240C
+#define ACP_I2STDM_TXFRMT                             0x1242410
+#define ACP_I2STDM0_MSTRCLKGEN                        0x1242414
+#define ACP_I2STDM1_MSTRCLKGEN                        0x1242418
+#define ACP_I2STDM2_MSTRCLKGEN                        0x124241C
+#define ACP_I2STDM_REFCLKGEN                          0x1242420
+
+/* Registers from ACP_BT_TDM block */
+#define ACP_BTTDM_IER                                 0x1242800
+#define ACP_BTTDM_IRER                                0x1242804
+#define ACP_BTTDM_RXFRMT                              0x1242808
+#define ACP_BTTDM_ITER                                0x124280C
+#define ACP_BTTDM_TXFRMT                              0x1242810
+#define ACP_HSTDM_IER                                 0x1242814
+#define ACP_HSTDM_IRER                                0x1242818
+#define ACP_HSTDM_RXFRMT                              0x124281C
+#define ACP_HSTDM_ITER                                0x1242820
+#define ACP_HSTDM_TXFRMT                              0x1242824
+#endif
index ec04e33..8617793 100644 (file)
@@ -11,7 +11,6 @@ if SND_ATMEL_SOC
 
 config SND_ATMEL_SOC_PDC
        bool
-       depends on HAS_DMA
 
 config SND_ATMEL_SOC_DMA
        bool
index e6ded6f..bcd4f3e 100644 (file)
@@ -56,7 +56,7 @@
 /* Validity Bit Mode */
 #define SPDIFRX_MR_VBMODE_MASK         GENAMSK(1, 1)
 #define SPDIFRX_MR_VBMODE_ALWAYS_LOAD \
-       (0 << 1)        /* Load sample regardles of validity bit value */
+       (0 << 1)        /* Load sample regardless of validity bit value */
 #define SPDIFRX_MR_VBMODE_DISCARD_IF_VB1 \
        (1 << 1)        /* Load sample only if validity bit is 0 */
 
@@ -519,7 +519,7 @@ static int mchp_spdifrx_cs_get(struct mchp_spdifrx_dev *dev,
        /* check for new data available */
        ret = wait_for_completion_interruptible_timeout(&ch_stat->done,
                                                        msecs_to_jiffies(100));
-       /* IP might not be started or valid stream might not be prezent */
+       /* IP might not be started or valid stream might not be present */
        if (ret < 0) {
                dev_dbg(dev->dev, "channel status for channel %d timeout\n",
                        channel);
@@ -571,7 +571,7 @@ static int mchp_spdifrx_subcode_ch_get(struct mchp_spdifrx_dev *dev,
        mchp_spdifrx_isr_blockend_en(dev);
        ret = wait_for_completion_interruptible_timeout(&user_data->done,
                                                        msecs_to_jiffies(100));
-       /* IP might not be started or valid stream might not be prezent */
+       /* IP might not be started or valid stream might not be present */
        if (ret <= 0) {
                dev_dbg(dev->dev, "user data for channel %d timeout\n",
                        channel);
index 3bd350a..d243800 100644 (file)
@@ -80,7 +80,7 @@
 #define SPDIFTX_MR_VALID1                      BIT(24)
 #define SPDIFTX_MR_VALID2                      BIT(25)
 
-/* Disable Null Frame on underrrun */
+/* Disable Null Frame on underrun */
 #define SPDIFTX_MR_DNFR_MASK           GENMASK(27, 27)
 #define SPDIFTX_MR_DNFR_INVALID                (0 << 27)
 #define SPDIFTX_MR_DNFR_VALID          (1 << 27)
index 59e2edb..50c3dc6 100644 (file)
@@ -23,7 +23,7 @@
 //   IN2 +---o--+------------+--o---+ OUT2
 //               loop2 relays
 //
-// The 'loop1' gpio pin controlls two relays, which are either in loop
+// The 'loop1' gpio pin controls two relays, which are either in loop
 // position, meaning that input and output are directly connected, or
 // they are in mixer position, meaning that the signal is passed through
 // the 'Sum' mixer. Similarly for 'loop2'.
index 7ec8559..b5096f6 100644 (file)
@@ -46,10 +46,6 @@ static int bcm63xx_pcm_hw_params(struct snd_soc_component *component,
 {
        struct i2s_dma_desc *dma_desc;
        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-       runtime->dma_bytes = params_buffer_bytes(params);
 
        dma_desc = kzalloc(sizeof(*dma_desc), GFP_NOWAIT);
        if (!dma_desc)
@@ -68,7 +64,6 @@ static int bcm63xx_pcm_hw_free(struct snd_soc_component *component,
 
        dma_desc = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
        kfree(dma_desc);
-       snd_pcm_set_runtime_buffer(substream, NULL);
 
        return 0;
 }
@@ -190,19 +185,6 @@ bcm63xx_pcm_pointer(struct snd_soc_component *component,
        return x == substream->runtime->buffer_size ? 0 : x;
 }
 
-static int bcm63xx_pcm_mmap(struct snd_soc_component *component,
-                               struct snd_pcm_substream *substream,
-                               struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       return  dma_mmap_wc(substream->pcm->card->dev, vma,
-                           runtime->dma_area,
-                           runtime->dma_addr,
-                           runtime->dma_bytes);
-
-}
-
 static int bcm63xx_pcm_open(struct snd_soc_component *component,
                        struct snd_pcm_substream *substream)
 {
@@ -362,25 +344,6 @@ static irqreturn_t i2s_dma_isr(int irq, void *bcm_i2s_priv)
        return IRQ_HANDLED;
 }
 
-static int bcm63xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
-       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-       struct snd_dma_buffer *buf = &substream->dma_buffer;
-       size_t size = bcm63xx_pcm_hardware.buffer_bytes_max;
-
-       buf->dev.type = SNDRV_DMA_TYPE_DEV;
-       buf->dev.dev = pcm->card->dev;
-       buf->private_data = NULL;
-
-       buf->area = dma_alloc_wc(pcm->card->dev,
-                                size, &buf->addr,
-                                GFP_KERNEL);
-       if (!buf->area)
-               return -ENOMEM;
-       buf->bytes = size;
-       return 0;
-}
-
 static int bcm63xx_soc_pcm_new(struct snd_soc_component *component,
                struct snd_soc_pcm_runtime *rtd)
 {
@@ -394,49 +357,18 @@ static int bcm63xx_soc_pcm_new(struct snd_soc_component *component,
 
        ret = dma_coerce_mask_and_coherent(pcm->card->dev, DMA_BIT_MASK(32));
        if (ret)
-               goto out;
-
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = bcm63xx_pcm_preallocate_dma_buffer(pcm,
-                                                SNDRV_PCM_STREAM_PLAYBACK);
-               if (ret)
-                       goto out;
+               return ret;
 
+       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
                i2s_priv->play_substream =
                        pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = bcm63xx_pcm_preallocate_dma_buffer(pcm,
-                                       SNDRV_PCM_STREAM_CAPTURE);
-               if (ret)
-                       goto out;
+       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream)
                i2s_priv->capture_substream =
                        pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
-       }
 
-out:
-       return ret;
-}
-
-static void bcm63xx_pcm_free_dma_buffers(struct snd_soc_component *component,
-                        struct snd_pcm *pcm)
-{
-       int stream;
-       struct snd_dma_buffer *buf;
-       struct snd_pcm_substream *substream;
-
-       for (stream = 0; stream < 2; stream++) {
-               substream = pcm->streams[stream].substream;
-               if (!substream)
-                       continue;
-               buf = &substream->dma_buffer;
-               if (!buf->area)
-                       continue;
-               dma_free_wc(pcm->card->dev, buf->bytes,
-                                       buf->area, buf->addr);
-               buf->area = NULL;
-       }
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
+                                           pcm->card->dev,
+                                           bcm63xx_pcm_hardware.buffer_bytes_max);
 }
 
 static const struct snd_soc_component_driver bcm63xx_soc_platform = {
@@ -447,9 +379,7 @@ static const struct snd_soc_component_driver bcm63xx_soc_platform = {
        .prepare = bcm63xx_pcm_prepare,
        .trigger = bcm63xx_pcm_trigger,
        .pointer = bcm63xx_pcm_pointer,
-       .mmap = bcm63xx_pcm_mmap,
        .pcm_construct = bcm63xx_soc_pcm_new,
-       .pcm_destruct = bcm63xx_pcm_free_dma_buffers,
 };
 
 int bcm63xx_soc_platform_probe(struct platform_device *pdev,
index 56b71b9..3abeaf0 100644 (file)
@@ -729,7 +729,7 @@ static struct snd_soc_component_driver cygnus_soc_platform = {
 int cygnus_soc_platform_register(struct device *dev,
                                 struct cygnus_audio *cygaud)
 {
-       int rc = 0;
+       int rc;
 
        dev_dbg(dev, "%s Enter\n", __func__);
 
index 9ff1600..82ee233 100644 (file)
@@ -848,7 +848,7 @@ config SND_SOC_HDAC_HDA
        select SND_HDA
 
 config SND_SOC_ICS43432
-       tristate
+       tristate "ICS43423 and compatible i2s microphones"
 
 config SND_SOC_INNO_RK3036
        tristate "Inno codec driver for RK3036 SoC"
@@ -1582,6 +1582,7 @@ config SND_SOC_WCD938X
 config SND_SOC_WCD938X_SDW
        tristate "WCD9380/WCD9385 Codec - SDW"
        select SND_SOC_WCD938X
+       select SND_SOC_WCD_MBHC
        depends on SOUNDWIRE
        select REGMAP_SOUNDWIRE
        help
index f37ab7e..278a55a 100644 (file)
@@ -316,6 +316,13 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
        int word_len = 0, master_rate = 0;
        struct snd_soc_component *component = dai->component;
        struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component);
+       bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+       u8 dacc0;
+
+       dev_dbg(dai->dev, "%s() rate=%u format=%#x width=%u channels=%u\n",
+               __func__, params_rate(params), params_format(params),
+               params_width(params), params_channels(params));
+
 
        /* bit size */
        switch (params_width(params)) {
@@ -346,6 +353,25 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
                break;
        }
 
+       if (is_playback) {
+               switch (params_rate(params)) {
+               case 48000:
+                       dacc0 = AD193X_DAC_SR_48;
+                       break;
+               case 96000:
+                       dacc0 = AD193X_DAC_SR_96;
+                       break;
+               case 192000:
+                       dacc0 = AD193X_DAC_SR_192;
+                       break;
+               default:
+                       dev_err(dai->dev, "invalid sampling rate: %d\n", params_rate(params));
+                       return -EINVAL;
+               }
+
+               regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL0, AD193X_DAC_SR_MASK, dacc0);
+       }
+
        regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL0,
                            AD193X_PLL_INPUT_MASK, master_rate);
 
@@ -385,7 +411,7 @@ static struct snd_soc_dai_driver ad193x_dai = {
                .stream_name = "Playback",
                .channels_min = 2,
                .channels_max = 8,
-               .rates = SNDRV_PCM_RATE_48000,
+               .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
                .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
                        SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
        },
@@ -407,7 +433,7 @@ static struct snd_soc_dai_driver ad193x_no_adc_dai = {
                .stream_name = "Playback",
                .channels_min = 2,
                .channels_max = 8,
-               .rates = SNDRV_PCM_RATE_48000,
+               .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
                .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
                        SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
        },
index 3778547..61f4648 100644 (file)
@@ -37,6 +37,10 @@ int ad193x_probe(struct device *dev, struct regmap *regmap,
 #define AD193X_PLL_CLK_SRC_MCLK        (1 << 1)
 #define AD193X_DAC_CTRL0        0x02
 #define AD193X_DAC_POWERDOWN           0x01
+#define AD193X_DAC_SR_MASK           0x06
+#define AD193X_DAC_SR_48       (0 << 1)
+#define AD193X_DAC_SR_96       (1 << 1)
+#define AD193X_DAC_SR_192      (2 << 1)
 #define AD193X_DAC_SERFMT_MASK         0xC0
 #define AD193X_DAC_SERFMT_STEREO       (0 << 6)
 #define AD193X_DAC_SERFMT_TDM          (1 << 6)
index 99c022b..fb1e4c3 100644 (file)
@@ -586,6 +586,7 @@ struct cs42l42_pll_params {
  * Table 4-5 from the Datasheet
  */
 static const struct cs42l42_pll_params pll_ratio_table[] = {
+       { 1411200, 0, 1, 0x00, 0x80, 0x000000, 0x03, 0x10, 11289600, 128, 2},
        { 1536000, 0, 1, 0x00, 0x7D, 0x000000, 0x03, 0x10, 12000000, 125, 2},
        { 2304000, 0, 1, 0x00, 0x55, 0xC00000, 0x02, 0x10, 12288000,  85, 2},
        { 2400000, 0, 1, 0x00, 0x50, 0x000000, 0x03, 0x10, 12000000,  80, 2},
@@ -843,6 +844,13 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
        if (channels == 1)
                cs42l42->bclk *= 2;
 
+       /*
+        * Assume 24-bit samples are in 32-bit slots, to prevent SCLK being
+        * more than assumed (which would result in overclocking).
+        */
+       if (params_width(params) == 24)
+               cs42l42->bclk = (cs42l42->bclk / 3) * 4;
+
        switch(substream->stream) {
        case SNDRV_PCM_STREAM_CAPTURE:
                if (channels == 2) {
@@ -890,10 +898,23 @@ static int cs42l42_set_sysclk(struct snd_soc_dai *dai,
 {
        struct snd_soc_component *component = dai->component;
        struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
+       int i;
 
-       cs42l42->sclk = freq;
+       if (freq == 0) {
+               cs42l42->sclk = 0;
+               return 0;
+       }
 
-       return 0;
+       for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) {
+               if (pll_ratio_table[i].sclk == freq) {
+                       cs42l42->sclk = freq;
+                       return 0;
+               }
+       }
+
+       dev_err(component->dev, "SCLK %u not supported\n", freq);
+
+       return -EINVAL;
 }
 
 static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
@@ -2106,4 +2127,7 @@ MODULE_DESCRIPTION("ASoC CS42L42 driver");
 MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
 MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
 MODULE_AUTHOR("Michael White, Cirrus Logic Inc, <michael.white@cirrus.com>");
+MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_AUTHOR("Vitaly Rodionov <vitalyr@opensource.cirrus.com>");
 MODULE_LICENSE("GPL");
index ec8d6e7..13258f3 100644 (file)
@@ -206,7 +206,7 @@ static int cx20442_write(struct snd_soc_component *component, unsigned int reg,
  */
 
 /* Modem init: echo off, digital speaker off, quiet off, voice mode */
-static const char *v253_init = "ate0m0q0+fclass=8\r";
+static const char v253_init[] = "ate0m0q0+fclass=8\r";
 
 /* Line discipline .open() */
 static int v253_open(struct tty_struct *tty)
@@ -279,11 +279,6 @@ static void v253_receive(struct tty_struct *tty, const unsigned char *cp,
        }
 }
 
-/* Line discipline .write_wakeup() */
-static void v253_wakeup(struct tty_struct *tty)
-{
-}
-
 struct tty_ldisc_ops v253_ops = {
        .name = "cx20442",
        .owner = THIS_MODULE,
@@ -291,7 +286,6 @@ struct tty_ldisc_ops v253_ops = {
        .close = v253_close,
        .hangup = v253_hangup,
        .receive_buf = v253_receive,
-       .write_wakeup = v253_wakeup,
 };
 EXPORT_SYMBOL_GPL(v253_ops);
 
index 47e749f..de4c846 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * I2S MEMS microphone driver for InvenSense ICS-43432
+ * I2S MEMS microphone driver for InvenSense ICS-43432 and similar
+ * MEMS-based microphones.
  *
  * - Non configurable.
  * - I2S interface, 64 BCLs per frame, 32 bits per channel, 24 bit data
@@ -53,6 +54,7 @@ static int ics43432_probe(struct platform_device *pdev)
 #ifdef CONFIG_OF
 static const struct of_device_id ics43432_ids[] = {
        { .compatible = "invensense,ics43432", },
+       { .compatible = "cui,cmm-4030d-261", },
        { }
 };
 MODULE_DEVICE_TABLE(of, ics43432_ids);
index 3622961..196b068 100644 (file)
@@ -1722,42 +1722,43 @@ static int rx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
        case RX_MACRO_AIF2_PB:
        case RX_MACRO_AIF3_PB:
        case RX_MACRO_AIF4_PB:
-       for (j = 0; j < INTERP_MAX; j++) {
-               reg = CDC_RX_RXn_RX_PATH_CTL(j);
-               mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j);
-               dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(j);
-
-               if (mute) {
-                       snd_soc_component_update_bits(component, reg,
-                                                     CDC_RX_PATH_PGA_MUTE_MASK,
-                                                     CDC_RX_PATH_PGA_MUTE_ENABLE);
-                       snd_soc_component_update_bits(component, mix_reg,
-                                                     CDC_RX_PATH_PGA_MUTE_MASK,
-                                                     CDC_RX_PATH_PGA_MUTE_ENABLE);
-               } else {
-                       snd_soc_component_update_bits(component, reg,
-                                                     CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
-                       snd_soc_component_update_bits(component, mix_reg,
-                                                     CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
-               }
-
-               if (j == INTERP_AUX)
-                       dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL;
+               for (j = 0; j < INTERP_MAX; j++) {
+                       reg = CDC_RX_RXn_RX_PATH_CTL(j);
+                       mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j);
+                       dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(j);
+
+                       if (mute) {
+                               snd_soc_component_update_bits(component, reg,
+                                                             CDC_RX_PATH_PGA_MUTE_MASK,
+                                                             CDC_RX_PATH_PGA_MUTE_ENABLE);
+                               snd_soc_component_update_bits(component, mix_reg,
+                                                             CDC_RX_PATH_PGA_MUTE_MASK,
+                                                             CDC_RX_PATH_PGA_MUTE_ENABLE);
+                       } else {
+                               snd_soc_component_update_bits(component, reg,
+                                                             CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
+                               snd_soc_component_update_bits(component, mix_reg,
+                                                             CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
+                       }
 
-               int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8;
-               int_mux_cfg1 = int_mux_cfg0 + 4;
-               int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0);
-               int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1);
+                       if (j == INTERP_AUX)
+                               dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL;
 
-               if (snd_soc_component_read(component, dsm_reg) & 0x01) {
-                       if (int_mux_cfg0_val || (int_mux_cfg1_val & 0xF0))
-                               snd_soc_component_update_bits(component, reg, 0x20, 0x20);
-                       if (int_mux_cfg1_val & 0x0F) {
-                               snd_soc_component_update_bits(component, reg, 0x20, 0x20);
-                               snd_soc_component_update_bits(component, mix_reg, 0x20, 0x20);
+                       int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8;
+                       int_mux_cfg1 = int_mux_cfg0 + 4;
+                       int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0);
+                       int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1);
+
+                       if (snd_soc_component_read(component, dsm_reg) & 0x01) {
+                               if (int_mux_cfg0_val || (int_mux_cfg1_val & 0xF0))
+                                       snd_soc_component_update_bits(component, reg, 0x20, 0x20);
+                               if (int_mux_cfg1_val & 0x0F) {
+                                       snd_soc_component_update_bits(component, reg, 0x20, 0x20);
+                                       snd_soc_component_update_bits(component, mix_reg, 0x20,
+                                                                     0x20);
+                               }
                        }
                }
-       }
                break;
        default:
                break;
index bc30a1d..b45ec35 100644 (file)
@@ -2158,13 +2158,11 @@ static void max98090_jack_work(struct work_struct *work)
 
                msleep(50);
 
-               reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS);
+               snd_soc_component_read(component, M98090_REG_JACK_STATUS);
 
                /* Weak pull up allows only insertion detection */
                snd_soc_component_update_bits(component, M98090_REG_JACK_DETECT,
                        M98090_JDWK_MASK, M98090_JDWK_MASK);
-       } else {
-               reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS);
        }
 
        reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS);
index 94773cc..b392567 100644 (file)
@@ -765,17 +765,26 @@ static int max98390_dsm_init(struct snd_soc_component *component)
        vendor = dmi_get_system_info(DMI_SYS_VENDOR);
        product = dmi_get_system_info(DMI_PRODUCT_NAME);
 
-       if (vendor && product) {
-               snprintf(filename, sizeof(filename), "dsm_param_%s_%s.bin",
-                       vendor, product);
+       if (!strcmp(max98390->dsm_param_name, "default")) {
+               if (vendor && product) {
+                       snprintf(filename, sizeof(filename),
+                               "dsm_param_%s_%s.bin", vendor, product);
+               } else {
+                       sprintf(filename, "dsm_param.bin");
+               }
        } else {
-               sprintf(filename, "dsm_param.bin");
+               snprintf(filename, sizeof(filename), "%s",
+                       max98390->dsm_param_name);
        }
        ret = request_firmware(&fw, filename, component->dev);
        if (ret) {
                ret = request_firmware(&fw, "dsm_param.bin", component->dev);
-               if (ret)
-                       goto err;
+               if (ret) {
+                       ret = request_firmware(&fw, "dsmparam.bin",
+                               component->dev);
+                       if (ret)
+                               goto err;
+               }
        }
 
        dev_dbg(component->dev,
@@ -1047,6 +1056,11 @@ static int max98390_i2c_probe(struct i2c_client *i2c,
                __func__, max98390->ref_rdc_value,
                max98390->ambient_temp_value);
 
+       ret = device_property_read_string(&i2c->dev, "maxim,dsm_param_name",
+                                      &max98390->dsm_param_name);
+       if (ret)
+               max98390->dsm_param_name = "default";
+
        /* voltage/current slot configuration */
        max98390_slot_config(i2c, max98390);
 
index e315167..c250740 100644 (file)
@@ -662,5 +662,6 @@ struct max98390_priv {
        unsigned int i_l_slot;
        unsigned int ref_rdc_value;
        unsigned int ambient_temp_value;
+       const char *dsm_param_name;
 };
 #endif
index 7831418..6d3d170 100644 (file)
@@ -234,7 +234,7 @@ static void recover_eint_setting(struct mt6359_accdet *priv)
 
 static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv)
 {
-       int ret = 0;
+       int ret;
        unsigned int value = 0;
 
        regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,
@@ -461,7 +461,7 @@ static irqreturn_t mt6359_accdet_irq(int irq, void *data)
 {
        struct mt6359_accdet *priv = data;
        unsigned int irq_val = 0, val = 0, value = 0;
-       int ret = 0;
+       int ret;
 
        mutex_lock(&priv->res_lock);
        regmap_read(priv->regmap, ACCDET_IRQ_ADDR, &irq_val);
@@ -551,7 +551,7 @@ static irqreturn_t mt6359_accdet_irq(int irq, void *data)
 
 static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
 {
-       int ret = 0;
+       int ret;
        struct device *dev = priv->dev;
        struct device_node *node = NULL;
        int pwm_deb[15] = {0};
@@ -926,7 +926,7 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
 {
        struct mt6359_accdet *priv;
        struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
-       int ret = 0;
+       int ret;
 
        dev_dbg(&pdev->dev, "%s(), dev name %s\n",
                __func__, dev_name(&pdev->dev));
@@ -1057,22 +1057,7 @@ static struct platform_driver mt6359_accdet_driver = {
        .probe = mt6359_accdet_probe,
 };
 
-static int __init mt6359_accdet_driver_init(void)
-{
-       int ret = 0;
-
-       ret = platform_driver_register(&mt6359_accdet_driver);
-       if (ret)
-               return -ENODEV;
-       return 0;
-}
-
-static void __exit mt6359_accdet_driver_exit(void)
-{
-       platform_driver_unregister(&mt6359_accdet_driver);
-}
-module_init(mt6359_accdet_driver_init);
-module_exit(mt6359_accdet_driver_exit);
+module_platform_driver(mt6359_accdet_driver)
 
 /* Module information */
 MODULE_DESCRIPTION("MT6359 ALSA SoC codec jack driver");
index 9238f12..c0c5952 100644 (file)
@@ -547,31 +547,6 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static void rt1015_flush_work(struct work_struct *work)
-{
-       struct rt1015_priv *rt1015 = container_of(work, struct rt1015_priv,
-                                               flush_work.work);
-       struct snd_soc_component *component = rt1015->component;
-       unsigned int val, i;
-
-       for (i = 0; i < 200; ++i) {
-               usleep_range(1000, 1500);
-               dev_dbg(component->dev, "Flush DAC (retry:%u)\n", i);
-               regmap_read(rt1015->regmap, RT1015_CLK_DET, &val);
-               if (val & 0x800)
-                       break;
-       }
-
-       regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597);
-       regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x05f7);
-       regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x0028);
-
-       if (val & 0x800)
-               dev_dbg(component->dev, "Flush DAC completed.\n");
-       else
-               dev_warn(component->dev, "Fail to flush DAC data.\n");
-}
-
 static const struct snd_kcontrol_new rt1015_snd_controls[] = {
        SOC_SINGLE_TLV("DAC Playback Volume", RT1015_DAC1, RT1015_DAC_VOL_SFT,
                127, 0, dac_vol_tlv),
@@ -630,10 +605,6 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w,
                }
                break;
 
-       case SND_SOC_DAPM_POST_PMU:
-               regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x00a8);
-               break;
-
        case SND_SOC_DAPM_POST_PMD:
                if (rt1015->bypass_boost == RT1015_Enable_Boost) {
                        snd_soc_component_write(component,
@@ -653,8 +624,6 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w,
                                RT1015_SYS_RST2, 0x0b9a);
                }
                rt1015->dac_is_used = 0;
-
-               cancel_delayed_work_sync(&rt1015->flush_work);
                break;
 
        default:
@@ -687,8 +656,6 @@ static int rt1015_amp_drv_event(struct snd_soc_dapm_widget *w,
                }
                break;
        case SND_SOC_DAPM_POST_PMU:
-               if (rt1015->hw_config == RT1015_HW_28)
-                       schedule_delayed_work(&rt1015->flush_work, msecs_to_jiffies(10));
                msleep(rt1015->pdata.power_up_delay_ms);
                break;
        default:
@@ -702,7 +669,7 @@ static const struct snd_soc_dapm_widget rt1015_dapm_widgets[] = {
                NULL, 0),
        SND_SOC_DAPM_AIF_IN("AIFRX", "AIF Playback", 0, SND_SOC_NOPM, 0, 0),
        SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0,
-               r1015_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+               r1015_dac_event, SND_SOC_DAPM_PRE_PMU |
                SND_SOC_DAPM_POST_PMD),
        SND_SOC_DAPM_OUT_DRV_E("Amp Drv", SND_SOC_NOPM, 0, 0, NULL, 0,
                        rt1015_amp_drv_event, SND_SOC_DAPM_PRE_PMU |
@@ -722,7 +689,7 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_component *component = dai->component;
        struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component);
-       int pre_div, bclk_ms, frame_size, lrck;
+       int pre_div, frame_size, lrck;
        unsigned int val_len = 0;
 
        lrck = params_rate(params);
@@ -739,10 +706,7 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       bclk_ms = frame_size > 32;
-
-       dev_dbg(component->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
-                               bclk_ms, pre_div, dai->id);
+       dev_dbg(component->dev, "pre_div is %d for iis %d\n", pre_div, dai->id);
 
        dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n",
                                lrck, pre_div, dai->id);
@@ -1028,7 +992,6 @@ static int rt1015_probe(struct snd_soc_component *component)
                snd_soc_component_get_drvdata(component);
 
        rt1015->component = component;
-       INIT_DELAYED_WORK(&rt1015->flush_work, rt1015_flush_work);
 
        return 0;
 }
@@ -1037,7 +1000,6 @@ static void rt1015_remove(struct snd_soc_component *component)
 {
        struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component);
 
-       cancel_delayed_work_sync(&rt1015->flush_work);
        regmap_write(rt1015->regmap, RT1015_RESET, 0);
 }
 
@@ -1180,8 +1142,6 @@ static int rt1015_i2c_probe(struct i2c_client *i2c,
                return ret;
        }
 
-       rt1015->hw_config = (i2c->addr == 0x29) ? RT1015_HW_29 : RT1015_HW_28;
-
        ret = regmap_read(rt1015->regmap, RT1015_DEVICE_ID, &val);
        if (ret) {
                dev_err(&i2c->dev,
index 1434453..c9f636a 100644 (file)
@@ -444,8 +444,6 @@ struct rt1015_priv {
        int bypass_boost;
        int dac_is_used;
        int cali_done;
-       int hw_config;
-       struct delayed_work flush_work;
 };
 
 #endif /* __RT1015_H__ */
index 40f2063..415cfb3 100644 (file)
@@ -127,6 +127,7 @@ static int rt1015p_platform_probe(struct platform_device *pdev)
 #ifdef CONFIG_OF
 static const struct of_device_id rt1015p_device_id[] = {
        { .compatible = "realtek,rt1015p" },
+       { .compatible = "realtek,rt1019p" },
        {}
 };
 MODULE_DEVICE_TABLE(of, rt1015p_device_id);
@@ -135,6 +136,7 @@ MODULE_DEVICE_TABLE(of, rt1015p_device_id);
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id rt1015p_acpi_match[] = {
        { "RTL1015", 0},
+       { "RTL1019", 0},
        { },
 };
 MODULE_DEVICE_TABLE(acpi, rt1015p_acpi_match);
index 7081142..4b1ad50 100644 (file)
@@ -494,7 +494,7 @@ static const struct snd_kcontrol_new rt5514_sto2_dmic_mux =
  */
 static int rt5514_calc_dmic_clk(struct snd_soc_component *component, int rate)
 {
-       int div[] = {2, 3, 4, 8, 12, 16, 24, 32};
+       static const int div[] = {2, 3, 4, 8, 12, 16, 24, 32};
        int i;
 
        if (rate < 1000000 * div[0]) {
index 9523f4b..cd1db5c 100644 (file)
@@ -2093,7 +2093,7 @@ int rt5640_sel_asrc_clk_src(struct snd_soc_component *component,
 }
 EXPORT_SYMBOL_GPL(rt5640_sel_asrc_clk_src);
 
-static void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component)
+void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component)
 {
        struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
 
@@ -2105,8 +2105,9 @@ static void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component)
        snd_soc_dapm_sync_unlocked(dapm);
        snd_soc_dapm_mutex_unlock(dapm);
 }
+EXPORT_SYMBOL_GPL(rt5640_enable_micbias1_for_ovcd);
 
-static void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component)
+void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component)
 {
        struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
 
@@ -2117,6 +2118,7 @@ static void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component
        snd_soc_dapm_sync_unlocked(dapm);
        snd_soc_dapm_mutex_unlock(dapm);
 }
+EXPORT_SYMBOL_GPL(rt5640_disable_micbias1_for_ovcd);
 
 static void rt5640_enable_micbias1_ovcd_irq(struct snd_soc_component *component)
 {
@@ -2241,7 +2243,7 @@ static void rt5640_button_press_work(struct work_struct *work)
        schedule_delayed_work(&rt5640->bp_work, msecs_to_jiffies(BP_POLL_TIME));
 }
 
-static int rt5640_detect_headset(struct snd_soc_component *component)
+int rt5640_detect_headset(struct snd_soc_component *component, struct gpio_desc *hp_det_gpio)
 {
        int i, headset_count = 0, headphone_count = 0;
 
@@ -2259,8 +2261,13 @@ static int rt5640_detect_headset(struct snd_soc_component *component)
                msleep(JACK_SETTLE_TIME);
 
                /* Check the jack is still connected before checking ovcd */
-               if (!rt5640_jack_inserted(component))
-                       return 0;
+               if (hp_det_gpio) {
+                       if (gpiod_get_value_cansleep(hp_det_gpio))
+                               return 0;
+               } else {
+                       if (!rt5640_jack_inserted(component))
+                               return 0;
+               }
 
                if (rt5640_micbias1_ovcd(component)) {
                        /*
@@ -2285,6 +2292,7 @@ static int rt5640_detect_headset(struct snd_soc_component *component)
        dev_err(component->dev, "Error detecting headset vs headphones, bad contact?, assuming headphones\n");
        return SND_JACK_HEADPHONE;
 }
+EXPORT_SYMBOL_GPL(rt5640_detect_headset);
 
 static void rt5640_jack_work(struct work_struct *work)
 {
@@ -2309,7 +2317,7 @@ static void rt5640_jack_work(struct work_struct *work)
                /* Jack inserted */
                WARN_ON(rt5640->ovcd_irq_enabled);
                rt5640_enable_micbias1_for_ovcd(component);
-               status = rt5640_detect_headset(component);
+               status = rt5640_detect_headset(component, NULL);
                if (status == SND_JACK_HEADSET) {
                        /* Enable ovcd IRQ for button press detect. */
                        rt5640_enable_micbias1_ovcd_irq(component);
@@ -2362,10 +2370,59 @@ static void rt5640_cancel_work(void *data)
        cancel_delayed_work_sync(&rt5640->bp_work);
 }
 
+void rt5640_set_ovcd_params(struct snd_soc_component *component)
+{
+       struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
+
+       snd_soc_component_write(component, RT5640_PR_BASE + RT5640_BIAS_CUR4,
+               0xa800 | rt5640->ovcd_sf);
+
+       snd_soc_component_update_bits(component, RT5640_MICBIAS,
+               RT5640_MIC1_OVTH_MASK | RT5640_MIC1_OVCD_MASK,
+               rt5640->ovcd_th | RT5640_MIC1_OVCD_EN);
+
+       /*
+        * The over-current-detect is only reliable in detecting the absence
+        * of over-current, when the mic-contact in the jack is short-circuited,
+        * the hardware periodically retries if it can apply the bias-current
+        * leading to the ovcd status flip-flopping 1-0-1 with it being 0 about
+        * 10% of the time, as we poll the ovcd status bit we might hit that
+        * 10%, so we enable sticky mode and when checking OVCD we clear the
+        * status, msleep() a bit and then check to get a reliable reading.
+        */
+       snd_soc_component_update_bits(component, RT5640_IRQ_CTRL2,
+               RT5640_MB1_OC_STKY_MASK, RT5640_MB1_OC_STKY_EN);
+}
+EXPORT_SYMBOL_GPL(rt5640_set_ovcd_params);
+
+static void rt5640_disable_jack_detect(struct snd_soc_component *component)
+{
+       struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
+
+       /*
+        * soc_remove_component() force-disables jack and thus rt5640->jack
+        * could be NULL at the time of driver's module unloading.
+        */
+       if (!rt5640->jack)
+               return;
+
+       free_irq(rt5640->irq, rt5640);
+       rt5640_cancel_work(rt5640);
+
+       if (rt5640->jack->status & SND_JACK_MICROPHONE) {
+               rt5640_disable_micbias1_ovcd_irq(component);
+               rt5640_disable_micbias1_for_ovcd(component);
+               snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0);
+       }
+
+       rt5640->jack = NULL;
+}
+
 static void rt5640_enable_jack_detect(struct snd_soc_component *component,
                                      struct snd_soc_jack *jack)
 {
        struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
+       int ret;
 
        /* Select JD-source */
        snd_soc_component_update_bits(component, RT5640_JD_CTRL,
@@ -2385,24 +2442,7 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
        /* Enabling jd2 in general control 2 */
        snd_soc_component_write(component, RT5640_DUMMY2, 0x4001);
 
-       snd_soc_component_write(component, RT5640_PR_BASE + RT5640_BIAS_CUR4,
-               0xa800 | rt5640->ovcd_sf);
-
-       snd_soc_component_update_bits(component, RT5640_MICBIAS,
-               RT5640_MIC1_OVTH_MASK | RT5640_MIC1_OVCD_MASK,
-               rt5640->ovcd_th | RT5640_MIC1_OVCD_EN);
-
-       /*
-        * The over-current-detect is only reliable in detecting the absence
-        * of over-current, when the mic-contact in the jack is short-circuited,
-        * the hardware periodically retries if it can apply the bias-current
-        * leading to the ovcd status flip-flopping 1-0-1 with it being 0 about
-        * 10% of the time, as we poll the ovcd status bit we might hit that
-        * 10%, so we enable sticky mode and when checking OVCD we clear the
-        * status, msleep() a bit and then check to get a reliable reading.
-        */
-       snd_soc_component_update_bits(component, RT5640_IRQ_CTRL2,
-               RT5640_MB1_OC_STKY_MASK, RT5640_MB1_OC_STKY_EN);
+       rt5640_set_ovcd_params(component);
 
        /*
         * All IRQs get or-ed together, so we need the jack IRQ to report 0
@@ -2423,32 +2463,19 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
                rt5640_enable_micbias1_ovcd_irq(component);
        }
 
-       enable_irq(rt5640->irq);
-       /* sync initial jack state */
-       queue_work(system_long_wq, &rt5640->jack_work);
-}
-
-static void rt5640_disable_jack_detect(struct snd_soc_component *component)
-{
-       struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
-
-       /*
-        * soc_remove_component() force-disables jack and thus rt5640->jack
-        * could be NULL at the time of driver's module unloading.
-        */
-       if (!rt5640->jack)
+       ret = request_irq(rt5640->irq, rt5640_irq,
+                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                         "rt5640", rt5640);
+       if (ret) {
+               dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret);
+               rt5640->irq = -ENXIO;
+               /* Undo above settings */
+               rt5640_disable_jack_detect(component);
                return;
-
-       disable_irq(rt5640->irq);
-       rt5640_cancel_work(rt5640);
-
-       if (rt5640->jack->status & SND_JACK_MICROPHONE) {
-               rt5640_disable_micbias1_ovcd_irq(component);
-               rt5640_disable_micbias1_for_ovcd(component);
-               snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0);
        }
 
-       rt5640->jack = NULL;
+       /* sync initial jack state */
+       queue_work(system_long_wq, &rt5640->jack_work);
 }
 
 static int rt5640_set_jack(struct snd_soc_component *component,
@@ -2836,18 +2863,6 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
        if (ret)
                return ret;
 
-       ret = devm_request_irq(&i2c->dev, rt5640->irq, rt5640_irq,
-                              IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
-                              | IRQF_ONESHOT, "rt5640", rt5640);
-       if (ret == 0) {
-               /* Gets re-enabled by rt5640_set_jack() */
-               disable_irq(rt5640->irq);
-       } else {
-               dev_warn(&i2c->dev, "Failed to reguest IRQ %d: %d\n",
-                        rt5640->irq, ret);
-               rt5640->irq = -ENXIO;
-       }
-
        return devm_snd_soc_register_component(&i2c->dev,
                                      &soc_component_dev_rt5640,
                                      rt5640_dai, ARRAY_SIZE(rt5640_dai));
index 4fd47f2..2c28f83 100644 (file)
@@ -10,6 +10,7 @@
 #define _RT5640_H
 
 #include <linux/clk.h>
+#include <linux/gpio/consumer.h>
 #include <linux/workqueue.h>
 #include <dt-bindings/sound/rt5640.h>
 
@@ -2157,4 +2158,9 @@ int rt5640_dmic_enable(struct snd_soc_component *component,
 int rt5640_sel_asrc_clk_src(struct snd_soc_component *component,
                unsigned int filter_mask, unsigned int clk_src);
 
+void rt5640_set_ovcd_params(struct snd_soc_component *component);
+void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component);
+void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component);
+int rt5640_detect_headset(struct snd_soc_component *component, struct gpio_desc *hp_det_gpio);
+
 #endif
index 4a56a52..b9d5d7a 100644 (file)
@@ -117,6 +117,13 @@ static struct snd_soc_dai_driver rt5682_dai[] = {
        },
 };
 
+static void rt5682_i2c_disable_regulators(void *data)
+{
+       struct rt5682_priv *rt5682 = data;
+
+       regulator_bulk_disable(ARRAY_SIZE(rt5682->supplies), rt5682->supplies);
+}
+
 static int rt5682_i2c_probe(struct i2c_client *i2c,
                const struct i2c_device_id *id)
 {
@@ -157,6 +164,11 @@ static int rt5682_i2c_probe(struct i2c_client *i2c,
                return ret;
        }
 
+       ret = devm_add_action_or_reset(&i2c->dev, rt5682_i2c_disable_regulators,
+                                      rt5682);
+       if (ret)
+               return ret;
+
        ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies),
                                    rt5682->supplies);
        if (ret) {
@@ -282,10 +294,7 @@ static void rt5682_i2c_shutdown(struct i2c_client *client)
 
 static int rt5682_i2c_remove(struct i2c_client *client)
 {
-       struct rt5682_priv *rt5682 = i2c_get_clientdata(client);
-
        rt5682_i2c_shutdown(client);
-       regulator_bulk_disable(ARRAY_SIZE(rt5682->supplies), rt5682->supplies);
 
        return 0;
 }
index 51ecaa2..e822fa1 100644 (file)
@@ -43,8 +43,9 @@ static const struct reg_sequence patch_list[] = {
        {RT5682_DAC_ADC_DIG_VOL1, 0xa020},
        {RT5682_I2C_CTRL, 0x000f},
        {RT5682_PLL2_INTERNAL, 0x8266},
-       {RT5682_SAR_IL_CMD_3, 0x8365},
-       {RT5682_SAR_IL_CMD_6, 0x0180},
+       {RT5682_SAR_IL_CMD_1, 0x22b7},
+       {RT5682_SAR_IL_CMD_3, 0x0365},
+       {RT5682_SAR_IL_CMD_6, 0x0110},
 };
 
 void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev)
@@ -1727,8 +1728,6 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = {
        SND_SOC_DAPM_MIXER("Stereo1 ADC MIXR", RT5682_STO1_ADC_DIG_VOL,
                RT5682_R_MUTE_SFT, 1, rt5682_sto1_adc_r_mix,
                ARRAY_SIZE(rt5682_sto1_adc_r_mix)),
-       SND_SOC_DAPM_SUPPLY("BTN Detection Mode", RT5682_SAR_IL_CMD_1,
-               14, 1, NULL, 0),
 
        /* ADC PGA */
        SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -1899,8 +1898,6 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
        {"Stereo1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux"},
        {"Stereo1 ADC MIXR", NULL, "ADC Stereo1 Filter"},
 
-       {"ADC Stereo1 Filter", NULL, "BTN Detection Mode"},
-
        {"Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL"},
        {"Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR"},
 
@@ -2916,10 +2913,47 @@ static void rt5682_remove(struct snd_soc_component *component)
 static int rt5682_suspend(struct snd_soc_component *component)
 {
        struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+       unsigned int val;
 
        if (rt5682->is_sdw)
                return 0;
 
+       cancel_delayed_work_sync(&rt5682->jack_detect_work);
+       cancel_delayed_work_sync(&rt5682->jd_check_work);
+       if (rt5682->hs_jack && rt5682->jack_type == SND_JACK_HEADSET) {
+               snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
+                       RT5682_MB1_PATH_MASK | RT5682_MB2_PATH_MASK,
+                       RT5682_CTRL_MB1_REG | RT5682_CTRL_MB2_REG);
+               val = snd_soc_component_read(component,
+                               RT5682_CBJ_CTRL_2) & RT5682_JACK_TYPE_MASK;
+
+               switch (val) {
+               case 0x1:
+                       snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+                               RT5682_SAR_SEL_MB1_MASK | RT5682_SAR_SEL_MB2_MASK,
+                               RT5682_SAR_SEL_MB1_NOSEL | RT5682_SAR_SEL_MB2_SEL);
+                       break;
+               case 0x2:
+                       snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+                               RT5682_SAR_SEL_MB1_MASK | RT5682_SAR_SEL_MB2_MASK,
+                               RT5682_SAR_SEL_MB1_SEL | RT5682_SAR_SEL_MB2_NOSEL);
+                       break;
+               default:
+                       break;
+               }
+
+               snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
+                       RT5682_PWR_CBJ, 0);
+
+               /* enter SAR ADC power saving mode */
+               snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+                       RT5682_SAR_BUTT_DET_MASK | RT5682_SAR_BUTDET_MODE_MASK |
+                       RT5682_SAR_BUTDET_RST_MASK | RT5682_SAR_SEL_MB1_MB2_MASK, 0);
+               snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+                       RT5682_SAR_BUTT_DET_MASK | RT5682_SAR_BUTDET_MODE_MASK | RT5682_SAR_BUTDET_RST_MASK,
+                       RT5682_SAR_BUTT_DET_EN | RT5682_SAR_BUTDET_POW_SAV | RT5682_SAR_BUTDET_RST_NORMAL);
+       }
+
        regcache_cache_only(rt5682->regmap, true);
        regcache_mark_dirty(rt5682->regmap);
        return 0;
@@ -2935,6 +2969,17 @@ static int rt5682_resume(struct snd_soc_component *component)
        regcache_cache_only(rt5682->regmap, false);
        regcache_sync(rt5682->regmap);
 
+       if (rt5682->hs_jack && rt5682->jack_type == SND_JACK_HEADSET) {
+               snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+                       RT5682_SAR_BUTDET_MODE_MASK | RT5682_SAR_SEL_MB1_MB2_MASK,
+                       RT5682_SAR_BUTDET_POW_NORM | RT5682_SAR_SEL_MB1_MB2_AUTO);
+               snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
+                       RT5682_MB1_PATH_MASK | RT5682_MB2_PATH_MASK,
+                       RT5682_CTRL_MB1_FSM | RT5682_CTRL_MB2_FSM);
+               snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
+                       RT5682_PWR_CBJ, RT5682_PWR_CBJ);
+       }
+
        mod_delayed_work(system_power_efficient_wq,
                &rt5682->jack_detect_work, msecs_to_jiffies(250));
 
index 2e9175b..d39c7d5 100644 (file)
@@ -714,7 +714,7 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component,
        unsigned long adc_clock_rate, dac_clock_rate;
        int ret;
 
-       struct clk_bulk_data clocks[] = {
+       static struct clk_bulk_data clocks[] = {
                { .id = "pll" },
                { .id = "nadc" },
                { .id = "madc" },
@@ -878,7 +878,7 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component,
 {
        int ret;
 
-       struct clk_bulk_data clocks[] = {
+       static struct clk_bulk_data clocks[] = {
                { .id = "madc" },
                { .id = "mdac" },
                { .id = "bdiv" },
@@ -994,7 +994,7 @@ static int aic32x4_component_probe(struct snd_soc_component *component)
        u32 tmp_reg;
        int ret;
 
-       struct clk_bulk_data clocks[] = {
+       static struct clk_bulk_data clocks[] = {
                { .id = "codec_clkin" },
                { .id = "pll" },
                { .id = "bdiv" },
@@ -1131,7 +1131,7 @@ static struct snd_soc_dai_driver aic32x4_tas2505_dai = {
        .playback = {
                         .stream_name = "Playback",
                         .channels_min = 1,
-                        .channels_max = 1,
+                        .channels_max = 2,
                         .rates = SNDRV_PCM_RATE_8000_96000,
                         .formats = AIC32X4_FORMATS,},
        .ops = &aic32x4_ops,
@@ -1144,7 +1144,7 @@ static int aic32x4_tas2505_component_probe(struct snd_soc_component *component)
        u32 tmp_reg;
        int ret;
 
-       struct clk_bulk_data clocks[] = {
+       static struct clk_bulk_data clocks[] = {
                { .id = "codec_clkin" },
                { .id = "pll" },
                { .id = "bdiv" },
index 86c92e0..d885ced 100644 (file)
@@ -4076,6 +4076,16 @@ static int wcd9335_setup_irqs(struct wcd9335_codec *wcd)
        return ret;
 }
 
+static void wcd9335_teardown_irqs(struct wcd9335_codec *wcd)
+{
+       int i;
+
+       /* disable interrupts on all slave ports */
+       for (i = 0; i < WCD9335_SLIM_NUM_PORT_REG; i++)
+               regmap_write(wcd->if_regmap, WCD9335_SLIM_PGD_PORT_INT_EN0 + i,
+                            0x00);
+}
+
 static void wcd9335_cdc_sido_ccl_enable(struct wcd9335_codec *wcd,
                                        bool ccl_flag)
 {
@@ -4844,6 +4854,7 @@ static void wcd9335_codec_init(struct snd_soc_component *component)
 static int wcd9335_codec_probe(struct snd_soc_component *component)
 {
        struct wcd9335_codec *wcd = dev_get_drvdata(component->dev);
+       int ret;
        int i;
 
        snd_soc_component_init_regmap(component, wcd->regmap);
@@ -4861,7 +4872,15 @@ static int wcd9335_codec_probe(struct snd_soc_component *component)
        for (i = 0; i < NUM_CODEC_DAIS; i++)
                INIT_LIST_HEAD(&wcd->dai[i].slim_ch_list);
 
-       return wcd9335_setup_irqs(wcd);
+       ret = wcd9335_setup_irqs(wcd);
+       if (ret)
+               goto free_clsh_ctrl;
+
+       return 0;
+
+free_clsh_ctrl:
+       wcd_clsh_ctrl_free(wcd->clsh_ctrl);
+       return ret;
 }
 
 static void wcd9335_codec_remove(struct snd_soc_component *comp)
@@ -4869,7 +4888,7 @@ static void wcd9335_codec_remove(struct snd_soc_component *comp)
        struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
 
        wcd_clsh_ctrl_free(wcd->clsh_ctrl);
-       free_irq(regmap_irq_get_virq(wcd->irq_data, WCD9335_IRQ_SLIMBUS), wcd);
+       wcd9335_teardown_irqs(wcd);
 }
 
 static int wcd9335_codec_set_sysclk(struct snd_soc_component *comp,
index 2fcc973..f0daf8d 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/regulator/consumer.h>
 
 #include "wcd-clsh-v2.h"
+#include "wcd-mbhc-v2.h"
 #include "wcd938x.h"
 
 #define WCD938X_MAX_MICBIAS            (4)
@@ -173,6 +174,11 @@ struct wcd938x_priv {
        struct device *rxdev;
        struct device_node *rxnode, *txnode;
        struct regmap *regmap;
+       struct mutex micb_lock;
+       /* mbhc module */
+       struct wcd_mbhc *wcd_mbhc;
+       struct wcd_mbhc_config mbhc_cfg;
+       struct wcd_mbhc_intr intr_ids;
        struct wcd_clsh_ctrl *clsh_info;
        struct irq_domain *virq;
        struct regmap_irq_chip *wcd_regmap_irq_chip;
@@ -201,24 +207,70 @@ struct wcd938x_priv {
        bool bcs_dis;
 };
 
-enum {
-       MIC_BIAS_1 = 1,
-       MIC_BIAS_2,
-       MIC_BIAS_3,
-       MIC_BIAS_4
-};
-
-enum {
-       MICB_PULLUP_ENABLE,
-       MICB_PULLUP_DISABLE,
-       MICB_ENABLE,
-       MICB_DISABLE,
-};
-
 static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800);
 static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(line_gain, 600, -3000);
 static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(analog_gain, 0, 3000);
 
+struct wcd938x_mbhc_zdet_param {
+       u16 ldo_ctl;
+       u16 noff;
+       u16 nshift;
+       u16 btn5;
+       u16 btn6;
+       u16 btn7;
+};
+
+static struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {
+       WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD938X_ANA_MBHC_MECH, 0x80),
+       WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD938X_ANA_MBHC_MECH, 0x40),
+       WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD938X_ANA_MBHC_MECH, 0x20),
+       WCD_MBHC_FIELD(WCD_MBHC_MIC_CLAMP_CTL, WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x30),
+       WCD_MBHC_FIELD(WCD_MBHC_ELECT_DETECTION_TYPE, WCD938X_ANA_MBHC_ELECT, 0x08),
+       WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT, 0x1F),
+       WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, WCD938X_ANA_MBHC_MECH, 0x04),
+       WCD_MBHC_FIELD(WCD_MBHC_HPHL_PLUG_TYPE, WCD938X_ANA_MBHC_MECH, 0x10),
+       WCD_MBHC_FIELD(WCD_MBHC_GND_PLUG_TYPE, WCD938X_ANA_MBHC_MECH, 0x08),
+       WCD_MBHC_FIELD(WCD_MBHC_SW_HPH_LP_100K_TO_GND, WCD938X_ANA_MBHC_MECH, 0x01),
+       WCD_MBHC_FIELD(WCD_MBHC_ELECT_SCHMT_ISRC, WCD938X_ANA_MBHC_ELECT, 0x06),
+       WCD_MBHC_FIELD(WCD_MBHC_FSM_EN, WCD938X_ANA_MBHC_ELECT, 0x80),
+       WCD_MBHC_FIELD(WCD_MBHC_INSREM_DBNC, WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x0F),
+       WCD_MBHC_FIELD(WCD_MBHC_BTN_DBNC, WCD938X_MBHC_NEW_CTL_1, 0x03),
+       WCD_MBHC_FIELD(WCD_MBHC_HS_VREF, WCD938X_MBHC_NEW_CTL_2, 0x03),
+       WCD_MBHC_FIELD(WCD_MBHC_HS_COMP_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x08),
+       WCD_MBHC_FIELD(WCD_MBHC_IN2P_CLAMP_STATE, WCD938X_ANA_MBHC_RESULT_3, 0x10),
+       WCD_MBHC_FIELD(WCD_MBHC_MIC_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x20),
+       WCD_MBHC_FIELD(WCD_MBHC_HPHL_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x80),
+       WCD_MBHC_FIELD(WCD_MBHC_HPHR_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x40),
+       WCD_MBHC_FIELD(WCD_MBHC_OCP_FSM_EN, WCD938X_HPH_OCP_CTL, 0x10),
+       WCD_MBHC_FIELD(WCD_MBHC_BTN_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x07),
+       WCD_MBHC_FIELD(WCD_MBHC_BTN_ISRC_CTL, WCD938X_ANA_MBHC_ELECT, 0x70),
+       WCD_MBHC_FIELD(WCD_MBHC_ELECT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0xFF),
+       WCD_MBHC_FIELD(WCD_MBHC_MICB_CTRL, WCD938X_ANA_MICB2, 0xC0),
+       WCD_MBHC_FIELD(WCD_MBHC_HPH_CNP_WG_TIME, WCD938X_HPH_CNP_WG_TIME, 0xFF),
+       WCD_MBHC_FIELD(WCD_MBHC_HPHR_PA_EN, WCD938X_ANA_HPH, 0x40),
+       WCD_MBHC_FIELD(WCD_MBHC_HPHL_PA_EN, WCD938X_ANA_HPH, 0x80),
+       WCD_MBHC_FIELD(WCD_MBHC_HPH_PA_EN, WCD938X_ANA_HPH, 0xC0),
+       WCD_MBHC_FIELD(WCD_MBHC_SWCH_LEVEL_REMOVE, WCD938X_ANA_MBHC_RESULT_3, 0x10),
+       WCD_MBHC_FIELD(WCD_MBHC_ANC_DET_EN, WCD938X_MBHC_CTL_BCS, 0x02),
+       WCD_MBHC_FIELD(WCD_MBHC_FSM_STATUS, WCD938X_MBHC_NEW_FSM_STATUS, 0x01),
+       WCD_MBHC_FIELD(WCD_MBHC_MUX_CTL, WCD938X_MBHC_NEW_CTL_2, 0x70),
+       WCD_MBHC_FIELD(WCD_MBHC_MOISTURE_STATUS, WCD938X_MBHC_NEW_FSM_STATUS, 0x20),
+       WCD_MBHC_FIELD(WCD_MBHC_HPHR_GND, WCD938X_HPH_PA_CTL2, 0x40),
+       WCD_MBHC_FIELD(WCD_MBHC_HPHL_GND, WCD938X_HPH_PA_CTL2, 0x10),
+       WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_DET_EN, WCD938X_HPH_L_TEST, 0x01),
+       WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_DET_EN, WCD938X_HPH_R_TEST, 0x01),
+       WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_STATUS, WCD938X_DIGITAL_INTR_STATUS_0, 0x80),
+       WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_STATUS, WCD938X_DIGITAL_INTR_STATUS_0, 0x20),
+       WCD_MBHC_FIELD(WCD_MBHC_ADC_EN, WCD938X_MBHC_NEW_CTL_1, 0x08),
+       WCD_MBHC_FIELD(WCD_MBHC_ADC_COMPLETE, WCD938X_MBHC_NEW_FSM_STATUS, 0x40),
+       WCD_MBHC_FIELD(WCD_MBHC_ADC_TIMEOUT, WCD938X_MBHC_NEW_FSM_STATUS, 0x80),
+       WCD_MBHC_FIELD(WCD_MBHC_ADC_RESULT, WCD938X_MBHC_NEW_ADC_RESULT, 0xFF),
+       WCD_MBHC_FIELD(WCD_MBHC_MICB2_VOUT, WCD938X_ANA_MICB2, 0x3F),
+       WCD_MBHC_FIELD(WCD_MBHC_ADC_MODE, WCD938X_MBHC_NEW_CTL_1, 0x10),
+       WCD_MBHC_FIELD(WCD_MBHC_DETECTION_DONE, WCD938X_MBHC_NEW_CTL_1, 0x04),
+       WCD_MBHC_FIELD(WCD_MBHC_ELECT_ISRC_EN, WCD938X_ANA_MBHC_ZDET, 0x02),
+};
+
 static const struct reg_default wcd938x_defaults[] = {
        {WCD938X_ANA_PAGE_REGISTER,                            0x00},
        {WCD938X_ANA_BIAS,                                     0x00},
@@ -1360,7 +1412,6 @@ static int wcd938x_io_init(struct wcd938x_priv *wcd938x)
 
 static int wcd938x_sdw_connect_port(struct wcd938x_sdw_ch_info *ch_info,
                                    struct sdw_port_config *port_config,
-                                   u32 mstr_port_num,
                                    u8 enable)
 {
        u8 ch_mask, port_num;
@@ -1380,14 +1431,12 @@ static int wcd938x_sdw_connect_port(struct wcd938x_sdw_ch_info *ch_info,
 
 static int wcd938x_connect_port(struct wcd938x_sdw_priv *wcd, u8 ch_id, u8 enable)
 {
-       u8 port_num, mstr_port_num;
+       u8 port_num;
 
        port_num = wcd->ch_info[ch_id].port_num;
-       mstr_port_num = wcd->port_map[port_num - 1];
 
        return wcd938x_sdw_connect_port(&wcd->ch_info[ch_id],
                                        &wcd->port_config[port_num],
-                                       mstr_port_num,
                                        enable);
 }
 
@@ -1623,7 +1672,6 @@ static int wcd938x_codec_aux_dac_event(struct snd_soc_dapm_widget *w,
 {
        struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
        struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
-       int ret = 0;
 
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
@@ -1651,7 +1699,7 @@ static int wcd938x_codec_aux_dac_event(struct snd_soc_dapm_widget *w,
                                WCD938X_ANA_RX_DIV4_CLK_EN_MASK, 0);
                break;
        }
-       return ret;
+       return 0;
 
 }
 
@@ -1728,6 +1776,8 @@ static int wcd938x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
                        usleep_range(7000, 7100);
                snd_soc_component_write_field(component, WCD938X_ANA_HPH,
                                              WCD938X_HPHR_EN_MASK, 0);
+               wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+                                            WCD_EVENT_PRE_HPHR_PA_OFF);
                set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
                break;
        case SND_SOC_DAPM_POST_PMD:
@@ -1743,6 +1793,8 @@ static int wcd938x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
                                usleep_range(7000, 7100);
                        clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);
                }
+               wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+                                            WCD_EVENT_POST_HPHR_PA_OFF);
                snd_soc_component_write_field(component, WCD938X_ANA_HPH,
                                              WCD938X_HPHR_REF_EN_MASK, 0);
                snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL1,
@@ -1830,6 +1882,7 @@ static int wcd938x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
                        usleep_range(7000, 7100);
                snd_soc_component_write_field(component, WCD938X_ANA_HPH,
                                              WCD938X_HPHL_EN_MASK, 0);
+               wcd_mbhc_event_notify(wcd938x->wcd_mbhc, WCD_EVENT_PRE_HPHL_PA_OFF);
                set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
                break;
        case SND_SOC_DAPM_POST_PMD:
@@ -1845,6 +1898,8 @@ static int wcd938x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
                                usleep_range(7000, 7100);
                        clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);
                }
+               wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+                                            WCD_EVENT_POST_HPHL_PA_OFF);
                snd_soc_component_write_field(component, WCD938X_ANA_HPH,
                                              WCD938X_HPHL_REF_EN_MASK, 0);
                snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL0,
@@ -1866,7 +1921,6 @@ static int wcd938x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
        struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
        struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
        int hph_mode = wcd938x->hph_mode;
-       int ret = 0;
 
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
@@ -1902,7 +1956,7 @@ static int wcd938x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
                                                      WCD938X_EN_CUR_DET_MASK, 1);
                break;
        }
-       return ret;
+       return 0;
 }
 
 static int wcd938x_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
@@ -2355,7 +2409,14 @@ static int wcd938x_micbias_control(struct snd_soc_component *component,
                        snd_soc_component_write_field(component, micb_reg,
                                                      WCD938X_MICB_EN_MASK,
                                                      WCD938X_MICB_ENABLE);
+                       if (micb_num  == MIC_BIAS_2)
+                               wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+                                                     WCD_EVENT_POST_MICBIAS_2_ON);
                }
+               if (micb_num  == MIC_BIAS_2 && is_dapm)
+                       wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+                                             WCD_EVENT_POST_DAPM_MICBIAS_2_ON);
+
 
                break;
        case MICB_DISABLE:
@@ -2369,10 +2430,19 @@ static int wcd938x_micbias_control(struct snd_soc_component *component,
                                                      WCD938X_MICB_PULL_UP);
                else if ((wcd938x->micb_ref[micb_index] == 0) &&
                         (wcd938x->pullup_ref[micb_index] == 0)) {
+                       if (micb_num  == MIC_BIAS_2)
+                               wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+                                                     WCD_EVENT_PRE_MICBIAS_2_OFF);
 
                        snd_soc_component_write_field(component, micb_reg,
                                                      WCD938X_MICB_EN_MASK, 0);
+                       if (micb_num  == MIC_BIAS_2)
+                               wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+                                                     WCD_EVENT_POST_MICBIAS_2_OFF);
                }
+               if (is_dapm && micb_num  == MIC_BIAS_2)
+                       wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+                                             WCD_EVENT_POST_DAPM_MICBIAS_2_OFF);
                break;
        }
 
@@ -2845,6 +2915,704 @@ static int wcd938x_set_swr_port(struct snd_kcontrol *kcontrol,
 
 }
 
+/* MBHC related */
+static void wcd938x_mbhc_clk_setup(struct snd_soc_component *component,
+                                  bool enable)
+{
+       snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_1,
+                                     WCD938X_MBHC_CTL_RCO_EN_MASK, enable);
+}
+
+static void wcd938x_mbhc_mbhc_bias_control(struct snd_soc_component *component,
+                                          bool enable)
+{
+       snd_soc_component_write_field(component, WCD938X_ANA_MBHC_ELECT,
+                                     WCD938X_ANA_MBHC_BIAS_EN, enable);
+}
+
+static void wcd938x_mbhc_program_btn_thr(struct snd_soc_component *component,
+                                        int *btn_low, int *btn_high,
+                                        int num_btn, bool is_micbias)
+{
+       int i, vth;
+
+       if (num_btn > WCD_MBHC_DEF_BUTTONS) {
+               dev_err(component->dev, "%s: invalid number of buttons: %d\n",
+                       __func__, num_btn);
+               return;
+       }
+
+       for (i = 0; i < num_btn; i++) {
+               vth = ((btn_high[i] * 2) / 25) & 0x3F;
+               snd_soc_component_write_field(component, WCD938X_ANA_MBHC_BTN0 + i,
+                                          WCD938X_MBHC_BTN_VTH_MASK, vth);
+               dev_dbg(component->dev, "%s: btn_high[%d]: %d, vth: %d\n",
+                       __func__, i, btn_high[i], vth);
+       }
+}
+
+static bool wcd938x_mbhc_micb_en_status(struct snd_soc_component *component, int micb_num)
+{
+       u8 val;
+
+       if (micb_num == MIC_BIAS_2) {
+               val = snd_soc_component_read_field(component,
+                                                  WCD938X_ANA_MICB2,
+                                                  WCD938X_ANA_MICB2_ENABLE_MASK);
+               if (val == WCD938X_MICB_ENABLE)
+                       return true;
+       }
+       return false;
+}
+
+static void wcd938x_mbhc_hph_l_pull_up_control(struct snd_soc_component *component,
+                                                       int pull_up_cur)
+{
+       /* Default pull up current to 2uA */
+       if (pull_up_cur > HS_PULLUP_I_OFF || pull_up_cur < HS_PULLUP_I_3P0_UA)
+               pull_up_cur = HS_PULLUP_I_2P0_UA;
+
+       snd_soc_component_write_field(component,
+                                     WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT,
+                                     WCD938X_HSDET_PULLUP_C_MASK, pull_up_cur);
+}
+
+static int wcd938x_mbhc_request_micbias(struct snd_soc_component *component,
+                                       int micb_num, int req)
+{
+       return wcd938x_micbias_control(component, micb_num, req, false);
+}
+
+static void wcd938x_mbhc_micb_ramp_control(struct snd_soc_component *component,
+                                          bool enable)
+{
+       if (enable) {
+               snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,
+                                   WCD938X_RAMP_SHIFT_CTRL_MASK, 0x0C);
+               snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,
+                                   WCD938X_RAMP_EN_MASK, 1);
+       } else {
+               snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,
+                                   WCD938X_RAMP_EN_MASK, 0);
+               snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,
+                                   WCD938X_RAMP_SHIFT_CTRL_MASK, 0);
+       }
+}
+
+static int wcd938x_get_micb_vout_ctl_val(u32 micb_mv)
+{
+       /* min micbias voltage is 1V and maximum is 2.85V */
+       if (micb_mv < 1000 || micb_mv > 2850)
+               return -EINVAL;
+
+       return (micb_mv - 1000) / 50;
+}
+
+static int wcd938x_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
+                                           int req_volt, int micb_num)
+{
+       struct wcd938x_priv *wcd938x =  snd_soc_component_get_drvdata(component);
+       int cur_vout_ctl, req_vout_ctl, micb_reg, micb_en, ret = 0;
+
+       switch (micb_num) {
+       case MIC_BIAS_1:
+               micb_reg = WCD938X_ANA_MICB1;
+               break;
+       case MIC_BIAS_2:
+               micb_reg = WCD938X_ANA_MICB2;
+               break;
+       case MIC_BIAS_3:
+               micb_reg = WCD938X_ANA_MICB3;
+               break;
+       case MIC_BIAS_4:
+               micb_reg = WCD938X_ANA_MICB4;
+               break;
+       default:
+               return -EINVAL;
+       }
+       mutex_lock(&wcd938x->micb_lock);
+       /*
+        * If requested micbias voltage is same as current micbias
+        * voltage, then just return. Otherwise, adjust voltage as
+        * per requested value. If micbias is already enabled, then
+        * to avoid slow micbias ramp-up or down enable pull-up
+        * momentarily, change the micbias value and then re-enable
+        * micbias.
+        */
+       micb_en = snd_soc_component_read_field(component, micb_reg,
+                                               WCD938X_MICB_EN_MASK);
+       cur_vout_ctl = snd_soc_component_read_field(component, micb_reg,
+                                                   WCD938X_MICB_VOUT_MASK);
+
+       req_vout_ctl = wcd938x_get_micb_vout_ctl_val(req_volt);
+       if (req_vout_ctl < 0) {
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       if (cur_vout_ctl == req_vout_ctl) {
+               ret = 0;
+               goto exit;
+       }
+
+       if (micb_en == WCD938X_MICB_ENABLE)
+               snd_soc_component_write_field(component, micb_reg,
+                                             WCD938X_MICB_EN_MASK,
+                                             WCD938X_MICB_PULL_UP);
+
+       snd_soc_component_write_field(component, micb_reg,
+                                     WCD938X_MICB_VOUT_MASK,
+                                     req_vout_ctl);
+
+       if (micb_en == WCD938X_MICB_ENABLE) {
+               snd_soc_component_write_field(component, micb_reg,
+                                             WCD938X_MICB_EN_MASK,
+                                             WCD938X_MICB_ENABLE);
+               /*
+                * Add 2ms delay as per HW requirement after enabling
+                * micbias
+                */
+               usleep_range(2000, 2100);
+       }
+exit:
+       mutex_unlock(&wcd938x->micb_lock);
+       return ret;
+}
+
+static int wcd938x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *component,
+                                               int micb_num, bool req_en)
+{
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+       int rc, micb_mv;
+
+       if (micb_num != MIC_BIAS_2)
+               return -EINVAL;
+       /*
+        * If device tree micbias level is already above the minimum
+        * voltage needed to detect threshold microphone, then do
+        * not change the micbias, just return.
+        */
+       if (wcd938x->micb2_mv >= WCD_MBHC_THR_HS_MICB_MV)
+               return 0;
+
+       micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd938x->micb2_mv;
+
+       rc = wcd938x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2);
+
+       return rc;
+}
+
+static inline void wcd938x_mbhc_get_result_params(struct wcd938x_priv *wcd938x,
+                                               s16 *d1_a, u16 noff,
+                                               int32_t *zdet)
+{
+       int i;
+       int val, val1;
+       s16 c1;
+       s32 x1, d1;
+       int32_t denom;
+       int minCode_param[] = {
+                       3277, 1639, 820, 410, 205, 103, 52, 26
+       };
+
+       regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x20);
+       for (i = 0; i < WCD938X_ZDET_NUM_MEASUREMENTS; i++) {
+               regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_2, &val);
+               if (val & 0x80)
+                       break;
+       }
+       val = val << 0x8;
+       regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_1, &val1);
+       val |= val1;
+       regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x00);
+       x1 = WCD938X_MBHC_GET_X1(val);
+       c1 = WCD938X_MBHC_GET_C1(val);
+       /* If ramp is not complete, give additional 5ms */
+       if ((c1 < 2) && x1)
+               usleep_range(5000, 5050);
+
+       if (!c1 || !x1) {
+               pr_err("%s: Impedance detect ramp error, c1=%d, x1=0x%x\n",
+                       __func__, c1, x1);
+               goto ramp_down;
+       }
+       d1 = d1_a[c1];
+       denom = (x1 * d1) - (1 << (14 - noff));
+       if (denom > 0)
+               *zdet = (WCD938X_MBHC_ZDET_CONST * 1000) / denom;
+       else if (x1 < minCode_param[noff])
+               *zdet = WCD938X_ZDET_FLOATING_IMPEDANCE;
+
+       pr_err("%s: d1=%d, c1=%d, x1=0x%x, z_val=%d(milliOhm)\n",
+               __func__, d1, c1, x1, *zdet);
+ramp_down:
+       i = 0;
+       while (x1) {
+               regmap_read(wcd938x->regmap,
+                                WCD938X_ANA_MBHC_RESULT_1, &val);
+               regmap_read(wcd938x->regmap,
+                                WCD938X_ANA_MBHC_RESULT_2, &val1);
+               val = val << 0x08;
+               val |= val1;
+               x1 = WCD938X_MBHC_GET_X1(val);
+               i++;
+               if (i == WCD938X_ZDET_NUM_MEASUREMENTS)
+                       break;
+       }
+}
+
+static void wcd938x_mbhc_zdet_ramp(struct snd_soc_component *component,
+                                struct wcd938x_mbhc_zdet_param *zdet_param,
+                                int32_t *zl, int32_t *zr, s16 *d1_a)
+{
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+       int32_t zdet = 0;
+
+       snd_soc_component_write_field(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL,
+                               WCD938X_ZDET_MAXV_CTL_MASK, zdet_param->ldo_ctl);
+       snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN5,
+                                   WCD938X_VTH_MASK, zdet_param->btn5);
+       snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN6,
+                                     WCD938X_VTH_MASK, zdet_param->btn6);
+       snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN7,
+                                    WCD938X_VTH_MASK, zdet_param->btn7);
+       snd_soc_component_write_field(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL,
+                               WCD938X_ZDET_RANGE_CTL_MASK, zdet_param->noff);
+       snd_soc_component_update_bits(component, WCD938X_MBHC_NEW_ZDET_RAMP_CTL,
+                               0x0F, zdet_param->nshift);
+
+       if (!zl)
+               goto z_right;
+       /* Start impedance measurement for HPH_L */
+       regmap_update_bits(wcd938x->regmap,
+                          WCD938X_ANA_MBHC_ZDET, 0x80, 0x80);
+       dev_dbg(component->dev, "%s: ramp for HPH_L, noff = %d\n",
+               __func__, zdet_param->noff);
+       wcd938x_mbhc_get_result_params(wcd938x, d1_a, zdet_param->noff, &zdet);
+       regmap_update_bits(wcd938x->regmap,
+                          WCD938X_ANA_MBHC_ZDET, 0x80, 0x00);
+
+       *zl = zdet;
+
+z_right:
+       if (!zr)
+               return;
+       /* Start impedance measurement for HPH_R */
+       regmap_update_bits(wcd938x->regmap,
+                          WCD938X_ANA_MBHC_ZDET, 0x40, 0x40);
+       dev_dbg(component->dev, "%s: ramp for HPH_R, noff = %d\n",
+               __func__, zdet_param->noff);
+       wcd938x_mbhc_get_result_params(wcd938x, d1_a, zdet_param->noff, &zdet);
+       regmap_update_bits(wcd938x->regmap,
+                          WCD938X_ANA_MBHC_ZDET, 0x40, 0x00);
+
+       *zr = zdet;
+}
+
+static inline void wcd938x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component,
+                                             int32_t *z_val, int flag_l_r)
+{
+       s16 q1;
+       int q1_cal;
+
+       if (*z_val < (WCD938X_ZDET_VAL_400/1000))
+               q1 = snd_soc_component_read(component,
+                       WCD938X_DIGITAL_EFUSE_REG_23 + (2 * flag_l_r));
+       else
+               q1 = snd_soc_component_read(component,
+                       WCD938X_DIGITAL_EFUSE_REG_24 + (2 * flag_l_r));
+       if (q1 & 0x80)
+               q1_cal = (10000 - ((q1 & 0x7F) * 25));
+       else
+               q1_cal = (10000 + (q1 * 25));
+       if (q1_cal > 0)
+               *z_val = ((*z_val) * 10000) / q1_cal;
+}
+
+static void wcd938x_wcd_mbhc_calc_impedance(struct snd_soc_component *component,
+                                           uint32_t *zl, uint32_t *zr)
+{
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+       s16 reg0, reg1, reg2, reg3, reg4;
+       int32_t z1L, z1R, z1Ls;
+       int zMono, z_diff1, z_diff2;
+       bool is_fsm_disable = false;
+       struct wcd938x_mbhc_zdet_param zdet_param[] = {
+               {4, 0, 4, 0x08, 0x14, 0x18}, /* < 32ohm */
+               {2, 0, 3, 0x18, 0x7C, 0x90}, /* 32ohm < Z < 400ohm */
+               {1, 4, 5, 0x18, 0x7C, 0x90}, /* 400ohm < Z < 1200ohm */
+               {1, 6, 7, 0x18, 0x7C, 0x90}, /* >1200ohm */
+       };
+       struct wcd938x_mbhc_zdet_param *zdet_param_ptr = NULL;
+       s16 d1_a[][4] = {
+               {0, 30, 90, 30},
+               {0, 30, 30, 5},
+               {0, 30, 30, 5},
+               {0, 30, 30, 5},
+       };
+       s16 *d1 = NULL;
+
+       reg0 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN5);
+       reg1 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN6);
+       reg2 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN7);
+       reg3 = snd_soc_component_read(component, WCD938X_MBHC_CTL_CLK);
+       reg4 = snd_soc_component_read(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL);
+
+       if (snd_soc_component_read(component, WCD938X_ANA_MBHC_ELECT) & 0x80) {
+               is_fsm_disable = true;
+               regmap_update_bits(wcd938x->regmap,
+                                  WCD938X_ANA_MBHC_ELECT, 0x80, 0x00);
+       }
+
+       /* For NO-jack, disable L_DET_EN before Z-det measurements */
+       if (wcd938x->mbhc_cfg.hphl_swh)
+               regmap_update_bits(wcd938x->regmap,
+                                  WCD938X_ANA_MBHC_MECH, 0x80, 0x00);
+
+       /* Turn off 100k pull down on HPHL */
+       regmap_update_bits(wcd938x->regmap,
+                          WCD938X_ANA_MBHC_MECH, 0x01, 0x00);
+
+       /* Disable surge protection before impedance detection.
+        * This is done to give correct value for high impedance.
+        */
+       regmap_update_bits(wcd938x->regmap,
+                          WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0x00);
+       /* 1ms delay needed after disable surge protection */
+       usleep_range(1000, 1010);
+
+       /* First get impedance on Left */
+       d1 = d1_a[1];
+       zdet_param_ptr = &zdet_param[1];
+       wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);
+
+       if (!WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1L))
+               goto left_ch_impedance;
+
+       /* Second ramp for left ch */
+       if (z1L < WCD938X_ZDET_VAL_32) {
+               zdet_param_ptr = &zdet_param[0];
+               d1 = d1_a[0];
+       } else if ((z1L > WCD938X_ZDET_VAL_400) &&
+                 (z1L <= WCD938X_ZDET_VAL_1200)) {
+               zdet_param_ptr = &zdet_param[2];
+               d1 = d1_a[2];
+       } else if (z1L > WCD938X_ZDET_VAL_1200) {
+               zdet_param_ptr = &zdet_param[3];
+               d1 = d1_a[3];
+       }
+       wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);
+
+left_ch_impedance:
+       if ((z1L == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
+               (z1L > WCD938X_ZDET_VAL_100K)) {
+               *zl = WCD938X_ZDET_FLOATING_IMPEDANCE;
+               zdet_param_ptr = &zdet_param[1];
+               d1 = d1_a[1];
+       } else {
+               *zl = z1L/1000;
+               wcd938x_wcd_mbhc_qfuse_cal(component, zl, 0);
+       }
+       dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n",
+               __func__, *zl);
+
+       /* Start of right impedance ramp and calculation */
+       wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1);
+       if (WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1R)) {
+               if (((z1R > WCD938X_ZDET_VAL_1200) &&
+                       (zdet_param_ptr->noff == 0x6)) ||
+                       ((*zl) != WCD938X_ZDET_FLOATING_IMPEDANCE))
+                       goto right_ch_impedance;
+               /* Second ramp for right ch */
+               if (z1R < WCD938X_ZDET_VAL_32) {
+                       zdet_param_ptr = &zdet_param[0];
+                       d1 = d1_a[0];
+               } else if ((z1R > WCD938X_ZDET_VAL_400) &&
+                       (z1R <= WCD938X_ZDET_VAL_1200)) {
+                       zdet_param_ptr = &zdet_param[2];
+                       d1 = d1_a[2];
+               } else if (z1R > WCD938X_ZDET_VAL_1200) {
+                       zdet_param_ptr = &zdet_param[3];
+                       d1 = d1_a[3];
+               }
+               wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1);
+       }
+right_ch_impedance:
+       if ((z1R == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
+               (z1R > WCD938X_ZDET_VAL_100K)) {
+               *zr = WCD938X_ZDET_FLOATING_IMPEDANCE;
+       } else {
+               *zr = z1R/1000;
+               wcd938x_wcd_mbhc_qfuse_cal(component, zr, 1);
+       }
+       dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n",
+               __func__, *zr);
+
+       /* Mono/stereo detection */
+       if ((*zl == WCD938X_ZDET_FLOATING_IMPEDANCE) &&
+               (*zr == WCD938X_ZDET_FLOATING_IMPEDANCE)) {
+               dev_dbg(component->dev,
+                       "%s: plug type is invalid or extension cable\n",
+                       __func__);
+               goto zdet_complete;
+       }
+       if ((*zl == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
+           (*zr == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
+           ((*zl < WCD_MONO_HS_MIN_THR) && (*zr > WCD_MONO_HS_MIN_THR)) ||
+           ((*zl > WCD_MONO_HS_MIN_THR) && (*zr < WCD_MONO_HS_MIN_THR))) {
+               dev_dbg(component->dev,
+                       "%s: Mono plug type with one ch floating or shorted to GND\n",
+                       __func__);
+               wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_MONO);
+               goto zdet_complete;
+       }
+       snd_soc_component_write_field(component, WCD938X_HPH_R_ATEST,
+                                     WCD938X_HPHPA_GND_OVR_MASK, 1);
+       snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,
+                                     WCD938X_HPHPA_GND_R_MASK, 1);
+       if (*zl < (WCD938X_ZDET_VAL_32/1000))
+               wcd938x_mbhc_zdet_ramp(component, &zdet_param[0], &z1Ls, NULL, d1);
+       else
+               wcd938x_mbhc_zdet_ramp(component, &zdet_param[1], &z1Ls, NULL, d1);
+       snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,
+                                     WCD938X_HPHPA_GND_R_MASK, 0);
+       snd_soc_component_write_field(component, WCD938X_HPH_R_ATEST,
+                                     WCD938X_HPHPA_GND_OVR_MASK, 0);
+       z1Ls /= 1000;
+       wcd938x_wcd_mbhc_qfuse_cal(component, &z1Ls, 0);
+       /* Parallel of left Z and 9 ohm pull down resistor */
+       zMono = ((*zl) * 9) / ((*zl) + 9);
+       z_diff1 = (z1Ls > zMono) ? (z1Ls - zMono) : (zMono - z1Ls);
+       z_diff2 = ((*zl) > z1Ls) ? ((*zl) - z1Ls) : (z1Ls - (*zl));
+       if ((z_diff1 * (*zl + z1Ls)) > (z_diff2 * (z1Ls + zMono))) {
+               dev_dbg(component->dev, "%s: stereo plug type detected\n",
+                       __func__);
+               wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_STEREO);
+       } else {
+               dev_dbg(component->dev, "%s: MONO plug type detected\n",
+                       __func__);
+               wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_MONO);
+       }
+
+       /* Enable surge protection again after impedance detection */
+       regmap_update_bits(wcd938x->regmap,
+                          WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0);
+zdet_complete:
+       snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN5, reg0);
+       snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN6, reg1);
+       snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN7, reg2);
+       /* Turn on 100k pull down on HPHL */
+       regmap_update_bits(wcd938x->regmap,
+                          WCD938X_ANA_MBHC_MECH, 0x01, 0x01);
+
+       /* For NO-jack, re-enable L_DET_EN after Z-det measurements */
+       if (wcd938x->mbhc_cfg.hphl_swh)
+               regmap_update_bits(wcd938x->regmap,
+                                  WCD938X_ANA_MBHC_MECH, 0x80, 0x80);
+
+       snd_soc_component_write(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL, reg4);
+       snd_soc_component_write(component, WCD938X_MBHC_CTL_CLK, reg3);
+       if (is_fsm_disable)
+               regmap_update_bits(wcd938x->regmap,
+                                  WCD938X_ANA_MBHC_ELECT, 0x80, 0x80);
+}
+
+static void wcd938x_mbhc_gnd_det_ctrl(struct snd_soc_component *component,
+                       bool enable)
+{
+       if (enable) {
+               snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,
+                                             WCD938X_MBHC_HSG_PULLUP_COMP_EN, 1);
+               snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,
+                                             WCD938X_MBHC_GND_DET_EN_MASK, 1);
+       } else {
+               snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,
+                                             WCD938X_MBHC_GND_DET_EN_MASK, 0);
+               snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,
+                                             WCD938X_MBHC_HSG_PULLUP_COMP_EN, 0);
+       }
+}
+
+static void wcd938x_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component,
+                                         bool enable)
+{
+       snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,
+                                     WCD938X_HPHPA_GND_R_MASK, enable);
+       snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,
+                                     WCD938X_HPHPA_GND_L_MASK, enable);
+}
+
+static void wcd938x_mbhc_moisture_config(struct snd_soc_component *component)
+{
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+       if (wcd938x->mbhc_cfg.moist_rref == R_OFF) {
+               snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+                                   WCD938X_M_RTH_CTL_MASK, R_OFF);
+               return;
+       }
+
+       /* Do not enable moisture detection if jack type is NC */
+       if (!wcd938x->mbhc_cfg.hphl_swh) {
+               dev_dbg(component->dev, "%s: disable moisture detection for NC\n",
+                       __func__);
+               snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+                                   WCD938X_M_RTH_CTL_MASK, R_OFF);
+               return;
+       }
+
+       snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+                           WCD938X_M_RTH_CTL_MASK, wcd938x->mbhc_cfg.moist_rref);
+}
+
+static void wcd938x_mbhc_moisture_detect_en(struct snd_soc_component *component, bool enable)
+{
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+       if (enable)
+               snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+                                       WCD938X_M_RTH_CTL_MASK, wcd938x->mbhc_cfg.moist_rref);
+       else
+               snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+                                   WCD938X_M_RTH_CTL_MASK, R_OFF);
+}
+
+static bool wcd938x_mbhc_get_moisture_status(struct snd_soc_component *component)
+{
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+       bool ret = false;
+
+       if (wcd938x->mbhc_cfg.moist_rref == R_OFF) {
+               snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+                                   WCD938X_M_RTH_CTL_MASK, R_OFF);
+               goto done;
+       }
+
+       /* Do not enable moisture detection if jack type is NC */
+       if (!wcd938x->mbhc_cfg.hphl_swh) {
+               dev_dbg(component->dev, "%s: disable moisture detection for NC\n",
+                       __func__);
+               snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+                                   WCD938X_M_RTH_CTL_MASK, R_OFF);
+               goto done;
+       }
+
+       /*
+        * If moisture_en is already enabled, then skip to plug type
+        * detection.
+        */
+       if (snd_soc_component_read_field(component, WCD938X_MBHC_NEW_CTL_2, WCD938X_M_RTH_CTL_MASK))
+               goto done;
+
+       wcd938x_mbhc_moisture_detect_en(component, true);
+       /* Read moisture comparator status */
+       ret = ((snd_soc_component_read(component, WCD938X_MBHC_NEW_FSM_STATUS)
+                               & 0x20) ? 0 : 1);
+
+done:
+       return ret;
+
+}
+
+static void wcd938x_mbhc_moisture_polling_ctrl(struct snd_soc_component *component,
+                                               bool enable)
+{
+       snd_soc_component_write_field(component,
+                             WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL,
+                             WCD938X_MOISTURE_EN_POLLING_MASK, enable);
+}
+
+static const struct wcd_mbhc_cb mbhc_cb = {
+       .clk_setup = wcd938x_mbhc_clk_setup,
+       .mbhc_bias = wcd938x_mbhc_mbhc_bias_control,
+       .set_btn_thr = wcd938x_mbhc_program_btn_thr,
+       .micbias_enable_status = wcd938x_mbhc_micb_en_status,
+       .hph_pull_up_control_v2 = wcd938x_mbhc_hph_l_pull_up_control,
+       .mbhc_micbias_control = wcd938x_mbhc_request_micbias,
+       .mbhc_micb_ramp_control = wcd938x_mbhc_micb_ramp_control,
+       .mbhc_micb_ctrl_thr_mic = wcd938x_mbhc_micb_ctrl_threshold_mic,
+       .compute_impedance = wcd938x_wcd_mbhc_calc_impedance,
+       .mbhc_gnd_det_ctrl = wcd938x_mbhc_gnd_det_ctrl,
+       .hph_pull_down_ctrl = wcd938x_mbhc_hph_pull_down_ctrl,
+       .mbhc_moisture_config = wcd938x_mbhc_moisture_config,
+       .mbhc_get_moisture_status = wcd938x_mbhc_get_moisture_status,
+       .mbhc_moisture_polling_ctrl = wcd938x_mbhc_moisture_polling_ctrl,
+       .mbhc_moisture_detect_en = wcd938x_mbhc_moisture_detect_en,
+};
+
+static int wcd938x_get_hph_type(struct snd_kcontrol *kcontrol,
+                             struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+       ucontrol->value.integer.value[0] = wcd_mbhc_get_hph_type(wcd938x->wcd_mbhc);
+
+       return 0;
+}
+
+static int wcd938x_hph_impedance_get(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       uint32_t zl, zr;
+       bool hphr;
+       struct soc_mixer_control *mc;
+       struct snd_soc_component *component =
+                                       snd_soc_kcontrol_component(kcontrol);
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+       mc = (struct soc_mixer_control *)(kcontrol->private_value);
+       hphr = mc->shift;
+       wcd_mbhc_get_impedance(wcd938x->wcd_mbhc, &zl, &zr);
+       dev_dbg(component->dev, "%s: zl=%u(ohms), zr=%u(ohms)\n", __func__, zl, zr);
+       ucontrol->value.integer.value[0] = hphr ? zr : zl;
+
+       return 0;
+}
+
+static const struct snd_kcontrol_new hph_type_detect_controls[] = {
+       SOC_SINGLE_EXT("HPH Type", 0, 0, UINT_MAX, 0,
+                      wcd938x_get_hph_type, NULL),
+};
+
+static const struct snd_kcontrol_new impedance_detect_controls[] = {
+       SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
+                      wcd938x_hph_impedance_get, NULL),
+       SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
+                      wcd938x_hph_impedance_get, NULL),
+};
+
+static int wcd938x_mbhc_init(struct snd_soc_component *component)
+{
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+       struct wcd_mbhc_intr *intr_ids = &wcd938x->intr_ids;
+
+       intr_ids->mbhc_sw_intr = regmap_irq_get_virq(wcd938x->irq_chip,
+                                                   WCD938X_IRQ_MBHC_SW_DET);
+       intr_ids->mbhc_btn_press_intr = regmap_irq_get_virq(wcd938x->irq_chip,
+                                                          WCD938X_IRQ_MBHC_BUTTON_PRESS_DET);
+       intr_ids->mbhc_btn_release_intr = regmap_irq_get_virq(wcd938x->irq_chip,
+                                                            WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET);
+       intr_ids->mbhc_hs_ins_intr = regmap_irq_get_virq(wcd938x->irq_chip,
+                                                       WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET);
+       intr_ids->mbhc_hs_rem_intr = regmap_irq_get_virq(wcd938x->irq_chip,
+                                                       WCD938X_IRQ_MBHC_ELECT_INS_REM_DET);
+       intr_ids->hph_left_ocp = regmap_irq_get_virq(wcd938x->irq_chip,
+                                                   WCD938X_IRQ_HPHL_OCP_INT);
+       intr_ids->hph_right_ocp = regmap_irq_get_virq(wcd938x->irq_chip,
+                                                    WCD938X_IRQ_HPHR_OCP_INT);
+
+       wcd938x->wcd_mbhc = wcd_mbhc_init(component, &mbhc_cb, intr_ids, wcd_mbhc_fields, true);
+
+       snd_soc_add_component_controls(component, impedance_detect_controls,
+                                      ARRAY_SIZE(impedance_detect_controls));
+       snd_soc_add_component_controls(component, hph_type_detect_controls,
+                                      ARRAY_SIZE(hph_type_detect_controls));
+
+       return 0;
+}
+/* END MBHC */
+
 static const struct snd_kcontrol_new wcd938x_snd_controls[] = {
        SOC_SINGLE_EXT("HPHL_COMP Switch", WCD938X_COMP_L, 0, 1, 0,
                       wcd938x_get_compander, wcd938x_set_compander),
@@ -3225,15 +3993,6 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = {
        {"EAR", NULL, "EAR PGA"},
 };
 
-static int wcd938x_get_micb_vout_ctl_val(u32 micb_mv)
-{
-       /* min micbias voltage is 1V and maximum is 2.85V */
-       if (micb_mv < 1000 || micb_mv > 2850)
-               return -EINVAL;
-
-       return (micb_mv - 1000) / 50;
-}
-
 static int wcd938x_set_micbias_data(struct wcd938x_priv *wcd938x)
 {
        int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4;
@@ -3372,10 +4131,27 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
        default:
                break;
        }
+
+       ret = wcd938x_mbhc_init(component);
+       if (ret)
+               dev_err(component->dev,  "mbhc initialization failed\n");
 err:
        return ret;
 }
 
+static int wcd938x_codec_set_jack(struct snd_soc_component *comp,
+                                 struct snd_soc_jack *jack, void *data)
+{
+       struct wcd938x_priv *wcd = dev_get_drvdata(comp->dev);
+
+       if (!jack)
+               return wcd_mbhc_start(wcd->wcd_mbhc, &wcd->mbhc_cfg, jack);
+
+       wcd_mbhc_stop(wcd->wcd_mbhc);
+
+       return 0;
+}
+
 static const struct snd_soc_component_driver soc_codec_dev_wcd938x = {
        .name = "wcd938x_codec",
        .probe = wcd938x_soc_codec_probe,
@@ -3385,6 +4161,7 @@ static const struct snd_soc_component_driver soc_codec_dev_wcd938x = {
        .num_dapm_widgets = ARRAY_SIZE(wcd938x_dapm_widgets),
        .dapm_routes = wcd938x_audio_map,
        .num_dapm_routes = ARRAY_SIZE(wcd938x_audio_map),
+       .set_jack = wcd938x_codec_set_jack,
 };
 
 static void wcd938x_dt_parse_micbias_info(struct device *dev, struct wcd938x_priv *wcd)
@@ -3420,6 +4197,7 @@ static void wcd938x_dt_parse_micbias_info(struct device *dev, struct wcd938x_pri
 
 static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device *dev)
 {
+       struct wcd_mbhc_config *cfg = &wcd938x->mbhc_cfg;
        int ret;
 
        wcd938x->reset_gpio = of_get_named_gpio(dev->of_node, "reset-gpios", 0);
@@ -3448,6 +4226,17 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device
 
        wcd938x_dt_parse_micbias_info(dev, wcd938x);
 
+       cfg->mbhc_micbias = MIC_BIAS_2;
+       cfg->anc_micbias = MIC_BIAS_2;
+       cfg->v_hs_max = WCD_MBHC_HS_V_MAX;
+       cfg->num_btn = WCD938X_MBHC_MAX_BUTTONS;
+       cfg->micb_mv = wcd938x->micb2_mv;
+       cfg->linein_th = 5000;
+       cfg->hs_thr = 1700;
+       cfg->hph_thr = 50;
+
+       wcd_dt_parse_mbhc_data(dev, cfg);
+
        return 0;
 }
 
@@ -3679,6 +4468,7 @@ static int wcd938x_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        dev_set_drvdata(dev, wcd938x);
+       mutex_init(&wcd938x->micb_lock);
 
        ret = wcd938x_populate_dt_data(wcd938x, dev);
        if (ret) {
@@ -3703,7 +4493,7 @@ static int wcd938x_probe(struct platform_device *pdev)
        pm_runtime_enable(dev);
        pm_runtime_idle(dev);
 
-       return ret;
+       return 0;
 }
 
 static int wcd938x_remove(struct platform_device *pdev)
index 07b08de..ea82039 100644 (file)
@@ -658,7 +658,6 @@ struct wcd938x_sdw_priv {
        struct sdw_port_config port_config[WCD938X_MAX_SWR_PORTS];
        struct wcd938x_sdw_ch_info *ch_info;
        bool port_enable[WCD938X_MAX_SWR_CH_IDS];
-       int port_map[WCD938X_MAX_SWR_PORTS];
        int active_ports;
        int num_ports;
        bool is_tx;
index fe15cbc..f7c8009 100644 (file)
@@ -747,6 +747,8 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
 static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
 {
        wm_adsp_debugfs_clear(dsp);
+       debugfs_remove_recursive(dsp->debugfs_root);
+       dsp->debugfs_root = NULL;
 }
 #else
 static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
@@ -2029,10 +2031,9 @@ static struct wm_coeff_ctl *wm_adsp_get_ctl(struct wm_adsp *dsp,
                if (!pos->subname)
                        continue;
                if (strncmp(pos->subname, name, pos->subname_len) == 0 &&
-                   strncmp(pos->fw_name, fw_txt,
-                           SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0 &&
-                               pos->alg_region.alg == alg &&
-                               pos->alg_region.type == type) {
+                   pos->fw_name == fw_txt &&
+                   pos->alg_region.alg == alg &&
+                   pos->alg_region.type == type) {
                        rslt = pos;
                        break;
                }
index 8ebf76e..33ce257 100644 (file)
@@ -642,7 +642,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
 
        dev->dev = &pdev->dev;
 
-       irq = platform_get_irq(pdev, 0);
+       irq = platform_get_irq_optional(pdev, 0);
        if (irq >= 0) {
                ret = devm_request_irq(&pdev->dev, irq, i2s_irq_handler, 0,
                                pdev->name, dev);
index c313a26..cd9b36e 100644 (file)
@@ -284,8 +284,6 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
                return ret;
        }
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
        return 0;
 }
 
@@ -297,8 +295,6 @@ static int fsl_asrc_dma_hw_free(struct snd_soc_component *component,
        struct fsl_asrc_pair *pair = runtime->private_data;
        u8 dir = tx ? OUT : IN;
 
-       snd_pcm_set_runtime_buffer(substream, NULL);
-
        if (pair->dma_chan[!dir])
                dma_release_channel(pair->dma_chan[!dir]);
 
@@ -423,9 +419,8 @@ static int fsl_asrc_dma_pcm_new(struct snd_soc_component *component,
                                struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
-       struct snd_pcm_substream *substream;
        struct snd_pcm *pcm = rtd->pcm;
-       int ret, i;
+       int ret;
 
        ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
        if (ret) {
@@ -433,43 +428,8 @@ static int fsl_asrc_dma_pcm_new(struct snd_soc_component *component,
                return ret;
        }
 
-       for_each_pcm_streams(i) {
-               substream = pcm->streams[i].substream;
-               if (!substream)
-                       continue;
-
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
-                               FSL_ASRC_DMABUF_SIZE, &substream->dma_buffer);
-               if (ret) {
-                       dev_err(card->dev, "failed to allocate DMA buffer\n");
-                       goto err;
-               }
-       }
-
-       return 0;
-
-err:
-       if (--i == 0 && pcm->streams[i].substream)
-               snd_dma_free_pages(&pcm->streams[i].substream->dma_buffer);
-
-       return ret;
-}
-
-static void fsl_asrc_dma_pcm_free(struct snd_soc_component *component,
-                                 struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       int i;
-
-       for_each_pcm_streams(i) {
-               substream = pcm->streams[i].substream;
-               if (!substream)
-                       continue;
-
-               snd_dma_free_pages(&substream->dma_buffer);
-               substream->dma_buffer.area = NULL;
-               substream->dma_buffer.addr = 0;
-       }
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                           card->dev, FSL_ASRC_DMABUF_SIZE);
 }
 
 struct snd_soc_component_driver fsl_asrc_component = {
@@ -481,6 +441,5 @@ struct snd_soc_component_driver fsl_asrc_component = {
        .close          = fsl_asrc_dma_shutdown,
        .pointer        = fsl_asrc_dma_pcm_pointer,
        .pcm_construct  = fsl_asrc_dma_pcm_new,
-       .pcm_destruct   = fsl_asrc_dma_pcm_free,
 };
 EXPORT_SYMBOL_GPL(fsl_asrc_component);
index 84bd8a5..808fb61 100644 (file)
@@ -290,32 +290,9 @@ static int fsl_dma_new(struct snd_soc_component *component,
        if (ret)
                return ret;
 
-       /* Some codecs have separate DAIs for playback and capture, so we
-        * should allocate a DMA buffer only for the streams that are valid.
-        */
-
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
-                       fsl_dma_hardware.buffer_bytes_max,
-                       &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
-               if (ret) {
-                       dev_err(card->dev, "can't alloc playback dma buffer\n");
-                       return ret;
-               }
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
-                       fsl_dma_hardware.buffer_bytes_max,
-                       &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
-               if (ret) {
-                       dev_err(card->dev, "can't alloc capture dma buffer\n");
-                       snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
-                       return ret;
-               }
-       }
-
-       return 0;
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                           card->dev,
+                                           fsl_dma_hardware.buffer_bytes_max);
 }
 
 /**
@@ -442,7 +419,6 @@ static int fsl_dma_open(struct snd_soc_component *component,
 
        dma->assigned = true;
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
        snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware);
        runtime->private_data = dma_private;
 
@@ -815,25 +791,6 @@ static int fsl_dma_close(struct snd_soc_component *component,
        return 0;
 }
 
-/*
- * Remove this PCM driver.
- */
-static void fsl_dma_free_dma_buffers(struct snd_soc_component *component,
-                                    struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
-               substream = pcm->streams[i].substream;
-               if (substream) {
-                       snd_dma_free_pages(&substream->dma_buffer);
-                       substream->dma_buffer.area = NULL;
-                       substream->dma_buffer.addr = 0;
-               }
-       }
-}
-
 /**
  * find_ssi_node -- returns the SSI node that points to its DMA channel node
  *
@@ -904,7 +861,6 @@ static int fsl_soc_dma_probe(struct platform_device *pdev)
        dma->dai.hw_free = fsl_dma_hw_free;
        dma->dai.pointer = fsl_dma_pointer;
        dma->dai.pcm_construct = fsl_dma_new;
-       dma->dai.pcm_destruct = fsl_dma_free_dma_buffers;
 
        /* Store the SSI-specific information that we need */
        dma->ssi_stx_phys = res.start + REG_SSI_STX0;
index ea5c973..d60f4da 100644 (file)
@@ -165,25 +165,25 @@ static int fsl_rpmsg_probe(struct platform_device *pdev)
        }
 
        /* Get the optional clocks */
-       rpmsg->ipg = devm_clk_get(&pdev->dev, "ipg");
+       rpmsg->ipg = devm_clk_get_optional(&pdev->dev, "ipg");
        if (IS_ERR(rpmsg->ipg))
-               rpmsg->ipg = NULL;
+               return PTR_ERR(rpmsg->ipg);
 
-       rpmsg->mclk = devm_clk_get(&pdev->dev, "mclk");
+       rpmsg->mclk = devm_clk_get_optional(&pdev->dev, "mclk");
        if (IS_ERR(rpmsg->mclk))
-               rpmsg->mclk = NULL;
+               return PTR_ERR(rpmsg->mclk);
 
-       rpmsg->dma = devm_clk_get(&pdev->dev, "dma");
+       rpmsg->dma = devm_clk_get_optional(&pdev->dev, "dma");
        if (IS_ERR(rpmsg->dma))
-               rpmsg->dma = NULL;
+               return PTR_ERR(rpmsg->dma);
 
-       rpmsg->pll8k = devm_clk_get(&pdev->dev, "pll8k");
+       rpmsg->pll8k = devm_clk_get_optional(&pdev->dev, "pll8k");
        if (IS_ERR(rpmsg->pll8k))
-               rpmsg->pll8k = NULL;
+               return PTR_ERR(rpmsg->pll8k);
 
-       rpmsg->pll11k = devm_clk_get(&pdev->dev, "pll11k");
+       rpmsg->pll11k = devm_clk_get_optional(&pdev->dev, "pll11k");
        if (IS_ERR(rpmsg->pll11k))
-               rpmsg->pll11k = NULL;
+               return PTR_ERR(rpmsg->pll11k);
 
        platform_set_drvdata(pdev, rpmsg);
        pm_runtime_enable(&pdev->dev);
index fb7c29f..31c5ee6 100644 (file)
@@ -1189,10 +1189,8 @@ static int fsl_xcvr_probe(struct platform_device *pdev)
 
        /* get IRQs */
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(dev, "no irq[0]: %d\n", irq);
+       if (irq < 0)
                return irq;
-       }
 
        ret = devm_request_irq(dev, irq, irq0_isr, 0, pdev->name, xcvr);
        if (ret) {
index f20d5b1..0d12400 100644 (file)
@@ -81,7 +81,6 @@ static int snd_imx_pcm_hw_params(struct snd_soc_component *component,
        iprtd->offset = 0;
        iprtd->poll_time_ns = 1000000000 / params_rate(params) *
                                params_period_size(params);
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
        return 0;
 }
@@ -213,40 +212,6 @@ static int snd_imx_close(struct snd_soc_component *component,
        return 0;
 }
 
-static int snd_imx_pcm_mmap(struct snd_soc_component *component,
-                           struct snd_pcm_substream *substream,
-                           struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       int ret;
-
-       ret = dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
-                         runtime->dma_addr, runtime->dma_bytes);
-
-       pr_debug("%s: ret: %d %p %pad 0x%08zx\n", __func__, ret,
-                       runtime->dma_area,
-                       &runtime->dma_addr,
-                       runtime->dma_bytes);
-       return ret;
-}
-
-static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
-       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-       struct snd_dma_buffer *buf = &substream->dma_buffer;
-       size_t size = IMX_SSI_DMABUF_SIZE;
-
-       buf->dev.type = SNDRV_DMA_TYPE_DEV;
-       buf->dev.dev = pcm->card->dev;
-       buf->private_data = NULL;
-       buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL);
-       if (!buf->area)
-               return -ENOMEM;
-       buf->bytes = size;
-
-       return 0;
-}
-
 static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
@@ -257,21 +222,9 @@ static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
        if (ret)
                return ret;
 
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = imx_pcm_preallocate_dma_buffer(pcm,
-                       SNDRV_PCM_STREAM_PLAYBACK);
-               if (ret)
-                       return ret;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = imx_pcm_preallocate_dma_buffer(pcm,
-                       SNDRV_PCM_STREAM_CAPTURE);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
+                                           pcm->card->dev,
+                                           IMX_SSI_DMABUF_SIZE);
 }
 
 static int ssi_irq;
@@ -307,32 +260,11 @@ static int snd_imx_pcm_new(struct snd_soc_component *component,
        return 0;
 }
 
-static void imx_pcm_free(struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       struct snd_dma_buffer *buf;
-       int stream;
-
-       for (stream = 0; stream < 2; stream++) {
-               substream = pcm->streams[stream].substream;
-               if (!substream)
-                       continue;
-
-               buf = &substream->dma_buffer;
-               if (!buf->area)
-                       continue;
-
-               dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr);
-               buf->area = NULL;
-       }
-}
-
 static void snd_imx_pcm_free(struct snd_soc_component *component,
                             struct snd_pcm *pcm)
 {
        mxc_set_irq_fiq(ssi_irq, 0);
        release_fiq(&fh);
-       imx_pcm_free(pcm);
 }
 
 static const struct snd_soc_component_driver imx_soc_component_fiq = {
@@ -342,7 +274,6 @@ static const struct snd_soc_component_driver imx_soc_component_fiq = {
        .prepare        = snd_imx_pcm_prepare,
        .trigger        = snd_imx_pcm_trigger,
        .pointer        = snd_imx_pcm_pointer,
-       .mmap           = snd_imx_pcm_mmap,
        .pcm_construct  = snd_imx_pcm_new,
        .pcm_destruct   = snd_imx_pcm_free,
 };
index 6d6c44c..3504904 100644 (file)
@@ -139,7 +139,6 @@ static int imx_rpmsg_pcm_hw_params(struct snd_soc_component *component,
                                   struct snd_pcm_hw_params *params)
 {
        struct rpmsg_info *info = dev_get_drvdata(component->dev);
-       struct snd_pcm_runtime *runtime = substream->runtime;
        struct rpmsg_msg *msg;
        int ret = 0;
 
@@ -183,21 +182,11 @@ static int imx_rpmsg_pcm_hw_params(struct snd_soc_component *component,
                break;
        }
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-       runtime->dma_bytes = params_buffer_bytes(params);
-
        info->send_message(msg, info);
 
        return ret;
 }
 
-static int imx_rpmsg_pcm_hw_free(struct snd_soc_component *component,
-                                struct snd_pcm_substream *substream)
-{
-       snd_pcm_set_runtime_buffer(substream, NULL);
-       return 0;
-}
-
 static snd_pcm_uframes_t imx_rpmsg_pcm_pointer(struct snd_soc_component *component,
                                               struct snd_pcm_substream *substream)
 {
@@ -347,18 +336,6 @@ static int imx_rpmsg_pcm_prepare(struct snd_soc_component *component,
        return 0;
 }
 
-static int imx_rpmsg_pcm_mmap(struct snd_soc_component *component,
-                             struct snd_pcm_substream *substream,
-                             struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       return dma_mmap_wc(substream->pcm->card->dev, vma,
-                          runtime->dma_area,
-                          runtime->dma_addr,
-                          runtime->dma_bytes);
-}
-
 static void imx_rpmsg_pcm_dma_complete(void *arg)
 {
        struct snd_pcm_substream *substream = arg;
@@ -609,47 +586,6 @@ static int imx_rpmsg_pcm_ack(struct snd_soc_component *component,
        return 0;
 }
 
-static int imx_rpmsg_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
-                                               int stream, int size)
-{
-       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-       struct snd_dma_buffer *buf = &substream->dma_buffer;
-
-       buf->dev.type = SNDRV_DMA_TYPE_DEV;
-       buf->dev.dev = pcm->card->dev;
-       buf->private_data = NULL;
-       buf->area = dma_alloc_wc(pcm->card->dev, size,
-                                &buf->addr, GFP_KERNEL);
-       if (!buf->area)
-               return -ENOMEM;
-
-       buf->bytes = size;
-       return 0;
-}
-
-static void imx_rpmsg_pcm_free_dma_buffers(struct snd_soc_component *component,
-                                          struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       struct snd_dma_buffer *buf;
-       int stream;
-
-       for (stream = SNDRV_PCM_STREAM_PLAYBACK;
-            stream < SNDRV_PCM_STREAM_LAST; stream++) {
-               substream = pcm->streams[stream].substream;
-               if (!substream)
-                       continue;
-
-               buf = &substream->dma_buffer;
-               if (!buf->area)
-                       continue;
-
-               dma_free_wc(pcm->card->dev, buf->bytes,
-                           buf->area, buf->addr);
-               buf->area = NULL;
-       }
-}
-
 static int imx_rpmsg_pcm_new(struct snd_soc_component *component,
                             struct snd_soc_pcm_runtime *rtd)
 {
@@ -663,40 +599,19 @@ static int imx_rpmsg_pcm_new(struct snd_soc_component *component,
        if (ret)
                return ret;
 
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = imx_rpmsg_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-                                                          rpmsg->buffer_size);
-               if (ret)
-                       goto out;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = imx_rpmsg_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE,
-                                                          rpmsg->buffer_size);
-               if (ret)
-                       goto out;
-       }
-
        imx_rpmsg_pcm_hardware.buffer_bytes_max = rpmsg->buffer_size;
-out:
-       /* free preallocated buffers in case of error */
-       if (ret)
-               imx_rpmsg_pcm_free_dma_buffers(component, pcm);
-
-       return ret;
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
+                                           pcm->card->dev, rpmsg->buffer_size);
 }
 
 static const struct snd_soc_component_driver imx_rpmsg_soc_component = {
        .name           = IMX_PCM_DRV_NAME,
        .pcm_construct  = imx_rpmsg_pcm_new,
-       .pcm_destruct   = imx_rpmsg_pcm_free_dma_buffers,
        .open           = imx_rpmsg_pcm_open,
        .close          = imx_rpmsg_pcm_close,
        .hw_params      = imx_rpmsg_pcm_hw_params,
-       .hw_free        = imx_rpmsg_pcm_hw_free,
        .trigger        = imx_rpmsg_pcm_trigger,
        .pointer        = imx_rpmsg_pcm_pointer,
-       .mmap           = imx_rpmsg_pcm_mmap,
        .ack            = imx_rpmsg_pcm_ack,
        .prepare        = imx_rpmsg_pcm_prepare,
 };
index f0cae8c..f96fe4f 100644 (file)
@@ -125,7 +125,7 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
        snd_soc_card_set_drvdata(&data->card, data);
        ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
        if (ret) {
-               dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+               dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n");
                goto fail;
        }
 
index 6c65cd8..9014978 100644 (file)
@@ -98,13 +98,6 @@ static irqreturn_t psc_dma_bcom_irq(int irq, void *_psc_dma_stream)
        return IRQ_HANDLED;
 }
 
-static int psc_dma_hw_free(struct snd_soc_component *component,
-                          struct snd_pcm_substream *substream)
-{
-       snd_pcm_set_runtime_buffer(substream, NULL);
-       return 0;
-}
-
 /**
  * psc_dma_trigger: start and stop the DMA transfer.
  *
@@ -285,15 +278,6 @@ psc_dma_pointer(struct snd_soc_component *component,
        return bytes_to_frames(substream->runtime, count);
 }
 
-static int psc_dma_hw_params(struct snd_soc_component *component,
-                            struct snd_pcm_substream *substream,
-                            struct snd_pcm_hw_params *params)
-{
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
-       return 0;
-}
-
 static int psc_dma_new(struct snd_soc_component *component,
                       struct snd_soc_pcm_runtime *rtd)
 {
@@ -310,60 +294,17 @@ static int psc_dma_new(struct snd_soc_component *component,
        if (rc)
                return rc;
 
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
-                               size, &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
-               if (rc)
-                       goto playback_alloc_err;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
-                               size, &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
-               if (rc)
-                       goto capture_alloc_err;
-       }
-
-       return 0;
-
- capture_alloc_err:
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
-               snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
-
- playback_alloc_err:
-       dev_err(card->dev, "Cannot allocate buffer(s)\n");
-
-       return -ENOMEM;
-}
-
-static void psc_dma_free(struct snd_soc_component *component,
-                        struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       int stream;
-
-       dev_dbg(component->dev, "psc_dma_free(pcm=%p)\n", pcm);
-
-       for (stream = 0; stream < 2; stream++) {
-               substream = pcm->streams[stream].substream;
-               if (substream) {
-                       snd_dma_free_pages(&substream->dma_buffer);
-                       substream->dma_buffer.area = NULL;
-                       substream->dma_buffer.addr = 0;
-               }
-       }
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, card->dev,
+                                           size);
 }
 
 static const struct snd_soc_component_driver mpc5200_audio_dma_component = {
        .name           = DRV_NAME,
        .open           = psc_dma_open,
        .close          = psc_dma_close,
-       .hw_free        = psc_dma_hw_free,
        .pointer        = psc_dma_pointer,
        .trigger        = psc_dma_trigger,
-       .hw_params      = psc_dma_hw_params,
        .pcm_construct  = psc_dma_new,
-       .pcm_destruct   = psc_dma_free,
 };
 
 int mpc5200_audio_dma_create(struct platform_device *op)
index 677f7da..10c63b7 100644 (file)
@@ -640,8 +640,8 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv,
                        cnf_num += li->num[i].codecs;
        }
 
-       dais = devm_kcalloc(dev, dai_num, sizeof(*dais),      GFP_KERNEL);
-       dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dai_props), GFP_KERNEL);
+       dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL);
+       dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dlcs), GFP_KERNEL);
        if (!dais || !dlcs)
                return -ENOMEM;
 
index 905c796..5db2f48 100644 (file)
@@ -127,7 +127,7 @@ static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
        snd_pcm_uframes_t period_size;
        ssize_t periodbytes;
        ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
-       u32 buffer_addr = virt_to_phys(substream->runtime->dma_area);
+       u32 buffer_addr = substream->runtime->dma_addr;
 
        channels = substream->runtime->channels;
        period_size = substream->runtime->period_size;
index a8a9aa0..4e83820 100644 (file)
@@ -128,7 +128,7 @@ int sst_post_message_mrfld(struct intel_sst_drv *sst_drv_ctx,
                while (header.p.header_high.part.busy) {
                        if (loop_count > 25) {
                                dev_err(sst_drv_ctx->dev,
-                                       "sst: Busy wait failed, cant send this msg\n");
+                                       "sst: Busy wait failed, can't send this msg\n");
                                retval = -EBUSY;
                                goto out;
                        }
index a0af915..055248f 100644 (file)
@@ -37,6 +37,7 @@ struct byt_cht_es8316_private {
        struct clk *mclk;
        struct snd_soc_jack jack;
        struct gpio_desc *speaker_en_gpio;
+       struct device *codec_dev;
        bool speaker_en;
 };
 
@@ -461,6 +462,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
        const struct dmi_system_id *dmi_id;
        struct device *dev = &pdev->dev;
        struct snd_soc_acpi_mach *mach;
+       struct fwnode_handle *fwnode;
        const char *platform_name;
        struct acpi_device *adev;
        struct device *codec_dev;
@@ -491,6 +493,9 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
                         "i2c-%s", acpi_dev_name(adev));
                put_device(&adev->dev);
                byt_cht_es8316_dais[dai_index].codecs->name = codec_name;
+       } else {
+               dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
+               return -ENXIO;
        }
 
        /* override plaform name, if required */
@@ -535,15 +540,25 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
        }
 
        /* get speaker enable GPIO */
-       codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name);
+       codec_dev = acpi_get_first_physical_node(adev);
        if (!codec_dev)
                return -EPROBE_DEFER;
+       priv->codec_dev = get_device(codec_dev);
 
        if (quirk & BYT_CHT_ES8316_JD_INVERTED)
                props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted");
 
        if (cnt) {
-               ret = device_add_properties(codec_dev, props);
+               fwnode = fwnode_create_software_node(props, NULL);
+               if (IS_ERR(fwnode)) {
+                       put_device(codec_dev);
+                       return PTR_ERR(fwnode);
+               }
+
+               ret = device_add_software_node(codec_dev, to_software_node(fwnode));
+
+               fwnode_handle_put(fwnode);
+
                if (ret) {
                        put_device(codec_dev);
                        return ret;
@@ -555,7 +570,6 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
                gpiod_get_index(codec_dev, "speaker-enable", 0,
                                /* see comment in byt_cht_es8316_resume */
                                GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
-       put_device(codec_dev);
 
        if (IS_ERR(priv->speaker_en_gpio)) {
                ret = PTR_ERR(priv->speaker_en_gpio);
@@ -567,7 +581,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
                        dev_err(dev, "get speaker GPIO failed: %d\n", ret);
                        fallthrough;
                case -EPROBE_DEFER:
-                       return ret;
+                       goto err_put_codec;
                }
        }
 
@@ -605,10 +619,15 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
        if (ret) {
                gpiod_put(priv->speaker_en_gpio);
                dev_err(dev, "snd_soc_register_card failed: %d\n", ret);
-               return ret;
+               goto err_put_codec;
        }
        platform_set_drvdata(pdev, &byt_cht_es8316_card);
        return 0;
+
+err_put_codec:
+       device_remove_software_node(priv->codec_dev);
+       put_device(priv->codec_dev);
+       return ret;
 }
 
 static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev)
@@ -617,6 +636,8 @@ static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev)
        struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
 
        gpiod_put(priv->speaker_en_gpio);
+       device_remove_software_node(priv->codec_dev);
+       put_device(priv->codec_dev);
        return 0;
 }
 
index 91a6d71..a6e8372 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/dmi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
 #include <linux/input.h>
 #include <linux/slab.h>
 #include <sound/pcm.h>
@@ -73,6 +75,10 @@ enum {
 #define BYT_RT5640_MCLK_EN             BIT(22)
 #define BYT_RT5640_MCLK_25MHZ          BIT(23)
 #define BYT_RT5640_NO_SPEAKERS         BIT(24)
+#define BYT_RT5640_LINEOUT             BIT(25)
+#define BYT_RT5640_LINEOUT_AS_HP2      BIT(26)
+#define BYT_RT5640_HSMIC2_ON_IN1       BIT(27)
+#define BYT_RT5640_JD_HP_ELITEP_1000G2 BIT(28)
 
 #define BYTCR_INPUT_DEFAULTS                           \
        (BYT_RT5640_IN3_MAP |                           \
@@ -86,7 +92,10 @@ enum {
 
 struct byt_rt5640_private {
        struct snd_soc_jack jack;
+       struct snd_soc_jack jack2;
+       struct gpio_desc *hsmic_detect;
        struct clk *mclk;
+       struct device *codec_dev;
 };
 static bool is_bytcr;
 
@@ -125,6 +134,8 @@ static void log_quirks(struct device *dev)
                dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map);
                break;
        }
+       if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1)
+               dev_info(dev, "quirk HSMIC2_ON_IN1 enabled\n");
        if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {
                dev_info(dev, "quirk realtek,jack-detect-source %ld\n",
                         BYT_RT5640_JDSRC(byt_rt5640_quirk));
@@ -135,10 +146,16 @@ static void log_quirks(struct device *dev)
        }
        if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)
                dev_info(dev, "quirk JD_NOT_INV enabled\n");
+       if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)
+               dev_info(dev, "quirk JD_HP_ELITEPAD_1000G2 enabled\n");
        if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER)
                dev_info(dev, "quirk MONO_SPEAKER enabled\n");
        if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)
                dev_info(dev, "quirk NO_SPEAKERS enabled\n");
+       if (byt_rt5640_quirk & BYT_RT5640_LINEOUT)
+               dev_info(dev, "quirk LINEOUT enabled\n");
+       if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)
+               dev_info(dev, "quirk LINEOUT_AS_HP2 enabled\n");
        if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
                dev_info(dev, "quirk DIFF_MIC enabled\n");
        if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {
@@ -224,6 +241,20 @@ static int byt_rt5640_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
 #define BYT_CODEC_DAI1 "rt5640-aif1"
 #define BYT_CODEC_DAI2 "rt5640-aif2"
 
+static struct snd_soc_dai *byt_rt5640_get_codec_dai(struct snd_soc_dapm_context *dapm)
+{
+       struct snd_soc_card *card = dapm->card;
+       struct snd_soc_dai *codec_dai;
+
+       codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
+       if (!codec_dai)
+               codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);
+       if (!codec_dai)
+               dev_err(card->dev, "Error codec dai not found\n");
+
+       return codec_dai;
+}
+
 static int platform_clock_control(struct snd_soc_dapm_widget *w,
                                  struct snd_kcontrol *k, int  event)
 {
@@ -233,15 +264,9 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
        struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
        int ret;
 
-       codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
+       codec_dai = byt_rt5640_get_codec_dai(dapm);
        if (!codec_dai)
-               codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);
-
-       if (!codec_dai) {
-               dev_err(card->dev,
-                       "Codec dai not found; Unable to set platform clock\n");
                return -EIO;
-       }
 
        if (SND_SOC_DAPM_EVENT_ON(event)) {
                if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
@@ -276,23 +301,48 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
+static int byt_rt5640_event_lineout(struct snd_soc_dapm_widget *w,
+                       struct snd_kcontrol *k, int event)
+{
+       unsigned int gpio_ctrl3_val = RT5640_GP1_PF_OUT;
+       struct snd_soc_dai *codec_dai;
+
+       if (!(byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2))
+               return 0;
+
+       /*
+        * On devices which use line-out as a second headphones output,
+        * the codec's GPIO1 pin is used to enable an external HP-amp.
+        */
+
+       codec_dai = byt_rt5640_get_codec_dai(w->dapm);
+       if (!codec_dai)
+               return -EIO;
+
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               gpio_ctrl3_val |= RT5640_GP1_OUT_HI;
+
+       snd_soc_component_update_bits(codec_dai->component, RT5640_GPIO_CTRL3,
+               RT5640_GP1_PF_MASK | RT5640_GP1_OUT_MASK, gpio_ctrl3_val);
+
+       return 0;
+}
+
 static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
        SND_SOC_DAPM_HP("Headphone", NULL),
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
+       SND_SOC_DAPM_MIC("Headset Mic 2", NULL),
        SND_SOC_DAPM_MIC("Internal Mic", NULL),
        SND_SOC_DAPM_SPK("Speaker", NULL),
+       SND_SOC_DAPM_LINE("Line Out", byt_rt5640_event_lineout),
        SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
                            platform_clock_control, SND_SOC_DAPM_PRE_PMU |
                            SND_SOC_DAPM_POST_PMD),
-
 };
 
 static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
        {"Headphone", NULL, "Platform Clock"},
        {"Headset Mic", NULL, "Platform Clock"},
-       {"Internal Mic", NULL, "Platform Clock"},
-       {"Speaker", NULL, "Platform Clock"},
-
        {"Headset Mic", NULL, "MICBIAS1"},
        {"IN2P", NULL, "Headset Mic"},
        {"Headphone", NULL, "HPOL"},
@@ -300,23 +350,33 @@ static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
 };
 
 static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = {
+       {"Internal Mic", NULL, "Platform Clock"},
        {"DMIC1", NULL, "Internal Mic"},
 };
 
 static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = {
+       {"Internal Mic", NULL, "Platform Clock"},
        {"DMIC2", NULL, "Internal Mic"},
 };
 
 static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = {
+       {"Internal Mic", NULL, "Platform Clock"},
        {"Internal Mic", NULL, "MICBIAS1"},
        {"IN1P", NULL, "Internal Mic"},
 };
 
 static const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = {
+       {"Internal Mic", NULL, "Platform Clock"},
        {"Internal Mic", NULL, "MICBIAS1"},
        {"IN3P", NULL, "Internal Mic"},
 };
 
+static const struct snd_soc_dapm_route byt_rt5640_hsmic2_in1_map[] = {
+       {"Headset Mic 2", NULL, "Platform Clock"},
+       {"Headset Mic 2", NULL, "MICBIAS1"},
+       {"IN1P", NULL, "Headset Mic 2"},
+};
+
 static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = {
        {"ssp2 Tx", NULL, "codec_out0"},
        {"ssp2 Tx", NULL, "codec_out1"},
@@ -354,6 +414,7 @@ static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = {
 };
 
 static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = {
+       {"Speaker", NULL, "Platform Clock"},
        {"Speaker", NULL, "SPOLP"},
        {"Speaker", NULL, "SPOLN"},
        {"Speaker", NULL, "SPORP"},
@@ -361,15 +422,24 @@ static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = {
 };
 
 static const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = {
+       {"Speaker", NULL, "Platform Clock"},
        {"Speaker", NULL, "SPOLP"},
        {"Speaker", NULL, "SPOLN"},
 };
 
+static const struct snd_soc_dapm_route byt_rt5640_lineout_map[] = {
+       {"Line Out", NULL, "Platform Clock"},
+       {"Line Out", NULL, "LOUTR"},
+       {"Line Out", NULL, "LOUTL"},
+};
+
 static const struct snd_kcontrol_new byt_rt5640_controls[] = {
        SOC_DAPM_PIN_SWITCH("Headphone"),
        SOC_DAPM_PIN_SWITCH("Headset Mic"),
+       SOC_DAPM_PIN_SWITCH("Headset Mic 2"),
        SOC_DAPM_PIN_SWITCH("Internal Mic"),
        SOC_DAPM_PIN_SWITCH("Speaker"),
+       SOC_DAPM_PIN_SWITCH("Line Out"),
 };
 
 static struct snd_soc_jack_pin rt5640_pins[] = {
@@ -383,6 +453,75 @@ static struct snd_soc_jack_pin rt5640_pins[] = {
        },
 };
 
+static struct snd_soc_jack_pin rt5640_pins2[] = {
+       {
+               /* The 2nd headset jack uses lineout with an external HP-amp */
+               .pin    = "Line Out",
+               .mask   = SND_JACK_HEADPHONE,
+       },
+       {
+               .pin    = "Headset Mic 2",
+               .mask   = SND_JACK_MICROPHONE,
+       },
+};
+
+static struct snd_soc_jack_gpio rt5640_jack_gpio = {
+       .name = "hp-detect",
+       .report = SND_JACK_HEADSET,
+       .invert = true,
+       .debounce_time = 200,
+};
+
+static struct snd_soc_jack_gpio rt5640_jack2_gpio = {
+       .name = "hp2-detect",
+       .report = SND_JACK_HEADSET,
+       .invert = true,
+       .debounce_time = 200,
+};
+
+static const struct acpi_gpio_params acpi_gpio0 = { 0, 0, false };
+static const struct acpi_gpio_params acpi_gpio1 = { 1, 0, false };
+static const struct acpi_gpio_params acpi_gpio2 = { 2, 0, false };
+
+static const struct acpi_gpio_mapping byt_rt5640_hp_elitepad_1000g2_gpios[] = {
+       { "hp-detect-gpios", &acpi_gpio0, 1, },
+       { "headset-mic-detect-gpios", &acpi_gpio1, 1, },
+       { "hp2-detect-gpios", &acpi_gpio2, 1, },
+       { },
+};
+
+static int byt_rt5640_hp_elitepad_1000g2_jack1_check(void *data)
+{
+       struct byt_rt5640_private *priv = data;
+       int jack_status, mic_status;
+
+       jack_status = gpiod_get_value_cansleep(rt5640_jack_gpio.desc);
+       if (jack_status)
+               return 0;
+
+       mic_status = gpiod_get_value_cansleep(priv->hsmic_detect);
+       if (mic_status)
+               return SND_JACK_HEADPHONE;
+       else
+               return SND_JACK_HEADSET;
+}
+
+static int byt_rt5640_hp_elitepad_1000g2_jack2_check(void *data)
+{
+       struct snd_soc_component *component = data;
+       int jack_status, report;
+
+       jack_status = gpiod_get_value_cansleep(rt5640_jack2_gpio.desc);
+       if (jack_status)
+               return 0;
+
+       rt5640_enable_micbias1_for_ovcd(component);
+       report = rt5640_detect_headset(component, rt5640_jack2_gpio.desc);
+       rt5640_disable_micbias1_for_ovcd(component);
+
+       return report;
+}
+
 static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream,
                                        struct snd_pcm_hw_params *params)
 {
@@ -590,8 +729,12 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"),
                },
-               .driver_data = (void *)(BYT_RT5640_IN1_MAP |
-                                       BYT_RT5640_MCLK_EN),
+               .driver_data = (void *)(BYT_RT5640_DMIC2_MAP |
+                                       BYT_RT5640_MCLK_EN |
+                                       BYT_RT5640_LINEOUT |
+                                       BYT_RT5640_LINEOUT_AS_HP2 |
+                                       BYT_RT5640_HSMIC2_ON_IN1 |
+                                       BYT_RT5640_JD_HP_ELITEP_1000G2),
        },
        {       /* HP Pavilion x2 10-k0XX, 10-n0XX */
                .matches = {
@@ -912,15 +1055,13 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
  * Note this MUST be called before snd_soc_register_card(), so that the props
  * are in place before the codec component driver's probe function parses them.
  */
-static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name)
+static int byt_rt5640_add_codec_device_props(struct device *i2c_dev,
+                                            struct byt_rt5640_private *priv)
 {
        struct property_entry props[MAX_NO_PROPS] = {};
-       struct device *i2c_dev;
-       int ret, cnt = 0;
-
-       i2c_dev = bus_find_device_by_name(&i2c_bus_type, NULL, i2c_dev_name);
-       if (!i2c_dev)
-               return -EPROBE_DEFER;
+       struct fwnode_handle *fwnode;
+       int cnt = 0;
+       int ret;
 
        switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
        case BYT_RT5640_DMIC1_MAP:
@@ -960,8 +1101,15 @@ static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name)
        if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)
                props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
 
-       ret = device_add_properties(i2c_dev, props);
-       put_device(i2c_dev);
+       fwnode = fwnode_create_software_node(props, NULL);
+       if (IS_ERR(fwnode)) {
+               /* put_device() is handled in caller */
+               return PTR_ERR(fwnode);
+       }
+
+       ret = device_add_software_node(i2c_dev, to_software_node(fwnode));
+
+       fwnode_handle_put(fwnode);
 
        return ret;
 }
@@ -1021,6 +1169,14 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
        if (ret)
                return ret;
 
+       if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1) {
+               ret = snd_soc_dapm_add_routes(&card->dapm,
+                                       byt_rt5640_hsmic2_in1_map,
+                                       ARRAY_SIZE(byt_rt5640_hsmic2_in1_map));
+               if (ret)
+                       return ret;
+       }
+
        if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {
                ret = snd_soc_dapm_add_routes(&card->dapm,
                                        byt_rt5640_ssp2_aif2_map,
@@ -1053,6 +1209,14 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
        if (ret)
                return ret;
 
+       if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) {
+               ret = snd_soc_dapm_add_routes(&card->dapm,
+                                       byt_rt5640_lineout_map,
+                                       ARRAY_SIZE(byt_rt5640_lineout_map));
+               if (ret)
+                       return ret;
+       }
+
        if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
                /*
                 * The firmware might enable the clock at
@@ -1093,9 +1257,53 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
                snd_soc_component_set_jack(component, &priv->jack, NULL);
        }
 
+       if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {
+               ret = snd_soc_card_jack_new(card, "Headset",
+                                           SND_JACK_HEADSET,
+                                           &priv->jack, rt5640_pins,
+                                           ARRAY_SIZE(rt5640_pins));
+               if (ret)
+                       return ret;
+
+               ret = snd_soc_card_jack_new(card, "Headset 2",
+                                           SND_JACK_HEADSET,
+                                           &priv->jack2, rt5640_pins2,
+                                           ARRAY_SIZE(rt5640_pins2));
+               if (ret)
+                       return ret;
+
+               rt5640_jack_gpio.data = priv;
+               rt5640_jack_gpio.gpiod_dev = priv->codec_dev;
+               rt5640_jack_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack1_check;
+               ret = snd_soc_jack_add_gpios(&priv->jack, 1, &rt5640_jack_gpio);
+               if (ret)
+                       return ret;
+
+               rt5640_set_ovcd_params(component);
+               rt5640_jack2_gpio.data = component;
+               rt5640_jack2_gpio.gpiod_dev = priv->codec_dev;
+               rt5640_jack2_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack2_check;
+               ret = snd_soc_jack_add_gpios(&priv->jack2, 1, &rt5640_jack2_gpio);
+               if (ret) {
+                       snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio);
+                       return ret;
+               }
+       }
+
        return 0;
 }
 
+static void byt_rt5640_exit(struct snd_soc_pcm_runtime *runtime)
+{
+       struct snd_soc_card *card = runtime->card;
+       struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
+
+       if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {
+               snd_soc_jack_free_gpios(&priv->jack2, 1, &rt5640_jack2_gpio);
+               snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio);
+       }
+}
+
 static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd,
                            struct snd_pcm_hw_params *params)
 {
@@ -1208,6 +1416,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
                .dpcm_playback = 1,
                .dpcm_capture = 1,
                .init = byt_rt5640_init,
+               .exit = byt_rt5640_exit,
                .ops = &byt_rt5640_be_ssp2_ops,
                SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
        },
@@ -1218,7 +1427,7 @@ static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN];
 #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
 static char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */
 #endif
-static char byt_rt5640_components[32]; /* = "cfg-spk:* cfg-mic:*" */
+static char byt_rt5640_components[64]; /* = "cfg-spk:* cfg-mic:* ..." */
 
 static int byt_rt5640_suspend(struct snd_soc_card *card)
 {
@@ -1288,10 +1497,13 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
        static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" };
        __maybe_unused const char *spk_type;
        const struct dmi_system_id *dmi_id;
+       const char *headset2_string = "";
+       const char *lineout_string = "";
        struct byt_rt5640_private *priv;
        struct snd_soc_acpi_mach *mach;
        const char *platform_name;
        struct acpi_device *adev;
+       struct device *codec_dev;
        bool sof_parent;
        int ret_val = 0;
        int dai_index = 0;
@@ -1324,6 +1536,9 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
                         "i2c-%s", acpi_dev_name(adev));
                put_device(&adev->dev);
                byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name;
+       } else {
+               dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
+               return -ENXIO;
        }
 
        /*
@@ -1400,10 +1615,29 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
                byt_rt5640_quirk = quirk_override;
        }
 
+       codec_dev = acpi_get_first_physical_node(adev);
+       if (!codec_dev)
+               return -EPROBE_DEFER;
+       priv->codec_dev = get_device(codec_dev);
+
+       if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {
+               acpi_dev_add_driver_gpios(ACPI_COMPANION(priv->codec_dev),
+                                         byt_rt5640_hp_elitepad_1000g2_gpios);
+
+               priv->hsmic_detect = devm_fwnode_gpiod_get(&pdev->dev, codec_dev->fwnode,
+                                                          "headset-mic-detect", GPIOD_IN,
+                                                          "headset-mic-detect");
+               if (IS_ERR(priv->hsmic_detect)) {
+                       ret_val = PTR_ERR(priv->hsmic_detect);
+                       dev_err_probe(&pdev->dev, ret_val, "getting hsmic-detect GPIO\n");
+                       goto err_device;
+               }
+       }
+
        /* Must be called before register_card, also see declaration comment. */
-       ret_val = byt_rt5640_add_codec_device_props(byt_rt5640_codec_name);
+       ret_val = byt_rt5640_add_codec_device_props(codec_dev, priv);
        if (ret_val)
-               return ret_val;
+               goto err_remove_gpios;
 
        log_quirks(&pdev->dev);
 
@@ -1434,7 +1668,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
                         * for all other errors, including -EPROBE_DEFER
                         */
                        if (ret_val != -ENOENT)
-                               return ret_val;
+                               goto err;
                        byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;
                }
        }
@@ -1450,9 +1684,20 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
                spk_type = "stereo";
        }
 
+       if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) {
+               if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)
+                       lineout_string = " cfg-hp2:lineout";
+               else
+                       lineout_string = " cfg-lineout:2";
+       }
+
+       if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1)
+               headset2_string = " cfg-hs2:in1";
+
        snprintf(byt_rt5640_components, sizeof(byt_rt5640_components),
-                "cfg-spk:%d cfg-mic:%s aif:%d", cfg_spk,
-                map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif);
+                "cfg-spk:%d cfg-mic:%s aif:%d%s%s", cfg_spk,
+                map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif,
+                lineout_string, headset2_string);
        byt_rt5640_card.components = byt_rt5640_components;
 #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
        snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name),
@@ -1467,7 +1712,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
        ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card,
                                                        platform_name);
        if (ret_val)
-               return ret_val;
+               goto err;
 
        sof_parent = snd_soc_acpi_sof_parent(&pdev->dev);
 
@@ -1489,10 +1734,32 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
        if (ret_val) {
                dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
                        ret_val);
-               return ret_val;
+               goto err;
        }
        platform_set_drvdata(pdev, &byt_rt5640_card);
        return ret_val;
+
+err:
+       device_remove_software_node(priv->codec_dev);
+err_remove_gpios:
+       if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)
+               acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev));
+err_device:
+       put_device(priv->codec_dev);
+       return ret_val;
+}
+
+static int snd_byt_rt5640_mc_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
+
+       if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)
+               acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev));
+
+       device_remove_software_node(priv->codec_dev);
+       put_device(priv->codec_dev);
+       return 0;
 }
 
 static struct platform_driver snd_byt_rt5640_mc_driver = {
@@ -1500,6 +1767,7 @@ static struct platform_driver snd_byt_rt5640_mc_driver = {
                .name = "bytcr_rt5640",
        },
        .probe = snd_byt_rt5640_mc_probe,
+       .remove = snd_byt_rt5640_mc_remove,
 };
 
 module_platform_driver(snd_byt_rt5640_mc_driver);
index e13c0c6..e94c912 100644 (file)
@@ -85,6 +85,7 @@ struct byt_rt5651_private {
        struct gpio_desc *ext_amp_gpio;
        struct gpio_desc *hp_detect;
        struct snd_soc_jack jack;
+       struct device *codec_dev;
 };
 
 static const struct acpi_gpio_mapping *byt_rt5651_gpios;
@@ -527,10 +528,13 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
  * Note this MUST be called before snd_soc_register_card(), so that the props
  * are in place before the codec component driver's probe function parses them.
  */
-static int byt_rt5651_add_codec_device_props(struct device *i2c_dev)
+static int byt_rt5651_add_codec_device_props(struct device *i2c_dev,
+                                            struct byt_rt5651_private *priv)
 {
        struct property_entry props[MAX_NO_PROPS] = {};
+       struct fwnode_handle *fwnode;
        int cnt = 0;
+       int ret;
 
        props[cnt++] = PROPERTY_ENTRY_U32("realtek,jack-detect-source",
                                BYT_RT5651_JDSRC(byt_rt5651_quirk));
@@ -547,7 +551,17 @@ static int byt_rt5651_add_codec_device_props(struct device *i2c_dev)
        if (byt_rt5651_quirk & BYT_RT5651_JD_NOT_INV)
                props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
 
-       return device_add_properties(i2c_dev, props);
+       fwnode = fwnode_create_software_node(props, NULL);
+       if (IS_ERR(fwnode)) {
+               /* put_device(i2c_dev) is handled in caller */
+               return PTR_ERR(fwnode);
+       }
+
+       ret = device_add_software_node(i2c_dev, to_software_node(fwnode));
+
+       fwnode_handle_put(fwnode);
+
+       return ret;
 }
 
 static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
@@ -920,13 +934,13 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
                byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name;
        } else {
                dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
-               return -ENODEV;
+               return -ENXIO;
        }
 
-       codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,
-                                           byt_rt5651_codec_name);
+       codec_dev = acpi_get_first_physical_node(adev);
        if (!codec_dev)
                return -EPROBE_DEFER;
+       priv->codec_dev = get_device(codec_dev);
 
        /*
         * swap SSP0 if bytcr is detected
@@ -994,11 +1008,9 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
        }
 
        /* Must be called before register_card, also see declaration comment. */
-       ret_val = byt_rt5651_add_codec_device_props(codec_dev);
-       if (ret_val) {
-               put_device(codec_dev);
-               return ret_val;
-       }
+       ret_val = byt_rt5651_add_codec_device_props(codec_dev, priv);
+       if (ret_val)
+               goto err_device;
 
        /* Cherry Trail devices use an external amplifier enable gpio */
        if (soc_intel_is_cht() && !byt_rt5651_gpios)
@@ -1022,8 +1034,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
                                        ret_val);
                                fallthrough;
                        case -EPROBE_DEFER:
-                               put_device(codec_dev);
-                               return ret_val;
+                               goto err;
                        }
                }
                priv->hp_detect = devm_fwnode_gpiod_get(&pdev->dev,
@@ -1042,14 +1053,11 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
                                        ret_val);
                                fallthrough;
                        case -EPROBE_DEFER:
-                               put_device(codec_dev);
-                               return ret_val;
+                               goto err;
                        }
                }
        }
 
-       put_device(codec_dev);
-
        log_quirks(&pdev->dev);
 
        if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) ||
@@ -1073,7 +1081,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
                         * for all other errors, including -EPROBE_DEFER
                         */
                        if (ret_val != -ENOENT)
-                               return ret_val;
+                               goto err;
                        byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN;
                }
        }
@@ -1102,7 +1110,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
        ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5651_card,
                                                        platform_name);
        if (ret_val)
-               return ret_val;
+               goto err;
 
        sof_parent = snd_soc_acpi_sof_parent(&pdev->dev);
 
@@ -1124,10 +1132,26 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
        if (ret_val) {
                dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
                        ret_val);
-               return ret_val;
+               goto err;
        }
        platform_set_drvdata(pdev, &byt_rt5651_card);
        return ret_val;
+
+err:
+       device_remove_software_node(priv->codec_dev);
+err_device:
+       put_device(priv->codec_dev);
+       return ret_val;
+}
+
+static int snd_byt_rt5651_mc_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
+
+       device_remove_software_node(priv->codec_dev);
+       put_device(priv->codec_dev);
+       return 0;
 }
 
 static struct platform_driver snd_byt_rt5651_mc_driver = {
@@ -1135,6 +1159,7 @@ static struct platform_driver snd_byt_rt5651_mc_driver = {
                .name = "bytcr_rt5651",
        },
        .probe = snd_byt_rt5651_mc_probe,
+       .remove = snd_byt_rt5651_mc_remove,
 };
 
 module_platform_driver(snd_byt_rt5651_mc_driver);
index a31a7a7..2b43459 100644 (file)
@@ -199,7 +199,7 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream,
                }
                if (!strcmp(codec_dai->component->name, MAX98373_DEV0_NAME)) {
                        ret = snd_soc_dai_set_tdm_slot(codec_dai,
-                                                       0x03, 3, 8, 24);
+                                                       0x30, 3, 8, 16);
                        if (ret < 0) {
                                dev_err(runtime->dev,
                                                "DEV0 TDM slot err:%d\n", ret);
@@ -208,10 +208,10 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream,
                }
                if (!strcmp(codec_dai->component->name, MAX98373_DEV1_NAME)) {
                        ret = snd_soc_dai_set_tdm_slot(codec_dai,
-                                                       0x0C, 3, 8, 24);
+                                                       0xC0, 3, 8, 16);
                        if (ret < 0) {
                                dev_err(runtime->dev,
-                                               "DEV0 TDM slot err:%d\n", ret);
+                                               "DEV1 TDM slot err:%d\n", ret);
                                return ret;
                        }
                }
@@ -311,24 +311,6 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
         * The above 2 loops are mutually exclusive based on the stream direction,
         * thus rtd_dpcm variable will never be overwritten
         */
-       /*
-        * Topology for kblda7219m98373 & kblmax98373 supports only S24_LE,
-        * where as kblda7219m98927 & kblmax98927 supports S16_LE by default.
-        * Skipping the port wise FE and BE configuration for kblda7219m98373 &
-        * kblmax98373 as the topology (FE & BE) supports S24_LE only.
-        */
-
-       if (!strcmp(rtd->card->name, "kblda7219m98373") ||
-               !strcmp(rtd->card->name, "kblmax98373")) {
-               /* The ADSP will convert the FE rate to 48k, stereo */
-               rate->min = rate->max = 48000;
-               chan->min = chan->max = DUAL_CHANNEL;
-
-               /* set SSP to 24 bit */
-               snd_mask_none(fmt);
-               snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
-               return 0;
-       }
 
        /*
         * The ADSP will convert the FE rate to 48k, stereo, 24 bit
@@ -479,31 +461,20 @@ static struct snd_pcm_hw_constraint_list constraints_channels_quad = {
 static int kbl_fe_startup(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
-       struct snd_soc_pcm_runtime *soc_rt = asoc_substream_to_rtd(substream);
 
        /*
         * On this platform for PCM device we support,
         * 48Khz
         * stereo
+        * 16 bit audio
         */
 
        runtime->hw.channels_max = DUAL_CHANNEL;
        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
                                           &constraints_channels);
-       /*
-        * Setup S24_LE (32 bit container and 24 bit valid data) for
-        * kblda7219m98373 & kblmax98373. For kblda7219m98927 &
-        * kblmax98927 keeping it as 16/16 due to topology FW dependency.
-        */
-       if (!strcmp(soc_rt->card->name, "kblda7219m98373") ||
-               !strcmp(soc_rt->card->name, "kblmax98373")) {
-               runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_LE;
-               snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
-
-       } else {
-               runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
-               snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
-       }
+
+       runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+       snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
 
        snd_pcm_hw_constraint_list(runtime, 0,
                                SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
@@ -536,23 +507,11 @@ static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
 static int kabylake_dmic_startup(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
-       struct snd_soc_pcm_runtime *soc_rt = asoc_substream_to_rtd(substream);
 
        runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL;
        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
                        &constraints_channels_quad);
 
-       /*
-        * Topology for kblda7219m98373 & kblmax98373 supports only S24_LE.
-        * The DMIC also configured for S24_LE. Forcing the DMIC format to
-        * S24_LE due to the topology FW dependency.
-        */
-       if (!strcmp(soc_rt->card->name, "kblda7219m98373") ||
-               !strcmp(soc_rt->card->name, "kblmax98373")) {
-               runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_LE;
-               snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
-       }
-
        return snd_pcm_hw_constraint_list(substream->runtime, 0,
                        SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
 }
index 42aadf8..ce78c18 100644 (file)
@@ -16,6 +16,7 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/sof.h>
 #include <sound/soc-acpi.h>
 #include <dt-bindings/sound/cs42l42.h>
 #include "../../codecs/hdac_hdmi.h"
 #define SOF_CS42L42_NUM_HDMIDEV_MASK           (GENMASK(9, 7))
 #define SOF_CS42L42_NUM_HDMIDEV(quirk) \
        (((quirk) << SOF_CS42L42_NUM_HDMIDEV_SHIFT) & SOF_CS42L42_NUM_HDMIDEV_MASK)
-#define SOF_MAX98357A_SPEAKER_AMP_PRESENT      BIT(10)
+#define SOF_CS42L42_DAILINK_SHIFT              10
+#define SOF_CS42L42_DAILINK_MASK               (GENMASK(24, 10))
+#define SOF_CS42L42_DAILINK(link1, link2, link3, link4, link5) \
+       ((((link1) | ((link2) << 3) | ((link3) << 6) | ((link4) << 9) | ((link5) << 12)) << SOF_CS42L42_DAILINK_SHIFT) & SOF_CS42L42_DAILINK_MASK)
+#define SOF_MAX98357A_SPEAKER_AMP_PRESENT      BIT(25)
+#define SOF_MAX98360A_SPEAKER_AMP_PRESENT      BIT(26)
+
+enum {
+       LINK_NONE = 0,
+       LINK_HP = 1,
+       LINK_SPK = 2,
+       LINK_DMIC = 3,
+       LINK_HDMI = 4,
+};
 
 /* Default: SSP2 */
 static unsigned long sof_cs42l42_quirk = SOF_CS42L42_SSP_CODEC(2);
@@ -122,7 +136,12 @@ static int sof_cs42l42_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
        int clk_freq, ret;
 
-       clk_freq = 3072000; /* BCLK freq */
+       clk_freq = sof_dai_get_bclk(rtd); /* BCLK freq */
+
+       if (clk_freq <= 0) {
+               dev_err(rtd->dev, "get bclk freq failed: %d\n", clk_freq);
+               return -EINVAL;
+       }
 
        /* Configure sysclk for codec */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0,
@@ -259,133 +278,168 @@ static struct snd_soc_dai_link_component dmic_component[] = {
        }
 };
 
-static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
-                                                         int ssp_codec,
-                                                         int ssp_amp,
-                                                         int dmic_be_num,
-                                                         int hdmi_num)
+static int create_spk_amp_dai_links(struct device *dev,
+                                   struct snd_soc_dai_link *links,
+                                   struct snd_soc_dai_link_component *cpus,
+                                   int *id, int ssp_amp)
 {
-       struct snd_soc_dai_link_component *idisp_components;
-       struct snd_soc_dai_link_component *cpus;
-       struct snd_soc_dai_link *links;
-       int i, id = 0;
-
-       links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
-                            sof_audio_card_cs42l42.num_links, GFP_KERNEL);
-       cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
-                            sof_audio_card_cs42l42.num_links, GFP_KERNEL);
-       if (!links || !cpus)
-               goto devm_err;
+       int ret = 0;
 
        /* speaker amp */
-       if (sof_cs42l42_quirk & SOF_SPEAKER_AMP_PRESENT) {
-               links[id].name = devm_kasprintf(dev, GFP_KERNEL,
-                                               "SSP%d-Codec", ssp_amp);
-               if (!links[id].name)
-                       goto devm_err;
+       if (!(sof_cs42l42_quirk & SOF_SPEAKER_AMP_PRESENT))
+               return 0;
 
-               links[id].id = id;
+       links[*id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec",
+                                        ssp_amp);
+       if (!links[*id].name) {
+               ret = -ENOMEM;
+               goto devm_err;
+       }
 
-               if (sof_cs42l42_quirk & SOF_MAX98357A_SPEAKER_AMP_PRESENT) {
-                       max_98357a_dai_link(&links[id]);
-               } else {
-                       dev_err(dev, "no amp defined\n");
-                       goto devm_err;
-               }
+       links[*id].id = *id;
 
-               links[id].platforms = platform_component;
-               links[id].num_platforms = ARRAY_SIZE(platform_component);
-               links[id].dpcm_playback = 1;
-               links[id].no_pcm = 1;
-               links[id].cpus = &cpus[id];
-               links[id].num_cpus = 1;
-
-               links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
-                                                         "SSP%d Pin",
-                                                         ssp_amp);
-               if (!links[id].cpus->dai_name)
-                       goto devm_err;
+       if (sof_cs42l42_quirk & SOF_MAX98357A_SPEAKER_AMP_PRESENT) {
+               max_98357a_dai_link(&links[*id]);
+       } else if (sof_cs42l42_quirk & SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
+               max_98360a_dai_link(&links[*id]);
+       } else {
+               dev_err(dev, "no amp defined\n");
+               ret = -EINVAL;
+               goto devm_err;
+       }
 
-               id++;
+       links[*id].platforms = platform_component;
+       links[*id].num_platforms = ARRAY_SIZE(platform_component);
+       links[*id].dpcm_playback = 1;
+       links[*id].no_pcm = 1;
+       links[*id].cpus = &cpus[*id];
+       links[*id].num_cpus = 1;
+
+       links[*id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
+                                                  "SSP%d Pin", ssp_amp);
+       if (!links[*id].cpus->dai_name) {
+               ret = -ENOMEM;
+               goto devm_err;
        }
 
+       (*id)++;
+
+devm_err:
+       return ret;
+}
+
+static int create_hp_codec_dai_links(struct device *dev,
+                                    struct snd_soc_dai_link *links,
+                                    struct snd_soc_dai_link_component *cpus,
+                                    int *id, int ssp_codec)
+{
        /* codec SSP */
-       links[id].name = devm_kasprintf(dev, GFP_KERNEL,
-                                       "SSP%d-Codec", ssp_codec);
-       if (!links[id].name)
+       links[*id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec",
+                                        ssp_codec);
+       if (!links[*id].name)
                goto devm_err;
 
-       links[id].id = id;
-       links[id].codecs = cs42l42_component;
-       links[id].num_codecs = ARRAY_SIZE(cs42l42_component);
-       links[id].platforms = platform_component;
-       links[id].num_platforms = ARRAY_SIZE(platform_component);
-       links[id].init = sof_cs42l42_init;
-       links[id].exit = sof_cs42l42_exit;
-       links[id].ops = &sof_cs42l42_ops;
-       links[id].dpcm_playback = 1;
-       links[id].dpcm_capture = 1;
-       links[id].no_pcm = 1;
-       links[id].cpus = &cpus[id];
-       links[id].num_cpus = 1;
-
-       links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
-                                                 "SSP%d Pin",
-                                                 ssp_codec);
-       if (!links[id].cpus->dai_name)
+       links[*id].id = *id;
+       links[*id].codecs = cs42l42_component;
+       links[*id].num_codecs = ARRAY_SIZE(cs42l42_component);
+       links[*id].platforms = platform_component;
+       links[*id].num_platforms = ARRAY_SIZE(platform_component);
+       links[*id].init = sof_cs42l42_init;
+       links[*id].exit = sof_cs42l42_exit;
+       links[*id].ops = &sof_cs42l42_ops;
+       links[*id].dpcm_playback = 1;
+       links[*id].dpcm_capture = 1;
+       links[*id].no_pcm = 1;
+       links[*id].cpus = &cpus[*id];
+       links[*id].num_cpus = 1;
+
+       links[*id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
+                                                  "SSP%d Pin",
+                                                  ssp_codec);
+       if (!links[*id].cpus->dai_name)
                goto devm_err;
 
-       id++;
+       (*id)++;
+
+       return 0;
+
+devm_err:
+       return -ENOMEM;
+}
+
+static int create_dmic_dai_links(struct device *dev,
+                                struct snd_soc_dai_link *links,
+                                struct snd_soc_dai_link_component *cpus,
+                                int *id, int dmic_be_num)
+{
+       int i;
 
        /* dmic */
-       if (dmic_be_num > 0) {
-               /* at least we have dmic01 */
-               links[id].name = "dmic01";
-               links[id].cpus = &cpus[id];
-               links[id].cpus->dai_name = "DMIC01 Pin";
-               links[id].init = dmic_init;
-               if (dmic_be_num > 1) {
-                       /* set up 2 BE links at most */
-                       links[id + 1].name = "dmic16k";
-                       links[id + 1].cpus = &cpus[id + 1];
-                       links[id + 1].cpus->dai_name = "DMIC16k Pin";
-                       dmic_be_num = 2;
-               }
+       if (dmic_be_num <= 0)
+               return 0;
+
+       /* at least we have dmic01 */
+       links[*id].name = "dmic01";
+       links[*id].cpus = &cpus[*id];
+       links[*id].cpus->dai_name = "DMIC01 Pin";
+       links[*id].init = dmic_init;
+       if (dmic_be_num > 1) {
+               /* set up 2 BE links at most */
+               links[*id + 1].name = "dmic16k";
+               links[*id + 1].cpus = &cpus[*id + 1];
+               links[*id + 1].cpus->dai_name = "DMIC16k Pin";
+               dmic_be_num = 2;
        }
 
        for (i = 0; i < dmic_be_num; i++) {
-               links[id].id = id;
-               links[id].num_cpus = 1;
-               links[id].codecs = dmic_component;
-               links[id].num_codecs = ARRAY_SIZE(dmic_component);
-               links[id].platforms = platform_component;
-               links[id].num_platforms = ARRAY_SIZE(platform_component);
-               links[id].ignore_suspend = 1;
-               links[id].dpcm_capture = 1;
-               links[id].no_pcm = 1;
-               id++;
+               links[*id].id = *id;
+               links[*id].num_cpus = 1;
+               links[*id].codecs = dmic_component;
+               links[*id].num_codecs = ARRAY_SIZE(dmic_component);
+               links[*id].platforms = platform_component;
+               links[*id].num_platforms = ARRAY_SIZE(platform_component);
+               links[*id].ignore_suspend = 1;
+               links[*id].dpcm_capture = 1;
+               links[*id].no_pcm = 1;
+
+               (*id)++;
        }
 
+       return 0;
+}
+
+static int create_hdmi_dai_links(struct device *dev,
+                                struct snd_soc_dai_link *links,
+                                struct snd_soc_dai_link_component *cpus,
+                                int *id, int hdmi_num)
+{
+       struct snd_soc_dai_link_component *idisp_components;
+       int i;
+
        /* HDMI */
-       if (hdmi_num > 0) {
-               idisp_components = devm_kzalloc(dev,
-                                               sizeof(struct snd_soc_dai_link_component) *
-                                               hdmi_num, GFP_KERNEL);
-               if (!idisp_components)
-                       goto devm_err;
-       }
+       if (hdmi_num <= 0)
+               return 0;
+
+       idisp_components = devm_kzalloc(dev,
+                                       sizeof(struct snd_soc_dai_link_component) *
+                                       hdmi_num, GFP_KERNEL);
+       if (!idisp_components)
+               goto devm_err;
+
        for (i = 1; i <= hdmi_num; i++) {
-               links[id].name = devm_kasprintf(dev, GFP_KERNEL,
-                                               "iDisp%d", i);
-               if (!links[id].name)
+               links[*id].name = devm_kasprintf(dev, GFP_KERNEL,
+                                                "iDisp%d", i);
+               if (!links[*id].name)
                        goto devm_err;
 
-               links[id].id = id;
-               links[id].cpus = &cpus[id];
-               links[id].num_cpus = 1;
-               links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
-                                                         "iDisp%d Pin", i);
-               if (!links[id].cpus->dai_name)
+               links[*id].id = *id;
+               links[*id].cpus = &cpus[*id];
+               links[*id].num_cpus = 1;
+               links[*id].cpus->dai_name = devm_kasprintf(dev,
+                                                          GFP_KERNEL,
+                                                          "iDisp%d Pin",
+                                                          i);
+               if (!links[*id].cpus->dai_name)
                        goto devm_err;
 
                idisp_components[i - 1].name = "ehdaudio0D2";
@@ -396,14 +450,86 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
                if (!idisp_components[i - 1].dai_name)
                        goto devm_err;
 
-               links[id].codecs = &idisp_components[i - 1];
-               links[id].num_codecs = 1;
-               links[id].platforms = platform_component;
-               links[id].num_platforms = ARRAY_SIZE(platform_component);
-               links[id].init = sof_hdmi_init;
-               links[id].dpcm_playback = 1;
-               links[id].no_pcm = 1;
-               id++;
+               links[*id].codecs = &idisp_components[i - 1];
+               links[*id].num_codecs = 1;
+               links[*id].platforms = platform_component;
+               links[*id].num_platforms = ARRAY_SIZE(platform_component);
+               links[*id].init = sof_hdmi_init;
+               links[*id].dpcm_playback = 1;
+               links[*id].no_pcm = 1;
+
+               (*id)++;
+       }
+
+       return 0;
+
+devm_err:
+       return -ENOMEM;
+}
+
+static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
+                                                         int ssp_codec,
+                                                         int ssp_amp,
+                                                         int dmic_be_num,
+                                                         int hdmi_num)
+{
+       struct snd_soc_dai_link_component *cpus;
+       struct snd_soc_dai_link *links;
+       int ret, id = 0, link_seq;
+
+       links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
+                            sof_audio_card_cs42l42.num_links, GFP_KERNEL);
+       cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
+                            sof_audio_card_cs42l42.num_links, GFP_KERNEL);
+       if (!links || !cpus)
+               goto devm_err;
+
+       link_seq = (sof_cs42l42_quirk & SOF_CS42L42_DAILINK_MASK) >> SOF_CS42L42_DAILINK_SHIFT;
+
+       while (link_seq) {
+               int link_type = link_seq & 0x07;
+
+               switch (link_type) {
+               case LINK_HP:
+                       ret = create_hp_codec_dai_links(dev, links, cpus, &id, ssp_codec);
+                       if (ret < 0) {
+                               dev_err(dev, "fail to create hp codec dai links, ret %d\n",
+                                       ret);
+                               goto devm_err;
+                       }
+                       break;
+               case LINK_SPK:
+                       ret = create_spk_amp_dai_links(dev, links, cpus, &id, ssp_amp);
+                       if (ret < 0) {
+                               dev_err(dev, "fail to create spk amp dai links, ret %d\n",
+                                       ret);
+                               goto devm_err;
+                       }
+                       break;
+               case LINK_DMIC:
+                       ret = create_dmic_dai_links(dev, links, cpus, &id, dmic_be_num);
+                       if (ret < 0) {
+                               dev_err(dev, "fail to create dmic dai links, ret %d\n",
+                                       ret);
+                               goto devm_err;
+                       }
+                       break;
+               case LINK_HDMI:
+                       ret = create_hdmi_dai_links(dev, links, cpus, &id, hdmi_num);
+                       if (ret < 0) {
+                               dev_err(dev, "fail to create hdmi dai links, ret %d\n",
+                                       ret);
+                               goto devm_err;
+                       }
+                       break;
+               case LINK_NONE:
+                       /* caught here if it's not used as terminator in macro */
+               default:
+                       dev_err(dev, "invalid link type %d\n", link_type);
+                       goto devm_err;
+               }
+
+               link_seq >>= 3;
        }
 
        return links;
@@ -484,7 +610,16 @@ static const struct platform_device_id board_ids[] = {
                .driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(2) |
                                        SOF_SPEAKER_AMP_PRESENT |
                                        SOF_MAX98357A_SPEAKER_AMP_PRESENT |
-                                       SOF_CS42L42_SSP_AMP(1)),
+                                       SOF_CS42L42_SSP_AMP(1)) |
+                                       SOF_CS42L42_DAILINK(LINK_SPK, LINK_HP, LINK_DMIC, LINK_HDMI, LINK_NONE),
+       },
+       {
+               .name = "jsl_cs4242_mx98360a",
+               .driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(0) |
+                                       SOF_SPEAKER_AMP_PRESENT |
+                                       SOF_MAX98360A_SPEAKER_AMP_PRESENT |
+                                       SOF_CS42L42_SSP_AMP(1)) |
+                                       SOF_CS42L42_DAILINK(LINK_HP, LINK_DMIC, LINK_HDMI, LINK_SPK, LINK_NONE),
        },
        { }
 };
index e9c52f8..e66dfe6 100644 (file)
@@ -134,7 +134,7 @@ void max_98373_set_codec_conf(struct snd_soc_card *card)
 EXPORT_SYMBOL_NS(max_98373_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON);
 
 /*
- * Maxim MAX98357A
+ * Maxim MAX98357A/MAX98360A
  */
 static const struct snd_kcontrol_new max_98357a_kcontrols[] = {
        SOC_DAPM_PIN_SWITCH("Spk"),
@@ -156,6 +156,13 @@ static struct snd_soc_dai_link_component max_98357a_components[] = {
        }
 };
 
+static struct snd_soc_dai_link_component max_98360a_components[] = {
+       {
+               .name = MAX_98360A_DEV0_NAME,
+               .dai_name = MAX_98357A_CODEC_DAI,
+       }
+};
+
 static int max_98357a_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_card *card = rtd->card;
@@ -193,5 +200,13 @@ void max_98357a_dai_link(struct snd_soc_dai_link *link)
 }
 EXPORT_SYMBOL_NS(max_98357a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
 
+void max_98360a_dai_link(struct snd_soc_dai_link *link)
+{
+       link->codecs = max_98360a_components;
+       link->num_codecs = ARRAY_SIZE(max_98360a_components);
+       link->init = max_98357a_init;
+}
+EXPORT_SYMBOL_NS(max_98360a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
+
 MODULE_DESCRIPTION("ASoC Intel SOF Maxim helpers");
 MODULE_LICENSE("GPL");
index 2674f1e..3ff5e8f 100644 (file)
@@ -25,11 +25,13 @@ void max_98373_set_codec_conf(struct snd_soc_card *card);
 int max_98373_trigger(struct snd_pcm_substream *substream, int cmd);
 
 /*
- * Maxim MAX98357A
+ * Maxim MAX98357A/MAX98360A
  */
 #define MAX_98357A_CODEC_DAI   "HiFi"
 #define MAX_98357A_DEV0_NAME   "MX98357A:00"
+#define MAX_98360A_DEV0_NAME   "MX98360A:00"
 
 void max_98357a_dai_link(struct snd_soc_dai_link *link);
+void max_98360a_dai_link(struct snd_soc_dai_link *link);
 
 #endif /* __SOF_MAXIM_COMMON_H */
index 2ec9c62..6815204 100644 (file)
 
 #define SOF_PCM512X_SSP_CODEC(quirk)           ((quirk) & GENMASK(3, 0))
 #define SOF_PCM512X_SSP_CODEC_MASK                     (GENMASK(3, 0))
+#define SOF_PCM512X_ENABLE_SSP_CAPTURE         BIT(4)
+#define SOF_PCM512X_ENABLE_DMIC                        BIT(5)
 
 #define IDISP_CODEC_MASK       0x4
 
 /* Default: SSP5 */
-static unsigned long sof_pcm512x_quirk = SOF_PCM512X_SSP_CODEC(5);
+static unsigned long sof_pcm512x_quirk =
+       SOF_PCM512X_SSP_CODEC(5) |
+       SOF_PCM512X_ENABLE_SSP_CAPTURE |
+       SOF_PCM512X_ENABLE_DMIC;
 
 static bool is_legacy_cpu;
 
@@ -244,8 +249,9 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
        links[id].dpcm_playback = 1;
        /*
         * capture only supported with specific versions of the Hifiberry DAC+
-        * links[id].dpcm_capture = 1;
         */
+       if (sof_pcm512x_quirk & SOF_PCM512X_ENABLE_SSP_CAPTURE)
+               links[id].dpcm_capture = 1;
        links[id].no_pcm = 1;
        links[id].cpus = &cpus[id];
        links[id].num_cpus = 1;
@@ -380,6 +386,9 @@ static int sof_audio_probe(struct platform_device *pdev)
 
        ssp_codec = sof_pcm512x_quirk & SOF_PCM512X_SSP_CODEC_MASK;
 
+       if (!(sof_pcm512x_quirk & SOF_PCM512X_ENABLE_DMIC))
+               dmic_be_num = 0;
+
        /* compute number of dai links */
        sof_audio_card_pcm512x.num_links = 1 + dmic_be_num + hdmi_num;
 
index 3921722..f096bd6 100644 (file)
@@ -162,6 +162,20 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
                                        SOF_RT5682_SSP_AMP(2) |
                                        SOF_RT5682_NUM_HDMIDEV(4)),
        },
+       {
+               .callback = sof_rt5682_quirk_cb,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
+                       DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"),
+               },
+               .driver_data = (void *)(SOF_RT5682_MCLK_EN |
+                                       SOF_RT5682_SSP_CODEC(0) |
+                                       SOF_SPEAKER_AMP_PRESENT |
+                                       SOF_MAX98373_SPEAKER_AMP_PRESENT |
+                                       SOF_RT5682_SSP_AMP(2) |
+                                       SOF_RT5682_NUM_HDMIDEV(4)),
+       },
        {}
 };
 
@@ -456,10 +470,6 @@ static const struct snd_kcontrol_new sof_controls[] = {
 
 };
 
-static const struct snd_kcontrol_new speaker_controls[] = {
-       SOC_DAPM_PIN_SWITCH("Spk"),
-};
-
 static const struct snd_soc_dapm_widget sof_widgets[] = {
        SND_SOC_DAPM_HP("Headphone Jack", NULL),
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
@@ -467,10 +477,6 @@ static const struct snd_soc_dapm_widget sof_widgets[] = {
        SND_SOC_DAPM_SPK("Right Spk", NULL),
 };
 
-static const struct snd_soc_dapm_widget speaker_widgets[] = {
-       SND_SOC_DAPM_SPK("Spk", NULL),
-};
-
 static const struct snd_soc_dapm_widget dmic_widgets[] = {
        SND_SOC_DAPM_MIC("SoC DMIC", NULL),
 };
@@ -484,11 +490,6 @@ static const struct snd_soc_dapm_route sof_map[] = {
        { "IN1P", NULL, "Headset Mic" },
 };
 
-static const struct snd_soc_dapm_route speaker_map[] = {
-       /* speaker */
-       { "Spk", NULL, "Speaker" },
-};
-
 static const struct snd_soc_dapm_route speaker_map_lr[] = {
        { "Left Spk", NULL, "Left SPO" },
        { "Right Spk", NULL, "Right SPO" },
@@ -505,34 +506,6 @@ static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd)
                                       ARRAY_SIZE(speaker_map_lr));
 }
 
-static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_soc_card *card = rtd->card;
-       int ret;
-
-       ret = snd_soc_dapm_new_controls(&card->dapm, speaker_widgets,
-                                       ARRAY_SIZE(speaker_widgets));
-       if (ret) {
-               dev_err(rtd->dev, "unable to add dapm controls, ret %d\n", ret);
-               /* Don't need to add routes if widget addition failed */
-               return ret;
-       }
-
-       ret = snd_soc_add_card_controls(card, speaker_controls,
-                                       ARRAY_SIZE(speaker_controls));
-       if (ret) {
-               dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);
-               return ret;
-       }
-
-       ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map,
-                                     ARRAY_SIZE(speaker_map));
-
-       if (ret)
-               dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
-       return ret;
-}
-
 static int dmic_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_card *card = rtd->card;
@@ -594,13 +567,6 @@ static struct snd_soc_dai_link_component dmic_component[] = {
        }
 };
 
-static struct snd_soc_dai_link_component max98360a_component[] = {
-       {
-               .name = "MX98360A:00",
-               .dai_name = "HiFi",
-       }
-};
-
 static struct snd_soc_dai_link_component rt1015_components[] = {
        {
                .name = "i2c-10EC1015:00",
@@ -775,9 +741,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
                        links[id].dpcm_capture = 1;
                } else if (sof_rt5682_quirk &
                                SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
-                       links[id].codecs = max98360a_component;
-                       links[id].num_codecs = ARRAY_SIZE(max98360a_component);
-                       links[id].init = speaker_codec_init;
+                       max_98360a_dai_link(&links[id]);
                } else if (sof_rt5682_quirk &
                                SOF_RT1011_SPEAKER_AMP_PRESENT) {
                        sof_rt1011_dai_link(&links[id]);
index 82d909e..6602eda 100644 (file)
@@ -13,8 +13,9 @@
 #include <sound/soc.h>
 #include <sound/soc-acpi.h>
 #include "sof_sdw_common.h"
+#include "../../codecs/rt711.h"
 
-unsigned long sof_sdw_quirk = SOF_RT711_JD_SRC_JD1;
+unsigned long sof_sdw_quirk = RT711_JD1;
 static int quirk_override = -1;
 module_param_named(quirk, quirk_override, int, 0444);
 MODULE_PARM_DESC(quirk, "Board-specific quirk override");
@@ -63,7 +64,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
                        DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
                },
-               .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
+               .driver_data = (void *)(RT711_JD2 |
                                        SOF_RT715_DAI_ID_FIX),
        },
        {
@@ -73,7 +74,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
                        DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
                },
-               .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
+               .driver_data = (void *)(RT711_JD2 |
                                        SOF_RT715_DAI_ID_FIX),
        },
        {
@@ -82,7 +83,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
                        DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
                },
-               .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
+               .driver_data = (void *)(RT711_JD2 |
                                        SOF_RT715_DAI_ID_FIX |
                                        SOF_SDW_FOUR_SPK),
        },
@@ -92,7 +93,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
                        DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
                },
-               .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
+               .driver_data = (void *)(RT711_JD2 |
                                        SOF_RT715_DAI_ID_FIX |
                                        SOF_SDW_FOUR_SPK),
        },
@@ -114,7 +115,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
                                  "Tiger Lake Client Platform"),
                },
                .driver_data = (void *)(SOF_SDW_TGL_HDMI |
-                                       SOF_RT711_JD_SRC_JD1 |
+                                       RT711_JD1 |
                                        SOF_SDW_PCH_DMIC |
                                        SOF_SSP_PORT(SOF_I2S_SSP2)),
        },
@@ -125,9 +126,21 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
                        DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
                },
                .driver_data = (void *)(SOF_SDW_TGL_HDMI |
-                                       SOF_RT711_JD_SRC_JD2 |
+                                       RT711_JD2 |
                                        SOF_RT715_DAI_ID_FIX),
        },
+       {
+               /* Dell XPS 9710 */
+               .callback = sof_sdw_quirk_cb,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D")
+               },
+               .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+                                       RT711_JD2 |
+                                       SOF_RT715_DAI_ID_FIX |
+                                       SOF_SDW_FOUR_SPK),
+       },
        {
                .callback = sof_sdw_quirk_cb,
                .matches = {
@@ -135,7 +148,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
                        DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
                },
                .driver_data = (void *)(SOF_SDW_TGL_HDMI |
-                                       SOF_RT711_JD_SRC_JD2 |
+                                       RT711_JD2 |
                                        SOF_RT715_DAI_ID_FIX |
                                        SOF_SDW_FOUR_SPK),
        },
@@ -175,7 +188,18 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
                },
                .driver_data = (void *)(SOF_SDW_TGL_HDMI |
                                        SOF_SDW_PCH_DMIC |
-                                       SOF_RT711_JD_SRC_JD2),
+                                       RT711_JD2),
+       },
+       {
+               /* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
+               .callback = sof_sdw_quirk_cb,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"),
+               },
+               .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+                                       SOF_SDW_PCH_DMIC |
+                                       RT711_JD1),
        },
        /* TigerLake-SDCA devices */
        {
@@ -185,7 +209,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
                        DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
                },
                .driver_data = (void *)(SOF_SDW_TGL_HDMI |
-                                       SOF_RT711_JD_SRC_JD2 |
+                                       RT711_JD2 |
                                        SOF_RT715_DAI_ID_FIX |
                                        SOF_SDW_FOUR_SPK),
        },
@@ -196,7 +220,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
                },
-               .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 |
+               .driver_data = (void *)(RT711_JD2_100K |
                                        SOF_SDW_TGL_HDMI |
                                        SOF_RT715_DAI_ID_FIX |
                                        SOF_BT_OFFLOAD_SSP(2) |
@@ -328,7 +352,8 @@ static const struct snd_soc_ops sdw_ops = {
        .shutdown = sdw_shutdown,
 };
 
-static int sof_sdw_mic_codec_mockup_init(const struct snd_soc_acpi_link_adr *link,
+static int sof_sdw_mic_codec_mockup_init(struct snd_soc_card *card,
+                                        const struct snd_soc_acpi_link_adr *link,
                                         struct snd_soc_dai_link *dai_links,
                                         struct sof_sdw_codec_info *info,
                                         bool playback)
@@ -673,7 +698,8 @@ static int create_codec_dai_name(struct device *dev,
        return 0;
 }
 
-static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link,
+static int set_codec_init_func(struct snd_soc_card *card,
+                              const struct snd_soc_acpi_link_adr *link,
                               struct snd_soc_dai_link *dai_links,
                               bool playback, int group_id)
 {
@@ -696,7 +722,8 @@ static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link,
                        if (link->adr_d[i].endpoints->group_id != group_id)
                                continue;
                        if (codec_info_list[codec_index].init)
-                               codec_info_list[codec_index].init(link,
+                               codec_info_list[codec_index].init(card,
+                                               link,
                                                dai_links,
                                                &codec_info_list[codec_index],
                                                playback);
@@ -781,7 +808,8 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
        return 0;
 }
 
-static int create_sdw_dailink(struct device *dev, int *be_index,
+static int create_sdw_dailink(struct snd_soc_card *card,
+                             struct device *dev, int *be_index,
                              struct snd_soc_dai_link *dai_links,
                              int sdw_be_num, int sdw_cpu_dai_num,
                              struct snd_soc_dai_link_component *cpus,
@@ -902,7 +930,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index,
                              codecs, codec_num,
                              NULL, &sdw_ops);
 
-               ret = set_codec_init_func(link, dai_links + (*be_index)++,
+               ret = set_codec_init_func(card, link, dai_links + (*be_index)++,
                                          playback, group_id);
                if (ret < 0) {
                        dev_err(dev, "failed to init codec %d", codec_index);
@@ -1083,7 +1111,7 @@ static int sof_card_dai_links_create(struct device *dev,
                    group_generated[endpoint->group_id])
                        continue;
 
-               ret = create_sdw_dailink(dev, &be_id, links, sdw_be_num,
+               ret = create_sdw_dailink(card, dev, &be_id, links, sdw_be_num,
                                         sdw_cpu_dai_num, cpus, adr_link,
                                         &cpu_id, group_generated,
                                         codec_conf, codec_conf_count,
@@ -1146,7 +1174,7 @@ SSP:
                              ssp_components, 1,
                              NULL, info->ops);
 
-               ret = info->init(NULL, links + link_id, info, 0);
+               ret = info->init(card, NULL, links + link_id, info, 0);
                if (ret < 0)
                        return ret;
 
@@ -1369,7 +1397,7 @@ static int mc_remove(struct platform_device *pdev)
                for_each_card_prelinks(card, j, link) {
                        if (!strcmp(link->codecs[0].dai_name,
                                    codec_info_list[i].dai_name)) {
-                               ret = codec_info_list[i].exit(&pdev->dev, link);
+                               ret = codec_info_list[i].exit(card, link);
                                if (ret)
                                        dev_warn(&pdev->dev,
                                                 "codec exit failed %d\n",
index ec57404..b35f5a9 100644 (file)
 /* 8 combinations with 4 links + unused group 0 */
 #define SDW_MAX_GROUPS 9
 
-enum {
-       SOF_RT711_JD_SRC_JD1 = 1,
-       SOF_RT711_JD_SRC_JD2 = 2,
-};
-
 enum {
        SOF_PRE_TGL_HDMI_COUNT = 3,
        SOF_TGL_HDMI_COUNT = 4,
@@ -41,21 +36,21 @@ enum {
        SOF_I2S_SSP5 = BIT(5),
 };
 
-#define SOF_RT711_JDSRC(quirk)         ((quirk) & GENMASK(1, 0))
-#define SOF_SDW_FOUR_SPK               BIT(2)
-#define SOF_SDW_TGL_HDMI               BIT(3)
-#define SOF_SDW_PCH_DMIC               BIT(4)
-#define SOF_SSP_PORT(x)                (((x) & GENMASK(5, 0)) << 5)
-#define SOF_SSP_GET_PORT(quirk)        (((quirk) >> 5) & GENMASK(5, 0))
-#define SOF_RT715_DAI_ID_FIX           BIT(11)
-#define SOF_SDW_NO_AGGREGATION         BIT(12)
+#define SOF_RT711_JDSRC(quirk)         ((quirk) & GENMASK(3, 0))
+#define SOF_SDW_FOUR_SPK               BIT(4)
+#define SOF_SDW_TGL_HDMI               BIT(5)
+#define SOF_SDW_PCH_DMIC               BIT(6)
+#define SOF_SSP_PORT(x)                (((x) & GENMASK(5, 0)) << 7)
+#define SOF_SSP_GET_PORT(quirk)        (((quirk) >> 7) & GENMASK(5, 0))
+#define SOF_RT715_DAI_ID_FIX           BIT(13)
+#define SOF_SDW_NO_AGGREGATION         BIT(14)
 
 /* BT audio offload: reserve 3 bits for future */
-#define SOF_BT_OFFLOAD_SSP_SHIFT       13
-#define SOF_BT_OFFLOAD_SSP_MASK        (GENMASK(15, 13))
+#define SOF_BT_OFFLOAD_SSP_SHIFT       15
+#define SOF_BT_OFFLOAD_SSP_MASK        (GENMASK(17, 15))
 #define SOF_BT_OFFLOAD_SSP(quirk)      \
        (((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK)
-#define SOF_SSP_BT_OFFLOAD_PRESENT     BIT(16)
+#define SOF_SSP_BT_OFFLOAD_PRESENT     BIT(18)
 
 struct sof_sdw_codec_info {
        const int part_id;
@@ -67,12 +62,13 @@ struct sof_sdw_codec_info {
        const char *dai_name;
        const struct snd_soc_ops *ops;
 
-       int  (*init)(const struct snd_soc_acpi_link_adr *link,
+       int  (*init)(struct snd_soc_card *card,
+                    const struct snd_soc_acpi_link_adr *link,
                     struct snd_soc_dai_link *dai_links,
                     struct sof_sdw_codec_info *info,
                     bool playback);
 
-       int (*exit)(struct device *dev, struct snd_soc_dai_link *dai_link);
+       int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
        bool late_probe;
        int (*codec_card_late_probe)(struct snd_soc_card *card);
 };
@@ -81,6 +77,7 @@ struct mc_private {
        struct list_head hdmi_pcm_list;
        bool idisp_codec;
        struct snd_soc_jack sdw_headset;
+       struct device *headset_codec_dev; /* only one headset per card */
 };
 
 extern unsigned long sof_sdw_quirk;
@@ -100,21 +97,24 @@ int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card);
 int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd);
 
 /* RT711 support */
-int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt711_init(struct snd_soc_card *card,
+                      const struct snd_soc_acpi_link_adr *link,
                       struct snd_soc_dai_link *dai_links,
                       struct sof_sdw_codec_info *info,
                       bool playback);
-int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link);
+int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
 
 /* RT711-SDCA support */
-int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt711_sdca_init(struct snd_soc_card *card,
+                           const struct snd_soc_acpi_link_adr *link,
                            struct snd_soc_dai_link *dai_links,
                            struct sof_sdw_codec_info *info,
                            bool playback);
-int sof_sdw_rt711_sdca_exit(struct device *dev, struct snd_soc_dai_link *dai_link);
+int sof_sdw_rt711_sdca_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
 
 /* RT700 support */
-int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt700_init(struct snd_soc_card *card,
+                      const struct snd_soc_acpi_link_adr *link,
                       struct snd_soc_dai_link *dai_links,
                       struct sof_sdw_codec_info *info,
                       bool playback);
@@ -122,31 +122,36 @@ int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link,
 /* RT1308 support */
 extern struct snd_soc_ops sof_sdw_rt1308_i2s_ops;
 
-int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt1308_init(struct snd_soc_card *card,
+                       const struct snd_soc_acpi_link_adr *link,
                        struct snd_soc_dai_link *dai_links,
                        struct sof_sdw_codec_info *info,
                        bool playback);
 
 /* RT1316 support */
-int sof_sdw_rt1316_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt1316_init(struct snd_soc_card *card,
+                       const struct snd_soc_acpi_link_adr *link,
                        struct snd_soc_dai_link *dai_links,
                        struct sof_sdw_codec_info *info,
                        bool playback);
 
 /* RT715 support */
-int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt715_init(struct snd_soc_card *card,
+                      const struct snd_soc_acpi_link_adr *link,
                       struct snd_soc_dai_link *dai_links,
                       struct sof_sdw_codec_info *info,
                       bool playback);
 
 /* RT715-SDCA support */
-int sof_sdw_rt715_sdca_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt715_sdca_init(struct snd_soc_card *card,
+                           const struct snd_soc_acpi_link_adr *link,
                            struct snd_soc_dai_link *dai_links,
                            struct sof_sdw_codec_info *info,
                            bool playback);
 
 /* MAX98373 support */
-int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_mx8373_init(struct snd_soc_card *card,
+                       const struct snd_soc_acpi_link_adr *link,
                        struct snd_soc_dai_link *dai_links,
                        struct sof_sdw_codec_info *info,
                        bool playback);
@@ -154,7 +159,8 @@ int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link,
 int sof_sdw_mx8373_late_probe(struct snd_soc_card *card);
 
 /* RT5682 support */
-int sof_sdw_rt5682_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt5682_init(struct snd_soc_card *card,
+                       const struct snd_soc_acpi_link_adr *link,
                        struct snd_soc_dai_link *dai_links,
                        struct sof_sdw_codec_info *info,
                        bool playback);
index 25daef9..77a3f32 100644 (file)
@@ -90,7 +90,7 @@ static int mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enabl
 
 static int mx8373_sdw_prepare(struct snd_pcm_substream *substream)
 {
-       int ret = 0;
+       int ret;
 
        /* according to soc_pcm_prepare dai link prepare is called first */
        ret = sdw_prepare(substream);
@@ -102,7 +102,7 @@ static int mx8373_sdw_prepare(struct snd_pcm_substream *substream)
 
 static int mx8373_sdw_hw_free(struct snd_pcm_substream *substream)
 {
-       int ret = 0;
+       int ret;
 
        /* according to soc_pcm_hw_free dai link free is called first */
        ret = sdw_hw_free(substream);
@@ -120,7 +120,8 @@ static const struct snd_soc_ops max_98373_sdw_ops = {
        .shutdown = sdw_shutdown,
 };
 
-int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_mx8373_init(struct snd_soc_card *card,
+                       const struct snd_soc_acpi_link_adr *link,
                        struct snd_soc_dai_link *dai_links,
                        struct sof_sdw_codec_info *info,
                        bool playback)
index 0d476f6..f078fb1 100644 (file)
@@ -127,7 +127,8 @@ struct snd_soc_ops sof_sdw_rt1308_i2s_ops = {
        .hw_params = rt1308_i2s_hw_params,
 };
 
-int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt1308_init(struct snd_soc_card *card,
+                       const struct snd_soc_acpi_link_adr *link,
                        struct snd_soc_dai_link *dai_links,
                        struct sof_sdw_codec_info *info,
                        bool playback)
index d6e1ebf..58194b3 100644 (file)
@@ -89,7 +89,8 @@ static int all_spk_init(struct snd_soc_pcm_runtime *rtd)
        return second_spk_init(rtd);
 }
 
-int sof_sdw_rt1316_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt1316_init(struct snd_soc_card *card,
+                       const struct snd_soc_acpi_link_adr *link,
                        struct snd_soc_dai_link *dai_links,
                        struct sof_sdw_codec_info *info,
                        bool playback)
index 5fa1a59..ea55479 100644 (file)
@@ -111,7 +111,8 @@ static int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd)
        return ret;
 }
 
-int sof_sdw_rt5682_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt5682_init(struct snd_soc_card *card,
+                       const struct snd_soc_acpi_link_adr *link,
                        struct snd_soc_dai_link *dai_links,
                        struct sof_sdw_codec_info *info,
                        bool playback)
index 21e7e4a..bb9584c 100644 (file)
@@ -110,7 +110,8 @@ static int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd)
        return ret;
 }
 
-int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt700_init(struct snd_soc_card *card,
+                      const struct snd_soc_acpi_link_adr *link,
                       struct snd_soc_dai_link *dai_links,
                       struct sof_sdw_codec_info *info,
                       bool playback)
index 04074c0..c38b70c 100644 (file)
  * Note this MUST be called before snd_soc_register_card(), so that the props
  * are in place before the codec component driver's probe function parses them.
  */
-static int rt711_add_codec_device_props(const char *sdw_dev_name)
+static int rt711_add_codec_device_props(struct device *sdw_dev)
 {
        struct property_entry props[MAX_NO_PROPS] = {};
-       struct device *sdw_dev;
+       struct fwnode_handle *fwnode;
        int ret;
 
-       sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_dev_name);
-       if (!sdw_dev)
-               return -EPROBE_DEFER;
+       if (!SOF_RT711_JDSRC(sof_sdw_quirk))
+               return 0;
+       props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_RT711_JDSRC(sof_sdw_quirk));
 
-       if (SOF_RT711_JDSRC(sof_sdw_quirk)) {
-               props[0] = PROPERTY_ENTRY_U32("realtek,jd-src",
-                                             SOF_RT711_JDSRC(sof_sdw_quirk));
-       }
+       fwnode = fwnode_create_software_node(props, NULL);
+       if (IS_ERR(fwnode))
+               return PTR_ERR(fwnode);
+
+       ret = device_add_software_node(sdw_dev, to_software_node(fwnode));
 
-       ret = device_add_properties(sdw_dev, props);
-       put_device(sdw_dev);
+       fwnode_handle_put(fwnode);
 
        return ret;
 }
@@ -135,26 +135,24 @@ static int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd)
        return ret;
 }
 
-int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link)
+int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
 {
-       struct device *sdw_dev;
-
-       sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL,
-                                         dai_link->codecs[0].name);
-       if (!sdw_dev)
-               return -EINVAL;
+       struct mc_private *ctx = snd_soc_card_get_drvdata(card);
 
-       device_remove_properties(sdw_dev);
-       put_device(sdw_dev);
+       device_remove_software_node(ctx->headset_codec_dev);
+       put_device(ctx->headset_codec_dev);
 
        return 0;
 }
 
-int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt711_init(struct snd_soc_card *card,
+                      const struct snd_soc_acpi_link_adr *link,
                       struct snd_soc_dai_link *dai_links,
                       struct sof_sdw_codec_info *info,
                       bool playback)
 {
+       struct mc_private *ctx = snd_soc_card_get_drvdata(card);
+       struct device *sdw_dev;
        int ret;
 
        /*
@@ -164,9 +162,16 @@ int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link,
        if (!playback)
                return 0;
 
-       ret = rt711_add_codec_device_props(dai_links->codecs[0].name);
-       if (ret < 0)
+       sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name);
+       if (!sdw_dev)
+               return -EPROBE_DEFER;
+
+       ret = rt711_add_codec_device_props(sdw_dev);
+       if (ret < 0) {
+               put_device(sdw_dev);
                return ret;
+       }
+       ctx->headset_codec_dev = sdw_dev;
 
        dai_links->init = rt711_rtd_init;
 
index 19496f0..4215ddc 100644 (file)
  * Note this MUST be called before snd_soc_register_card(), so that the props
  * are in place before the codec component driver's probe function parses them.
  */
-static int rt711_sdca_add_codec_device_props(const char *sdw_dev_name)
+static int rt711_sdca_add_codec_device_props(struct device *sdw_dev)
 {
        struct property_entry props[MAX_NO_PROPS] = {};
-       struct device *sdw_dev;
+       struct fwnode_handle *fwnode;
        int ret;
 
-       sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_dev_name);
-       if (!sdw_dev)
-               return -EPROBE_DEFER;
+       if (!SOF_RT711_JDSRC(sof_sdw_quirk))
+               return 0;
 
-       if (SOF_RT711_JDSRC(sof_sdw_quirk)) {
-               props[0] = PROPERTY_ENTRY_U32("realtek,jd-src",
-                                             SOF_RT711_JDSRC(sof_sdw_quirk));
-       }
+       props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_RT711_JDSRC(sof_sdw_quirk));
 
-       ret = device_add_properties(sdw_dev, props);
-       put_device(sdw_dev);
+       fwnode = fwnode_create_software_node(props, NULL);
+       if (IS_ERR(fwnode))
+               return PTR_ERR(fwnode);
+
+       ret = device_add_software_node(sdw_dev, to_software_node(fwnode));
+
+       fwnode_handle_put(fwnode);
 
        return ret;
 }
@@ -135,26 +136,24 @@ static int rt711_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
        return ret;
 }
 
-int sof_sdw_rt711_sdca_exit(struct device *dev, struct snd_soc_dai_link *dai_link)
+int sof_sdw_rt711_sdca_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
 {
-       struct device *sdw_dev;
-
-       sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL,
-                                         dai_link->codecs[0].name);
-       if (!sdw_dev)
-               return -EINVAL;
+       struct mc_private *ctx = snd_soc_card_get_drvdata(card);
 
-       device_remove_properties(sdw_dev);
-       put_device(sdw_dev);
+       device_remove_software_node(ctx->headset_codec_dev);
+       put_device(ctx->headset_codec_dev);
 
        return 0;
 }
 
-int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt711_sdca_init(struct snd_soc_card *card,
+                           const struct snd_soc_acpi_link_adr *link,
                            struct snd_soc_dai_link *dai_links,
                            struct sof_sdw_codec_info *info,
                            bool playback)
 {
+       struct mc_private *ctx = snd_soc_card_get_drvdata(card);
+       struct device *sdw_dev;
        int ret;
 
        /*
@@ -164,9 +163,16 @@ int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link,
        if (!playback)
                return 0;
 
-       ret = rt711_sdca_add_codec_device_props(dai_links->codecs[0].name);
-       if (ret < 0)
+       sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name);
+       if (!sdw_dev)
+               return -EPROBE_DEFER;
+
+       ret = rt711_sdca_add_codec_device_props(sdw_dev);
+       if (ret < 0) {
+               put_device(sdw_dev);
                return ret;
+       }
+       ctx->headset_codec_dev = sdw_dev;
 
        dai_links->init = rt711_sdca_rtd_init;
 
index 9b298f7..c8af378 100644 (file)
@@ -24,7 +24,8 @@ static int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
-int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt715_init(struct snd_soc_card *card,
+                      const struct snd_soc_acpi_link_adr *link,
                       struct snd_soc_dai_link *dai_links,
                       struct sof_sdw_codec_info *info,
                       bool playback)
index c056e56..85d3d8c 100644 (file)
@@ -24,7 +24,8 @@ static int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
-int sof_sdw_rt715_sdca_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt715_sdca_init(struct snd_soc_card *card,
+                           const struct snd_soc_acpi_link_adr *link,
                            struct snd_soc_dai_link *dai_links,
                            struct sof_sdw_codec_info *info,
                            bool playback)
index 42ef51c..b591c6f 100644 (file)
@@ -75,7 +75,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = {
        },
        {
                .id = "DLGS7219",
-               .drv_name = "cml_da7219_max98357a",
+               .drv_name = "cml_da7219_mx98357a",
                .machine_quirk = snd_soc_acpi_codec_list,
                .quirk_data = &max98390_spk_codecs,
                .sof_fw_filename = "sof-cml.ri",
index 3586ce7..69ff728 100644 (file)
@@ -73,6 +73,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
                .quirk_data = &mx98360a_spk,
                .sof_tplg_filename = "sof-jsl-rt5682-mx98360a.tplg",
        },
+       {
+               .id = "10134242",
+               .drv_name = "jsl_cs4242_mx98360a",
+               .sof_fw_filename = "sof-jsl.ri",
+               .machine_quirk = snd_soc_acpi_codec_list,
+               .quirk_data = &mx98360a_spk,
+               .sof_tplg_filename = "sof-jsl-cs42l42-mx98360a.tplg",
+       },
        {},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines);
index ba5ff46..741bf2f 100644 (file)
@@ -87,7 +87,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = {
        },
        {
                .id = "DLGS7219",
-               .drv_name = "kbl_da7219_max98357a",
+               .drv_name = "kbl_da7219_mx98357a",
                .fw_filename = "intel/dsp_fw_kbl.bin",
                .machine_quirk = snd_soc_acpi_codec_list,
                .quirk_data = &kbl_7219_98357_codecs,
index e2488f0..785d5f5 100644 (file)
@@ -197,6 +197,15 @@ static const struct snd_soc_acpi_link_adr tgl_rvp[] = {
        {}
 };
 
+static const struct snd_soc_acpi_link_adr tgl_rvp_headset_only[] = {
+       {
+               .mask = BIT(0),
+               .num_adr = ARRAY_SIZE(rt711_0_adr),
+               .adr_d = rt711_0_adr,
+       },
+       {}
+};
+
 static const struct snd_soc_acpi_link_adr tgl_hp[] = {
        {
                .mask = BIT(0),
@@ -421,6 +430,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
                .drv_name = "sof_sdw",
                .sof_tplg_filename = "sof-tgl-sdw-max98373-rt5682.tplg",
        },
+       {
+               .link_mask = 0x1, /* rt711 on link 0 */
+               .links = tgl_rvp_headset_only,
+               .drv_name = "sof_sdw",
+               .sof_tplg_filename = "sof-tgl-rt711.tplg",
+       },
        {},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_sdw_machines);
index 476ef18..eaad180 100644 (file)
@@ -472,6 +472,75 @@ static void skl_set_base_module_format(struct skl_dev *skl,
        base_cfg->is_pages = res->is_pages;
 }
 
+static void fill_pin_params(struct skl_audio_data_format *pin_fmt,
+                           struct skl_module_fmt *format)
+{
+       pin_fmt->number_of_channels = format->channels;
+       pin_fmt->s_freq = format->s_freq;
+       pin_fmt->bit_depth = format->bit_depth;
+       pin_fmt->valid_bit_depth = format->valid_bit_depth;
+       pin_fmt->ch_cfg = format->ch_cfg;
+       pin_fmt->sample_type = format->sample_type;
+       pin_fmt->channel_map = format->ch_map;
+       pin_fmt->interleaving = format->interleaving_style;
+}
+
+/*
+ * Any module configuration begins with a base module configuration but
+ * can be followed by a generic extension containing audio format for all
+ * module's pins that are in use.
+ */
+static void skl_set_base_ext_module_format(struct skl_dev *skl,
+                                          struct skl_module_cfg *mconfig,
+                                          struct skl_base_cfg_ext *base_cfg_ext)
+{
+       struct skl_module *module = mconfig->module;
+       struct skl_module_pin_resources *pin_res;
+       struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx];
+       struct skl_module_res *res = &module->resources[mconfig->res_idx];
+       struct skl_module_fmt *format;
+       struct skl_pin_format *pin_fmt;
+       char *params;
+       int i;
+
+       base_cfg_ext->nr_input_pins = res->nr_input_pins;
+       base_cfg_ext->nr_output_pins = res->nr_output_pins;
+       base_cfg_ext->priv_param_length =
+               mconfig->formats_config[SKL_PARAM_INIT].caps_size;
+
+       for (i = 0; i < res->nr_input_pins; i++) {
+               pin_res = &res->input[i];
+               pin_fmt = &base_cfg_ext->pins_fmt[i];
+
+               pin_fmt->pin_idx = pin_res->pin_index;
+               pin_fmt->buf_size = pin_res->buf_size;
+
+               format = &fmt->inputs[pin_res->pin_index].fmt;
+               fill_pin_params(&pin_fmt->audio_fmt, format);
+       }
+
+       for (i = 0; i < res->nr_output_pins; i++) {
+               pin_res = &res->output[i];
+               pin_fmt = &base_cfg_ext->pins_fmt[res->nr_input_pins + i];
+
+               pin_fmt->pin_idx = pin_res->pin_index;
+               pin_fmt->buf_size = pin_res->buf_size;
+
+               format = &fmt->outputs[pin_res->pin_index].fmt;
+               fill_pin_params(&pin_fmt->audio_fmt, format);
+       }
+
+       if (!base_cfg_ext->priv_param_length)
+               return;
+
+       params = (char *)base_cfg_ext + sizeof(struct skl_base_cfg_ext);
+       params += (base_cfg_ext->nr_input_pins + base_cfg_ext->nr_output_pins) *
+                 sizeof(struct skl_pin_format);
+
+       memcpy(params, mconfig->formats_config[SKL_PARAM_INIT].caps,
+              mconfig->formats_config[SKL_PARAM_INIT].caps_size);
+}
+
 /*
  * Copies copier capabilities into copier module and updates copier module
  * config size.
@@ -479,15 +548,15 @@ static void skl_set_base_module_format(struct skl_dev *skl,
 static void skl_copy_copier_caps(struct skl_module_cfg *mconfig,
                                struct skl_cpr_cfg *cpr_mconfig)
 {
-       if (mconfig->formats_config.caps_size == 0)
+       if (mconfig->formats_config[SKL_PARAM_INIT].caps_size == 0)
                return;
 
        memcpy(cpr_mconfig->gtw_cfg.config_data,
-                       mconfig->formats_config.caps,
-                       mconfig->formats_config.caps_size);
+                       mconfig->formats_config[SKL_PARAM_INIT].caps,
+                       mconfig->formats_config[SKL_PARAM_INIT].caps_size);
 
        cpr_mconfig->gtw_cfg.config_length =
-                       (mconfig->formats_config.caps_size) / 4;
+                       (mconfig->formats_config[SKL_PARAM_INIT].caps_size) / 4;
 }
 
 #define SKL_NON_GATEWAY_CPR_NODE_ID 0xFFFFFFFF
@@ -737,28 +806,6 @@ static void skl_set_copier_format(struct skl_dev *skl,
        skl_setup_cpr_gateway_cfg(skl, mconfig, cpr_mconfig);
 }
 
-/*
- * Algo module are DSP pre processing modules. Algo module take base module
- * configuration and params
- */
-
-static void skl_set_algo_format(struct skl_dev *skl,
-                       struct skl_module_cfg *mconfig,
-                       struct skl_algo_cfg *algo_mcfg)
-{
-       struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)algo_mcfg;
-
-       skl_set_base_module_format(skl, mconfig, base_cfg);
-
-       if (mconfig->formats_config.caps_size == 0)
-               return;
-
-       memcpy(algo_mcfg->params,
-                       mconfig->formats_config.caps,
-                       mconfig->formats_config.caps_size);
-
-}
-
 /*
  * Mic select module allows selecting one or many input channels, thus
  * acting as a demux.
@@ -781,12 +828,14 @@ static void skl_set_base_outfmt_format(struct skl_dev *skl,
 static u16 skl_get_module_param_size(struct skl_dev *skl,
                        struct skl_module_cfg *mconfig)
 {
+       struct skl_module_res *res;
+       struct skl_module *module = mconfig->module;
        u16 param_size;
 
        switch (mconfig->m_type) {
        case SKL_MODULE_TYPE_COPIER:
                param_size = sizeof(struct skl_cpr_cfg);
-               param_size += mconfig->formats_config.caps_size;
+               param_size += mconfig->formats_config[SKL_PARAM_INIT].caps_size;
                return param_size;
 
        case SKL_MODULE_TYPE_SRCINT:
@@ -795,22 +844,24 @@ static u16 skl_get_module_param_size(struct skl_dev *skl,
        case SKL_MODULE_TYPE_UPDWMIX:
                return sizeof(struct skl_up_down_mixer_cfg);
 
-       case SKL_MODULE_TYPE_ALGO:
-               param_size = sizeof(struct skl_base_cfg);
-               param_size += mconfig->formats_config.caps_size;
-               return param_size;
-
        case SKL_MODULE_TYPE_BASE_OUTFMT:
        case SKL_MODULE_TYPE_MIC_SELECT:
-       case SKL_MODULE_TYPE_KPB:
                return sizeof(struct skl_base_outfmt_cfg);
 
-       default:
-               /*
-                * return only base cfg when no specific module type is
-                * specified
-                */
+       case SKL_MODULE_TYPE_MIXER:
+       case SKL_MODULE_TYPE_KPB:
                return sizeof(struct skl_base_cfg);
+
+       case SKL_MODULE_TYPE_ALGO:
+       default:
+               res = &module->resources[mconfig->res_idx];
+
+               param_size = sizeof(struct skl_base_cfg) + sizeof(struct skl_base_cfg_ext);
+               param_size += (res->nr_input_pins + res->nr_output_pins) *
+                             sizeof(struct skl_pin_format);
+               param_size += mconfig->formats_config[SKL_PARAM_INIT].caps_size;
+
+               return param_size;
        }
 
        return 0;
@@ -851,20 +902,23 @@ static int skl_set_module_format(struct skl_dev *skl,
                skl_set_updown_mixer_format(skl, module_config, *param_data);
                break;
 
-       case SKL_MODULE_TYPE_ALGO:
-               skl_set_algo_format(skl, module_config, *param_data);
-               break;
-
        case SKL_MODULE_TYPE_BASE_OUTFMT:
        case SKL_MODULE_TYPE_MIC_SELECT:
-       case SKL_MODULE_TYPE_KPB:
                skl_set_base_outfmt_format(skl, module_config, *param_data);
                break;
 
-       default:
+       case SKL_MODULE_TYPE_MIXER:
+       case SKL_MODULE_TYPE_KPB:
                skl_set_base_module_format(skl, module_config, *param_data);
                break;
 
+       case SKL_MODULE_TYPE_ALGO:
+       default:
+               skl_set_base_module_format(skl, module_config, *param_data);
+               skl_set_base_ext_module_format(skl, module_config,
+                                              *param_data +
+                                              sizeof(struct skl_base_cfg));
+               break;
        }
 
        dev_dbg(skl->dev, "Module type=%d id=%d config size: %d bytes\n",
@@ -1085,19 +1139,6 @@ int skl_unbind_modules(struct skl_dev *skl,
        return ret;
 }
 
-static void fill_pin_params(struct skl_audio_data_format *pin_fmt,
-                               struct skl_module_fmt *format)
-{
-       pin_fmt->number_of_channels = format->channels;
-       pin_fmt->s_freq = format->s_freq;
-       pin_fmt->bit_depth = format->bit_depth;
-       pin_fmt->valid_bit_depth = format->valid_bit_depth;
-       pin_fmt->ch_cfg = format->ch_cfg;
-       pin_fmt->sample_type = format->sample_type;
-       pin_fmt->channel_map = format->ch_map;
-       pin_fmt->interleaving = format->interleaving_style;
-}
-
 #define CPR_SINK_FMT_PARAM_ID 2
 
 /*
index b1ca64d..9ecaf6a 100644 (file)
@@ -1214,13 +1214,6 @@ static snd_pcm_uframes_t skl_platform_soc_pointer(
        return bytes_to_frames(substream->runtime, pos);
 }
 
-static int skl_platform_soc_mmap(struct snd_soc_component *component,
-                                struct snd_pcm_substream *substream,
-                                struct vm_area_struct *area)
-{
-       return snd_pcm_lib_default_mmap(substream, area);
-}
-
 static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream,
                                u64 nsec)
 {
@@ -1317,21 +1310,6 @@ static int skl_get_module_info(struct skl_dev *skl,
                return -EIO;
        }
 
-       list_for_each_entry(module, &skl->uuid_list, list) {
-               if (guid_equal(uuid_mod, &module->uuid)) {
-                       mconfig->id.module_id = module->id;
-                       if (mconfig->module)
-                               mconfig->module->loadable = module->is_loadable;
-                       ret = 0;
-                       break;
-               }
-       }
-
-       if (ret)
-               return ret;
-
-       uuid_mod = &module->uuid;
-       ret = -EIO;
        for (i = 0; i < skl->nr_modules; i++) {
                skl_module = skl->modules[i];
                uuid_tplg = &skl_module->uuid;
@@ -1341,10 +1319,18 @@ static int skl_get_module_info(struct skl_dev *skl,
                        break;
                }
        }
+
        if (skl->nr_modules && ret)
                return ret;
 
+       ret = -EIO;
        list_for_each_entry(module, &skl->uuid_list, list) {
+               if (guid_equal(uuid_mod, &module->uuid)) {
+                       mconfig->id.module_id = module->id;
+                       mconfig->module->loadable = module->is_loadable;
+                       ret = 0;
+               }
+
                for (i = 0; i < MAX_IN_QUEUE; i++) {
                        pin_id = &mconfig->m_in_pin[i].id;
                        if (guid_equal(&pin_id->mod_uuid, &module->uuid))
@@ -1358,7 +1344,7 @@ static int skl_get_module_info(struct skl_dev *skl,
                }
        }
 
-       return 0;
+       return ret;
 }
 
 static int skl_populate_modules(struct skl_dev *skl)
@@ -1460,7 +1446,6 @@ static const struct snd_soc_component_driver skl_component  = {
        .trigger        = skl_platform_soc_trigger,
        .pointer        = skl_platform_soc_pointer,
        .get_time_info  = skl_platform_soc_get_time_info,
-       .mmap           = skl_platform_soc_mmap,
        .pcm_construct  = skl_platform_soc_new,
        .module_get_upon_open = 1, /* increment refcount when a pcm is opened */
 };
index c0fdab3..b036852 100644 (file)
@@ -113,7 +113,7 @@ static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w,
 
 static void skl_dump_mconfig(struct skl_dev *skl, struct skl_module_cfg *mcfg)
 {
-       struct skl_module_iface *iface = &mcfg->module->formats[0];
+       struct skl_module_iface *iface = &mcfg->module->formats[mcfg->fmt_idx];
 
        dev_dbg(skl->dev, "Dumping config\n");
        dev_dbg(skl->dev, "Input Format:\n");
@@ -195,8 +195,8 @@ static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg,
        struct skl_module_fmt *in_fmt, *out_fmt;
 
        /* Fixups will be applied to pin 0 only */
-       in_fmt = &m_cfg->module->formats[0].inputs[0].fmt;
-       out_fmt = &m_cfg->module->formats[0].outputs[0].fmt;
+       in_fmt = &m_cfg->module->formats[m_cfg->fmt_idx].inputs[0].fmt;
+       out_fmt = &m_cfg->module->formats[m_cfg->fmt_idx].outputs[0].fmt;
 
        if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                if (is_fe) {
@@ -239,9 +239,9 @@ static void skl_tplg_update_buffer_size(struct skl_dev *skl,
        /* Since fixups is applied to pin 0 only, ibs, obs needs
         * change for pin 0 only
         */
-       res = &mcfg->module->resources[0];
-       in_fmt = &mcfg->module->formats[0].inputs[0].fmt;
-       out_fmt = &mcfg->module->formats[0].outputs[0].fmt;
+       res = &mcfg->module->resources[mcfg->res_idx];
+       in_fmt = &mcfg->module->formats[mcfg->fmt_idx].inputs[0].fmt;
+       out_fmt = &mcfg->module->formats[mcfg->fmt_idx].outputs[0].fmt;
 
        if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT)
                multiplier = 5;
@@ -292,7 +292,7 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
        struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx];
 
        /* check if we already have blob */
-       if (m_cfg->formats_config.caps_size > 0)
+       if (m_cfg->formats_config[SKL_PARAM_INIT].caps_size > 0)
                return 0;
 
        dev_dbg(skl->dev, "Applying default cfg blob\n");
@@ -328,8 +328,8 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
        cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type,
                                        s_fmt, ch, s_freq, dir, dev_type);
        if (cfg) {
-               m_cfg->formats_config.caps_size = cfg->size;
-               m_cfg->formats_config.caps = (u32 *) &cfg->caps;
+               m_cfg->formats_config[SKL_PARAM_INIT].caps_size = cfg->size;
+               m_cfg->formats_config[SKL_PARAM_INIT].caps = (u32 *)&cfg->caps;
        } else {
                dev_err(skl->dev, "Blob NULL for id %x type %d dirn %d\n",
                                        m_cfg->vbus_id, link_type, dir);
@@ -386,9 +386,9 @@ static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w,
        struct skl_algo_data *bc;
        struct skl_specific_cfg *sp_cfg;
 
-       if (mconfig->formats_config.caps_size > 0 &&
-               mconfig->formats_config.set_params == SKL_PARAM_SET) {
-               sp_cfg = &mconfig->formats_config;
+       if (mconfig->formats_config[SKL_PARAM_SET].caps_size > 0 &&
+           mconfig->formats_config[SKL_PARAM_SET].set_params == SKL_PARAM_SET) {
+               sp_cfg = &mconfig->formats_config[SKL_PARAM_SET];
                ret = skl_set_module_params(skl, sp_cfg->caps,
                                        sp_cfg->caps_size,
                                        sp_cfg->param_id, mconfig);
@@ -438,8 +438,10 @@ static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w)
                        if (bc->set_params != SKL_PARAM_INIT)
                                continue;
 
-                       mconfig->formats_config.caps = (u32 *)bc->params;
-                       mconfig->formats_config.caps_size = bc->size;
+                       mconfig->formats_config[SKL_PARAM_INIT].caps =
+                                                       (u32 *)bc->params;
+                       mconfig->formats_config[SKL_PARAM_INIT].caps_size =
+                                                               bc->size;
 
                        break;
                }
@@ -498,8 +500,6 @@ skl_tplg_init_pipe_modules(struct skl_dev *skl, struct skl_pipe *pipe)
                                mconfig->id.module_id, mconfig->guid);
                        if (ret < 0)
                                return ret;
-
-                       mconfig->m_state = SKL_MODULE_LOADED;
                }
 
                /* prepare the DMA if the module is gateway cpr */
@@ -558,8 +558,7 @@ static int skl_tplg_unload_pipe_modules(struct skl_dev *skl,
                mconfig  = w_module->w->priv;
                uuid_mod = (guid_t *)mconfig->guid;
 
-               if (mconfig->module->loadable && skl->dsp->fw_ops.unload_mod &&
-                       mconfig->m_state > SKL_MODULE_UNINIT) {
+               if (mconfig->module->loadable && skl->dsp->fw_ops.unload_mod) {
                        ret = skl->dsp->fw_ops.unload_mod(skl->dsp,
                                                mconfig->id.module_id);
                        if (ret < 0)
@@ -641,8 +640,9 @@ skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig)
                return 0;
        }
 
-       if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) {
-               dev_dbg(skl->dev, "No conn_type detected, take 0th config\n");
+       if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE || pipe->nr_cfgs == 1) {
+               dev_dbg(skl->dev, "No conn_type or just 1 pathcfg, taking 0th for %d\n",
+                       pipe->ppl_id);
                pipe->cur_config_idx = 0;
                pipe->memory_pages = pconfig->mem_pages;
 
@@ -801,9 +801,10 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w,
                        return 0;
        }
 
-       if (mconfig->formats_config.caps_size > 0 &&
-               mconfig->formats_config.set_params == SKL_PARAM_BIND) {
-               sp_cfg = &mconfig->formats_config;
+       if (mconfig->formats_config[SKL_PARAM_BIND].caps_size > 0 &&
+           mconfig->formats_config[SKL_PARAM_BIND].set_params ==
+                                                               SKL_PARAM_BIND) {
+               sp_cfg = &mconfig->formats_config[SKL_PARAM_BIND];
                ret = skl_set_module_params(skl, sp_cfg->caps,
                                        sp_cfg->caps_size,
                                        sp_cfg->param_id, mconfig);
@@ -1463,12 +1464,6 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
        struct skl_dev *skl = get_skl_ctx(w->dapm->dev);
 
        if (ac->params) {
-               /*
-                * Widget data is expected to be stripped of T and L
-                */
-               size -= 2 * sizeof(unsigned int);
-               data += 2;
-
                if (size > ac->max)
                        return -EINVAL;
                ac->size = size;
@@ -1505,7 +1500,8 @@ static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol,
 static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig,
        struct skl_mic_sel_config *mic_cfg, struct device *dev)
 {
-       struct skl_specific_cfg *sp_cfg = &mconfig->formats_config;
+       struct skl_specific_cfg *sp_cfg =
+                               &mconfig->formats_config[SKL_PARAM_INIT];
 
        sp_cfg->caps_size = sizeof(struct skl_mic_sel_config);
        sp_cfg->set_params = SKL_PARAM_SET;
@@ -1637,11 +1633,12 @@ int skl_tplg_update_pipe_params(struct device *dev,
                        struct skl_module_cfg *mconfig,
                        struct skl_pipe_params *params)
 {
-       struct skl_module_res *res = &mconfig->module->resources[0];
+       struct skl_module_res *res;
        struct skl_dev *skl = get_skl_ctx(dev);
        struct skl_module_fmt *format = NULL;
        u8 cfg_idx = mconfig->pipe->cur_config_idx;
 
+       res = &mconfig->module->resources[mconfig->res_idx];
        skl_tplg_fill_dma_id(mconfig, params);
        mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx;
        mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx;
@@ -1650,9 +1647,9 @@ int skl_tplg_update_pipe_params(struct device *dev,
                return 0;
 
        if (params->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               format = &mconfig->module->formats[0].inputs[0].fmt;
+               format = &mconfig->module->formats[mconfig->fmt_idx].inputs[0].fmt;
        else
-               format = &mconfig->module->formats[0].outputs[0].fmt;
+               format = &mconfig->module->formats[mconfig->fmt_idx].outputs[0].fmt;
 
        /* set the hw_params */
        format->s_freq = params->s_freq;
@@ -1827,7 +1824,7 @@ static u8 skl_tplg_be_link_type(int dev_type)
  * Fill the BE gateway parameters
  * The BE gateway expects a blob of parameters which are kept in the ACPI
  * NHLT blob, so query the blob for interface type (i2s/pdm) and instance.
- * The port can have multiple settings so pick based on the PCM
+ * The port can have multiple settings so pick based on the pipeline
  * parameters
  */
 static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
@@ -1835,6 +1832,8 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
                                struct skl_pipe_params *params)
 {
        struct nhlt_specific_cfg *cfg;
+       struct skl_pipe *pipe = mconfig->pipe;
+       struct skl_pipe_fmt *pipe_fmt;
        struct skl_dev *skl = get_skl_ctx(dai->dev);
        int link_type = skl_tplg_be_link_type(mconfig->dev_type);
        u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type);
@@ -1844,20 +1843,23 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
        if (link_type == NHLT_LINK_HDA)
                return 0;
 
+       if (pipe->direction == SNDRV_PCM_STREAM_PLAYBACK)
+               pipe_fmt = &pipe->configs[pipe->pipe_config_idx].out_fmt;
+       else
+               pipe_fmt = &pipe->configs[pipe->pipe_config_idx].in_fmt;
+
        /* update the blob based on virtual bus_id*/
        cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type,
-                                       params->s_fmt, params->ch,
-                                       params->s_freq, params->stream,
+                                       pipe_fmt->bps, pipe_fmt->channels,
+                                       pipe_fmt->freq, pipe->direction,
                                        dev_type);
        if (cfg) {
-               mconfig->formats_config.caps_size = cfg->size;
-               mconfig->formats_config.caps = (u32 *) &cfg->caps;
+               mconfig->formats_config[SKL_PARAM_INIT].caps_size = cfg->size;
+               mconfig->formats_config[SKL_PARAM_INIT].caps = (u32 *)&cfg->caps;
        } else {
-               dev_err(dai->dev, "Blob NULL for id %x type %d dirn %d\n",
-                                       mconfig->vbus_id, link_type,
-                                       params->stream);
-               dev_err(dai->dev, "PCM: ch %d, freq %d, fmt %d\n",
-                                params->ch, params->s_freq, params->s_fmt);
+               dev_err(dai->dev, "Blob NULL for id:%d type:%d dirn:%d ch:%d, freq:%d, fmt:%d\n",
+                       mconfig->vbus_id, link_type, params->stream,
+                       params->ch, params->s_freq, params->s_fmt);
                return -EINVAL;
        }
 
@@ -2570,19 +2572,26 @@ static int skl_tplg_get_token(struct device *dev,
 
                break;
 
+       case SKL_TKN_U32_FMT_CFG_IDX:
+               if (tkn_elem->value > SKL_MAX_PARAMS_TYPES)
+                       return -EINVAL;
+
+               mconfig->fmt_cfg_idx = tkn_elem->value;
+               break;
+
        case SKL_TKN_U32_CAPS_SIZE:
-               mconfig->formats_config.caps_size =
+               mconfig->formats_config[mconfig->fmt_cfg_idx].caps_size =
                        tkn_elem->value;
 
                break;
 
        case SKL_TKN_U32_CAPS_SET_PARAMS:
-               mconfig->formats_config.set_params =
+               mconfig->formats_config[mconfig->fmt_cfg_idx].set_params =
                                tkn_elem->value;
                break;
 
        case SKL_TKN_U32_CAPS_PARAMS_ID:
-               mconfig->formats_config.param_id =
+               mconfig->formats_config[mconfig->fmt_cfg_idx].param_id =
                                tkn_elem->value;
                break;
 
@@ -2796,6 +2805,7 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w,
        struct skl_dfw_v4_module *dfw =
                                (struct skl_dfw_v4_module *)tplg_w->priv.data;
        int ret;
+       int idx = mconfig->fmt_cfg_idx;
 
        dev_dbg(dev, "Parsing Skylake v4 widget topology data\n");
 
@@ -2829,7 +2839,7 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w,
        mconfig->dev_type = dfw->dev_type;
        mconfig->hw_conn_type = dfw->hw_conn_type;
        mconfig->time_slot = dfw->time_slot;
-       mconfig->formats_config.caps_size = dfw->caps.caps_size;
+       mconfig->formats_config[idx].caps_size = dfw->caps.caps_size;
 
        mconfig->m_in_pin = devm_kcalloc(dev,
                                MAX_IN_QUEUE, sizeof(*mconfig->m_in_pin),
@@ -2850,21 +2860,39 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w,
                                    dfw->is_dynamic_out_pin,
                                    mconfig->module->max_output_pins);
 
-       if (mconfig->formats_config.caps_size) {
-               mconfig->formats_config.set_params = dfw->caps.set_params;
-               mconfig->formats_config.param_id = dfw->caps.param_id;
-               mconfig->formats_config.caps =
-               devm_kzalloc(dev, mconfig->formats_config.caps_size,
+       if (mconfig->formats_config[idx].caps_size) {
+               mconfig->formats_config[idx].set_params = dfw->caps.set_params;
+               mconfig->formats_config[idx].param_id = dfw->caps.param_id;
+               mconfig->formats_config[idx].caps =
+               devm_kzalloc(dev, mconfig->formats_config[idx].caps_size,
                             GFP_KERNEL);
-               if (!mconfig->formats_config.caps)
+               if (!mconfig->formats_config[idx].caps)
                        return -ENOMEM;
-               memcpy(mconfig->formats_config.caps, dfw->caps.caps,
+               memcpy(mconfig->formats_config[idx].caps, dfw->caps.caps,
                       dfw->caps.caps_size);
        }
 
        return 0;
 }
 
+static int skl_tplg_get_caps_data(struct device *dev, char *data,
+                                 struct skl_module_cfg *mconfig)
+{
+       int idx = mconfig->fmt_cfg_idx;
+
+       if (mconfig->formats_config[idx].caps_size > 0) {
+               mconfig->formats_config[idx].caps =
+                       devm_kzalloc(dev, mconfig->formats_config[idx].caps_size,
+                                    GFP_KERNEL);
+               if (!mconfig->formats_config[idx].caps)
+                       return -ENOMEM;
+               memcpy(mconfig->formats_config[idx].caps, data,
+                      mconfig->formats_config[idx].caps_size);
+       }
+
+       return mconfig->formats_config[idx].caps_size;
+}
+
 /*
  * Parse the private data for the token and corresponding value.
  * The private data can have multiple data blocks. So, a data block
@@ -2925,18 +2953,14 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w,
                if (block_type == SKL_TYPE_TUPLE) {
                        ret = skl_tplg_get_tokens(dev, data,
                                        skl, mconfig, block_size);
-
-                       if (ret < 0)
-                               return ret;
-
-                       --num_blocks;
                } else {
-                       if (mconfig->formats_config.caps_size > 0)
-                               memcpy(mconfig->formats_config.caps, data,
-                                       mconfig->formats_config.caps_size);
-                       --num_blocks;
-                       ret = mconfig->formats_config.caps_size;
+                       ret = skl_tplg_get_caps_data(dev, data, mconfig);
                }
+
+               if (ret < 0)
+                       return ret;
+
+               --num_blocks;
                off += ret;
        }
 
@@ -3027,6 +3051,9 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, int index,
         */
        mconfig->id.module_id = -1;
 
+       /* To provide backward compatibility, set default as SKL_PARAM_INIT */
+       mconfig->fmt_cfg_idx = SKL_PARAM_INIT;
+
        /* Parse private data for tuples */
        ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig);
        if (ret < 0)
index fb01186..f0695b2 100644 (file)
@@ -81,6 +81,8 @@ enum skl_s_freq {
        SKL_FS_INVALID
 };
 
+#define SKL_MAX_PARAMS_TYPES   4
+
 enum skl_widget_type {
        SKL_WIDGET_VMIXER = 1,
        SKL_WIDGET_MIXER = 2,
@@ -150,6 +152,21 @@ struct skl_up_down_mixer_cfg {
        u32 ch_map;
 } __packed;
 
+struct skl_pin_format {
+       u32 pin_idx;
+       u32 buf_size;
+       struct skl_audio_data_format audio_fmt;
+} __packed;
+
+struct skl_base_cfg_ext {
+       u16 nr_input_pins;
+       u16 nr_output_pins;
+       u8 reserved[8];
+       u32 priv_param_length;
+       /* Input pin formats followed by output ones. */
+       struct skl_pin_format pins_fmt[0];
+} __packed;
+
 struct skl_algo_cfg {
        struct skl_base_cfg  base_cfg;
        char params[];
@@ -311,10 +328,8 @@ struct skl_pipe {
 
 enum skl_module_state {
        SKL_MODULE_UNINIT = 0,
-       SKL_MODULE_LOADED = 1,
-       SKL_MODULE_INIT_DONE = 2,
-       SKL_MODULE_BIND_DONE = 3,
-       SKL_MODULE_UNLOADED = 4,
+       SKL_MODULE_INIT_DONE = 1,
+       SKL_MODULE_BIND_DONE = 2,
 };
 
 enum d0i3_capability {
@@ -373,6 +388,7 @@ struct skl_module_cfg {
        struct skl_module *module;
        int res_idx;
        int fmt_idx;
+       int fmt_cfg_idx;
        u8 domain;
        bool homogenous_inputs;
        bool homogenous_outputs;
@@ -403,7 +419,7 @@ struct skl_module_cfg {
        enum skl_hw_conn_type  hw_conn_type;
        enum skl_module_state m_state;
        struct skl_pipe *pipe;
-       struct skl_specific_cfg formats_config;
+       struct skl_specific_cfg formats_config[SKL_MAX_PARAMS_TYPES];
        struct skl_pipe_mcfg mod_cfg[SKL_MAX_MODULES_IN_PIPE];
 };
 
index 74dae43..cf567a8 100644 (file)
@@ -184,3 +184,27 @@ config SND_SOC_MT8192_MT6359_RT1015_RT5682
          with the MT6359 RT1015 RT5682 audio codec.
          Select Y if you have such device.
          If unsure select "N".
+
+config SND_SOC_MT8195
+       tristate "ASoC support for Mediatek MT8195 chip"
+       select SND_SOC_MEDIATEK
+       help
+         This adds ASoC platform driver support for Mediatek MT8195 chip
+         that can be used with other codecs.
+         Select Y if you have such device.
+         If unsure select "N".
+
+config SND_SOC_MT8195_MT6359_RT1019_RT5682
+       tristate "ASoC Audio driver for MT8195 with MT6359 RT1019 RT5682 codec"
+       depends on I2C
+       depends on SND_SOC_MT8195
+       select SND_SOC_MT6359
+       select SND_SOC_RT1015P
+       select SND_SOC_RT5682_I2C
+       select SND_SOC_DMIC
+       select SND_SOC_HDMI_CODEC
+       help
+         This adds ASoC driver for Mediatek MT8195 boards
+         with the MT6359 RT1019 RT5682 audio codec.
+         Select Y if you have such device.
+         If unsure select "N".
index f6cb6b8..34778ca 100644 (file)
@@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
 obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
 obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
 obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
+obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
index 3cb2adf..baaa588 100644 (file)
@@ -139,7 +139,7 @@ int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream,
                substream->runtime->dma_area,
                substream->runtime->dma_bytes);
 
-       memset_io(substream->runtime->dma_area, 0,
+       memset_io((void __force __iomem *)substream->runtime->dma_area, 0,
                  substream->runtime->dma_bytes);
 
        /* set addr */
@@ -433,11 +433,20 @@ int mtk_memif_set_addr(struct mtk_base_afe *afe, int id,
                                 phys_buf_addr_upper_32);
        }
 
-       /* set MSB to 33-bit */
-       if (memif->data->msb_reg >= 0)
+       /*
+        * set MSB to 33-bit, for memif address
+        * only for memif base address, if msb_end_reg exists
+        */
+       if (memif->data->msb_reg)
                mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg,
                                       1, msb_at_bit33, memif->data->msb_shift);
 
+       /* set MSB to 33-bit, for memif end address */
+       if (memif->data->msb_end_reg)
+               mtk_regmap_update_bits(afe->regmap, memif->data->msb_end_reg,
+                                      1, msb_at_bit33,
+                                      memif->data->msb_end_shift);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(mtk_memif_set_addr);
@@ -464,6 +473,13 @@ int mtk_memif_set_channel(struct mtk_base_afe *afe,
        else
                mono = (channel == 1) ? 1 : 0;
 
+       /* for specific configuration of memif mono mode */
+       if (memif->data->int_odd_flag_reg)
+               mtk_regmap_update_bits(afe->regmap,
+                                      memif->data->int_odd_flag_reg,
+                                      1, mono,
+                                      memif->data->int_odd_flag_shift);
+
        return mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg,
                                      1, mono, memif->data->mono_shift);
 }
index a6f68c6..ef83e78 100644 (file)
@@ -29,6 +29,8 @@ struct mtk_base_memif_data {
        int quad_ch_reg;
        int quad_ch_mask;
        int quad_ch_shift;
+       int int_odd_flag_reg;
+       int int_odd_flag_shift;
        int enable_reg;
        int enable_shift;
        int hd_reg;
@@ -37,10 +39,13 @@ struct mtk_base_memif_data {
        int hd_align_mshift;
        int msb_reg;
        int msb_shift;
-       int msb2_reg;
-       int msb2_shift;
+       int msb_end_reg;
+       int msb_end_shift;
        int agent_disable_reg;
        int agent_disable_shift;
+       int ch_num_reg;
+       int ch_num_shift;
+       int ch_num_maskbit;
        /* playback memif only */
        int pbuf_reg;
        int pbuf_mask;
@@ -62,6 +67,7 @@ struct mtk_base_irq_data {
        int irq_en_shift;
        int irq_clr_reg;
        int irq_clr_shift;
+       int irq_status_shift;
 };
 
 struct device;
index c4a598c..14e77df 100644 (file)
@@ -1119,25 +1119,26 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
        afe->regmap = syscon_node_to_regmap(dev->parent->of_node);
        if (IS_ERR(afe->regmap)) {
                dev_err(dev, "could not get regmap from parent\n");
-               return PTR_ERR(afe->regmap);
+               ret = PTR_ERR(afe->regmap);
+               goto err_pm_disable;
        }
        ret = regmap_attach_dev(dev, afe->regmap, &mt8183_afe_regmap_config);
        if (ret) {
                dev_warn(dev, "regmap_attach_dev fail, ret %d\n", ret);
-               return ret;
+               goto err_pm_disable;
        }
 
        rstc = devm_reset_control_get(dev, "audiosys");
        if (IS_ERR(rstc)) {
                ret = PTR_ERR(rstc);
                dev_err(dev, "could not get audiosys reset:%d\n", ret);
-               return ret;
+               goto err_pm_disable;
        }
 
        ret = reset_control_reset(rstc);
        if (ret) {
                dev_err(dev, "failed to trigger audio reset:%d\n", ret);
-               return ret;
+               goto err_pm_disable;
        }
 
        /* enable clock for regcache get default value from hw */
@@ -1147,7 +1148,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
        ret = regmap_reinit_cache(afe->regmap, &mt8183_afe_regmap_config);
        if (ret) {
                dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret);
-               return ret;
+               goto err_pm_disable;
        }
 
        pm_runtime_put_sync(&pdev->dev);
@@ -1160,8 +1161,10 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
        afe->memif_size = MT8183_MEMIF_NUM;
        afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
                                  GFP_KERNEL);
-       if (!afe->memif)
-               return -ENOMEM;
+       if (!afe->memif) {
+               ret = -ENOMEM;
+               goto err_pm_disable;
+       }
 
        for (i = 0; i < afe->memif_size; i++) {
                afe->memif[i].data = &memif_data[i];
@@ -1178,22 +1181,26 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
        afe->irqs_size = MT8183_IRQ_NUM;
        afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
                                 GFP_KERNEL);
-       if (!afe->irqs)
-               return -ENOMEM;
+       if (!afe->irqs) {
+               ret = -ENOMEM;
+               goto err_pm_disable;
+       }
 
        for (i = 0; i < afe->irqs_size; i++)
                afe->irqs[i].irq_data = &irq_data[i];
 
        /* request irq */
        irq_id = platform_get_irq(pdev, 0);
-       if (irq_id < 0)
-               return irq_id;
+       if (irq_id < 0) {
+               ret = irq_id;
+               goto err_pm_disable;
+       }
 
        ret = devm_request_irq(dev, irq_id, mt8183_afe_irq_handler,
                               IRQF_TRIGGER_NONE, "asys-isr", (void *)afe);
        if (ret) {
                dev_err(dev, "could not request_irq for asys-isr\n");
-               return ret;
+               goto err_pm_disable;
        }
 
        /* init sub_dais */
@@ -1204,7 +1211,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
                if (ret) {
                        dev_warn(afe->dev, "dai register i %d fail, ret %d\n",
                                 i, ret);
-                       return ret;
+                       goto err_pm_disable;
                }
        }
 
@@ -1213,7 +1220,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
        if (ret) {
                dev_warn(afe->dev, "mtk_afe_combine_sub_dai fail, ret %d\n",
                         ret);
-               return ret;
+               goto err_pm_disable;
        }
 
        afe->mtk_afe_hardware = &mt8183_afe_hardware;
@@ -1229,7 +1236,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
                                              NULL, 0);
        if (ret) {
                dev_warn(dev, "err_platform\n");
-               return ret;
+               goto err_pm_disable;
        }
 
        ret = devm_snd_soc_register_component(afe->dev,
@@ -1238,10 +1245,14 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
                                              afe->num_dai_drivers);
        if (ret) {
                dev_warn(dev, "err_dai_component\n");
-               return ret;
+               goto err_pm_disable;
        }
 
        return ret;
+
+err_pm_disable:
+       pm_runtime_disable(&pdev->dev);
+       return ret;
 }
 
 static int mt8183_afe_pcm_dev_remove(struct platform_device *pdev)
index 7a1724f..31c2803 100644 (file)
@@ -2229,12 +2229,13 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev)
        afe->regmap = syscon_node_to_regmap(dev->parent->of_node);
        if (IS_ERR(afe->regmap)) {
                dev_err(dev, "could not get regmap from parent\n");
-               return PTR_ERR(afe->regmap);
+               ret = PTR_ERR(afe->regmap);
+               goto err_pm_disable;
        }
        ret = regmap_attach_dev(dev, afe->regmap, &mt8192_afe_regmap_config);
        if (ret) {
                dev_warn(dev, "regmap_attach_dev fail, ret %d\n", ret);
-               return ret;
+               goto err_pm_disable;
        }
 
        /* enable clock for regcache get default value from hw */
@@ -2244,7 +2245,7 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev)
        ret = regmap_reinit_cache(afe->regmap, &mt8192_afe_regmap_config);
        if (ret) {
                dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret);
-               return ret;
+               goto err_pm_disable;
        }
 
        pm_runtime_put_sync(&pdev->dev);
@@ -2257,8 +2258,10 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev)
        afe->memif_size = MT8192_MEMIF_NUM;
        afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
                                  GFP_KERNEL);
-       if (!afe->memif)
-               return -ENOMEM;
+       if (!afe->memif) {
+               ret = -ENOMEM;
+               goto err_pm_disable;
+       }
 
        for (i = 0; i < afe->memif_size; i++) {
                afe->memif[i].data = &memif_data[i];
@@ -2272,22 +2275,26 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev)
        afe->irqs_size = MT8192_IRQ_NUM;
        afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
                                 GFP_KERNEL);
-       if (!afe->irqs)
-               return -ENOMEM;
+       if (!afe->irqs) {
+               ret = -ENOMEM;
+               goto err_pm_disable;
+       }
 
        for (i = 0; i < afe->irqs_size; i++)
                afe->irqs[i].irq_data = &irq_data[i];
 
        /* request irq */
        irq_id = platform_get_irq(pdev, 0);
-       if (irq_id < 0)
-               return irq_id;
+       if (irq_id < 0) {
+               ret = irq_id;
+               goto err_pm_disable;
+       }
 
        ret = devm_request_irq(dev, irq_id, mt8192_afe_irq_handler,
                               IRQF_TRIGGER_NONE, "asys-isr", (void *)afe);
        if (ret) {
                dev_err(dev, "could not request_irq for Afe_ISR_Handle\n");
-               return ret;
+               goto err_pm_disable;
        }
 
        /* init sub_dais */
diff --git a/sound/soc/mediatek/mt8195/Makefile b/sound/soc/mediatek/mt8195/Makefile
new file mode 100644 (file)
index 0000000..44775f4
--- /dev/null
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# platform driver
+snd-soc-mt8195-afe-objs := \
+       mt8195-audsys-clk.o \
+       mt8195-afe-clk.o \
+       mt8195-afe-pcm.o \
+       mt8195-dai-adda.o \
+       mt8195-dai-etdm.o \
+       mt8195-dai-pcm.o
+
+obj-$(CONFIG_SND_SOC_MT8195) += snd-soc-mt8195-afe.o
+
+# machine driver
+obj-$(CONFIG_SND_SOC_MT8195_MT6359_RT1019_RT5682) += mt8195-mt6359-rt1019-rt5682.o
diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
new file mode 100644 (file)
index 0000000..8420b2c
--- /dev/null
@@ -0,0 +1,441 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mt8195-afe-clk.c  --  Mediatek 8195 afe clock ctrl
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ *         Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/clk.h>
+
+#include "mt8195-afe-common.h"
+#include "mt8195-afe-clk.h"
+#include "mt8195-reg.h"
+#include "mt8195-audsys-clk.h"
+
+static const char *aud_clks[MT8195_CLK_NUM] = {
+       /* xtal */
+       [MT8195_CLK_XTAL_26M] = "clk26m",
+       /* divider */
+       [MT8195_CLK_TOP_APLL1] = "apll1_ck",
+       [MT8195_CLK_TOP_APLL2] = "apll2_ck",
+       [MT8195_CLK_TOP_APLL12_DIV0] = "apll12_div0",
+       [MT8195_CLK_TOP_APLL12_DIV1] = "apll12_div1",
+       [MT8195_CLK_TOP_APLL12_DIV2] = "apll12_div2",
+       [MT8195_CLK_TOP_APLL12_DIV3] = "apll12_div3",
+       [MT8195_CLK_TOP_APLL12_DIV9] = "apll12_div9",
+       /* mux */
+       [MT8195_CLK_TOP_A1SYS_HP_SEL] = "a1sys_hp_sel",
+       [MT8195_CLK_TOP_AUD_INTBUS_SEL] = "aud_intbus_sel",
+       [MT8195_CLK_TOP_AUDIO_H_SEL] = "audio_h_sel",
+       [MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL] = "audio_local_bus_sel",
+       [MT8195_CLK_TOP_DPTX_M_SEL] = "dptx_m_sel",
+       [MT8195_CLK_TOP_I2SO1_M_SEL] = "i2so1_m_sel",
+       [MT8195_CLK_TOP_I2SO2_M_SEL] = "i2so2_m_sel",
+       [MT8195_CLK_TOP_I2SI1_M_SEL] = "i2si1_m_sel",
+       [MT8195_CLK_TOP_I2SI2_M_SEL] = "i2si2_m_sel",
+       /* clock gate */
+       [MT8195_CLK_INFRA_AO_AUDIO_26M_B] = "infra_ao_audio_26m_b",
+       [MT8195_CLK_SCP_ADSP_AUDIODSP] = "scp_adsp_audiodsp",
+       /* afe clock gate */
+       [MT8195_CLK_AUD_AFE] = "aud_afe",
+       [MT8195_CLK_AUD_APLL] = "aud_apll",
+       [MT8195_CLK_AUD_APLL2] = "aud_apll2",
+       [MT8195_CLK_AUD_DAC] = "aud_dac",
+       [MT8195_CLK_AUD_ADC] = "aud_adc",
+       [MT8195_CLK_AUD_DAC_HIRES] = "aud_dac_hires",
+       [MT8195_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp",
+       [MT8195_CLK_AUD_ADC_HIRES] = "aud_adc_hires",
+       [MT8195_CLK_AUD_ADDA6_ADC] = "aud_adda6_adc",
+       [MT8195_CLK_AUD_ADDA6_ADC_HIRES] = "aud_adda6_adc_hires",
+       [MT8195_CLK_AUD_I2SIN] = "aud_i2sin",
+       [MT8195_CLK_AUD_TDM_IN] = "aud_tdm_in",
+       [MT8195_CLK_AUD_I2S_OUT] = "aud_i2s_out",
+       [MT8195_CLK_AUD_TDM_OUT] = "aud_tdm_out",
+       [MT8195_CLK_AUD_HDMI_OUT] = "aud_hdmi_out",
+       [MT8195_CLK_AUD_ASRC11] = "aud_asrc11",
+       [MT8195_CLK_AUD_ASRC12] = "aud_asrc12",
+       [MT8195_CLK_AUD_A1SYS] = "aud_a1sys",
+       [MT8195_CLK_AUD_A2SYS] = "aud_a2sys",
+       [MT8195_CLK_AUD_PCMIF] = "aud_pcmif",
+       [MT8195_CLK_AUD_MEMIF_UL1] = "aud_memif_ul1",
+       [MT8195_CLK_AUD_MEMIF_UL2] = "aud_memif_ul2",
+       [MT8195_CLK_AUD_MEMIF_UL3] = "aud_memif_ul3",
+       [MT8195_CLK_AUD_MEMIF_UL4] = "aud_memif_ul4",
+       [MT8195_CLK_AUD_MEMIF_UL5] = "aud_memif_ul5",
+       [MT8195_CLK_AUD_MEMIF_UL6] = "aud_memif_ul6",
+       [MT8195_CLK_AUD_MEMIF_UL8] = "aud_memif_ul8",
+       [MT8195_CLK_AUD_MEMIF_UL9] = "aud_memif_ul9",
+       [MT8195_CLK_AUD_MEMIF_UL10] = "aud_memif_ul10",
+       [MT8195_CLK_AUD_MEMIF_DL2] = "aud_memif_dl2",
+       [MT8195_CLK_AUD_MEMIF_DL3] = "aud_memif_dl3",
+       [MT8195_CLK_AUD_MEMIF_DL6] = "aud_memif_dl6",
+       [MT8195_CLK_AUD_MEMIF_DL7] = "aud_memif_dl7",
+       [MT8195_CLK_AUD_MEMIF_DL8] = "aud_memif_dl8",
+       [MT8195_CLK_AUD_MEMIF_DL10] = "aud_memif_dl10",
+       [MT8195_CLK_AUD_MEMIF_DL11] = "aud_memif_dl11",
+};
+
+int mt8195_afe_get_mclk_source_clk_id(int sel)
+{
+       switch (sel) {
+       case MT8195_MCK_SEL_26M:
+               return MT8195_CLK_XTAL_26M;
+       case MT8195_MCK_SEL_APLL1:
+               return MT8195_CLK_TOP_APLL1;
+       case MT8195_MCK_SEL_APLL2:
+               return MT8195_CLK_TOP_APLL2;
+       default:
+               return -EINVAL;
+       }
+}
+
+int mt8195_afe_get_mclk_source_rate(struct mtk_base_afe *afe, int apll)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       int clk_id = mt8195_afe_get_mclk_source_clk_id(apll);
+
+       if (clk_id < 0) {
+               dev_dbg(afe->dev, "invalid clk id\n");
+               return 0;
+       }
+
+       return clk_get_rate(afe_priv->clk[clk_id]);
+}
+
+int mt8195_afe_get_default_mclk_source_by_rate(int rate)
+{
+       return ((rate % 8000) == 0) ?
+               MT8195_MCK_SEL_APLL1 : MT8195_MCK_SEL_APLL2;
+}
+
+int mt8195_afe_init_clock(struct mtk_base_afe *afe)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       int i;
+
+       mt8195_audsys_clk_register(afe);
+
+       afe_priv->clk =
+               devm_kcalloc(afe->dev, MT8195_CLK_NUM, sizeof(*afe_priv->clk),
+                            GFP_KERNEL);
+       if (!afe_priv->clk)
+               return -ENOMEM;
+
+       for (i = 0; i < MT8195_CLK_NUM; i++) {
+               afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
+               if (IS_ERR(afe_priv->clk[i])) {
+                       dev_dbg(afe->dev, "%s(), devm_clk_get %s fail, ret %ld\n",
+                               __func__, aud_clks[i],
+                               PTR_ERR(afe_priv->clk[i]));
+                       return PTR_ERR(afe_priv->clk[i]);
+               }
+       }
+
+       return 0;
+}
+
+void mt8195_afe_deinit_clock(struct mtk_base_afe *afe)
+{
+       mt8195_audsys_clk_unregister(afe);
+}
+
+int mt8195_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+       int ret;
+
+       if (clk) {
+               ret = clk_prepare_enable(clk);
+               if (ret) {
+                       dev_dbg(afe->dev, "%s(), failed to enable clk\n",
+                               __func__);
+                       return ret;
+               }
+       } else {
+               dev_dbg(afe->dev, "NULL clk\n");
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mt8195_afe_enable_clk);
+
+void mt8195_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+       if (clk)
+               clk_disable_unprepare(clk);
+       else
+               dev_dbg(afe->dev, "NULL clk\n");
+}
+EXPORT_SYMBOL_GPL(mt8195_afe_disable_clk);
+
+int mt8195_afe_prepare_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+       int ret;
+
+       if (clk) {
+               ret = clk_prepare(clk);
+               if (ret) {
+                       dev_dbg(afe->dev, "%s(), failed to prepare clk\n",
+                               __func__);
+                       return ret;
+               }
+       } else {
+               dev_dbg(afe->dev, "NULL clk\n");
+       }
+       return 0;
+}
+
+void mt8195_afe_unprepare_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+       if (clk)
+               clk_unprepare(clk);
+       else
+               dev_dbg(afe->dev, "NULL clk\n");
+}
+
+int mt8195_afe_enable_clk_atomic(struct mtk_base_afe *afe, struct clk *clk)
+{
+       int ret;
+
+       if (clk) {
+               ret = clk_enable(clk);
+               if (ret) {
+                       dev_dbg(afe->dev, "%s(), failed to clk enable\n",
+                               __func__);
+                       return ret;
+               }
+       } else {
+               dev_dbg(afe->dev, "NULL clk\n");
+       }
+       return 0;
+}
+
+void mt8195_afe_disable_clk_atomic(struct mtk_base_afe *afe, struct clk *clk)
+{
+       if (clk)
+               clk_disable(clk);
+       else
+               dev_dbg(afe->dev, "NULL clk\n");
+}
+
+int mt8195_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk,
+                           unsigned int rate)
+{
+       int ret;
+
+       if (clk) {
+               ret = clk_set_rate(clk, rate);
+               if (ret) {
+                       dev_dbg(afe->dev, "%s(), failed to set clk rate\n",
+                               __func__);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+int mt8195_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk,
+                             struct clk *parent)
+{
+       int ret;
+
+       if (clk && parent) {
+               ret = clk_set_parent(clk, parent);
+               if (ret) {
+                       dev_dbg(afe->dev, "%s(), failed to set clk parent\n",
+                               __func__);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static unsigned int get_top_cg_reg(unsigned int cg_type)
+{
+       switch (cg_type) {
+       case MT8195_TOP_CG_A1SYS_TIMING:
+       case MT8195_TOP_CG_A2SYS_TIMING:
+       case MT8195_TOP_CG_26M_TIMING:
+               return ASYS_TOP_CON;
+       default:
+               return 0;
+       }
+}
+
+static unsigned int get_top_cg_mask(unsigned int cg_type)
+{
+       switch (cg_type) {
+       case MT8195_TOP_CG_A1SYS_TIMING:
+               return ASYS_TOP_CON_A1SYS_TIMING_ON;
+       case MT8195_TOP_CG_A2SYS_TIMING:
+               return ASYS_TOP_CON_A2SYS_TIMING_ON;
+       case MT8195_TOP_CG_26M_TIMING:
+               return ASYS_TOP_CON_26M_TIMING_ON;
+       default:
+               return 0;
+       }
+}
+
+static unsigned int get_top_cg_on_val(unsigned int cg_type)
+{
+       switch (cg_type) {
+       case MT8195_TOP_CG_A1SYS_TIMING:
+       case MT8195_TOP_CG_A2SYS_TIMING:
+       case MT8195_TOP_CG_26M_TIMING:
+               return get_top_cg_mask(cg_type);
+       default:
+               return 0;
+       }
+}
+
+static unsigned int get_top_cg_off_val(unsigned int cg_type)
+{
+       switch (cg_type) {
+       case MT8195_TOP_CG_A1SYS_TIMING:
+       case MT8195_TOP_CG_A2SYS_TIMING:
+       case MT8195_TOP_CG_26M_TIMING:
+               return 0;
+       default:
+               return get_top_cg_mask(cg_type);
+       }
+}
+
+static int mt8195_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
+{
+       unsigned int reg = get_top_cg_reg(cg_type);
+       unsigned int mask = get_top_cg_mask(cg_type);
+       unsigned int val = get_top_cg_on_val(cg_type);
+
+       regmap_update_bits(afe->regmap, reg, mask, val);
+       return 0;
+}
+
+static int mt8195_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
+{
+       unsigned int reg = get_top_cg_reg(cg_type);
+       unsigned int mask = get_top_cg_mask(cg_type);
+       unsigned int val = get_top_cg_off_val(cg_type);
+
+       regmap_update_bits(afe->regmap, reg, mask, val);
+       return 0;
+}
+
+int mt8195_afe_enable_reg_rw_clk(struct mtk_base_afe *afe)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       int i;
+       unsigned int clk_array[] = {
+               MT8195_CLK_SCP_ADSP_AUDIODSP, /* bus clock for infra */
+               MT8195_CLK_TOP_AUDIO_H_SEL, /* clock for ADSP bus */
+               MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL, /* bus clock for DRAM access */
+               MT8195_CLK_TOP_AUD_INTBUS_SEL, /* bus clock for AFE SRAM access */
+               MT8195_CLK_INFRA_AO_AUDIO_26M_B, /* audio 26M clock */
+               MT8195_CLK_AUD_AFE, /* AFE HW master switch */
+               MT8195_CLK_AUD_A1SYS_HP, /* AFE HW clock*/
+               MT8195_CLK_AUD_A1SYS, /* AFE HW clock */
+       };
+
+       for (i = 0; i < ARRAY_SIZE(clk_array); i++)
+               mt8195_afe_enable_clk(afe, afe_priv->clk[clk_array[i]]);
+
+       return 0;
+}
+
+int mt8195_afe_disable_reg_rw_clk(struct mtk_base_afe *afe)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       int i;
+       unsigned int clk_array[] = {
+               MT8195_CLK_AUD_A1SYS,
+               MT8195_CLK_AUD_A1SYS_HP,
+               MT8195_CLK_AUD_AFE,
+               MT8195_CLK_INFRA_AO_AUDIO_26M_B,
+               MT8195_CLK_TOP_AUD_INTBUS_SEL,
+               MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL,
+               MT8195_CLK_TOP_AUDIO_H_SEL,
+               MT8195_CLK_SCP_ADSP_AUDIODSP,
+       };
+
+       for (i = 0; i < ARRAY_SIZE(clk_array); i++)
+               mt8195_afe_disable_clk(afe, afe_priv->clk[clk_array[i]]);
+
+       return 0;
+}
+
+static int mt8195_afe_enable_afe_on(struct mtk_base_afe *afe)
+{
+       regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1);
+       return 0;
+}
+
+static int mt8195_afe_disable_afe_on(struct mtk_base_afe *afe)
+{
+       regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x0);
+       return 0;
+}
+
+static int mt8195_afe_enable_timing_sys(struct mtk_base_afe *afe)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       int i;
+       unsigned int clk_array[] = {
+               MT8195_CLK_AUD_A1SYS,
+               MT8195_CLK_AUD_A2SYS,
+       };
+       unsigned int cg_array[] = {
+               MT8195_TOP_CG_A1SYS_TIMING,
+               MT8195_TOP_CG_A2SYS_TIMING,
+               MT8195_TOP_CG_26M_TIMING,
+       };
+
+       for (i = 0; i < ARRAY_SIZE(clk_array); i++)
+               mt8195_afe_enable_clk(afe, afe_priv->clk[clk_array[i]]);
+
+       for (i = 0; i < ARRAY_SIZE(cg_array); i++)
+               mt8195_afe_enable_top_cg(afe, cg_array[i]);
+
+       return 0;
+}
+
+static int mt8195_afe_disable_timing_sys(struct mtk_base_afe *afe)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       int i;
+       unsigned int clk_array[] = {
+               MT8195_CLK_AUD_A2SYS,
+               MT8195_CLK_AUD_A1SYS,
+       };
+       unsigned int cg_array[] = {
+               MT8195_TOP_CG_26M_TIMING,
+               MT8195_TOP_CG_A2SYS_TIMING,
+               MT8195_TOP_CG_A1SYS_TIMING,
+       };
+
+       for (i = 0; i < ARRAY_SIZE(cg_array); i++)
+               mt8195_afe_disable_top_cg(afe, cg_array[i]);
+
+       for (i = 0; i < ARRAY_SIZE(clk_array); i++)
+               mt8195_afe_disable_clk(afe, afe_priv->clk[clk_array[i]]);
+
+       return 0;
+}
+
+int mt8195_afe_enable_main_clock(struct mtk_base_afe *afe)
+{
+       mt8195_afe_enable_timing_sys(afe);
+
+       mt8195_afe_enable_afe_on(afe);
+
+       return 0;
+}
+
+int mt8195_afe_disable_main_clock(struct mtk_base_afe *afe)
+{
+       mt8195_afe_disable_afe_on(afe);
+
+       mt8195_afe_disable_timing_sys(afe);
+
+       return 0;
+}
diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.h b/sound/soc/mediatek/mt8195/mt8195-afe-clk.h
new file mode 100644 (file)
index 0000000..f8e6eeb
--- /dev/null
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8195-afe-clk.h  --  Mediatek 8195 afe clock ctrl definition
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ *         Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#ifndef _MT8195_AFE_CLK_H_
+#define _MT8195_AFE_CLK_H_
+
+enum {
+       /* xtal */
+       MT8195_CLK_XTAL_26M,
+       /* divider */
+       MT8195_CLK_TOP_APLL1,
+       MT8195_CLK_TOP_APLL2,
+       MT8195_CLK_TOP_APLL12_DIV0,
+       MT8195_CLK_TOP_APLL12_DIV1,
+       MT8195_CLK_TOP_APLL12_DIV2,
+       MT8195_CLK_TOP_APLL12_DIV3,
+       MT8195_CLK_TOP_APLL12_DIV9,
+       /* mux */
+       MT8195_CLK_TOP_A1SYS_HP_SEL,
+       MT8195_CLK_TOP_AUD_INTBUS_SEL,
+       MT8195_CLK_TOP_AUDIO_H_SEL,
+       MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL,
+       MT8195_CLK_TOP_DPTX_M_SEL,
+       MT8195_CLK_TOP_I2SO1_M_SEL,
+       MT8195_CLK_TOP_I2SO2_M_SEL,
+       MT8195_CLK_TOP_I2SI1_M_SEL,
+       MT8195_CLK_TOP_I2SI2_M_SEL,
+       /* clock gate */
+       MT8195_CLK_INFRA_AO_AUDIO_26M_B,
+       MT8195_CLK_SCP_ADSP_AUDIODSP,
+       MT8195_CLK_AUD_AFE,
+       MT8195_CLK_AUD_APLL,
+       MT8195_CLK_AUD_APLL2,
+       MT8195_CLK_AUD_DAC,
+       MT8195_CLK_AUD_ADC,
+       MT8195_CLK_AUD_DAC_HIRES,
+       MT8195_CLK_AUD_A1SYS_HP,
+       MT8195_CLK_AUD_ADC_HIRES,
+       MT8195_CLK_AUD_ADDA6_ADC,
+       MT8195_CLK_AUD_ADDA6_ADC_HIRES,
+       MT8195_CLK_AUD_I2SIN,
+       MT8195_CLK_AUD_TDM_IN,
+       MT8195_CLK_AUD_I2S_OUT,
+       MT8195_CLK_AUD_TDM_OUT,
+       MT8195_CLK_AUD_HDMI_OUT,
+       MT8195_CLK_AUD_ASRC11,
+       MT8195_CLK_AUD_ASRC12,
+       MT8195_CLK_AUD_A1SYS,
+       MT8195_CLK_AUD_A2SYS,
+       MT8195_CLK_AUD_PCMIF,
+       MT8195_CLK_AUD_MEMIF_UL1,
+       MT8195_CLK_AUD_MEMIF_UL2,
+       MT8195_CLK_AUD_MEMIF_UL3,
+       MT8195_CLK_AUD_MEMIF_UL4,
+       MT8195_CLK_AUD_MEMIF_UL5,
+       MT8195_CLK_AUD_MEMIF_UL6,
+       MT8195_CLK_AUD_MEMIF_UL8,
+       MT8195_CLK_AUD_MEMIF_UL9,
+       MT8195_CLK_AUD_MEMIF_UL10,
+       MT8195_CLK_AUD_MEMIF_DL2,
+       MT8195_CLK_AUD_MEMIF_DL3,
+       MT8195_CLK_AUD_MEMIF_DL6,
+       MT8195_CLK_AUD_MEMIF_DL7,
+       MT8195_CLK_AUD_MEMIF_DL8,
+       MT8195_CLK_AUD_MEMIF_DL10,
+       MT8195_CLK_AUD_MEMIF_DL11,
+       MT8195_CLK_NUM,
+};
+
+enum {
+       MT8195_MCK_SEL_26M,
+       MT8195_MCK_SEL_APLL1,
+       MT8195_MCK_SEL_APLL2,
+       MT8195_MCK_SEL_APLL3,
+       MT8195_MCK_SEL_APLL4,
+       MT8195_MCK_SEL_APLL5,
+       MT8195_MCK_SEL_HDMIRX_APLL,
+       MT8195_MCK_SEL_NUM,
+};
+
+struct mtk_base_afe;
+
+int mt8195_afe_get_mclk_source_clk_id(int sel);
+int mt8195_afe_get_mclk_source_rate(struct mtk_base_afe *afe, int apll);
+int mt8195_afe_get_default_mclk_source_by_rate(int rate);
+int mt8195_afe_init_clock(struct mtk_base_afe *afe);
+void mt8195_afe_deinit_clock(struct mtk_base_afe *afe);
+int mt8195_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk);
+void mt8195_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk);
+int mt8195_afe_prepare_clk(struct mtk_base_afe *afe, struct clk *clk);
+void mt8195_afe_unprepare_clk(struct mtk_base_afe *afe, struct clk *clk);
+int mt8195_afe_enable_clk_atomic(struct mtk_base_afe *afe, struct clk *clk);
+void mt8195_afe_disable_clk_atomic(struct mtk_base_afe *afe, struct clk *clk);
+int mt8195_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk,
+                           unsigned int rate);
+int mt8195_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk,
+                             struct clk *parent);
+int mt8195_afe_enable_main_clock(struct mtk_base_afe *afe);
+int mt8195_afe_disable_main_clock(struct mtk_base_afe *afe);
+int mt8195_afe_enable_reg_rw_clk(struct mtk_base_afe *afe);
+int mt8195_afe_disable_reg_rw_clk(struct mtk_base_afe *afe);
+
+#endif
diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-common.h b/sound/soc/mediatek/mt8195/mt8195-afe-common.h
new file mode 100644 (file)
index 0000000..f93f439
--- /dev/null
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8195-afe-common.h  --  Mediatek 8195 audio driver definitions
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ *         Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#ifndef _MT_8195_AFE_COMMON_H_
+#define _MT_8195_AFE_COMMON_H_
+
+#include <sound/soc.h>
+#include <linux/list.h>
+#include <linux/regmap.h>
+#include "../common/mtk-base-afe.h"
+
+enum {
+       MT8195_DAI_START,
+       MT8195_AFE_MEMIF_START = MT8195_DAI_START,
+       MT8195_AFE_MEMIF_DL2 = MT8195_AFE_MEMIF_START,
+       MT8195_AFE_MEMIF_DL3,
+       MT8195_AFE_MEMIF_DL6,
+       MT8195_AFE_MEMIF_DL7,
+       MT8195_AFE_MEMIF_DL8,
+       MT8195_AFE_MEMIF_DL10,
+       MT8195_AFE_MEMIF_DL11,
+       MT8195_AFE_MEMIF_UL_START,
+       MT8195_AFE_MEMIF_UL1 = MT8195_AFE_MEMIF_UL_START,
+       MT8195_AFE_MEMIF_UL2,
+       MT8195_AFE_MEMIF_UL3,
+       MT8195_AFE_MEMIF_UL4,
+       MT8195_AFE_MEMIF_UL5,
+       MT8195_AFE_MEMIF_UL6,
+       MT8195_AFE_MEMIF_UL8,
+       MT8195_AFE_MEMIF_UL9,
+       MT8195_AFE_MEMIF_UL10,
+       MT8195_AFE_MEMIF_END,
+       MT8195_AFE_MEMIF_NUM = (MT8195_AFE_MEMIF_END - MT8195_AFE_MEMIF_START),
+       MT8195_AFE_IO_START = MT8195_AFE_MEMIF_END,
+       MT8195_AFE_IO_DL_SRC = MT8195_AFE_IO_START,
+       MT8195_AFE_IO_DPTX,
+       MT8195_AFE_IO_ETDM_START,
+       MT8195_AFE_IO_ETDM1_IN = MT8195_AFE_IO_ETDM_START,
+       MT8195_AFE_IO_ETDM2_IN,
+       MT8195_AFE_IO_ETDM1_OUT,
+       MT8195_AFE_IO_ETDM2_OUT,
+       MT8195_AFE_IO_ETDM3_OUT,
+       MT8195_AFE_IO_ETDM_END,
+       MT8195_AFE_IO_ETDM_NUM =
+               (MT8195_AFE_IO_ETDM_END - MT8195_AFE_IO_ETDM_START),
+       MT8195_AFE_IO_PCM = MT8195_AFE_IO_ETDM_END,
+       MT8195_AFE_IO_UL_SRC1,
+       MT8195_AFE_IO_UL_SRC2,
+       MT8195_AFE_IO_END,
+       MT8195_AFE_IO_NUM = (MT8195_AFE_IO_END - MT8195_AFE_IO_START),
+       MT8195_DAI_END = MT8195_AFE_IO_END,
+       MT8195_DAI_NUM = (MT8195_DAI_END - MT8195_DAI_START),
+};
+
+enum {
+       MT8195_TOP_CG_A1SYS_TIMING,
+       MT8195_TOP_CG_A2SYS_TIMING,
+       MT8195_TOP_CG_26M_TIMING,
+       MT8195_TOP_CG_NUM,
+};
+
+enum {
+       MT8195_AFE_IRQ_1,
+       MT8195_AFE_IRQ_2,
+       MT8195_AFE_IRQ_3,
+       MT8195_AFE_IRQ_8,
+       MT8195_AFE_IRQ_9,
+       MT8195_AFE_IRQ_10,
+       MT8195_AFE_IRQ_13,
+       MT8195_AFE_IRQ_14,
+       MT8195_AFE_IRQ_15,
+       MT8195_AFE_IRQ_16,
+       MT8195_AFE_IRQ_17,
+       MT8195_AFE_IRQ_18,
+       MT8195_AFE_IRQ_19,
+       MT8195_AFE_IRQ_20,
+       MT8195_AFE_IRQ_21,
+       MT8195_AFE_IRQ_22,
+       MT8195_AFE_IRQ_23,
+       MT8195_AFE_IRQ_24,
+       MT8195_AFE_IRQ_25,
+       MT8195_AFE_IRQ_26,
+       MT8195_AFE_IRQ_27,
+       MT8195_AFE_IRQ_28,
+       MT8195_AFE_IRQ_NUM,
+};
+
+enum {
+       MT8195_ETDM_OUT1_1X_EN = 9,
+       MT8195_ETDM_OUT2_1X_EN = 10,
+       MT8195_ETDM_OUT3_1X_EN = 11,
+       MT8195_ETDM_IN1_1X_EN = 12,
+       MT8195_ETDM_IN2_1X_EN = 13,
+       MT8195_ETDM_IN1_NX_EN = 25,
+       MT8195_ETDM_IN2_NX_EN = 26,
+};
+
+enum {
+       MT8195_MTKAIF_MISO_0,
+       MT8195_MTKAIF_MISO_1,
+       MT8195_MTKAIF_MISO_2,
+       MT8195_MTKAIF_MISO_NUM,
+};
+
+struct mtk_dai_memif_irq_priv {
+       unsigned int asys_timing_sel;
+};
+
+struct mtkaif_param {
+       bool mtkaif_calibration_ok;
+       int mtkaif_chosen_phase[MT8195_MTKAIF_MISO_NUM];
+       int mtkaif_phase_cycle[MT8195_MTKAIF_MISO_NUM];
+       int mtkaif_dmic_on;
+       int mtkaif_adda6_only;
+};
+
+struct clk;
+
+struct mt8195_afe_private {
+       struct clk **clk;
+       struct clk_lookup **lookup;
+       struct regmap *topckgen;
+       int pm_runtime_bypass_reg_ctl;
+#ifdef CONFIG_DEBUG_FS
+       struct dentry **debugfs_dentry;
+#endif
+       int afe_on_ref_cnt;
+       int top_cg_ref_cnt[MT8195_TOP_CG_NUM];
+       spinlock_t afe_ctrl_lock;       /* Lock for afe control */
+       struct mtk_dai_memif_irq_priv irq_priv[MT8195_AFE_IRQ_NUM];
+       struct mtkaif_param mtkaif_params;
+
+       /* dai */
+       void *dai_priv[MT8195_DAI_NUM];
+};
+
+int mt8195_afe_fs_timing(unsigned int rate);
+/* dai register */
+int mt8195_dai_adda_register(struct mtk_base_afe *afe);
+int mt8195_dai_etdm_register(struct mtk_base_afe *afe);
+int mt8195_dai_pcm_register(struct mtk_base_afe *afe);
+
+#define MT8195_SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put, id) \
+{ \
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+       .info = snd_soc_info_enum_double, \
+       .get = xhandler_get, .put = xhandler_put, \
+       .device = id, \
+       .private_value = (unsigned long)&xenum, \
+}
+
+#endif
diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
new file mode 100644 (file)
index 0000000..6635c3f
--- /dev/null
@@ -0,0 +1,3281 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mediatek ALSA SoC AFE platform driver for 8195
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ *         Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include "mt8195-afe-common.h"
+#include "mt8195-afe-clk.h"
+#include "mt8195-reg.h"
+#include "../common/mtk-afe-platform-driver.h"
+#include "../common/mtk-afe-fe-dai.h"
+
+#define MT8195_MEMIF_BUFFER_BYTES_ALIGN  (0x40)
+#define MT8195_MEMIF_DL7_MAX_PERIOD_SIZE (0x3fff)
+
+struct mtk_dai_memif_priv {
+       unsigned int asys_timing_sel;
+};
+
+static const struct snd_pcm_hardware mt8195_afe_hardware = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_MMAP_VALID,
+       .formats = SNDRV_PCM_FMTBIT_S16_LE |
+                  SNDRV_PCM_FMTBIT_S24_LE |
+                  SNDRV_PCM_FMTBIT_S32_LE,
+       .period_bytes_min = 64,
+       .period_bytes_max = 256 * 1024,
+       .periods_min = 2,
+       .periods_max = 256,
+       .buffer_bytes_max = 256 * 2 * 1024,
+};
+
+struct mt8195_afe_rate {
+       unsigned int rate;
+       unsigned int reg_value;
+};
+
+static const struct mt8195_afe_rate mt8195_afe_rates[] = {
+       { .rate = 8000, .reg_value = 0, },
+       { .rate = 12000, .reg_value = 1, },
+       { .rate = 16000, .reg_value = 2, },
+       { .rate = 24000, .reg_value = 3, },
+       { .rate = 32000, .reg_value = 4, },
+       { .rate = 48000, .reg_value = 5, },
+       { .rate = 96000, .reg_value = 6, },
+       { .rate = 192000, .reg_value = 7, },
+       { .rate = 384000, .reg_value = 8, },
+       { .rate = 7350, .reg_value = 16, },
+       { .rate = 11025, .reg_value = 17, },
+       { .rate = 14700, .reg_value = 18, },
+       { .rate = 22050, .reg_value = 19, },
+       { .rate = 29400, .reg_value = 20, },
+       { .rate = 44100, .reg_value = 21, },
+       { .rate = 88200, .reg_value = 22, },
+       { .rate = 176400, .reg_value = 23, },
+       { .rate = 352800, .reg_value = 24, },
+};
+
+int mt8195_afe_fs_timing(unsigned int rate)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mt8195_afe_rates); i++)
+               if (mt8195_afe_rates[i].rate == rate)
+                       return mt8195_afe_rates[i].reg_value;
+
+       return -EINVAL;
+}
+
+static int mt8195_memif_fs(struct snd_pcm_substream *substream,
+                          unsigned int rate)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_component *component =
+                       snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+       int id = asoc_rtd_to_cpu(rtd, 0)->id;
+       struct mtk_base_afe_memif *memif = &afe->memif[id];
+       int fs = mt8195_afe_fs_timing(rate);
+
+       switch (memif->data->id) {
+       case MT8195_AFE_MEMIF_DL10:
+               fs = MT8195_ETDM_OUT3_1X_EN;
+               break;
+       case MT8195_AFE_MEMIF_UL8:
+               fs = MT8195_ETDM_IN1_NX_EN;
+               break;
+       case MT8195_AFE_MEMIF_UL3:
+               fs = MT8195_ETDM_IN2_NX_EN;
+               break;
+       default:
+               break;
+       }
+
+       return fs;
+}
+
+static int mt8195_irq_fs(struct snd_pcm_substream *substream,
+                        unsigned int rate)
+{
+       int fs = mt8195_memif_fs(substream, rate);
+
+       switch (fs) {
+       case MT8195_ETDM_IN1_NX_EN:
+               fs = MT8195_ETDM_IN1_1X_EN;
+               break;
+       case MT8195_ETDM_IN2_NX_EN:
+               fs = MT8195_ETDM_IN2_1X_EN;
+               break;
+       default:
+               break;
+       }
+
+       return fs;
+}
+
+enum {
+       MT8195_AFE_CM0,
+       MT8195_AFE_CM1,
+       MT8195_AFE_CM2,
+       MT8195_AFE_CM_NUM,
+};
+
+struct mt8195_afe_channel_merge {
+       int id;
+       int reg;
+       unsigned int sel_shift;
+       unsigned int sel_maskbit;
+       unsigned int sel_default;
+       unsigned int ch_num_shift;
+       unsigned int ch_num_maskbit;
+       unsigned int en_shift;
+       unsigned int en_maskbit;
+       unsigned int update_cnt_shift;
+       unsigned int update_cnt_maskbit;
+       unsigned int update_cnt_default;
+};
+
+static const struct mt8195_afe_channel_merge
+       mt8195_afe_cm[MT8195_AFE_CM_NUM] = {
+       [MT8195_AFE_CM0] = {
+               .id = MT8195_AFE_CM0,
+               .reg = AFE_CM0_CON,
+               .sel_shift = 30,
+               .sel_maskbit = 0x1,
+               .sel_default = 1,
+               .ch_num_shift = 2,
+               .ch_num_maskbit = 0x3f,
+               .en_shift = 0,
+               .en_maskbit = 0x1,
+               .update_cnt_shift = 16,
+               .update_cnt_maskbit = 0x1fff,
+               .update_cnt_default = 0x3,
+       },
+       [MT8195_AFE_CM1] = {
+               .id = MT8195_AFE_CM1,
+               .reg = AFE_CM1_CON,
+               .sel_shift = 30,
+               .sel_maskbit = 0x1,
+               .sel_default = 1,
+               .ch_num_shift = 2,
+               .ch_num_maskbit = 0x1f,
+               .en_shift = 0,
+               .en_maskbit = 0x1,
+               .update_cnt_shift = 16,
+               .update_cnt_maskbit = 0x1fff,
+               .update_cnt_default = 0x3,
+       },
+       [MT8195_AFE_CM2] = {
+               .id = MT8195_AFE_CM2,
+               .reg = AFE_CM2_CON,
+               .sel_shift = 30,
+               .sel_maskbit = 0x1,
+               .sel_default = 1,
+               .ch_num_shift = 2,
+               .ch_num_maskbit = 0x1f,
+               .en_shift = 0,
+               .en_maskbit = 0x1,
+               .update_cnt_shift = 16,
+               .update_cnt_maskbit = 0x1fff,
+               .update_cnt_default = 0x3,
+       },
+};
+
+static int mt8195_afe_memif_is_ul(int id)
+{
+       if (id >= MT8195_AFE_MEMIF_UL_START && id < MT8195_AFE_MEMIF_END)
+               return 1;
+       else
+               return 0;
+}
+
+static const struct mt8195_afe_channel_merge*
+mt8195_afe_found_cm(struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       int id = -EINVAL;
+
+       if (mt8195_afe_memif_is_ul(dai->id) == 0)
+               return NULL;
+
+       switch (dai->id) {
+       case MT8195_AFE_MEMIF_UL9:
+               id = MT8195_AFE_CM0;
+               break;
+       case MT8195_AFE_MEMIF_UL2:
+               id = MT8195_AFE_CM1;
+               break;
+       case MT8195_AFE_MEMIF_UL10:
+               id = MT8195_AFE_CM2;
+               break;
+       default:
+               break;
+       }
+
+       if (id < 0) {
+               dev_dbg(afe->dev, "%s, memif %d cannot find CM!\n",
+                       __func__, dai->id);
+               return NULL;
+       }
+
+       return &mt8195_afe_cm[id];
+}
+
+static int mt8195_afe_config_cm(struct mtk_base_afe *afe,
+                               const struct mt8195_afe_channel_merge *cm,
+                               unsigned int channels)
+{
+       if (!cm)
+               return -EINVAL;
+
+       regmap_update_bits(afe->regmap,
+                          cm->reg,
+                          cm->sel_maskbit << cm->sel_shift,
+                          cm->sel_default << cm->sel_shift);
+
+       regmap_update_bits(afe->regmap,
+                          cm->reg,
+                          cm->ch_num_maskbit << cm->ch_num_shift,
+                          (channels - 1) << cm->ch_num_shift);
+
+       regmap_update_bits(afe->regmap,
+                          cm->reg,
+                          cm->update_cnt_maskbit << cm->update_cnt_shift,
+                          cm->update_cnt_default << cm->update_cnt_shift);
+
+       return 0;
+}
+
+static int mt8195_afe_enable_cm(struct mtk_base_afe *afe,
+                               const struct mt8195_afe_channel_merge *cm,
+                               bool enable)
+{
+       if (!cm)
+               return -EINVAL;
+
+       regmap_update_bits(afe->regmap,
+                          cm->reg,
+                          cm->en_maskbit << cm->en_shift,
+                          enable << cm->en_shift);
+
+       return 0;
+}
+
+static int
+mt8195_afe_paired_memif_clk_prepare(struct snd_pcm_substream *substream,
+                                   struct snd_soc_dai *dai,
+                                   int enable)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       int id = asoc_rtd_to_cpu(rtd, 0)->id;
+       int clk_id;
+
+       if (id != MT8195_AFE_MEMIF_DL8 && id != MT8195_AFE_MEMIF_DL10)
+               return 0;
+
+       if (enable) {
+               clk_id = MT8195_CLK_AUD_MEMIF_DL10;
+               mt8195_afe_prepare_clk(afe, afe_priv->clk[clk_id]);
+               clk_id = MT8195_CLK_AUD_MEMIF_DL8;
+               mt8195_afe_prepare_clk(afe, afe_priv->clk[clk_id]);
+       } else {
+               clk_id = MT8195_CLK_AUD_MEMIF_DL8;
+               mt8195_afe_unprepare_clk(afe, afe_priv->clk[clk_id]);
+               clk_id = MT8195_CLK_AUD_MEMIF_DL10;
+               mt8195_afe_unprepare_clk(afe, afe_priv->clk[clk_id]);
+       }
+
+       return 0;
+}
+
+static int
+mt8195_afe_paired_memif_clk_enable(struct snd_pcm_substream *substream,
+                                  struct snd_soc_dai *dai,
+                                  int enable)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       int id = asoc_rtd_to_cpu(rtd, 0)->id;
+       int clk_id;
+
+       if (id != MT8195_AFE_MEMIF_DL8 && id != MT8195_AFE_MEMIF_DL10)
+               return 0;
+
+       if (enable) {
+               /* DL8_DL10_MEM */
+               clk_id = MT8195_CLK_AUD_MEMIF_DL10;
+               mt8195_afe_enable_clk_atomic(afe, afe_priv->clk[clk_id]);
+               udelay(1);
+               /* DL8_DL10_AGENT */
+               clk_id = MT8195_CLK_AUD_MEMIF_DL8;
+               mt8195_afe_enable_clk_atomic(afe, afe_priv->clk[clk_id]);
+       } else {
+               /* DL8_DL10_AGENT */
+               clk_id = MT8195_CLK_AUD_MEMIF_DL8;
+               mt8195_afe_disable_clk_atomic(afe, afe_priv->clk[clk_id]);
+               /* DL8_DL10_MEM */
+               clk_id = MT8195_CLK_AUD_MEMIF_DL10;
+               mt8195_afe_disable_clk_atomic(afe, afe_priv->clk[clk_id]);
+       }
+
+       return 0;
+}
+
+static int mt8195_afe_fe_startup(struct snd_pcm_substream *substream,
+                                struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       int id = asoc_rtd_to_cpu(rtd, 0)->id;
+       int ret = 0;
+
+       mt8195_afe_paired_memif_clk_prepare(substream, dai, 1);
+
+       ret = mtk_afe_fe_startup(substream, dai);
+
+       snd_pcm_hw_constraint_step(runtime, 0,
+                                  SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+                                  MT8195_MEMIF_BUFFER_BYTES_ALIGN);
+
+       if (id != MT8195_AFE_MEMIF_DL7)
+               goto out;
+
+       ret = snd_pcm_hw_constraint_minmax(runtime,
+                                          SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+                                          1,
+                                          MT8195_MEMIF_DL7_MAX_PERIOD_SIZE);
+       if (ret < 0)
+               dev_dbg(afe->dev, "hw_constraint_minmax failed\n");
+out:
+       return ret;
+}
+
+static void mt8195_afe_fe_shutdown(struct snd_pcm_substream *substream,
+                                  struct snd_soc_dai *dai)
+{
+       mtk_afe_fe_shutdown(substream, dai);
+       mt8195_afe_paired_memif_clk_prepare(substream, dai, 0);
+}
+
+static int mt8195_afe_fe_hw_params(struct snd_pcm_substream *substream,
+                                  struct snd_pcm_hw_params *params,
+                                  struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       int id = asoc_rtd_to_cpu(rtd, 0)->id;
+       struct mtk_base_afe_memif *memif = &afe->memif[id];
+       const struct mtk_base_memif_data *data = memif->data;
+       const struct mt8195_afe_channel_merge *cm = mt8195_afe_found_cm(dai);
+       unsigned int ch_num = params_channels(params);
+
+       mt8195_afe_config_cm(afe, cm, params_channels(params));
+
+       if (data->ch_num_reg >= 0) {
+               regmap_update_bits(afe->regmap, data->ch_num_reg,
+                                  data->ch_num_maskbit << data->ch_num_shift,
+                                  ch_num << data->ch_num_shift);
+       }
+
+       return mtk_afe_fe_hw_params(substream, params, dai);
+}
+
+static int mt8195_afe_fe_hw_free(struct snd_pcm_substream *substream,
+                                struct snd_soc_dai *dai)
+{
+       return mtk_afe_fe_hw_free(substream, dai);
+}
+
+static int mt8195_afe_fe_prepare(struct snd_pcm_substream *substream,
+                                struct snd_soc_dai *dai)
+{
+       return mtk_afe_fe_prepare(substream, dai);
+}
+
+static int mt8195_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd,
+                                struct snd_soc_dai *dai)
+{
+       int ret = 0;
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       const struct mt8195_afe_channel_merge *cm = mt8195_afe_found_cm(dai);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+               mt8195_afe_enable_cm(afe, cm, true);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               mt8195_afe_enable_cm(afe, cm, false);
+               break;
+       default:
+               break;
+       }
+
+       ret = mtk_afe_fe_trigger(substream, cmd, dai);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+               mt8195_afe_paired_memif_clk_enable(substream, dai, 1);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               mt8195_afe_paired_memif_clk_enable(substream, dai, 0);
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static int mt8195_afe_fe_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       return 0;
+}
+
+static const struct snd_soc_dai_ops mt8195_afe_fe_dai_ops = {
+       .startup        = mt8195_afe_fe_startup,
+       .shutdown       = mt8195_afe_fe_shutdown,
+       .hw_params      = mt8195_afe_fe_hw_params,
+       .hw_free        = mt8195_afe_fe_hw_free,
+       .prepare        = mt8195_afe_fe_prepare,
+       .trigger        = mt8195_afe_fe_trigger,
+       .set_fmt        = mt8195_afe_fe_set_fmt,
+};
+
+#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000 |\
+                      SNDRV_PCM_RATE_88200 |\
+                      SNDRV_PCM_RATE_96000 |\
+                      SNDRV_PCM_RATE_176400 |\
+                      SNDRV_PCM_RATE_192000 |\
+                      SNDRV_PCM_RATE_352800 |\
+                      SNDRV_PCM_RATE_384000)
+
+#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+                        SNDRV_PCM_FMTBIT_S24_LE |\
+                        SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mt8195_memif_dai_driver[] = {
+       /* FE DAIs: memory intefaces to CPU */
+       {
+               .name = "DL2",
+               .id = MT8195_AFE_MEMIF_DL2,
+               .playback = {
+                       .stream_name = "DL2",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "DL3",
+               .id = MT8195_AFE_MEMIF_DL3,
+               .playback = {
+                       .stream_name = "DL3",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "DL6",
+               .id = MT8195_AFE_MEMIF_DL6,
+               .playback = {
+                       .stream_name = "DL6",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "DL7",
+               .id = MT8195_AFE_MEMIF_DL7,
+               .playback = {
+                       .stream_name = "DL7",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "DL8",
+               .id = MT8195_AFE_MEMIF_DL8,
+               .playback = {
+                       .stream_name = "DL8",
+                       .channels_min = 1,
+                       .channels_max = 24,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "DL10",
+               .id = MT8195_AFE_MEMIF_DL10,
+               .playback = {
+                       .stream_name = "DL10",
+                       .channels_min = 1,
+                       .channels_max = 8,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "DL11",
+               .id = MT8195_AFE_MEMIF_DL11,
+               .playback = {
+                       .stream_name = "DL11",
+                       .channels_min = 1,
+                       .channels_max = 48,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "UL1",
+               .id = MT8195_AFE_MEMIF_UL1,
+               .capture = {
+                       .stream_name = "UL1",
+                       .channels_min = 1,
+                       .channels_max = 8,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "UL2",
+               .id = MT8195_AFE_MEMIF_UL2,
+               .capture = {
+                       .stream_name = "UL2",
+                       .channels_min = 1,
+                       .channels_max = 8,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "UL3",
+               .id = MT8195_AFE_MEMIF_UL3,
+               .capture = {
+                       .stream_name = "UL3",
+                       .channels_min = 1,
+                       .channels_max = 16,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "UL4",
+               .id = MT8195_AFE_MEMIF_UL4,
+               .capture = {
+                       .stream_name = "UL4",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "UL5",
+               .id = MT8195_AFE_MEMIF_UL5,
+               .capture = {
+                       .stream_name = "UL5",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "UL6",
+               .id = MT8195_AFE_MEMIF_UL6,
+               .capture = {
+                       .stream_name = "UL6",
+                       .channels_min = 1,
+                       .channels_max = 8,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "UL8",
+               .id = MT8195_AFE_MEMIF_UL8,
+               .capture = {
+                       .stream_name = "UL8",
+                       .channels_min = 1,
+                       .channels_max = 24,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "UL9",
+               .id = MT8195_AFE_MEMIF_UL9,
+               .capture = {
+                       .stream_name = "UL9",
+                       .channels_min = 1,
+                       .channels_max = 32,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+       {
+               .name = "UL10",
+               .id = MT8195_AFE_MEMIF_UL10,
+               .capture = {
+                       .stream_name = "UL10",
+                       .channels_min = 1,
+                       .channels_max = 4,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mt8195_afe_fe_dai_ops,
+       },
+};
+
+static const struct snd_kcontrol_new o002_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN2, 0, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I012 Switch", AFE_CONN2, 12, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN2, 20, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN2, 22, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN2_2, 6, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I072 Switch", AFE_CONN2_2, 8, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN2_5, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new o003_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN3, 1, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I013 Switch", AFE_CONN3, 13, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN3, 21, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN3, 23, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN3_2, 7, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I073 Switch", AFE_CONN3_2, 9, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I169 Switch", AFE_CONN3_5, 9, 1, 0),
+};
+
+static const struct snd_kcontrol_new o004_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN4, 0, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I014 Switch", AFE_CONN4, 14, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN4, 24, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I074 Switch", AFE_CONN4_2, 10, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I170 Switch", AFE_CONN4_5, 10, 1, 0),
+};
+
+static const struct snd_kcontrol_new o005_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN5, 1, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I015 Switch", AFE_CONN5, 15, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN5, 25, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I075 Switch", AFE_CONN5_2, 11, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I171 Switch", AFE_CONN5_5, 11, 1, 0),
+};
+
+static const struct snd_kcontrol_new o006_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN6, 0, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I016 Switch", AFE_CONN6, 16, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN6, 26, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I076 Switch", AFE_CONN6_2, 12, 1, 0),
+};
+
+static const struct snd_kcontrol_new o007_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN7, 1, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I017 Switch", AFE_CONN7, 17, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN7, 27, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I077 Switch", AFE_CONN7_2, 13, 1, 0),
+};
+
+static const struct snd_kcontrol_new o008_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I018 Switch", AFE_CONN8, 18, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN8, 28, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I078 Switch", AFE_CONN8_2, 14, 1, 0),
+};
+
+static const struct snd_kcontrol_new o009_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I019 Switch", AFE_CONN9, 19, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN9, 29, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I079 Switch", AFE_CONN9_2, 15, 1, 0),
+};
+
+static const struct snd_kcontrol_new o010_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN10, 22, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I030 Switch", AFE_CONN10, 30, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I046 Switch", AFE_CONN10_1, 14, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I072 Switch", AFE_CONN10_2, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new o011_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN11, 23, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I031 Switch", AFE_CONN11, 31, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I047 Switch", AFE_CONN11_1, 15, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I073 Switch", AFE_CONN11_2, 9, 1, 0),
+};
+
+static const struct snd_kcontrol_new o012_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN12, 24, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I032 Switch", AFE_CONN12_1, 0, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I048 Switch", AFE_CONN12_1, 16, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I074 Switch", AFE_CONN12_2, 10, 1, 0),
+};
+
+static const struct snd_kcontrol_new o013_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN13, 25, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I033 Switch", AFE_CONN13_1, 1, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I049 Switch", AFE_CONN13_1, 17, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I075 Switch", AFE_CONN13_2, 11, 1, 0),
+};
+
+static const struct snd_kcontrol_new o014_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN14, 26, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I034 Switch", AFE_CONN14_1, 2, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I050 Switch", AFE_CONN14_1, 18, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I076 Switch", AFE_CONN14_2, 12, 1, 0),
+};
+
+static const struct snd_kcontrol_new o015_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN15, 27, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I035 Switch", AFE_CONN15_1, 3, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I051 Switch", AFE_CONN15_1, 19, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I077 Switch", AFE_CONN15_2, 13, 1, 0),
+};
+
+static const struct snd_kcontrol_new o016_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN16, 28, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I036 Switch", AFE_CONN16_1, 4, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I052 Switch", AFE_CONN16_1, 20, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I078 Switch", AFE_CONN16_2, 14, 1, 0),
+};
+
+static const struct snd_kcontrol_new o017_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN17, 29, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I037 Switch", AFE_CONN17_1, 5, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I053 Switch", AFE_CONN17_1, 21, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I079 Switch", AFE_CONN17_2, 15, 1, 0),
+};
+
+static const struct snd_kcontrol_new o018_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I038 Switch", AFE_CONN18_1, 6, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I080 Switch", AFE_CONN18_2, 16, 1, 0),
+};
+
+static const struct snd_kcontrol_new o019_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I039 Switch", AFE_CONN19_1, 7, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I081 Switch", AFE_CONN19_2, 17, 1, 0),
+};
+
+static const struct snd_kcontrol_new o020_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I040 Switch", AFE_CONN20_1, 8, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I082 Switch", AFE_CONN20_2, 18, 1, 0),
+};
+
+static const struct snd_kcontrol_new o021_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I041 Switch", AFE_CONN21_1, 9, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I083 Switch", AFE_CONN21_2, 19, 1, 0),
+};
+
+static const struct snd_kcontrol_new o022_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I042 Switch", AFE_CONN22_1, 10, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I084 Switch", AFE_CONN22_2, 20, 1, 0),
+};
+
+static const struct snd_kcontrol_new o023_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I043 Switch", AFE_CONN23_1, 11, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I085 Switch", AFE_CONN23_2, 21, 1, 0),
+};
+
+static const struct snd_kcontrol_new o024_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I044 Switch", AFE_CONN24_1, 12, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I086 Switch", AFE_CONN24_2, 22, 1, 0),
+};
+
+static const struct snd_kcontrol_new o025_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I045 Switch", AFE_CONN25_1, 13, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I087 Switch", AFE_CONN25_2, 23, 1, 0),
+};
+
+static const struct snd_kcontrol_new o026_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I046 Switch", AFE_CONN26_1, 14, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I088 Switch", AFE_CONN26_2, 24, 1, 0),
+};
+
+static const struct snd_kcontrol_new o027_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I047 Switch", AFE_CONN27_1, 15, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I089 Switch", AFE_CONN27_2, 25, 1, 0),
+};
+
+static const struct snd_kcontrol_new o028_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I048 Switch", AFE_CONN28_1, 16, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I090 Switch", AFE_CONN28_2, 26, 1, 0),
+};
+
+static const struct snd_kcontrol_new o029_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I049 Switch", AFE_CONN29_1, 17, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I091 Switch", AFE_CONN29_2, 27, 1, 0),
+};
+
+static const struct snd_kcontrol_new o030_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I050 Switch", AFE_CONN30_1, 18, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I092 Switch", AFE_CONN30_2, 28, 1, 0),
+};
+
+static const struct snd_kcontrol_new o031_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I051 Switch", AFE_CONN31_1, 19, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I093 Switch", AFE_CONN31_2, 29, 1, 0),
+};
+
+static const struct snd_kcontrol_new o032_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I052 Switch", AFE_CONN32_1, 20, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I094 Switch", AFE_CONN32_2, 30, 1, 0),
+};
+
+static const struct snd_kcontrol_new o033_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I053 Switch", AFE_CONN33_1, 21, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I095 Switch", AFE_CONN33_2, 31, 1, 0),
+};
+
+static const struct snd_kcontrol_new o034_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN34, 0, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I002 Switch", AFE_CONN34, 2, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I012 Switch", AFE_CONN34, 12, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN34, 20, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN34_2, 6, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I072 Switch", AFE_CONN34_2, 8, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN34_5, 8, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I170 Switch", AFE_CONN34_5, 10, 1, 0),
+};
+
+static const struct snd_kcontrol_new o035_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN35, 1, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I003 Switch", AFE_CONN35, 3, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I013 Switch", AFE_CONN35, 13, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN35, 21, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN35_2, 7, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I073 Switch", AFE_CONN35_2, 9, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I137 Switch", AFE_CONN35_4, 9, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I139 Switch", AFE_CONN35_4, 11, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN35_5, 8, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I169 Switch", AFE_CONN35_5, 9, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I170 Switch", AFE_CONN35_5, 10, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I171 Switch", AFE_CONN35_5, 11, 1, 0),
+};
+
+static const struct snd_kcontrol_new o036_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN36, 0, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I012 Switch", AFE_CONN36, 12, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN36, 20, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN36_2, 6, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN36_5, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new o037_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN37, 1, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I013 Switch", AFE_CONN37, 13, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN37, 21, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN37_2, 7, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I169 Switch", AFE_CONN37_5, 9, 1, 0),
+};
+
+static const struct snd_kcontrol_new o038_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN38, 22, 1, 0),
+};
+
+static const struct snd_kcontrol_new o039_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN39, 23, 1, 0),
+};
+
+static const struct snd_kcontrol_new o040_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I002 Switch", AFE_CONN40, 2, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I012 Switch", AFE_CONN40, 12, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN40, 22, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN40_5, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new o041_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I003 Switch", AFE_CONN41, 3, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I013 Switch", AFE_CONN41, 13, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN41, 23, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I169 Switch", AFE_CONN41_5, 9, 1, 0),
+};
+
+static const struct snd_kcontrol_new o042_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I014 Switch", AFE_CONN42, 14, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN42, 24, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I170 Switch", AFE_CONN42_5, 10, 1, 0),
+};
+
+static const struct snd_kcontrol_new o043_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I015 Switch", AFE_CONN43, 15, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN43, 25, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I171 Switch", AFE_CONN43_5, 11, 1, 0),
+};
+
+static const struct snd_kcontrol_new o044_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I016 Switch", AFE_CONN44, 16, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN44, 26, 1, 0),
+};
+
+static const struct snd_kcontrol_new o045_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I017 Switch", AFE_CONN45, 17, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN45, 27, 1, 0),
+};
+
+static const struct snd_kcontrol_new o046_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I018 Switch", AFE_CONN46, 18, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN46, 28, 1, 0),
+};
+
+static const struct snd_kcontrol_new o047_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I019 Switch", AFE_CONN47, 19, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN47, 29, 1, 0),
+};
+
+static const struct snd_kcontrol_new o182_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN182, 24, 1, 0),
+};
+
+static const struct snd_kcontrol_new o183_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN183, 25, 1, 0),
+};
+
+static const char * const dl8_dl11_data_sel_mux_text[] = {
+       "dl8", "dl11",
+};
+
+static SOC_ENUM_SINGLE_DECL(dl8_dl11_data_sel_mux_enum,
+       AFE_DAC_CON2, 0, dl8_dl11_data_sel_mux_text);
+
+static const struct snd_kcontrol_new dl8_dl11_data_sel_mux =
+       SOC_DAPM_ENUM("DL8_DL11 Sink", dl8_dl11_data_sel_mux_enum);
+
+static const struct snd_soc_dapm_widget mt8195_memif_widgets[] = {
+       /* DL6 */
+       SND_SOC_DAPM_MIXER("I000", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I001", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       /* DL3 */
+       SND_SOC_DAPM_MIXER("I020", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I021", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       /* DL11 */
+       SND_SOC_DAPM_MIXER("I022", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I023", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I024", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I025", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I026", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I027", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I028", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I029", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I030", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I031", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I032", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I033", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I034", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I035", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I036", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I037", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I038", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I039", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I040", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I041", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I042", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I043", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I044", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I045", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       /* DL11/DL8 */
+       SND_SOC_DAPM_MIXER("I046", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I047", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I048", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I049", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I050", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I051", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I052", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I053", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I054", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I055", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I056", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I057", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I058", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I059", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I060", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I061", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I062", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I063", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I064", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I065", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I066", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I067", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I068", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I069", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       /* DL2 */
+       SND_SOC_DAPM_MIXER("I070", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I071", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       SND_SOC_DAPM_MUX("DL8_DL11 Mux",
+                        SND_SOC_NOPM, 0, 0, &dl8_dl11_data_sel_mux),
+
+       /* UL9 */
+       SND_SOC_DAPM_MIXER("O002", SND_SOC_NOPM, 0, 0,
+                          o002_mix, ARRAY_SIZE(o002_mix)),
+       SND_SOC_DAPM_MIXER("O003", SND_SOC_NOPM, 0, 0,
+                          o003_mix, ARRAY_SIZE(o003_mix)),
+       SND_SOC_DAPM_MIXER("O004", SND_SOC_NOPM, 0, 0,
+                          o004_mix, ARRAY_SIZE(o004_mix)),
+       SND_SOC_DAPM_MIXER("O005", SND_SOC_NOPM, 0, 0,
+                          o005_mix, ARRAY_SIZE(o005_mix)),
+       SND_SOC_DAPM_MIXER("O006", SND_SOC_NOPM, 0, 0,
+                          o006_mix, ARRAY_SIZE(o006_mix)),
+       SND_SOC_DAPM_MIXER("O007", SND_SOC_NOPM, 0, 0,
+                          o007_mix, ARRAY_SIZE(o007_mix)),
+       SND_SOC_DAPM_MIXER("O008", SND_SOC_NOPM, 0, 0,
+                          o008_mix, ARRAY_SIZE(o008_mix)),
+       SND_SOC_DAPM_MIXER("O009", SND_SOC_NOPM, 0, 0,
+                          o009_mix, ARRAY_SIZE(o009_mix)),
+       SND_SOC_DAPM_MIXER("O010", SND_SOC_NOPM, 0, 0,
+                          o010_mix, ARRAY_SIZE(o010_mix)),
+       SND_SOC_DAPM_MIXER("O011", SND_SOC_NOPM, 0, 0,
+                          o011_mix, ARRAY_SIZE(o011_mix)),
+       SND_SOC_DAPM_MIXER("O012", SND_SOC_NOPM, 0, 0,
+                          o012_mix, ARRAY_SIZE(o012_mix)),
+       SND_SOC_DAPM_MIXER("O013", SND_SOC_NOPM, 0, 0,
+                          o013_mix, ARRAY_SIZE(o013_mix)),
+       SND_SOC_DAPM_MIXER("O014", SND_SOC_NOPM, 0, 0,
+                          o014_mix, ARRAY_SIZE(o014_mix)),
+       SND_SOC_DAPM_MIXER("O015", SND_SOC_NOPM, 0, 0,
+                          o015_mix, ARRAY_SIZE(o015_mix)),
+       SND_SOC_DAPM_MIXER("O016", SND_SOC_NOPM, 0, 0,
+                          o016_mix, ARRAY_SIZE(o016_mix)),
+       SND_SOC_DAPM_MIXER("O017", SND_SOC_NOPM, 0, 0,
+                          o017_mix, ARRAY_SIZE(o017_mix)),
+       SND_SOC_DAPM_MIXER("O018", SND_SOC_NOPM, 0, 0,
+                          o018_mix, ARRAY_SIZE(o018_mix)),
+       SND_SOC_DAPM_MIXER("O019", SND_SOC_NOPM, 0, 0,
+                          o019_mix, ARRAY_SIZE(o019_mix)),
+       SND_SOC_DAPM_MIXER("O020", SND_SOC_NOPM, 0, 0,
+                          o020_mix, ARRAY_SIZE(o020_mix)),
+       SND_SOC_DAPM_MIXER("O021", SND_SOC_NOPM, 0, 0,
+                          o021_mix, ARRAY_SIZE(o021_mix)),
+       SND_SOC_DAPM_MIXER("O022", SND_SOC_NOPM, 0, 0,
+                          o022_mix, ARRAY_SIZE(o022_mix)),
+       SND_SOC_DAPM_MIXER("O023", SND_SOC_NOPM, 0, 0,
+                          o023_mix, ARRAY_SIZE(o023_mix)),
+       SND_SOC_DAPM_MIXER("O024", SND_SOC_NOPM, 0, 0,
+                          o024_mix, ARRAY_SIZE(o024_mix)),
+       SND_SOC_DAPM_MIXER("O025", SND_SOC_NOPM, 0, 0,
+                          o025_mix, ARRAY_SIZE(o025_mix)),
+       SND_SOC_DAPM_MIXER("O026", SND_SOC_NOPM, 0, 0,
+                          o026_mix, ARRAY_SIZE(o026_mix)),
+       SND_SOC_DAPM_MIXER("O027", SND_SOC_NOPM, 0, 0,
+                          o027_mix, ARRAY_SIZE(o027_mix)),
+       SND_SOC_DAPM_MIXER("O028", SND_SOC_NOPM, 0, 0,
+                          o028_mix, ARRAY_SIZE(o028_mix)),
+       SND_SOC_DAPM_MIXER("O029", SND_SOC_NOPM, 0, 0,
+                          o029_mix, ARRAY_SIZE(o029_mix)),
+       SND_SOC_DAPM_MIXER("O030", SND_SOC_NOPM, 0, 0,
+                          o030_mix, ARRAY_SIZE(o030_mix)),
+       SND_SOC_DAPM_MIXER("O031", SND_SOC_NOPM, 0, 0,
+                          o031_mix, ARRAY_SIZE(o031_mix)),
+       SND_SOC_DAPM_MIXER("O032", SND_SOC_NOPM, 0, 0,
+                          o032_mix, ARRAY_SIZE(o032_mix)),
+       SND_SOC_DAPM_MIXER("O033", SND_SOC_NOPM, 0, 0,
+                          o033_mix, ARRAY_SIZE(o033_mix)),
+
+       /* UL4 */
+       SND_SOC_DAPM_MIXER("O034", SND_SOC_NOPM, 0, 0,
+                          o034_mix, ARRAY_SIZE(o034_mix)),
+       SND_SOC_DAPM_MIXER("O035", SND_SOC_NOPM, 0, 0,
+                          o035_mix, ARRAY_SIZE(o035_mix)),
+
+       /* UL5 */
+       SND_SOC_DAPM_MIXER("O036", SND_SOC_NOPM, 0, 0,
+                          o036_mix, ARRAY_SIZE(o036_mix)),
+       SND_SOC_DAPM_MIXER("O037", SND_SOC_NOPM, 0, 0,
+                          o037_mix, ARRAY_SIZE(o037_mix)),
+
+       /* UL10 */
+       SND_SOC_DAPM_MIXER("O038", SND_SOC_NOPM, 0, 0,
+                          o038_mix, ARRAY_SIZE(o038_mix)),
+       SND_SOC_DAPM_MIXER("O039", SND_SOC_NOPM, 0, 0,
+                          o039_mix, ARRAY_SIZE(o039_mix)),
+       SND_SOC_DAPM_MIXER("O182", SND_SOC_NOPM, 0, 0,
+                          o182_mix, ARRAY_SIZE(o182_mix)),
+       SND_SOC_DAPM_MIXER("O183", SND_SOC_NOPM, 0, 0,
+                          o183_mix, ARRAY_SIZE(o183_mix)),
+
+       /* UL2 */
+       SND_SOC_DAPM_MIXER("O040", SND_SOC_NOPM, 0, 0,
+                          o040_mix, ARRAY_SIZE(o040_mix)),
+       SND_SOC_DAPM_MIXER("O041", SND_SOC_NOPM, 0, 0,
+                          o041_mix, ARRAY_SIZE(o041_mix)),
+       SND_SOC_DAPM_MIXER("O042", SND_SOC_NOPM, 0, 0,
+                          o042_mix, ARRAY_SIZE(o042_mix)),
+       SND_SOC_DAPM_MIXER("O043", SND_SOC_NOPM, 0, 0,
+                          o043_mix, ARRAY_SIZE(o043_mix)),
+       SND_SOC_DAPM_MIXER("O044", SND_SOC_NOPM, 0, 0,
+                          o044_mix, ARRAY_SIZE(o044_mix)),
+       SND_SOC_DAPM_MIXER("O045", SND_SOC_NOPM, 0, 0,
+                          o045_mix, ARRAY_SIZE(o045_mix)),
+       SND_SOC_DAPM_MIXER("O046", SND_SOC_NOPM, 0, 0,
+                          o046_mix, ARRAY_SIZE(o046_mix)),
+       SND_SOC_DAPM_MIXER("O047", SND_SOC_NOPM, 0, 0,
+                          o047_mix, ARRAY_SIZE(o047_mix)),
+};
+
+static const struct snd_soc_dapm_route mt8195_memif_routes[] = {
+       {"I000", NULL, "DL6"},
+       {"I001", NULL, "DL6"},
+
+       {"I020", NULL, "DL3"},
+       {"I021", NULL, "DL3"},
+
+       {"I022", NULL, "DL11"},
+       {"I023", NULL, "DL11"},
+       {"I024", NULL, "DL11"},
+       {"I025", NULL, "DL11"},
+       {"I026", NULL, "DL11"},
+       {"I027", NULL, "DL11"},
+       {"I028", NULL, "DL11"},
+       {"I029", NULL, "DL11"},
+       {"I030", NULL, "DL11"},
+       {"I031", NULL, "DL11"},
+       {"I032", NULL, "DL11"},
+       {"I033", NULL, "DL11"},
+       {"I034", NULL, "DL11"},
+       {"I035", NULL, "DL11"},
+       {"I036", NULL, "DL11"},
+       {"I037", NULL, "DL11"},
+       {"I038", NULL, "DL11"},
+       {"I039", NULL, "DL11"},
+       {"I040", NULL, "DL11"},
+       {"I041", NULL, "DL11"},
+       {"I042", NULL, "DL11"},
+       {"I043", NULL, "DL11"},
+       {"I044", NULL, "DL11"},
+       {"I045", NULL, "DL11"},
+
+       {"DL8_DL11 Mux", "dl8", "DL8"},
+       {"DL8_DL11 Mux", "dl11", "DL11"},
+
+       {"I046", NULL, "DL8_DL11 Mux"},
+       {"I047", NULL, "DL8_DL11 Mux"},
+       {"I048", NULL, "DL8_DL11 Mux"},
+       {"I049", NULL, "DL8_DL11 Mux"},
+       {"I050", NULL, "DL8_DL11 Mux"},
+       {"I051", NULL, "DL8_DL11 Mux"},
+       {"I052", NULL, "DL8_DL11 Mux"},
+       {"I053", NULL, "DL8_DL11 Mux"},
+       {"I054", NULL, "DL8_DL11 Mux"},
+       {"I055", NULL, "DL8_DL11 Mux"},
+       {"I056", NULL, "DL8_DL11 Mux"},
+       {"I057", NULL, "DL8_DL11 Mux"},
+       {"I058", NULL, "DL8_DL11 Mux"},
+       {"I059", NULL, "DL8_DL11 Mux"},
+       {"I060", NULL, "DL8_DL11 Mux"},
+       {"I061", NULL, "DL8_DL11 Mux"},
+       {"I062", NULL, "DL8_DL11 Mux"},
+       {"I063", NULL, "DL8_DL11 Mux"},
+       {"I064", NULL, "DL8_DL11 Mux"},
+       {"I065", NULL, "DL8_DL11 Mux"},
+       {"I066", NULL, "DL8_DL11 Mux"},
+       {"I067", NULL, "DL8_DL11 Mux"},
+       {"I068", NULL, "DL8_DL11 Mux"},
+       {"I069", NULL, "DL8_DL11 Mux"},
+
+       {"I070", NULL, "DL2"},
+       {"I071", NULL, "DL2"},
+
+       {"UL9", NULL, "O002"},
+       {"UL9", NULL, "O003"},
+       {"UL9", NULL, "O004"},
+       {"UL9", NULL, "O005"},
+       {"UL9", NULL, "O006"},
+       {"UL9", NULL, "O007"},
+       {"UL9", NULL, "O008"},
+       {"UL9", NULL, "O009"},
+       {"UL9", NULL, "O010"},
+       {"UL9", NULL, "O011"},
+       {"UL9", NULL, "O012"},
+       {"UL9", NULL, "O013"},
+       {"UL9", NULL, "O014"},
+       {"UL9", NULL, "O015"},
+       {"UL9", NULL, "O016"},
+       {"UL9", NULL, "O017"},
+       {"UL9", NULL, "O018"},
+       {"UL9", NULL, "O019"},
+       {"UL9", NULL, "O020"},
+       {"UL9", NULL, "O021"},
+       {"UL9", NULL, "O022"},
+       {"UL9", NULL, "O023"},
+       {"UL9", NULL, "O024"},
+       {"UL9", NULL, "O025"},
+       {"UL9", NULL, "O026"},
+       {"UL9", NULL, "O027"},
+       {"UL9", NULL, "O028"},
+       {"UL9", NULL, "O029"},
+       {"UL9", NULL, "O030"},
+       {"UL9", NULL, "O031"},
+       {"UL9", NULL, "O032"},
+       {"UL9", NULL, "O033"},
+
+       {"UL4", NULL, "O034"},
+       {"UL4", NULL, "O035"},
+
+       {"UL5", NULL, "O036"},
+       {"UL5", NULL, "O037"},
+
+       {"UL10", NULL, "O038"},
+       {"UL10", NULL, "O039"},
+       {"UL10", NULL, "O182"},
+       {"UL10", NULL, "O183"},
+
+       {"UL2", NULL, "O040"},
+       {"UL2", NULL, "O041"},
+       {"UL2", NULL, "O042"},
+       {"UL2", NULL, "O043"},
+       {"UL2", NULL, "O044"},
+       {"UL2", NULL, "O045"},
+       {"UL2", NULL, "O046"},
+       {"UL2", NULL, "O047"},
+
+       {"O004", "I000 Switch", "I000"},
+       {"O005", "I001 Switch", "I001"},
+
+       {"O006", "I000 Switch", "I000"},
+       {"O007", "I001 Switch", "I001"},
+
+       {"O010", "I022 Switch", "I022"},
+       {"O011", "I023 Switch", "I023"},
+       {"O012", "I024 Switch", "I024"},
+       {"O013", "I025 Switch", "I025"},
+       {"O014", "I026 Switch", "I026"},
+       {"O015", "I027 Switch", "I027"},
+       {"O016", "I028 Switch", "I028"},
+       {"O017", "I029 Switch", "I029"},
+
+       {"O010", "I046 Switch", "I046"},
+       {"O011", "I047 Switch", "I047"},
+       {"O012", "I048 Switch", "I048"},
+       {"O013", "I049 Switch", "I049"},
+       {"O014", "I050 Switch", "I050"},
+       {"O015", "I051 Switch", "I051"},
+       {"O016", "I052 Switch", "I052"},
+       {"O017", "I053 Switch", "I053"},
+       {"O002", "I022 Switch", "I022"},
+       {"O003", "I023 Switch", "I023"},
+       {"O004", "I024 Switch", "I024"},
+       {"O005", "I025 Switch", "I025"},
+       {"O006", "I026 Switch", "I026"},
+       {"O007", "I027 Switch", "I027"},
+       {"O008", "I028 Switch", "I028"},
+       {"O009", "I029 Switch", "I029"},
+       {"O010", "I030 Switch", "I030"},
+       {"O011", "I031 Switch", "I031"},
+       {"O012", "I032 Switch", "I032"},
+       {"O013", "I033 Switch", "I033"},
+       {"O014", "I034 Switch", "I034"},
+       {"O015", "I035 Switch", "I035"},
+       {"O016", "I036 Switch", "I036"},
+       {"O017", "I037 Switch", "I037"},
+       {"O018", "I038 Switch", "I038"},
+       {"O019", "I039 Switch", "I039"},
+       {"O020", "I040 Switch", "I040"},
+       {"O021", "I041 Switch", "I041"},
+       {"O022", "I042 Switch", "I042"},
+       {"O023", "I043 Switch", "I043"},
+       {"O024", "I044 Switch", "I044"},
+       {"O025", "I045 Switch", "I045"},
+       {"O026", "I046 Switch", "I046"},
+       {"O027", "I047 Switch", "I047"},
+       {"O028", "I048 Switch", "I048"},
+       {"O029", "I049 Switch", "I049"},
+       {"O030", "I050 Switch", "I050"},
+       {"O031", "I051 Switch", "I051"},
+       {"O032", "I052 Switch", "I052"},
+       {"O033", "I053 Switch", "I053"},
+
+       {"O002", "I000 Switch", "I000"},
+       {"O003", "I001 Switch", "I001"},
+       {"O002", "I020 Switch", "I020"},
+       {"O003", "I021 Switch", "I021"},
+       {"O002", "I070 Switch", "I070"},
+       {"O003", "I071 Switch", "I071"},
+
+       {"O034", "I000 Switch", "I000"},
+       {"O035", "I001 Switch", "I001"},
+       {"O034", "I002 Switch", "I002"},
+       {"O035", "I003 Switch", "I003"},
+       {"O034", "I012 Switch", "I012"},
+       {"O035", "I013 Switch", "I013"},
+       {"O034", "I020 Switch", "I020"},
+       {"O035", "I021 Switch", "I021"},
+       {"O034", "I070 Switch", "I070"},
+       {"O035", "I071 Switch", "I071"},
+       {"O034", "I072 Switch", "I072"},
+       {"O035", "I073 Switch", "I073"},
+
+       {"O036", "I000 Switch", "I000"},
+       {"O037", "I001 Switch", "I001"},
+       {"O036", "I012 Switch", "I012"},
+       {"O037", "I013 Switch", "I013"},
+       {"O036", "I020 Switch", "I020"},
+       {"O037", "I021 Switch", "I021"},
+       {"O036", "I070 Switch", "I070"},
+       {"O037", "I071 Switch", "I071"},
+       {"O036", "I168 Switch", "I168"},
+       {"O037", "I169 Switch", "I169"},
+
+       {"O038", "I022 Switch", "I022"},
+       {"O039", "I023 Switch", "I023"},
+       {"O182", "I024 Switch", "I024"},
+       {"O183", "I025 Switch", "I025"},
+
+       {"O040", "I022 Switch", "I022"},
+       {"O041", "I023 Switch", "I023"},
+       {"O042", "I024 Switch", "I024"},
+       {"O043", "I025 Switch", "I025"},
+       {"O044", "I026 Switch", "I026"},
+       {"O045", "I027 Switch", "I027"},
+       {"O046", "I028 Switch", "I028"},
+       {"O047", "I029 Switch", "I029"},
+
+       {"O040", "I002 Switch", "I002"},
+       {"O041", "I003 Switch", "I003"},
+       {"O002", "I012 Switch", "I012"},
+       {"O003", "I013 Switch", "I013"},
+       {"O004", "I014 Switch", "I014"},
+       {"O005", "I015 Switch", "I015"},
+       {"O006", "I016 Switch", "I016"},
+       {"O007", "I017 Switch", "I017"},
+       {"O008", "I018 Switch", "I018"},
+       {"O009", "I019 Switch", "I019"},
+
+       {"O040", "I012 Switch", "I012"},
+       {"O041", "I013 Switch", "I013"},
+       {"O042", "I014 Switch", "I014"},
+       {"O043", "I015 Switch", "I015"},
+       {"O044", "I016 Switch", "I016"},
+       {"O045", "I017 Switch", "I017"},
+       {"O046", "I018 Switch", "I018"},
+       {"O047", "I019 Switch", "I019"},
+
+       {"O002", "I072 Switch", "I072"},
+       {"O003", "I073 Switch", "I073"},
+       {"O004", "I074 Switch", "I074"},
+       {"O005", "I075 Switch", "I075"},
+       {"O006", "I076 Switch", "I076"},
+       {"O007", "I077 Switch", "I077"},
+       {"O008", "I078 Switch", "I078"},
+       {"O009", "I079 Switch", "I079"},
+
+       {"O010", "I072 Switch", "I072"},
+       {"O011", "I073 Switch", "I073"},
+       {"O012", "I074 Switch", "I074"},
+       {"O013", "I075 Switch", "I075"},
+       {"O014", "I076 Switch", "I076"},
+       {"O015", "I077 Switch", "I077"},
+       {"O016", "I078 Switch", "I078"},
+       {"O017", "I079 Switch", "I079"},
+       {"O018", "I080 Switch", "I080"},
+       {"O019", "I081 Switch", "I081"},
+       {"O020", "I082 Switch", "I082"},
+       {"O021", "I083 Switch", "I083"},
+       {"O022", "I084 Switch", "I084"},
+       {"O023", "I085 Switch", "I085"},
+       {"O024", "I086 Switch", "I086"},
+       {"O025", "I087 Switch", "I087"},
+       {"O026", "I088 Switch", "I088"},
+       {"O027", "I089 Switch", "I089"},
+       {"O028", "I090 Switch", "I090"},
+       {"O029", "I091 Switch", "I091"},
+       {"O030", "I092 Switch", "I092"},
+       {"O031", "I093 Switch", "I093"},
+       {"O032", "I094 Switch", "I094"},
+       {"O033", "I095 Switch", "I095"},
+
+       {"O002", "I168 Switch", "I168"},
+       {"O003", "I169 Switch", "I169"},
+       {"O004", "I170 Switch", "I170"},
+       {"O005", "I171 Switch", "I171"},
+
+       {"O034", "I168 Switch", "I168"},
+       {"O035", "I168 Switch", "I168"},
+       {"O035", "I169 Switch", "I169"},
+
+       {"O034", "I170 Switch", "I170"},
+       {"O035", "I170 Switch", "I170"},
+       {"O035", "I171 Switch", "I171"},
+
+       {"O040", "I168 Switch", "I168"},
+       {"O041", "I169 Switch", "I169"},
+       {"O042", "I170 Switch", "I170"},
+       {"O043", "I171 Switch", "I171"},
+};
+
+static const char * const mt8195_afe_1x_en_sel_text[] = {
+       "a1sys_a2sys", "a3sys", "a4sys",
+};
+
+static const unsigned int mt8195_afe_1x_en_sel_values[] = {
+       0, 1, 2,
+};
+
+static int mt8195_memif_1x_en_sel_put(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component =
+               snd_soc_kcontrol_component(kcontrol);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_memif_priv *memif_priv;
+       unsigned int dai_id = kcontrol->id.device;
+       long val = ucontrol->value.integer.value[0];
+       int ret = 0;
+
+       memif_priv = afe_priv->dai_priv[dai_id];
+
+       if (val == memif_priv->asys_timing_sel)
+               return 0;
+
+       ret = snd_soc_put_enum_double(kcontrol, ucontrol);
+
+       memif_priv->asys_timing_sel = val;
+
+       return ret;
+}
+
+static int mt8195_asys_irq_1x_en_sel_put(struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component =
+               snd_soc_kcontrol_component(kcontrol);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       unsigned int id = kcontrol->id.device;
+       long val = ucontrol->value.integer.value[0];
+       int ret = 0;
+
+       if (val == afe_priv->irq_priv[id].asys_timing_sel)
+               return 0;
+
+       ret = snd_soc_put_enum_double(kcontrol, ucontrol);
+
+       afe_priv->irq_priv[id].asys_timing_sel = val;
+
+       return ret;
+}
+
+static SOC_VALUE_ENUM_SINGLE_DECL(dl2_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 18, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(dl3_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 20, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(dl6_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 22, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(dl7_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 24, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(dl8_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 26, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(dl10_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 28, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(dl11_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 30, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul1_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 0, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul2_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 2, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul3_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 4, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul4_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 6, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul5_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 8, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul6_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 10, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul8_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 12, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul9_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 14, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul10_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL1, 16, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq1_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 0, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq2_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 2, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq3_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 4, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq4_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 6, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq5_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 8, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq6_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 10, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq7_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 12, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq8_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 14, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq9_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 16, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq10_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 18, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq11_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 20, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq12_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 22, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq13_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 24, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq14_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 26, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq15_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 28, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq16_1x_en_sel_enum,
+                       A3_A4_TIMING_SEL6, 30, 0x3,
+                       mt8195_afe_1x_en_sel_text,
+                       mt8195_afe_1x_en_sel_values);
+
+static const struct snd_kcontrol_new mt8195_memif_controls[] = {
+       MT8195_SOC_ENUM_EXT("dl2_1x_en_sel",
+                           dl2_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_DL2),
+       MT8195_SOC_ENUM_EXT("dl3_1x_en_sel",
+                           dl3_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_DL3),
+       MT8195_SOC_ENUM_EXT("dl6_1x_en_sel",
+                           dl6_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_DL6),
+       MT8195_SOC_ENUM_EXT("dl7_1x_en_sel",
+                           dl7_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_DL7),
+       MT8195_SOC_ENUM_EXT("dl8_1x_en_sel",
+                           dl8_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_DL8),
+       MT8195_SOC_ENUM_EXT("dl10_1x_en_sel",
+                           dl10_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_DL10),
+       MT8195_SOC_ENUM_EXT("dl11_1x_en_sel",
+                           dl11_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_DL11),
+       MT8195_SOC_ENUM_EXT("ul1_1x_en_sel",
+                           ul1_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_UL1),
+       MT8195_SOC_ENUM_EXT("ul2_1x_en_sel",
+                           ul2_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_UL2),
+       MT8195_SOC_ENUM_EXT("ul3_1x_en_sel",
+                           ul3_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_UL3),
+       MT8195_SOC_ENUM_EXT("ul4_1x_en_sel",
+                           ul4_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_UL4),
+       MT8195_SOC_ENUM_EXT("ul5_1x_en_sel",
+                           ul5_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_UL5),
+       MT8195_SOC_ENUM_EXT("ul6_1x_en_sel",
+                           ul6_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_UL6),
+       MT8195_SOC_ENUM_EXT("ul8_1x_en_sel",
+                           ul8_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_UL8),
+       MT8195_SOC_ENUM_EXT("ul9_1x_en_sel",
+                           ul9_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_UL9),
+       MT8195_SOC_ENUM_EXT("ul10_1x_en_sel",
+                           ul10_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_memif_1x_en_sel_put,
+                           MT8195_AFE_MEMIF_UL10),
+       MT8195_SOC_ENUM_EXT("asys_irq1_1x_en_sel",
+                           asys_irq1_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_13),
+       MT8195_SOC_ENUM_EXT("asys_irq2_1x_en_sel",
+                           asys_irq2_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_14),
+       MT8195_SOC_ENUM_EXT("asys_irq3_1x_en_sel",
+                           asys_irq3_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_15),
+       MT8195_SOC_ENUM_EXT("asys_irq4_1x_en_sel",
+                           asys_irq4_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_16),
+       MT8195_SOC_ENUM_EXT("asys_irq5_1x_en_sel",
+                           asys_irq5_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_17),
+       MT8195_SOC_ENUM_EXT("asys_irq6_1x_en_sel",
+                           asys_irq6_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_18),
+       MT8195_SOC_ENUM_EXT("asys_irq7_1x_en_sel",
+                           asys_irq7_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_19),
+       MT8195_SOC_ENUM_EXT("asys_irq8_1x_en_sel",
+                           asys_irq8_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_20),
+       MT8195_SOC_ENUM_EXT("asys_irq9_1x_en_sel",
+                           asys_irq9_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_21),
+       MT8195_SOC_ENUM_EXT("asys_irq10_1x_en_sel",
+                           asys_irq10_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_22),
+       MT8195_SOC_ENUM_EXT("asys_irq11_1x_en_sel",
+                           asys_irq11_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_23),
+       MT8195_SOC_ENUM_EXT("asys_irq12_1x_en_sel",
+                           asys_irq12_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_24),
+       MT8195_SOC_ENUM_EXT("asys_irq13_1x_en_sel",
+                           asys_irq13_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_25),
+       MT8195_SOC_ENUM_EXT("asys_irq14_1x_en_sel",
+                           asys_irq14_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_26),
+       MT8195_SOC_ENUM_EXT("asys_irq15_1x_en_sel",
+                           asys_irq15_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_27),
+       MT8195_SOC_ENUM_EXT("asys_irq16_1x_en_sel",
+                           asys_irq16_1x_en_sel_enum,
+                           snd_soc_get_enum_double,
+                           mt8195_asys_irq_1x_en_sel_put,
+                           MT8195_AFE_IRQ_28),
+};
+
+static const struct snd_soc_component_driver mt8195_afe_pcm_dai_component = {
+       .name = "mt8195-afe-pcm-dai",
+};
+
+static const struct mtk_base_memif_data memif_data[MT8195_AFE_MEMIF_NUM] = {
+       [MT8195_AFE_MEMIF_DL2] = {
+               .name = "DL2",
+               .id = MT8195_AFE_MEMIF_DL2,
+               .reg_ofs_base = AFE_DL2_BASE,
+               .reg_ofs_cur = AFE_DL2_CUR,
+               .reg_ofs_end = AFE_DL2_END,
+               .fs_reg = AFE_MEMIF_AGENT_FS_CON0,
+               .fs_shift = 10,
+               .fs_maskbit = 0x1f,
+               .mono_reg = -1,
+               .mono_shift = 0,
+               .int_odd_flag_reg = -1,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 18,
+               .hd_reg = AFE_DL2_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 18,
+               .ch_num_reg = AFE_DL2_CON0,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0x1f,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 18,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 18,
+       },
+       [MT8195_AFE_MEMIF_DL3] = {
+               .name = "DL3",
+               .id = MT8195_AFE_MEMIF_DL3,
+               .reg_ofs_base = AFE_DL3_BASE,
+               .reg_ofs_cur = AFE_DL3_CUR,
+               .reg_ofs_end = AFE_DL3_END,
+               .fs_reg = AFE_MEMIF_AGENT_FS_CON0,
+               .fs_shift = 15,
+               .fs_maskbit = 0x1f,
+               .mono_reg = -1,
+               .mono_shift = 0,
+               .int_odd_flag_reg = -1,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 19,
+               .hd_reg = AFE_DL3_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 19,
+               .ch_num_reg = AFE_DL3_CON0,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0x1f,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 19,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 19,
+       },
+       [MT8195_AFE_MEMIF_DL6] = {
+               .name = "DL6",
+               .id = MT8195_AFE_MEMIF_DL6,
+               .reg_ofs_base = AFE_DL6_BASE,
+               .reg_ofs_cur = AFE_DL6_CUR,
+               .reg_ofs_end = AFE_DL6_END,
+               .fs_reg = AFE_MEMIF_AGENT_FS_CON1,
+               .fs_shift = 0,
+               .fs_maskbit = 0x1f,
+               .mono_reg = -1,
+               .mono_shift = 0,
+               .int_odd_flag_reg = -1,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 22,
+               .hd_reg = AFE_DL6_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 22,
+               .ch_num_reg = AFE_DL6_CON0,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0x1f,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 22,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 22,
+       },
+       [MT8195_AFE_MEMIF_DL7] = {
+               .name = "DL7",
+               .id = MT8195_AFE_MEMIF_DL7,
+               .reg_ofs_base = AFE_DL7_BASE,
+               .reg_ofs_cur = AFE_DL7_CUR,
+               .reg_ofs_end = AFE_DL7_END,
+               .fs_reg = -1,
+               .fs_shift = 0,
+               .fs_maskbit = 0,
+               .mono_reg = -1,
+               .mono_shift = 0,
+               .int_odd_flag_reg = -1,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 23,
+               .hd_reg = AFE_DL7_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 23,
+               .ch_num_reg = AFE_DL7_CON0,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0x1f,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 23,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 23,
+       },
+       [MT8195_AFE_MEMIF_DL8] = {
+               .name = "DL8",
+               .id = MT8195_AFE_MEMIF_DL8,
+               .reg_ofs_base = AFE_DL8_BASE,
+               .reg_ofs_cur = AFE_DL8_CUR,
+               .reg_ofs_end = AFE_DL8_END,
+               .fs_reg = AFE_MEMIF_AGENT_FS_CON1,
+               .fs_shift = 10,
+               .fs_maskbit = 0x1f,
+               .mono_reg = -1,
+               .mono_shift = 0,
+               .int_odd_flag_reg = -1,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 24,
+               .hd_reg = AFE_DL8_CON0,
+               .hd_shift = 6,
+               .agent_disable_reg = -1,
+               .agent_disable_shift = 0,
+               .ch_num_reg = AFE_DL8_CON0,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0x3f,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 24,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 24,
+       },
+       [MT8195_AFE_MEMIF_DL10] = {
+               .name = "DL10",
+               .id = MT8195_AFE_MEMIF_DL10,
+               .reg_ofs_base = AFE_DL10_BASE,
+               .reg_ofs_cur = AFE_DL10_CUR,
+               .reg_ofs_end = AFE_DL10_END,
+               .fs_reg = AFE_MEMIF_AGENT_FS_CON1,
+               .fs_shift = 20,
+               .fs_maskbit = 0x1f,
+               .mono_reg = -1,
+               .mono_shift = 0,
+               .int_odd_flag_reg = -1,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 26,
+               .hd_reg = AFE_DL10_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = -1,
+               .agent_disable_shift = 0,
+               .ch_num_reg = AFE_DL10_CON0,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0x1f,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 26,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 26,
+       },
+       [MT8195_AFE_MEMIF_DL11] = {
+               .name = "DL11",
+               .id = MT8195_AFE_MEMIF_DL11,
+               .reg_ofs_base = AFE_DL11_BASE,
+               .reg_ofs_cur = AFE_DL11_CUR,
+               .reg_ofs_end = AFE_DL11_END,
+               .fs_reg = AFE_MEMIF_AGENT_FS_CON1,
+               .fs_shift = 25,
+               .fs_maskbit = 0x1f,
+               .mono_reg = -1,
+               .mono_shift = 0,
+               .int_odd_flag_reg = -1,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 27,
+               .hd_reg = AFE_DL11_CON0,
+               .hd_shift = 7,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 27,
+               .ch_num_reg = AFE_DL11_CON0,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0x7f,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 27,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 27,
+       },
+       [MT8195_AFE_MEMIF_UL1] = {
+               .name = "UL1",
+               .id = MT8195_AFE_MEMIF_UL1,
+               .reg_ofs_base = AFE_UL1_BASE,
+               .reg_ofs_cur = AFE_UL1_CUR,
+               .reg_ofs_end = AFE_UL1_END,
+               .fs_reg = -1,
+               .fs_shift = 0,
+               .fs_maskbit = 0,
+               .mono_reg = AFE_UL1_CON0,
+               .mono_shift = 1,
+               .int_odd_flag_reg = AFE_UL1_CON0,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 1,
+               .hd_reg = AFE_UL1_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 0,
+               .ch_num_reg = -1,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 0,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 0,
+       },
+       [MT8195_AFE_MEMIF_UL2] = {
+               .name = "UL2",
+               .id = MT8195_AFE_MEMIF_UL2,
+               .reg_ofs_base = AFE_UL2_BASE,
+               .reg_ofs_cur = AFE_UL2_CUR,
+               .reg_ofs_end = AFE_UL2_END,
+               .fs_reg = AFE_MEMIF_AGENT_FS_CON2,
+               .fs_shift = 5,
+               .fs_maskbit = 0x1f,
+               .mono_reg = AFE_UL2_CON0,
+               .mono_shift = 1,
+               .int_odd_flag_reg = AFE_UL2_CON0,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 2,
+               .hd_reg = AFE_UL2_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 1,
+               .ch_num_reg = -1,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 1,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 1,
+       },
+       [MT8195_AFE_MEMIF_UL3] = {
+               .name = "UL3",
+               .id = MT8195_AFE_MEMIF_UL3,
+               .reg_ofs_base = AFE_UL3_BASE,
+               .reg_ofs_cur = AFE_UL3_CUR,
+               .reg_ofs_end = AFE_UL3_END,
+               .fs_reg = AFE_MEMIF_AGENT_FS_CON2,
+               .fs_shift = 10,
+               .fs_maskbit = 0x1f,
+               .mono_reg = AFE_UL3_CON0,
+               .mono_shift = 1,
+               .int_odd_flag_reg = AFE_UL3_CON0,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 3,
+               .hd_reg = AFE_UL3_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 2,
+               .ch_num_reg = -1,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 2,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 2,
+       },
+       [MT8195_AFE_MEMIF_UL4] = {
+               .name = "UL4",
+               .id = MT8195_AFE_MEMIF_UL4,
+               .reg_ofs_base = AFE_UL4_BASE,
+               .reg_ofs_cur = AFE_UL4_CUR,
+               .reg_ofs_end = AFE_UL4_END,
+               .fs_reg = AFE_MEMIF_AGENT_FS_CON2,
+               .fs_shift = 15,
+               .fs_maskbit = 0x1f,
+               .mono_reg = AFE_UL4_CON0,
+               .mono_shift = 1,
+               .int_odd_flag_reg = AFE_UL4_CON0,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 4,
+               .hd_reg = AFE_UL4_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 3,
+               .ch_num_reg = -1,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 3,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 3,
+       },
+       [MT8195_AFE_MEMIF_UL5] = {
+               .name = "UL5",
+               .id = MT8195_AFE_MEMIF_UL5,
+               .reg_ofs_base = AFE_UL5_BASE,
+               .reg_ofs_cur = AFE_UL5_CUR,
+               .reg_ofs_end = AFE_UL5_END,
+               .fs_reg = AFE_MEMIF_AGENT_FS_CON2,
+               .fs_shift = 20,
+               .fs_maskbit = 0x1f,
+               .mono_reg = AFE_UL5_CON0,
+               .mono_shift = 1,
+               .int_odd_flag_reg = AFE_UL5_CON0,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 5,
+               .hd_reg = AFE_UL5_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 4,
+               .ch_num_reg = -1,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 4,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 4,
+       },
+       [MT8195_AFE_MEMIF_UL6] = {
+               .name = "UL6",
+               .id = MT8195_AFE_MEMIF_UL6,
+               .reg_ofs_base = AFE_UL6_BASE,
+               .reg_ofs_cur = AFE_UL6_CUR,
+               .reg_ofs_end = AFE_UL6_END,
+               .fs_reg = -1,
+               .fs_shift = 0,
+               .fs_maskbit = 0,
+               .mono_reg = AFE_UL6_CON0,
+               .mono_shift = 1,
+               .int_odd_flag_reg = AFE_UL6_CON0,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 6,
+               .hd_reg = AFE_UL6_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 5,
+               .ch_num_reg = -1,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 5,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 5,
+       },
+       [MT8195_AFE_MEMIF_UL8] = {
+               .name = "UL8",
+               .id = MT8195_AFE_MEMIF_UL8,
+               .reg_ofs_base = AFE_UL8_BASE,
+               .reg_ofs_cur = AFE_UL8_CUR,
+               .reg_ofs_end = AFE_UL8_END,
+               .fs_reg = AFE_MEMIF_AGENT_FS_CON3,
+               .fs_shift = 5,
+               .fs_maskbit = 0x1f,
+               .mono_reg = AFE_UL8_CON0,
+               .mono_shift = 1,
+               .int_odd_flag_reg = AFE_UL8_CON0,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 8,
+               .hd_reg = AFE_UL8_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 7,
+               .ch_num_reg = -1,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 7,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 7,
+       },
+       [MT8195_AFE_MEMIF_UL9] = {
+               .name = "UL9",
+               .id = MT8195_AFE_MEMIF_UL9,
+               .reg_ofs_base = AFE_UL9_BASE,
+               .reg_ofs_cur = AFE_UL9_CUR,
+               .reg_ofs_end = AFE_UL9_END,
+               .fs_reg = AFE_MEMIF_AGENT_FS_CON3,
+               .fs_shift = 10,
+               .fs_maskbit = 0x1f,
+               .mono_reg = AFE_UL9_CON0,
+               .mono_shift = 1,
+               .int_odd_flag_reg = AFE_UL9_CON0,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 9,
+               .hd_reg = AFE_UL9_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 8,
+               .ch_num_reg = -1,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 8,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 8,
+       },
+       [MT8195_AFE_MEMIF_UL10] = {
+               .name = "UL10",
+               .id = MT8195_AFE_MEMIF_UL10,
+               .reg_ofs_base = AFE_UL10_BASE,
+               .reg_ofs_cur = AFE_UL10_CUR,
+               .reg_ofs_end = AFE_UL10_END,
+               .fs_reg = AFE_MEMIF_AGENT_FS_CON3,
+               .fs_shift = 15,
+               .fs_maskbit = 0x1f,
+               .mono_reg = AFE_UL10_CON0,
+               .mono_shift = 1,
+               .int_odd_flag_reg = AFE_UL10_CON0,
+               .int_odd_flag_shift = 0,
+               .enable_reg = AFE_DAC_CON0,
+               .enable_shift = 10,
+               .hd_reg = AFE_UL10_CON0,
+               .hd_shift = 5,
+               .agent_disable_reg = AUDIO_TOP_CON5,
+               .agent_disable_shift = 9,
+               .ch_num_reg = -1,
+               .ch_num_shift = 0,
+               .ch_num_maskbit = 0,
+               .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+               .msb_shift = 9,
+               .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+               .msb_end_shift = 9,
+       },
+};
+
+static const struct mtk_base_irq_data irq_data[MT8195_AFE_IRQ_NUM] = {
+       [MT8195_AFE_IRQ_1] = {
+               .id = MT8195_AFE_IRQ_1,
+               .irq_cnt_reg = -1,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0,
+               .irq_fs_reg = -1,
+               .irq_fs_shift = 0,
+               .irq_fs_maskbit = 0,
+               .irq_en_reg = AFE_IRQ1_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg = AFE_IRQ_MCU_CLR,
+               .irq_clr_shift = 0,
+               .irq_status_shift = 16,
+       },
+       [MT8195_AFE_IRQ_2] = {
+               .id = MT8195_AFE_IRQ_2,
+               .irq_cnt_reg = -1,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0,
+               .irq_fs_reg = -1,
+               .irq_fs_shift = 0,
+               .irq_fs_maskbit = 0,
+               .irq_en_reg = AFE_IRQ2_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg = AFE_IRQ_MCU_CLR,
+               .irq_clr_shift = 1,
+               .irq_status_shift = 17,
+       },
+       [MT8195_AFE_IRQ_3] = {
+               .id = MT8195_AFE_IRQ_3,
+               .irq_cnt_reg = AFE_IRQ3_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = -1,
+               .irq_fs_shift = 0,
+               .irq_fs_maskbit = 0,
+               .irq_en_reg = AFE_IRQ3_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg = AFE_IRQ_MCU_CLR,
+               .irq_clr_shift = 2,
+               .irq_status_shift = 18,
+       },
+       [MT8195_AFE_IRQ_8] = {
+               .id = MT8195_AFE_IRQ_8,
+               .irq_cnt_reg = -1,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0,
+               .irq_fs_reg = -1,
+               .irq_fs_shift = 0,
+               .irq_fs_maskbit = 0,
+               .irq_en_reg = AFE_IRQ8_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg = AFE_IRQ_MCU_CLR,
+               .irq_clr_shift = 7,
+               .irq_status_shift = 23,
+       },
+       [MT8195_AFE_IRQ_9] = {
+               .id = MT8195_AFE_IRQ_9,
+               .irq_cnt_reg = AFE_IRQ9_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = -1,
+               .irq_fs_shift = 0,
+               .irq_fs_maskbit = 0,
+               .irq_en_reg = AFE_IRQ9_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg = AFE_IRQ_MCU_CLR,
+               .irq_clr_shift = 8,
+               .irq_status_shift = 24,
+       },
+       [MT8195_AFE_IRQ_10] = {
+               .id = MT8195_AFE_IRQ_10,
+               .irq_cnt_reg = -1,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0,
+               .irq_fs_reg = -1,
+               .irq_fs_shift = 0,
+               .irq_fs_maskbit = 0,
+               .irq_en_reg = AFE_IRQ10_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg = AFE_IRQ_MCU_CLR,
+               .irq_clr_shift = 9,
+               .irq_status_shift = 25,
+       },
+       [MT8195_AFE_IRQ_13] = {
+               .id = MT8195_AFE_IRQ_13,
+               .irq_cnt_reg = ASYS_IRQ1_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ1_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ1_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 0,
+               .irq_status_shift = 0,
+       },
+       [MT8195_AFE_IRQ_14] = {
+               .id = MT8195_AFE_IRQ_14,
+               .irq_cnt_reg = ASYS_IRQ2_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ2_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ2_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 1,
+               .irq_status_shift = 1,
+       },
+       [MT8195_AFE_IRQ_15] = {
+               .id = MT8195_AFE_IRQ_15,
+               .irq_cnt_reg = ASYS_IRQ3_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ3_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ3_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 2,
+               .irq_status_shift = 2,
+       },
+       [MT8195_AFE_IRQ_16] = {
+               .id = MT8195_AFE_IRQ_16,
+               .irq_cnt_reg = ASYS_IRQ4_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ4_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ4_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 3,
+               .irq_status_shift = 3,
+       },
+       [MT8195_AFE_IRQ_17] = {
+               .id = MT8195_AFE_IRQ_17,
+               .irq_cnt_reg = ASYS_IRQ5_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ5_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ5_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 4,
+               .irq_status_shift = 4,
+       },
+       [MT8195_AFE_IRQ_18] = {
+               .id = MT8195_AFE_IRQ_18,
+               .irq_cnt_reg = ASYS_IRQ6_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ6_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ6_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 5,
+               .irq_status_shift = 5,
+       },
+       [MT8195_AFE_IRQ_19] = {
+               .id = MT8195_AFE_IRQ_19,
+               .irq_cnt_reg = ASYS_IRQ7_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ7_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ7_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 6,
+               .irq_status_shift = 6,
+       },
+       [MT8195_AFE_IRQ_20] = {
+               .id = MT8195_AFE_IRQ_20,
+               .irq_cnt_reg = ASYS_IRQ8_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ8_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ8_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 7,
+               .irq_status_shift = 7,
+       },
+       [MT8195_AFE_IRQ_21] = {
+               .id = MT8195_AFE_IRQ_21,
+               .irq_cnt_reg = ASYS_IRQ9_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ9_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ9_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 8,
+               .irq_status_shift = 8,
+       },
+       [MT8195_AFE_IRQ_22] = {
+               .id = MT8195_AFE_IRQ_22,
+               .irq_cnt_reg = ASYS_IRQ10_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ10_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ10_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 9,
+               .irq_status_shift = 9,
+       },
+       [MT8195_AFE_IRQ_23] = {
+               .id = MT8195_AFE_IRQ_23,
+               .irq_cnt_reg = ASYS_IRQ11_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ11_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ11_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 10,
+               .irq_status_shift = 10,
+       },
+       [MT8195_AFE_IRQ_24] = {
+               .id = MT8195_AFE_IRQ_24,
+               .irq_cnt_reg = ASYS_IRQ12_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ12_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ12_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 11,
+               .irq_status_shift = 11,
+       },
+       [MT8195_AFE_IRQ_25] = {
+               .id = MT8195_AFE_IRQ_25,
+               .irq_cnt_reg = ASYS_IRQ13_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ13_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ13_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 12,
+               .irq_status_shift = 12,
+       },
+       [MT8195_AFE_IRQ_26] = {
+               .id = MT8195_AFE_IRQ_26,
+               .irq_cnt_reg = ASYS_IRQ14_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ14_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ14_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 13,
+               .irq_status_shift = 13,
+       },
+       [MT8195_AFE_IRQ_27] = {
+               .id = MT8195_AFE_IRQ_27,
+               .irq_cnt_reg = ASYS_IRQ15_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ15_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ15_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 14,
+               .irq_status_shift = 14,
+       },
+       [MT8195_AFE_IRQ_28] = {
+               .id = MT8195_AFE_IRQ_28,
+               .irq_cnt_reg = ASYS_IRQ16_CON,
+               .irq_cnt_shift = 0,
+               .irq_cnt_maskbit = 0xffffff,
+               .irq_fs_reg = ASYS_IRQ16_CON,
+               .irq_fs_shift = 24,
+               .irq_fs_maskbit = 0x1ffff,
+               .irq_en_reg = ASYS_IRQ16_CON,
+               .irq_en_shift = 31,
+               .irq_clr_reg =  ASYS_IRQ_CLR,
+               .irq_clr_shift = 15,
+               .irq_status_shift = 15,
+       },
+};
+
+static const int mt8195_afe_memif_const_irqs[MT8195_AFE_MEMIF_NUM] = {
+       [MT8195_AFE_MEMIF_DL2] = MT8195_AFE_IRQ_13,
+       [MT8195_AFE_MEMIF_DL3] = MT8195_AFE_IRQ_14,
+       [MT8195_AFE_MEMIF_DL6] = MT8195_AFE_IRQ_15,
+       [MT8195_AFE_MEMIF_DL7] = MT8195_AFE_IRQ_1,
+       [MT8195_AFE_MEMIF_DL8] = MT8195_AFE_IRQ_16,
+       [MT8195_AFE_MEMIF_DL10] = MT8195_AFE_IRQ_17,
+       [MT8195_AFE_MEMIF_DL11] = MT8195_AFE_IRQ_18,
+       [MT8195_AFE_MEMIF_UL1] = MT8195_AFE_IRQ_3,
+       [MT8195_AFE_MEMIF_UL2] = MT8195_AFE_IRQ_19,
+       [MT8195_AFE_MEMIF_UL3] = MT8195_AFE_IRQ_20,
+       [MT8195_AFE_MEMIF_UL4] = MT8195_AFE_IRQ_21,
+       [MT8195_AFE_MEMIF_UL5] = MT8195_AFE_IRQ_22,
+       [MT8195_AFE_MEMIF_UL6] = MT8195_AFE_IRQ_9,
+       [MT8195_AFE_MEMIF_UL8] = MT8195_AFE_IRQ_23,
+       [MT8195_AFE_MEMIF_UL9] = MT8195_AFE_IRQ_24,
+       [MT8195_AFE_MEMIF_UL10] = MT8195_AFE_IRQ_25,
+};
+
+static bool mt8195_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+       /* these auto-gen reg has read-only bit, so put it as volatile */
+       /* volatile reg cannot be cached, so cannot be set when power off */
+       switch (reg) {
+       case AUDIO_TOP_CON0:
+       case AUDIO_TOP_CON1:
+       case AUDIO_TOP_CON3:
+       case AUDIO_TOP_CON4:
+       case AUDIO_TOP_CON5:
+       case AUDIO_TOP_CON6:
+       case ASYS_IRQ_CLR:
+       case ASYS_IRQ_STATUS:
+       case ASYS_IRQ_MON1:
+       case ASYS_IRQ_MON2:
+       case AFE_IRQ_MCU_CLR:
+       case AFE_IRQ_STATUS:
+       case AFE_IRQ3_CON_MON:
+       case AFE_IRQ_MCU_MON2:
+       case ADSP_IRQ_STATUS:
+       case AFE_APLL_TUNER_CFG:
+       case AFE_APLL_TUNER_CFG1:
+       case AUDIO_TOP_STA0:
+       case AUDIO_TOP_STA1:
+       case AFE_GAIN1_CUR:
+       case AFE_GAIN2_CUR:
+       case AFE_IEC_BURST_INFO:
+       case AFE_IEC_CHL_STAT0:
+       case AFE_IEC_CHL_STAT1:
+       case AFE_IEC_CHR_STAT0:
+       case AFE_IEC_CHR_STAT1:
+       case AFE_SPDIFIN_CHSTS1:
+       case AFE_SPDIFIN_CHSTS2:
+       case AFE_SPDIFIN_CHSTS3:
+       case AFE_SPDIFIN_CHSTS4:
+       case AFE_SPDIFIN_CHSTS5:
+       case AFE_SPDIFIN_CHSTS6:
+       case AFE_SPDIFIN_DEBUG1:
+       case AFE_SPDIFIN_DEBUG2:
+       case AFE_SPDIFIN_DEBUG3:
+       case AFE_SPDIFIN_DEBUG4:
+       case AFE_SPDIFIN_EC:
+       case AFE_SPDIFIN_CKLOCK_CFG:
+       case AFE_SPDIFIN_BR_DBG1:
+       case AFE_SPDIFIN_CKFBDIV:
+       case AFE_SPDIFIN_INT_EXT:
+       case AFE_SPDIFIN_INT_EXT2:
+       case SPDIFIN_FREQ_STATUS:
+       case SPDIFIN_USERCODE1:
+       case SPDIFIN_USERCODE2:
+       case SPDIFIN_USERCODE3:
+       case SPDIFIN_USERCODE4:
+       case SPDIFIN_USERCODE5:
+       case SPDIFIN_USERCODE6:
+       case SPDIFIN_USERCODE7:
+       case SPDIFIN_USERCODE8:
+       case SPDIFIN_USERCODE9:
+       case SPDIFIN_USERCODE10:
+       case SPDIFIN_USERCODE11:
+       case SPDIFIN_USERCODE12:
+       case AFE_SPDIFIN_APLL_TUNER_CFG:
+       case AFE_LINEIN_APLL_TUNER_MON:
+       case AFE_EARC_APLL_TUNER_MON:
+       case AFE_CM0_MON:
+       case AFE_CM1_MON:
+       case AFE_CM2_MON:
+       case AFE_MPHONE_MULTI_DET_MON0:
+       case AFE_MPHONE_MULTI_DET_MON1:
+       case AFE_MPHONE_MULTI_DET_MON2:
+       case AFE_MPHONE_MULTI2_DET_MON0:
+       case AFE_MPHONE_MULTI2_DET_MON1:
+       case AFE_MPHONE_MULTI2_DET_MON2:
+       case AFE_ADDA_MTKAIF_MON0:
+       case AFE_ADDA_MTKAIF_MON1:
+       case AFE_AUD_PAD_TOP:
+       case AFE_ADDA6_MTKAIF_MON0:
+       case AFE_ADDA6_MTKAIF_MON1:
+       case AFE_ADDA6_SRC_DEBUG_MON0:
+       case AFE_ADDA6_UL_SRC_MON0:
+       case AFE_ADDA6_UL_SRC_MON1:
+       case AFE_ASRC11_NEW_CON8:
+       case AFE_ASRC11_NEW_CON9:
+       case AFE_ASRC12_NEW_CON8:
+       case AFE_ASRC12_NEW_CON9:
+       case AFE_LRCK_CNT:
+       case AFE_DAC_MON0:
+       case AFE_DL2_CUR:
+       case AFE_DL3_CUR:
+       case AFE_DL6_CUR:
+       case AFE_DL7_CUR:
+       case AFE_DL8_CUR:
+       case AFE_DL10_CUR:
+       case AFE_DL11_CUR:
+       case AFE_UL1_CUR:
+       case AFE_UL2_CUR:
+       case AFE_UL3_CUR:
+       case AFE_UL4_CUR:
+       case AFE_UL5_CUR:
+       case AFE_UL6_CUR:
+       case AFE_UL8_CUR:
+       case AFE_UL9_CUR:
+       case AFE_UL10_CUR:
+       case AFE_DL8_CHK_SUM1:
+       case AFE_DL8_CHK_SUM2:
+       case AFE_DL8_CHK_SUM3:
+       case AFE_DL8_CHK_SUM4:
+       case AFE_DL8_CHK_SUM5:
+       case AFE_DL8_CHK_SUM6:
+       case AFE_DL10_CHK_SUM1:
+       case AFE_DL10_CHK_SUM2:
+       case AFE_DL10_CHK_SUM3:
+       case AFE_DL10_CHK_SUM4:
+       case AFE_DL10_CHK_SUM5:
+       case AFE_DL10_CHK_SUM6:
+       case AFE_DL11_CHK_SUM1:
+       case AFE_DL11_CHK_SUM2:
+       case AFE_DL11_CHK_SUM3:
+       case AFE_DL11_CHK_SUM4:
+       case AFE_DL11_CHK_SUM5:
+       case AFE_DL11_CHK_SUM6:
+       case AFE_UL1_CHK_SUM1:
+       case AFE_UL1_CHK_SUM2:
+       case AFE_UL2_CHK_SUM1:
+       case AFE_UL2_CHK_SUM2:
+       case AFE_UL3_CHK_SUM1:
+       case AFE_UL3_CHK_SUM2:
+       case AFE_UL4_CHK_SUM1:
+       case AFE_UL4_CHK_SUM2:
+       case AFE_UL5_CHK_SUM1:
+       case AFE_UL5_CHK_SUM2:
+       case AFE_UL6_CHK_SUM1:
+       case AFE_UL6_CHK_SUM2:
+       case AFE_UL8_CHK_SUM1:
+       case AFE_UL8_CHK_SUM2:
+       case AFE_DL2_CHK_SUM1:
+       case AFE_DL2_CHK_SUM2:
+       case AFE_DL3_CHK_SUM1:
+       case AFE_DL3_CHK_SUM2:
+       case AFE_DL6_CHK_SUM1:
+       case AFE_DL6_CHK_SUM2:
+       case AFE_DL7_CHK_SUM1:
+       case AFE_DL7_CHK_SUM2:
+       case AFE_UL9_CHK_SUM1:
+       case AFE_UL9_CHK_SUM2:
+       case AFE_BUS_MON1:
+       case UL1_MOD2AGT_CNT_LAT:
+       case UL2_MOD2AGT_CNT_LAT:
+       case UL3_MOD2AGT_CNT_LAT:
+       case UL4_MOD2AGT_CNT_LAT:
+       case UL5_MOD2AGT_CNT_LAT:
+       case UL6_MOD2AGT_CNT_LAT:
+       case UL8_MOD2AGT_CNT_LAT:
+       case UL9_MOD2AGT_CNT_LAT:
+       case UL10_MOD2AGT_CNT_LAT:
+       case AFE_MEMIF_BUF_FULL_MON:
+       case AFE_MEMIF_BUF_MON1:
+       case AFE_MEMIF_BUF_MON3:
+       case AFE_MEMIF_BUF_MON4:
+       case AFE_MEMIF_BUF_MON5:
+       case AFE_MEMIF_BUF_MON6:
+       case AFE_MEMIF_BUF_MON7:
+       case AFE_MEMIF_BUF_MON8:
+       case AFE_MEMIF_BUF_MON9:
+       case AFE_MEMIF_BUF_MON10:
+       case DL2_AGENT2MODULE_CNT:
+       case DL3_AGENT2MODULE_CNT:
+       case DL6_AGENT2MODULE_CNT:
+       case DL7_AGENT2MODULE_CNT:
+       case DL8_AGENT2MODULE_CNT:
+       case DL10_AGENT2MODULE_CNT:
+       case DL11_AGENT2MODULE_CNT:
+       case UL1_MODULE2AGENT_CNT:
+       case UL2_MODULE2AGENT_CNT:
+       case UL3_MODULE2AGENT_CNT:
+       case UL4_MODULE2AGENT_CNT:
+       case UL5_MODULE2AGENT_CNT:
+       case UL6_MODULE2AGENT_CNT:
+       case UL8_MODULE2AGENT_CNT:
+       case UL9_MODULE2AGENT_CNT:
+       case UL10_MODULE2AGENT_CNT:
+       case AFE_DMIC0_SRC_DEBUG_MON0:
+       case AFE_DMIC0_UL_SRC_MON0:
+       case AFE_DMIC0_UL_SRC_MON1:
+       case AFE_DMIC1_SRC_DEBUG_MON0:
+       case AFE_DMIC1_UL_SRC_MON0:
+       case AFE_DMIC1_UL_SRC_MON1:
+       case AFE_DMIC2_SRC_DEBUG_MON0:
+       case AFE_DMIC2_UL_SRC_MON0:
+       case AFE_DMIC2_UL_SRC_MON1:
+       case AFE_DMIC3_SRC_DEBUG_MON0:
+       case AFE_DMIC3_UL_SRC_MON0:
+       case AFE_DMIC3_UL_SRC_MON1:
+       case DMIC_GAIN1_CUR:
+       case DMIC_GAIN2_CUR:
+       case DMIC_GAIN3_CUR:
+       case DMIC_GAIN4_CUR:
+       case ETDM_IN1_MONITOR:
+       case ETDM_IN2_MONITOR:
+       case ETDM_OUT1_MONITOR:
+       case ETDM_OUT2_MONITOR:
+       case ETDM_OUT3_MONITOR:
+       case AFE_ADDA_SRC_DEBUG_MON0:
+       case AFE_ADDA_SRC_DEBUG_MON1:
+       case AFE_ADDA_DL_SDM_FIFO_MON:
+       case AFE_ADDA_DL_SRC_LCH_MON:
+       case AFE_ADDA_DL_SRC_RCH_MON:
+       case AFE_ADDA_DL_SDM_OUT_MON:
+       case AFE_GASRC0_NEW_CON8:
+       case AFE_GASRC0_NEW_CON9:
+       case AFE_GASRC0_NEW_CON12:
+       case AFE_GASRC1_NEW_CON8:
+       case AFE_GASRC1_NEW_CON9:
+       case AFE_GASRC1_NEW_CON12:
+       case AFE_GASRC2_NEW_CON8:
+       case AFE_GASRC2_NEW_CON9:
+       case AFE_GASRC2_NEW_CON12:
+       case AFE_GASRC3_NEW_CON8:
+       case AFE_GASRC3_NEW_CON9:
+       case AFE_GASRC3_NEW_CON12:
+       case AFE_GASRC4_NEW_CON8:
+       case AFE_GASRC4_NEW_CON9:
+       case AFE_GASRC4_NEW_CON12:
+       case AFE_GASRC5_NEW_CON8:
+       case AFE_GASRC5_NEW_CON9:
+       case AFE_GASRC5_NEW_CON12:
+       case AFE_GASRC6_NEW_CON8:
+       case AFE_GASRC6_NEW_CON9:
+       case AFE_GASRC6_NEW_CON12:
+       case AFE_GASRC7_NEW_CON8:
+       case AFE_GASRC7_NEW_CON9:
+       case AFE_GASRC7_NEW_CON12:
+       case AFE_GASRC8_NEW_CON8:
+       case AFE_GASRC8_NEW_CON9:
+       case AFE_GASRC8_NEW_CON12:
+       case AFE_GASRC9_NEW_CON8:
+       case AFE_GASRC9_NEW_CON9:
+       case AFE_GASRC9_NEW_CON12:
+       case AFE_GASRC10_NEW_CON8:
+       case AFE_GASRC10_NEW_CON9:
+       case AFE_GASRC10_NEW_CON12:
+       case AFE_GASRC11_NEW_CON8:
+       case AFE_GASRC11_NEW_CON9:
+       case AFE_GASRC11_NEW_CON12:
+       case AFE_GASRC12_NEW_CON8:
+       case AFE_GASRC12_NEW_CON9:
+       case AFE_GASRC12_NEW_CON12:
+       case AFE_GASRC13_NEW_CON8:
+       case AFE_GASRC13_NEW_CON9:
+       case AFE_GASRC13_NEW_CON12:
+       case AFE_GASRC14_NEW_CON8:
+       case AFE_GASRC14_NEW_CON9:
+       case AFE_GASRC14_NEW_CON12:
+       case AFE_GASRC15_NEW_CON8:
+       case AFE_GASRC15_NEW_CON9:
+       case AFE_GASRC15_NEW_CON12:
+       case AFE_GASRC16_NEW_CON8:
+       case AFE_GASRC16_NEW_CON9:
+       case AFE_GASRC16_NEW_CON12:
+       case AFE_GASRC17_NEW_CON8:
+       case AFE_GASRC17_NEW_CON9:
+       case AFE_GASRC17_NEW_CON12:
+       case AFE_GASRC18_NEW_CON8:
+       case AFE_GASRC18_NEW_CON9:
+       case AFE_GASRC18_NEW_CON12:
+       case AFE_GASRC19_NEW_CON8:
+       case AFE_GASRC19_NEW_CON9:
+       case AFE_GASRC19_NEW_CON12:
+               return true;
+       default:
+               return false;
+       };
+}
+
+static const struct regmap_config mt8195_afe_regmap_config = {
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .volatile_reg = mt8195_is_volatile_reg,
+       .max_register = AFE_MAX_REGISTER,
+       .num_reg_defaults_raw = ((AFE_MAX_REGISTER / 4) + 1),
+       .cache_type = REGCACHE_FLAT,
+};
+
+#define AFE_IRQ_CLR_BITS (0x387)
+#define ASYS_IRQ_CLR_BITS (0xffff)
+
+static irqreturn_t mt8195_afe_irq_handler(int irq_id, void *dev_id)
+{
+       struct mtk_base_afe *afe = dev_id;
+       unsigned int val = 0;
+       unsigned int asys_irq_clr_bits = 0;
+       unsigned int afe_irq_clr_bits = 0;
+       unsigned int irq_status_bits = 0;
+       unsigned int irq_clr_bits = 0;
+       unsigned int mcu_irq_mask = 0;
+       int i = 0;
+       int ret = 0;
+
+       ret = regmap_read(afe->regmap, AFE_IRQ_STATUS, &val);
+       if (ret) {
+               dev_info(afe->dev, "%s irq status err\n", __func__);
+               afe_irq_clr_bits = AFE_IRQ_CLR_BITS;
+               asys_irq_clr_bits = ASYS_IRQ_CLR_BITS;
+               goto err_irq;
+       }
+
+       ret = regmap_read(afe->regmap, AFE_IRQ_MASK, &mcu_irq_mask);
+       if (ret) {
+               dev_info(afe->dev, "%s read irq mask err\n", __func__);
+               afe_irq_clr_bits = AFE_IRQ_CLR_BITS;
+               asys_irq_clr_bits = ASYS_IRQ_CLR_BITS;
+               goto err_irq;
+       }
+
+       /* only clr cpu irq */
+       val &= mcu_irq_mask;
+
+       for (i = 0; i < MT8195_AFE_MEMIF_NUM; i++) {
+               struct mtk_base_afe_memif *memif = &afe->memif[i];
+               struct mtk_base_irq_data const *irq_data;
+
+               if (memif->irq_usage < 0)
+                       continue;
+
+               irq_data = afe->irqs[memif->irq_usage].irq_data;
+
+               irq_status_bits = BIT(irq_data->irq_status_shift);
+               irq_clr_bits = BIT(irq_data->irq_clr_shift);
+
+               if (!(val & irq_status_bits))
+                       continue;
+
+               if (irq_data->irq_clr_reg == ASYS_IRQ_CLR)
+                       asys_irq_clr_bits |= irq_clr_bits;
+               else
+                       afe_irq_clr_bits |= irq_clr_bits;
+
+               snd_pcm_period_elapsed(memif->substream);
+       }
+
+err_irq:
+       /* clear irq */
+       if (asys_irq_clr_bits)
+               regmap_write(afe->regmap, ASYS_IRQ_CLR, asys_irq_clr_bits);
+       if (afe_irq_clr_bits)
+               regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, afe_irq_clr_bits);
+
+       return IRQ_HANDLED;
+}
+
+static int mt8195_afe_runtime_suspend(struct device *dev)
+{
+       struct mtk_base_afe *afe = dev_get_drvdata(dev);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+
+       if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl)
+               goto skip_regmap;
+
+       mt8195_afe_disable_main_clock(afe);
+
+       regcache_cache_only(afe->regmap, true);
+       regcache_mark_dirty(afe->regmap);
+
+skip_regmap:
+       mt8195_afe_disable_reg_rw_clk(afe);
+
+       return 0;
+}
+
+static int mt8195_afe_runtime_resume(struct device *dev)
+{
+       struct mtk_base_afe *afe = dev_get_drvdata(dev);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+
+       mt8195_afe_enable_reg_rw_clk(afe);
+
+       if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl)
+               goto skip_regmap;
+
+       regcache_cache_only(afe->regmap, false);
+       regcache_sync(afe->regmap);
+
+       mt8195_afe_enable_main_clock(afe);
+skip_regmap:
+       return 0;
+}
+
+static int mt8195_afe_component_probe(struct snd_soc_component *component)
+{
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+       int ret = 0;
+
+       snd_soc_component_init_regmap(component, afe->regmap);
+
+       ret = mtk_afe_add_sub_dai_control(component);
+
+       return ret;
+}
+
+static const struct snd_soc_component_driver mt8195_afe_component = {
+       .name = AFE_PCM_NAME,
+       .pointer = mtk_afe_pcm_pointer,
+       .pcm_construct = mtk_afe_pcm_new,
+       .probe = mt8195_afe_component_probe,
+};
+
+static int init_memif_priv_data(struct mtk_base_afe *afe)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_memif_priv *memif_priv;
+       int i;
+
+       for (i = MT8195_AFE_MEMIF_START; i < MT8195_AFE_MEMIF_END; i++) {
+               memif_priv = devm_kzalloc(afe->dev,
+                                         sizeof(struct mtk_dai_memif_priv),
+                                         GFP_KERNEL);
+               if (!memif_priv)
+                       return -ENOMEM;
+
+               afe_priv->dai_priv[i] = memif_priv;
+       }
+
+       return 0;
+}
+
+static int mt8195_dai_memif_register(struct mtk_base_afe *afe)
+{
+       struct mtk_base_afe_dai *dai;
+
+       dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+       if (!dai)
+               return -ENOMEM;
+
+       list_add(&dai->list, &afe->sub_dais);
+
+       dai->dai_drivers = mt8195_memif_dai_driver;
+       dai->num_dai_drivers = ARRAY_SIZE(mt8195_memif_dai_driver);
+
+       dai->dapm_widgets = mt8195_memif_widgets;
+       dai->num_dapm_widgets = ARRAY_SIZE(mt8195_memif_widgets);
+       dai->dapm_routes = mt8195_memif_routes;
+       dai->num_dapm_routes = ARRAY_SIZE(mt8195_memif_routes);
+       dai->controls = mt8195_memif_controls;
+       dai->num_controls = ARRAY_SIZE(mt8195_memif_controls);
+
+       return init_memif_priv_data(afe);
+}
+
+typedef int (*dai_register_cb)(struct mtk_base_afe *);
+static const dai_register_cb dai_register_cbs[] = {
+       mt8195_dai_adda_register,
+       mt8195_dai_etdm_register,
+       mt8195_dai_pcm_register,
+       mt8195_dai_memif_register,
+};
+
+static const struct reg_sequence mt8195_afe_reg_defaults[] = {
+       { AFE_IRQ_MASK, 0x387ffff },
+       { AFE_IRQ3_CON, BIT(30) },
+       { AFE_IRQ9_CON, BIT(30) },
+       { ETDM_IN1_CON4, 0x12000100 },
+       { ETDM_IN2_CON4, 0x12000100 },
+};
+
+static const struct reg_sequence mt8195_cg_patch[] = {
+       { AUDIO_TOP_CON0, 0xfffffffb },
+       { AUDIO_TOP_CON1, 0xfffffffa },
+};
+
+static int mt8195_afe_init_registers(struct mtk_base_afe *afe)
+{
+       return regmap_multi_reg_write(afe->regmap,
+                       mt8195_afe_reg_defaults,
+                       ARRAY_SIZE(mt8195_afe_reg_defaults));
+}
+
+static void mt8195_afe_parse_of(struct mtk_base_afe *afe,
+                               struct device_node *np)
+{
+#if IS_ENABLED(CONFIG_SND_SOC_MT6359)
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+
+       afe_priv->topckgen = syscon_regmap_lookup_by_phandle(afe->dev->of_node,
+                                                            "mediatek,topckgen");
+       if (IS_ERR(afe_priv->topckgen)) {
+               dev_info(afe->dev, "%s() Cannot find topckgen controller: %ld\n",
+                        __func__, PTR_ERR(afe_priv->topckgen));
+       }
+#endif
+}
+
+static int mt8195_afe_pcm_dev_probe(struct platform_device *pdev)
+{
+       struct mtk_base_afe *afe;
+       struct mt8195_afe_private *afe_priv;
+       struct resource *res;
+       struct device *dev = &pdev->dev;
+       int i, irq_id, ret;
+       struct snd_soc_component *component;
+
+       ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(33));
+       if (ret)
+               return ret;
+
+       afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL);
+       if (!afe)
+               return -ENOMEM;
+
+       afe->platform_priv = devm_kzalloc(dev, sizeof(*afe_priv),
+                                         GFP_KERNEL);
+       if (!afe->platform_priv)
+               return -ENOMEM;
+
+       afe_priv = afe->platform_priv;
+       afe->dev = &pdev->dev;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       afe->base_addr = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(afe->base_addr))
+               return PTR_ERR(afe->base_addr);
+
+       /* initial audio related clock */
+       ret = mt8195_afe_init_clock(afe);
+       if (ret) {
+               dev_err(dev, "init clock error\n");
+               return ret;
+       }
+
+       spin_lock_init(&afe_priv->afe_ctrl_lock);
+
+       mutex_init(&afe->irq_alloc_lock);
+
+       /* irq initialize */
+       afe->irqs_size = MT8195_AFE_IRQ_NUM;
+       afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
+                                GFP_KERNEL);
+       if (!afe->irqs)
+               return -ENOMEM;
+
+       for (i = 0; i < afe->irqs_size; i++)
+               afe->irqs[i].irq_data = &irq_data[i];
+
+       /* init memif */
+       afe->memif_size = MT8195_AFE_MEMIF_NUM;
+       afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
+                                 GFP_KERNEL);
+       if (!afe->memif)
+               return -ENOMEM;
+
+       for (i = 0; i < afe->memif_size; i++) {
+               afe->memif[i].data = &memif_data[i];
+               afe->memif[i].irq_usage = mt8195_afe_memif_const_irqs[i];
+               afe->memif[i].const_irq = 1;
+               afe->irqs[afe->memif[i].irq_usage].irq_occupyed = true;
+       }
+
+       /* request irq */
+       irq_id = platform_get_irq(pdev, 0);
+       if (irq_id < 0) {
+               dev_err(dev, "%s no irq found\n", dev->of_node->name);
+               return -ENXIO;
+       }
+
+       ret = devm_request_irq(dev, irq_id, mt8195_afe_irq_handler,
+                              IRQF_TRIGGER_NONE, "asys-isr", (void *)afe);
+       if (ret) {
+               dev_err(dev, "could not request_irq for asys-isr\n");
+               return ret;
+       }
+
+       /* init sub_dais */
+       INIT_LIST_HEAD(&afe->sub_dais);
+
+       for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) {
+               ret = dai_register_cbs[i](afe);
+               if (ret) {
+                       dev_warn(dev, "dai register i %d fail, ret %d\n",
+                                i, ret);
+                       return ret;
+               }
+       }
+
+       /* init dai_driver and component_driver */
+       ret = mtk_afe_combine_sub_dai(afe);
+       if (ret) {
+               dev_warn(dev, "mtk_afe_combine_sub_dai fail, ret %d\n",
+                        ret);
+               return ret;
+       }
+
+       afe->mtk_afe_hardware = &mt8195_afe_hardware;
+       afe->memif_fs = mt8195_memif_fs;
+       afe->irq_fs = mt8195_irq_fs;
+
+       afe->runtime_resume = mt8195_afe_runtime_resume;
+       afe->runtime_suspend = mt8195_afe_runtime_suspend;
+
+       platform_set_drvdata(pdev, afe);
+
+       mt8195_afe_parse_of(afe, pdev->dev.of_node);
+
+       pm_runtime_enable(dev);
+       if (!pm_runtime_enabled(dev)) {
+               ret = mt8195_afe_runtime_resume(dev);
+               if (ret)
+                       return ret;
+       }
+
+       /* enable clock for regcache get default value from hw */
+       afe_priv->pm_runtime_bypass_reg_ctl = true;
+       pm_runtime_get_sync(dev);
+
+       afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr,
+                                           &mt8195_afe_regmap_config);
+       if (IS_ERR(afe->regmap)) {
+               ret = PTR_ERR(afe->regmap);
+               goto err_pm_put;
+       }
+
+       ret = regmap_register_patch(afe->regmap, mt8195_cg_patch,
+                                   ARRAY_SIZE(mt8195_cg_patch));
+       if (ret < 0) {
+               dev_err(dev, "Failed to apply cg patch\n");
+               goto err_pm_put;
+       }
+
+       /* register component */
+       ret = devm_snd_soc_register_component(dev, &mt8195_afe_component,
+                                             NULL, 0);
+       if (ret) {
+               dev_warn(dev, "err_platform\n");
+               goto err_pm_put;
+       }
+
+       component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL);
+       if (!component) {
+               ret = -ENOMEM;
+               goto err_pm_put;
+       }
+
+       ret = snd_soc_component_initialize(component,
+                                          &mt8195_afe_pcm_dai_component,
+                                          dev);
+       if (ret)
+               goto err_pm_put;
+
+#ifdef CONFIG_DEBUG_FS
+       component->debugfs_prefix = "pcm";
+#endif
+
+       ret = snd_soc_add_component(component,
+                                   afe->dai_drivers,
+                                   afe->num_dai_drivers);
+       if (ret) {
+               dev_warn(dev, "err_dai_component\n");
+               goto err_pm_put;
+       }
+
+       mt8195_afe_init_registers(afe);
+
+       pm_runtime_put_sync(dev);
+       afe_priv->pm_runtime_bypass_reg_ctl = false;
+
+       regcache_cache_only(afe->regmap, true);
+       regcache_mark_dirty(afe->regmap);
+
+       return 0;
+
+err_pm_put:
+       pm_runtime_put_sync(dev);
+       pm_runtime_disable(dev);
+
+       return ret;
+}
+
+static int mt8195_afe_pcm_dev_remove(struct platform_device *pdev)
+{
+       struct mtk_base_afe *afe = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_component(&pdev->dev);
+
+       pm_runtime_disable(&pdev->dev);
+       if (!pm_runtime_status_suspended(&pdev->dev))
+               mt8195_afe_runtime_suspend(&pdev->dev);
+
+       mt8195_afe_deinit_clock(afe);
+       return 0;
+}
+
+static const struct of_device_id mt8195_afe_pcm_dt_match[] = {
+       {.compatible = "mediatek,mt8195-audio", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, mt8195_afe_pcm_dt_match);
+
+static const struct dev_pm_ops mt8195_afe_pm_ops = {
+       SET_RUNTIME_PM_OPS(mt8195_afe_runtime_suspend,
+                          mt8195_afe_runtime_resume, NULL)
+};
+
+static struct platform_driver mt8195_afe_pcm_driver = {
+       .driver = {
+                  .name = "mt8195-audio",
+                  .of_match_table = mt8195_afe_pcm_dt_match,
+#ifdef CONFIG_PM
+                  .pm = &mt8195_afe_pm_ops,
+#endif
+       },
+       .probe = mt8195_afe_pcm_dev_probe,
+       .remove = mt8195_afe_pcm_dev_remove,
+};
+
+module_platform_driver(mt8195_afe_pcm_driver);
+
+MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 8195");
+MODULE_AUTHOR("Bicycle Tsai <bicycle.tsai@mediatek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/mediatek/mt8195/mt8195-audsys-clk.c b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.c
new file mode 100644 (file)
index 0000000..740aa6d
--- /dev/null
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mt8195-audsys-clk.h  --  Mediatek 8195 audsys clock control
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include "mt8195-afe-common.h"
+#include "mt8195-audsys-clk.h"
+#include "mt8195-audsys-clkid.h"
+#include "mt8195-reg.h"
+
+struct afe_gate {
+       int id;
+       const char *name;
+       const char *parent_name;
+       int reg;
+       u8 bit;
+       const struct clk_ops *ops;
+       unsigned long flags;
+       u8 cg_flags;
+};
+
+#define GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit, _flags, _cgflags) {\
+               .id = _id,                                      \
+               .name = _name,                                  \
+               .parent_name = _parent,                         \
+               .reg = _reg,                                    \
+               .bit = _bit,                                    \
+               .flags = _flags,                                \
+               .cg_flags = _cgflags,                           \
+       }
+
+#define GATE_AFE(_id, _name, _parent, _reg, _bit)              \
+       GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit,         \
+                      CLK_SET_RATE_PARENT, CLK_GATE_SET_TO_DISABLE)
+
+#define GATE_AUD0(_id, _name, _parent, _bit)                   \
+       GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON0, _bit)
+
+#define GATE_AUD1(_id, _name, _parent, _bit)                   \
+       GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON1, _bit)
+
+#define GATE_AUD3(_id, _name, _parent, _bit)                   \
+       GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON3, _bit)
+
+#define GATE_AUD4(_id, _name, _parent, _bit)                   \
+       GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON4, _bit)
+
+#define GATE_AUD5(_id, _name, _parent, _bit)                   \
+       GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON5, _bit)
+
+#define GATE_AUD6(_id, _name, _parent, _bit)                   \
+       GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON6, _bit)
+
+static const struct afe_gate aud_clks[CLK_AUD_NR_CLK] = {
+       /* AUD0 */
+       GATE_AUD0(CLK_AUD_AFE, "aud_afe", "a1sys_hp_sel", 2),
+       GATE_AUD0(CLK_AUD_LRCK_CNT, "aud_lrck_cnt", "a1sys_hp_sel", 4),
+       GATE_AUD0(CLK_AUD_SPDIFIN_TUNER_APLL, "aud_spdifin_tuner_apll", "apll4_sel", 10),
+       GATE_AUD0(CLK_AUD_SPDIFIN_TUNER_DBG, "aud_spdifin_tuner_dbg", "apll4_sel", 11),
+       GATE_AUD0(CLK_AUD_UL_TML, "aud_ul_tml", "a1sys_hp_sel", 18),
+       GATE_AUD0(CLK_AUD_APLL1_TUNER, "aud_apll1_tuner", "apll1_sel", 19),
+       GATE_AUD0(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner", "apll2_sel", 20),
+       GATE_AUD0(CLK_AUD_TOP0_SPDF, "aud_top0_spdf", "aud_iec_sel", 21),
+       GATE_AUD0(CLK_AUD_APLL, "aud_apll", "apll1_sel", 23),
+       GATE_AUD0(CLK_AUD_APLL2, "aud_apll2", "apll2_sel", 24),
+       GATE_AUD0(CLK_AUD_DAC, "aud_dac", "a1sys_hp_sel", 25),
+       GATE_AUD0(CLK_AUD_DAC_PREDIS, "aud_dac_predis", "a1sys_hp_sel", 26),
+       GATE_AUD0(CLK_AUD_TML, "aud_tml", "a1sys_hp_sel", 27),
+       GATE_AUD0(CLK_AUD_ADC, "aud_adc", "a1sys_hp_sel", 28),
+       GATE_AUD0(CLK_AUD_DAC_HIRES, "aud_dac_hires", "audio_h_sel", 31),
+
+       /* AUD1 */
+       GATE_AUD1(CLK_AUD_A1SYS_HP, "aud_a1sys_hp", "a1sys_hp_sel", 2),
+       GATE_AUD1(CLK_AUD_AFE_DMIC1, "aud_afe_dmic1", "a1sys_hp_sel", 10),
+       GATE_AUD1(CLK_AUD_AFE_DMIC2, "aud_afe_dmic2", "a1sys_hp_sel", 11),
+       GATE_AUD1(CLK_AUD_AFE_DMIC3, "aud_afe_dmic3", "a1sys_hp_sel", 12),
+       GATE_AUD1(CLK_AUD_AFE_DMIC4, "aud_afe_dmic4", "a1sys_hp_sel", 13),
+       GATE_AUD1(CLK_AUD_AFE_26M_DMIC_TM, "aud_afe_26m_dmic_tm", "a1sys_hp_sel", 14),
+       GATE_AUD1(CLK_AUD_UL_TML_HIRES, "aud_ul_tml_hires", "audio_h_sel", 16),
+       GATE_AUD1(CLK_AUD_ADC_HIRES, "aud_adc_hires", "audio_h_sel", 17),
+       GATE_AUD1(CLK_AUD_ADDA6_ADC, "aud_adda6_adc", "a1sys_hp_sel", 18),
+       GATE_AUD1(CLK_AUD_ADDA6_ADC_HIRES, "aud_adda6_adc_hires", "audio_h_sel", 19),
+
+       /* AUD3 */
+       GATE_AUD3(CLK_AUD_LINEIN_TUNER, "aud_linein_tuner", "apll5_sel", 5),
+       GATE_AUD3(CLK_AUD_EARC_TUNER, "aud_earc_tuner", "apll3_sel", 7),
+
+       /* AUD4 */
+       GATE_AUD4(CLK_AUD_I2SIN, "aud_i2sin", "a1sys_hp_sel", 0),
+       GATE_AUD4(CLK_AUD_TDM_IN, "aud_tdm_in", "a1sys_hp_sel", 1),
+       GATE_AUD4(CLK_AUD_I2S_OUT, "aud_i2s_out", "a1sys_hp_sel", 6),
+       GATE_AUD4(CLK_AUD_TDM_OUT, "aud_tdm_out", "a1sys_hp_sel", 7),
+       GATE_AUD4(CLK_AUD_HDMI_OUT, "aud_hdmi_out", "a1sys_hp_sel", 8),
+       GATE_AUD4(CLK_AUD_ASRC11, "aud_asrc11", "a1sys_hp_sel", 16),
+       GATE_AUD4(CLK_AUD_ASRC12, "aud_asrc12", "a1sys_hp_sel", 17),
+       GATE_AUD4(CLK_AUD_MULTI_IN, "aud_multi_in", "mphone_slave_b", 19),
+       GATE_AUD4(CLK_AUD_INTDIR, "aud_intdir", "intdir_sel", 20),
+       GATE_AUD4(CLK_AUD_A1SYS, "aud_a1sys", "a1sys_hp_sel", 21),
+       GATE_AUD4(CLK_AUD_A2SYS, "aud_a2sys", "a2sys_sel", 22),
+       GATE_AUD4(CLK_AUD_PCMIF, "aud_pcmif", "a1sys_hp_sel", 24),
+       GATE_AUD4(CLK_AUD_A3SYS, "aud_a3sys", "a3sys_sel", 30),
+       GATE_AUD4(CLK_AUD_A4SYS, "aud_a4sys", "a4sys_sel", 31),
+
+       /* AUD5 */
+       GATE_AUD5(CLK_AUD_MEMIF_UL1, "aud_memif_ul1", "a1sys_hp_sel", 0),
+       GATE_AUD5(CLK_AUD_MEMIF_UL2, "aud_memif_ul2", "a1sys_hp_sel", 1),
+       GATE_AUD5(CLK_AUD_MEMIF_UL3, "aud_memif_ul3", "a1sys_hp_sel", 2),
+       GATE_AUD5(CLK_AUD_MEMIF_UL4, "aud_memif_ul4", "a1sys_hp_sel", 3),
+       GATE_AUD5(CLK_AUD_MEMIF_UL5, "aud_memif_ul5", "a1sys_hp_sel", 4),
+       GATE_AUD5(CLK_AUD_MEMIF_UL6, "aud_memif_ul6", "a1sys_hp_sel", 5),
+       GATE_AUD5(CLK_AUD_MEMIF_UL8, "aud_memif_ul8", "a1sys_hp_sel", 7),
+       GATE_AUD5(CLK_AUD_MEMIF_UL9, "aud_memif_ul9", "a1sys_hp_sel", 8),
+       GATE_AUD5(CLK_AUD_MEMIF_UL10, "aud_memif_ul10", "a1sys_hp_sel", 9),
+       GATE_AUD5(CLK_AUD_MEMIF_DL2, "aud_memif_dl2", "a1sys_hp_sel", 18),
+       GATE_AUD5(CLK_AUD_MEMIF_DL3, "aud_memif_dl3", "a1sys_hp_sel", 19),
+       GATE_AUD5(CLK_AUD_MEMIF_DL6, "aud_memif_dl6", "a1sys_hp_sel", 22),
+       GATE_AUD5(CLK_AUD_MEMIF_DL7, "aud_memif_dl7", "a1sys_hp_sel", 23),
+       GATE_AUD5(CLK_AUD_MEMIF_DL8, "aud_memif_dl8", "a1sys_hp_sel", 24),
+       GATE_AUD5(CLK_AUD_MEMIF_DL10, "aud_memif_dl10", "a1sys_hp_sel", 26),
+       GATE_AUD5(CLK_AUD_MEMIF_DL11, "aud_memif_dl11", "a1sys_hp_sel", 27),
+
+       /* AUD6 */
+       GATE_AUD6(CLK_AUD_GASRC0, "aud_gasrc0", "asm_h_sel", 0),
+       GATE_AUD6(CLK_AUD_GASRC1, "aud_gasrc1", "asm_h_sel", 1),
+       GATE_AUD6(CLK_AUD_GASRC2, "aud_gasrc2", "asm_h_sel", 2),
+       GATE_AUD6(CLK_AUD_GASRC3, "aud_gasrc3", "asm_h_sel", 3),
+       GATE_AUD6(CLK_AUD_GASRC4, "aud_gasrc4", "asm_h_sel", 4),
+       GATE_AUD6(CLK_AUD_GASRC5, "aud_gasrc5", "asm_h_sel", 5),
+       GATE_AUD6(CLK_AUD_GASRC6, "aud_gasrc6", "asm_h_sel", 6),
+       GATE_AUD6(CLK_AUD_GASRC7, "aud_gasrc7", "asm_h_sel", 7),
+       GATE_AUD6(CLK_AUD_GASRC8, "aud_gasrc8", "asm_h_sel", 8),
+       GATE_AUD6(CLK_AUD_GASRC9, "aud_gasrc9", "asm_h_sel", 9),
+       GATE_AUD6(CLK_AUD_GASRC10, "aud_gasrc10", "asm_h_sel", 10),
+       GATE_AUD6(CLK_AUD_GASRC11, "aud_gasrc11", "asm_h_sel", 11),
+       GATE_AUD6(CLK_AUD_GASRC12, "aud_gasrc12", "asm_h_sel", 12),
+       GATE_AUD6(CLK_AUD_GASRC13, "aud_gasrc13", "asm_h_sel", 13),
+       GATE_AUD6(CLK_AUD_GASRC14, "aud_gasrc14", "asm_h_sel", 14),
+       GATE_AUD6(CLK_AUD_GASRC15, "aud_gasrc15", "asm_h_sel", 15),
+       GATE_AUD6(CLK_AUD_GASRC16, "aud_gasrc16", "asm_h_sel", 16),
+       GATE_AUD6(CLK_AUD_GASRC17, "aud_gasrc17", "asm_h_sel", 17),
+       GATE_AUD6(CLK_AUD_GASRC18, "aud_gasrc18", "asm_h_sel", 18),
+       GATE_AUD6(CLK_AUD_GASRC19, "aud_gasrc19", "asm_h_sel", 19),
+};
+
+int mt8195_audsys_clk_register(struct mtk_base_afe *afe)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct clk *clk;
+       struct clk_lookup *cl;
+       int i;
+
+       afe_priv->lookup = devm_kcalloc(afe->dev, CLK_AUD_NR_CLK,
+                                       sizeof(*afe_priv->lookup),
+                                       GFP_KERNEL);
+
+       if (!afe_priv->lookup)
+               return -ENOMEM;
+
+       for (i = 0; i < ARRAY_SIZE(aud_clks); i++) {
+               const struct afe_gate *gate = &aud_clks[i];
+
+               clk = clk_register_gate(afe->dev, gate->name, gate->parent_name,
+                                       gate->flags, afe->base_addr + gate->reg,
+                                       gate->bit, gate->cg_flags, NULL);
+
+               if (IS_ERR(clk)) {
+                       dev_err(afe->dev, "Failed to register clk %s: %ld\n",
+                               gate->name, PTR_ERR(clk));
+                       continue;
+               }
+
+               /* add clk_lookup for devm_clk_get(SND_SOC_DAPM_CLOCK_SUPPLY) */
+               cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+               if (!cl)
+                       return -ENOMEM;
+
+               cl->clk = clk;
+               cl->con_id = gate->name;
+               cl->dev_id = dev_name(afe->dev);
+               clkdev_add(cl);
+
+               afe_priv->lookup[i] = cl;
+       }
+
+       return 0;
+}
+
+void mt8195_audsys_clk_unregister(struct mtk_base_afe *afe)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct clk *clk;
+       struct clk_lookup *cl;
+       int i;
+
+       if (!afe_priv)
+               return;
+
+       for (i = 0; i < CLK_AUD_NR_CLK; i++) {
+               cl = afe_priv->lookup[i];
+               if (!cl)
+                       continue;
+
+               clk = cl->clk;
+               clk_unregister_gate(clk);
+
+               clkdev_drop(cl);
+       }
+}
diff --git a/sound/soc/mediatek/mt8195/mt8195-audsys-clk.h b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.h
new file mode 100644 (file)
index 0000000..239d310
--- /dev/null
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8195-audsys-clk.h  --  Mediatek 8195 audsys clock definition
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#ifndef _MT8195_AUDSYS_CLK_H_
+#define _MT8195_AUDSYS_CLK_H_
+
+int mt8195_audsys_clk_register(struct mtk_base_afe *afe);
+void mt8195_audsys_clk_unregister(struct mtk_base_afe *afe);
+
+#endif
diff --git a/sound/soc/mediatek/mt8195/mt8195-audsys-clkid.h b/sound/soc/mediatek/mt8195/mt8195-audsys-clkid.h
new file mode 100644 (file)
index 0000000..4dd0a5c
--- /dev/null
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8195-audsys-clkid.h  --  Mediatek 8195 audsys clock id definition
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#ifndef _MT8195_AUDSYS_CLKID_H_
+#define _MT8195_AUDSYS_CLKID_H_
+
+enum{
+       CLK_AUD_AFE,
+       CLK_AUD_LRCK_CNT,
+       CLK_AUD_SPDIFIN_TUNER_APLL,
+       CLK_AUD_SPDIFIN_TUNER_DBG,
+       CLK_AUD_UL_TML,
+       CLK_AUD_APLL1_TUNER,
+       CLK_AUD_APLL2_TUNER,
+       CLK_AUD_TOP0_SPDF,
+       CLK_AUD_APLL,
+       CLK_AUD_APLL2,
+       CLK_AUD_DAC,
+       CLK_AUD_DAC_PREDIS,
+       CLK_AUD_TML,
+       CLK_AUD_ADC,
+       CLK_AUD_DAC_HIRES,
+       CLK_AUD_A1SYS_HP,
+       CLK_AUD_AFE_DMIC1,
+       CLK_AUD_AFE_DMIC2,
+       CLK_AUD_AFE_DMIC3,
+       CLK_AUD_AFE_DMIC4,
+       CLK_AUD_AFE_26M_DMIC_TM,
+       CLK_AUD_UL_TML_HIRES,
+       CLK_AUD_ADC_HIRES,
+       CLK_AUD_ADDA6_ADC,
+       CLK_AUD_ADDA6_ADC_HIRES,
+       CLK_AUD_LINEIN_TUNER,
+       CLK_AUD_EARC_TUNER,
+       CLK_AUD_I2SIN,
+       CLK_AUD_TDM_IN,
+       CLK_AUD_I2S_OUT,
+       CLK_AUD_TDM_OUT,
+       CLK_AUD_HDMI_OUT,
+       CLK_AUD_ASRC11,
+       CLK_AUD_ASRC12,
+       CLK_AUD_MULTI_IN,
+       CLK_AUD_INTDIR,
+       CLK_AUD_A1SYS,
+       CLK_AUD_A2SYS,
+       CLK_AUD_PCMIF,
+       CLK_AUD_A3SYS,
+       CLK_AUD_A4SYS,
+       CLK_AUD_MEMIF_UL1,
+       CLK_AUD_MEMIF_UL2,
+       CLK_AUD_MEMIF_UL3,
+       CLK_AUD_MEMIF_UL4,
+       CLK_AUD_MEMIF_UL5,
+       CLK_AUD_MEMIF_UL6,
+       CLK_AUD_MEMIF_UL8,
+       CLK_AUD_MEMIF_UL9,
+       CLK_AUD_MEMIF_UL10,
+       CLK_AUD_MEMIF_DL2,
+       CLK_AUD_MEMIF_DL3,
+       CLK_AUD_MEMIF_DL6,
+       CLK_AUD_MEMIF_DL7,
+       CLK_AUD_MEMIF_DL8,
+       CLK_AUD_MEMIF_DL10,
+       CLK_AUD_MEMIF_DL11,
+       CLK_AUD_GASRC0,
+       CLK_AUD_GASRC1,
+       CLK_AUD_GASRC2,
+       CLK_AUD_GASRC3,
+       CLK_AUD_GASRC4,
+       CLK_AUD_GASRC5,
+       CLK_AUD_GASRC6,
+       CLK_AUD_GASRC7,
+       CLK_AUD_GASRC8,
+       CLK_AUD_GASRC9,
+       CLK_AUD_GASRC10,
+       CLK_AUD_GASRC11,
+       CLK_AUD_GASRC12,
+       CLK_AUD_GASRC13,
+       CLK_AUD_GASRC14,
+       CLK_AUD_GASRC15,
+       CLK_AUD_GASRC16,
+       CLK_AUD_GASRC17,
+       CLK_AUD_GASRC18,
+       CLK_AUD_GASRC19,
+       CLK_AUD_NR_CLK,
+};
+
+#endif
diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-adda.c b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c
new file mode 100644 (file)
index 0000000..878dec0
--- /dev/null
@@ -0,0 +1,830 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek ALSA SoC Audio DAI ADDA Control
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ *         Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include "mt8195-afe-clk.h"
+#include "mt8195-afe-common.h"
+#include "mt8195-reg.h"
+
+#define ADDA_DL_GAIN_LOOPBACK 0x1800
+#define ADDA_HIRES_THRES 48000
+
+enum {
+       SUPPLY_SEQ_CLOCK_SEL,
+       SUPPLY_SEQ_CLOCK_ON,
+       SUPPLY_SEQ_ADDA_DL_ON,
+       SUPPLY_SEQ_ADDA_MTKAIF_CFG,
+       SUPPLY_SEQ_ADDA_UL_ON,
+       SUPPLY_SEQ_ADDA_AFE_ON,
+};
+
+enum {
+       MTK_AFE_ADDA_DL_RATE_8K = 0,
+       MTK_AFE_ADDA_DL_RATE_11K = 1,
+       MTK_AFE_ADDA_DL_RATE_12K = 2,
+       MTK_AFE_ADDA_DL_RATE_16K = 3,
+       MTK_AFE_ADDA_DL_RATE_22K = 4,
+       MTK_AFE_ADDA_DL_RATE_24K = 5,
+       MTK_AFE_ADDA_DL_RATE_32K = 6,
+       MTK_AFE_ADDA_DL_RATE_44K = 7,
+       MTK_AFE_ADDA_DL_RATE_48K = 8,
+       MTK_AFE_ADDA_DL_RATE_96K = 9,
+       MTK_AFE_ADDA_DL_RATE_192K = 10,
+};
+
+enum {
+       MTK_AFE_ADDA_UL_RATE_8K = 0,
+       MTK_AFE_ADDA_UL_RATE_16K = 1,
+       MTK_AFE_ADDA_UL_RATE_32K = 2,
+       MTK_AFE_ADDA_UL_RATE_48K = 3,
+       MTK_AFE_ADDA_UL_RATE_96K = 4,
+       MTK_AFE_ADDA_UL_RATE_192K = 5,
+};
+
+enum {
+       DELAY_DATA_MISO1 = 0,
+       DELAY_DATA_MISO0 = 1,
+       DELAY_DATA_MISO2 = 1,
+};
+
+enum {
+       MTK_AFE_ADDA,
+       MTK_AFE_ADDA6,
+};
+
+struct mtk_dai_adda_priv {
+       bool hires_required;
+};
+
+static unsigned int afe_adda_dl_rate_transform(struct mtk_base_afe *afe,
+                                              unsigned int rate)
+{
+       switch (rate) {
+       case 8000:
+               return MTK_AFE_ADDA_DL_RATE_8K;
+       case 11025:
+               return MTK_AFE_ADDA_DL_RATE_11K;
+       case 12000:
+               return MTK_AFE_ADDA_DL_RATE_12K;
+       case 16000:
+               return MTK_AFE_ADDA_DL_RATE_16K;
+       case 22050:
+               return MTK_AFE_ADDA_DL_RATE_22K;
+       case 24000:
+               return MTK_AFE_ADDA_DL_RATE_24K;
+       case 32000:
+               return MTK_AFE_ADDA_DL_RATE_32K;
+       case 44100:
+               return MTK_AFE_ADDA_DL_RATE_44K;
+       case 48000:
+               return MTK_AFE_ADDA_DL_RATE_48K;
+       case 96000:
+               return MTK_AFE_ADDA_DL_RATE_96K;
+       case 192000:
+               return MTK_AFE_ADDA_DL_RATE_192K;
+       default:
+               dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
+                        __func__, rate);
+               return MTK_AFE_ADDA_DL_RATE_48K;
+       }
+}
+
+static unsigned int afe_adda_ul_rate_transform(struct mtk_base_afe *afe,
+                                              unsigned int rate)
+{
+       switch (rate) {
+       case 8000:
+               return MTK_AFE_ADDA_UL_RATE_8K;
+       case 16000:
+               return MTK_AFE_ADDA_UL_RATE_16K;
+       case 32000:
+               return MTK_AFE_ADDA_UL_RATE_32K;
+       case 48000:
+               return MTK_AFE_ADDA_UL_RATE_48K;
+       case 96000:
+               return MTK_AFE_ADDA_UL_RATE_96K;
+       case 192000:
+               return MTK_AFE_ADDA_UL_RATE_192K;
+       default:
+               dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
+                        __func__, rate);
+               return MTK_AFE_ADDA_UL_RATE_48K;
+       }
+}
+
+static int mt8195_adda_mtkaif_init(struct mtk_base_afe *afe)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtkaif_param *param = &afe_priv->mtkaif_params;
+       int delay_data;
+       int delay_cycle;
+       unsigned int mask = 0;
+       unsigned int val = 0;
+
+       /* set rx protocol 2 & mtkaif_rxif_clkinv_adc inverse */
+       mask = (MTKAIF_RXIF_CLKINV_ADC | MTKAIF_RXIF_PROTOCOL2);
+       val = (MTKAIF_RXIF_CLKINV_ADC | MTKAIF_RXIF_PROTOCOL2);
+
+       regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_CFG0, mask, val);
+       regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIF_CFG0, mask, val);
+
+       mask = RG_RX_PROTOCOL2;
+       val = RG_RX_PROTOCOL2;
+       regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP, mask, val);
+
+       if (!param->mtkaif_calibration_ok) {
+               dev_info(afe->dev, "%s(), calibration fail\n",  __func__);
+               return 0;
+       }
+
+       /* set delay for ch1, ch2 */
+       if (param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0] >=
+           param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1]) {
+               delay_data = DELAY_DATA_MISO1;
+               delay_cycle =
+                       param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0] -
+                       param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1];
+       } else {
+               delay_data = DELAY_DATA_MISO0;
+               delay_cycle =
+                       param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1] -
+                       param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0];
+       }
+
+       val = 0;
+       mask = (MTKAIF_RXIF_DELAY_DATA | MTKAIF_RXIF_DELAY_CYCLE_MASK);
+       val |= MTKAIF_RXIF_DELAY_CYCLE(delay_cycle) &
+              MTKAIF_RXIF_DELAY_CYCLE_MASK;
+       val |= delay_data << MTKAIF_RXIF_DELAY_DATA_SHIFT;
+       regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG2, mask, val);
+
+       /* set delay between ch3 and ch2 */
+       if (param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2] >=
+           param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1]) {
+               delay_data = DELAY_DATA_MISO1;
+               delay_cycle =
+                       param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2] -
+                       param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1];
+       } else {
+               delay_data = DELAY_DATA_MISO2;
+               delay_cycle =
+                       param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1] -
+                       param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2];
+       }
+
+       val = 0;
+       mask = (MTKAIF_RXIF_DELAY_DATA | MTKAIF_RXIF_DELAY_CYCLE_MASK);
+       val |= MTKAIF_RXIF_DELAY_CYCLE(delay_cycle) &
+              MTKAIF_RXIF_DELAY_CYCLE_MASK;
+       val |= delay_data << MTKAIF_RXIF_DELAY_DATA_SHIFT;
+       regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIF_RX_CFG2, mask, val);
+
+       return 0;
+}
+
+static int mtk_adda_mtkaif_cfg_event(struct snd_soc_dapm_widget *w,
+                                    struct snd_kcontrol *kcontrol,
+                                    int event)
+{
+       struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+       dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+               __func__, w->name, event);
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               mt8195_adda_mtkaif_init(afe);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w,
+                            struct snd_kcontrol *kcontrol,
+                            int event)
+{
+       struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+       dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+               __func__, w->name, event);
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMD:
+               /* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+               usleep_range(125, 135);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static void mtk_adda_ul_mictype(struct mtk_base_afe *afe, int adda, bool dmic)
+{
+       unsigned int reg = 0;
+       unsigned int mask = 0;
+       unsigned int val = 0;
+
+       switch (adda) {
+       case MTK_AFE_ADDA:
+               reg = AFE_ADDA_UL_SRC_CON0;
+               break;
+       case MTK_AFE_ADDA6:
+               reg = AFE_ADDA6_UL_SRC_CON0;
+               break;
+       default:
+               dev_info(afe->dev, "%s(), wrong parameter\n",  __func__);
+               return;
+       }
+
+       mask = (UL_SDM3_LEVEL_CTL | UL_MODE_3P25M_CH1_CTL |
+               UL_MODE_3P25M_CH2_CTL);
+
+       /* turn on dmic, ch1, ch2 */
+       if (dmic)
+               val = mask;
+
+       regmap_update_bits(afe->regmap, reg, mask, val);
+}
+
+static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,
+                            struct snd_kcontrol *kcontrol,
+                            int event)
+{
+       struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtkaif_param *param = &afe_priv->mtkaif_params;
+
+       dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+               __func__, w->name, event);
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               mtk_adda_ul_mictype(afe, MTK_AFE_ADDA, param->mtkaif_dmic_on);
+               break;
+       case SND_SOC_DAPM_POST_PMD:
+               /* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+               usleep_range(125, 135);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int mtk_adda6_ul_event(struct snd_soc_dapm_widget *w,
+                             struct snd_kcontrol *kcontrol,
+                             int event)
+{
+       struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtkaif_param *param = &afe_priv->mtkaif_params;
+       unsigned int val;
+
+       dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+               __func__, w->name, event);
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               mtk_adda_ul_mictype(afe, MTK_AFE_ADDA6, param->mtkaif_dmic_on);
+
+               val = (param->mtkaif_adda6_only ?
+                       ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE : 0);
+
+               regmap_update_bits(afe->regmap,
+                                  AFE_ADDA_MTKAIF_SYNCWORD_CFG,
+                                  ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE,
+                                  val);
+               break;
+       case SND_SOC_DAPM_POST_PMD:
+               /* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+               usleep_range(125, 135);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int mtk_audio_hires_event(struct snd_soc_dapm_widget *w,
+                                struct snd_kcontrol *kcontrol,
+                                int event)
+{
+       struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct clk *clk = afe_priv->clk[MT8195_CLK_TOP_AUDIO_H_SEL];
+       struct clk *clk_parent;
+
+       dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+               __func__, w->name, event);
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               clk_parent = afe_priv->clk[MT8195_CLK_TOP_APLL1];
+               break;
+       case SND_SOC_DAPM_POST_PMD:
+               clk_parent = afe_priv->clk[MT8195_CLK_XTAL_26M];
+               break;
+       default:
+               return 0;
+       }
+       mt8195_afe_set_clk_parent(afe, clk, clk_parent);
+
+       return 0;
+}
+
+static struct mtk_dai_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe,
+                                                      const char *name)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       int dai_id;
+
+       if (strstr(name, "aud_adc_hires"))
+               dai_id = MT8195_AFE_IO_UL_SRC1;
+       else if (strstr(name, "aud_adda6_adc_hires"))
+               dai_id = MT8195_AFE_IO_UL_SRC2;
+       else if (strstr(name, "aud_dac_hires"))
+               dai_id = MT8195_AFE_IO_DL_SRC;
+       else
+               return NULL;
+
+       return afe_priv->dai_priv[dai_id];
+}
+
+static int mtk_afe_adda_hires_connect(struct snd_soc_dapm_widget *source,
+                                     struct snd_soc_dapm_widget *sink)
+{
+       struct snd_soc_dapm_widget *w = source;
+       struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+       struct mtk_dai_adda_priv *adda_priv;
+
+       adda_priv = get_adda_priv_by_name(afe, w->name);
+
+       if (!adda_priv) {
+               dev_info(afe->dev, "adda_priv == NULL");
+               return 0;
+       }
+
+       return (adda_priv->hires_required) ? 1 : 0;
+}
+
+static const struct snd_kcontrol_new mtk_dai_adda_o176_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN176, 0, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I002 Switch", AFE_CONN176, 2, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN176, 20, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN176, 22, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN176_2, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_adda_o177_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN177, 1, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I003 Switch", AFE_CONN177, 3, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN177, 21, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN177, 23, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN177_2, 7, 1, 0),
+};
+
+static const char * const adda_dlgain_mux_map[] = {
+       "Bypass", "Connect",
+};
+
+static SOC_ENUM_SINGLE_DECL(adda_dlgain_mux_map_enum,
+                           SND_SOC_NOPM, 0,
+                           adda_dlgain_mux_map);
+
+static const struct snd_kcontrol_new adda_dlgain_mux_control =
+       SOC_DAPM_ENUM("DL_GAIN_MUX", adda_dlgain_mux_map_enum);
+
+static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {
+       SND_SOC_DAPM_MIXER("I168", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I169", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I170", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I171", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       SND_SOC_DAPM_MIXER("O176", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_adda_o176_mix,
+                          ARRAY_SIZE(mtk_dai_adda_o176_mix)),
+       SND_SOC_DAPM_MIXER("O177", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_adda_o177_mix,
+                          ARRAY_SIZE(mtk_dai_adda_o177_mix)),
+
+       SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON,
+                             AFE_ADDA_UL_DL_CON0,
+                             ADDA_AFE_ON_SHIFT, 0,
+                             NULL,
+                             0),
+
+       SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON,
+                             AFE_ADDA_DL_SRC2_CON0,
+                             DL_2_SRC_ON_TMP_CTRL_PRE_SHIFT, 0,
+                             mtk_adda_dl_event,
+                             SND_SOC_DAPM_POST_PMD),
+
+       SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
+                             AFE_ADDA_UL_SRC_CON0,
+                             UL_SRC_ON_TMP_CTL_SHIFT, 0,
+                             mtk_adda_ul_event,
+                             SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+       SND_SOC_DAPM_SUPPLY_S("ADDA6 Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
+                             AFE_ADDA6_UL_SRC_CON0,
+                             UL_SRC_ON_TMP_CTL_SHIFT, 0,
+                             mtk_adda6_ul_event,
+                             SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+       SND_SOC_DAPM_SUPPLY_S("AUDIO_HIRES", SUPPLY_SEQ_CLOCK_SEL,
+                             SND_SOC_NOPM,
+                             0, 0,
+                             mtk_audio_hires_event,
+                             SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+       SND_SOC_DAPM_SUPPLY_S("ADDA_MTKAIF_CFG", SUPPLY_SEQ_ADDA_MTKAIF_CFG,
+                             SND_SOC_NOPM,
+                             0, 0,
+                             mtk_adda_mtkaif_cfg_event,
+                             SND_SOC_DAPM_PRE_PMU),
+
+       SND_SOC_DAPM_MUX("DL_GAIN_MUX", SND_SOC_NOPM, 0, 0,
+                        &adda_dlgain_mux_control),
+
+       SND_SOC_DAPM_PGA("DL_GAIN", AFE_ADDA_DL_SRC2_CON0,
+                        DL_2_GAIN_ON_CTL_PRE_SHIFT, 0, NULL, 0),
+
+       SND_SOC_DAPM_INPUT("ADDA_INPUT"),
+       SND_SOC_DAPM_OUTPUT("ADDA_OUTPUT"),
+
+       SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac"),
+       SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc"),
+       SND_SOC_DAPM_CLOCK_SUPPLY("aud_adda6_adc"),
+       SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_hires"),
+       SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_hires"),
+       SND_SOC_DAPM_CLOCK_SUPPLY("aud_adda6_adc_hires"),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {
+       {"ADDA Capture", NULL, "ADDA Enable"},
+       {"ADDA Capture", NULL, "ADDA Capture Enable"},
+       {"ADDA Capture", NULL, "ADDA_MTKAIF_CFG"},
+       {"ADDA Capture", NULL, "aud_adc"},
+       {"ADDA Capture", NULL, "aud_adc_hires", mtk_afe_adda_hires_connect},
+       {"aud_adc_hires", NULL, "AUDIO_HIRES"},
+
+       {"ADDA6 Capture", NULL, "ADDA Enable"},
+       {"ADDA6 Capture", NULL, "ADDA6 Capture Enable"},
+       {"ADDA6 Capture", NULL, "ADDA_MTKAIF_CFG"},
+       {"ADDA6 Capture", NULL, "aud_adda6_adc"},
+       {"ADDA6 Capture", NULL, "aud_adda6_adc_hires",
+       mtk_afe_adda_hires_connect},
+       {"aud_adda6_adc_hires", NULL, "AUDIO_HIRES"},
+
+       {"I168", NULL, "ADDA Capture"},
+       {"I169", NULL, "ADDA Capture"},
+       {"I170", NULL, "ADDA6 Capture"},
+       {"I171", NULL, "ADDA6 Capture"},
+
+       {"ADDA Playback", NULL, "ADDA Enable"},
+       {"ADDA Playback", NULL, "ADDA Playback Enable"},
+       {"ADDA Playback", NULL, "aud_dac"},
+       {"ADDA Playback", NULL, "aud_dac_hires", mtk_afe_adda_hires_connect},
+       {"aud_dac_hires", NULL, "AUDIO_HIRES"},
+
+       {"DL_GAIN", NULL, "O176"},
+       {"DL_GAIN", NULL, "O177"},
+
+       {"DL_GAIN_MUX", "Bypass", "O176"},
+       {"DL_GAIN_MUX", "Bypass", "O177"},
+       {"DL_GAIN_MUX", "Connect", "DL_GAIN"},
+
+       {"ADDA Playback", NULL, "DL_GAIN_MUX"},
+
+       {"O176", "I000 Switch", "I000"},
+       {"O177", "I001 Switch", "I001"},
+
+       {"O176", "I002 Switch", "I002"},
+       {"O177", "I003 Switch", "I003"},
+
+       {"O176", "I020 Switch", "I020"},
+       {"O177", "I021 Switch", "I021"},
+
+       {"O176", "I022 Switch", "I022"},
+       {"O177", "I023 Switch", "I023"},
+
+       {"O176", "I070 Switch", "I070"},
+       {"O177", "I071 Switch", "I071"},
+
+       {"ADDA Capture", NULL, "ADDA_INPUT"},
+       {"ADDA6 Capture", NULL, "ADDA_INPUT"},
+       {"ADDA_OUTPUT", NULL, "ADDA Playback"},
+};
+
+static int mt8195_adda_dl_gain_put(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+       unsigned int reg = AFE_ADDA_DL_SRC2_CON1;
+       unsigned int mask = DL_2_GAIN_CTL_PRE_MASK;
+       unsigned int value = (unsigned int)(ucontrol->value.integer.value[0]);
+
+       regmap_update_bits(afe->regmap, reg, mask, DL_2_GAIN_CTL_PRE(value));
+       return 0;
+}
+
+static int mt8195_adda_dl_gain_get(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+       unsigned int reg = AFE_ADDA_DL_SRC2_CON1;
+       unsigned int mask = DL_2_GAIN_CTL_PRE_MASK;
+       unsigned int value = 0;
+
+       regmap_read(afe->regmap, reg, &value);
+
+       ucontrol->value.integer.value[0] = ((value & mask) >>
+                                           DL_2_GAIN_CTL_PRE_SHIFT);
+       return 0;
+}
+
+static int mt8195_adda6_only_get(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtkaif_param *param = &afe_priv->mtkaif_params;
+
+       ucontrol->value.integer.value[0] = param->mtkaif_adda6_only;
+       return 0;
+}
+
+static int mt8195_adda6_only_set(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtkaif_param *param = &afe_priv->mtkaif_params;
+       int mtkaif_adda6_only;
+
+       mtkaif_adda6_only = ucontrol->value.integer.value[0];
+
+       dev_info(afe->dev, "%s(), kcontrol name %s, mtkaif_adda6_only %d\n",
+                __func__, kcontrol->id.name, mtkaif_adda6_only);
+
+       param->mtkaif_adda6_only = mtkaif_adda6_only;
+
+       return 0;
+}
+
+static int mt8195_adda_dmic_get(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtkaif_param *param = &afe_priv->mtkaif_params;
+
+       ucontrol->value.integer.value[0] = param->mtkaif_dmic_on;
+       return 0;
+}
+
+static int mt8195_adda_dmic_set(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtkaif_param *param = &afe_priv->mtkaif_params;
+       int dmic_on;
+
+       dmic_on = ucontrol->value.integer.value[0];
+
+       dev_dbg(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n",
+               __func__, kcontrol->id.name, dmic_on);
+
+       param->mtkaif_dmic_on = dmic_on;
+       return 0;
+}
+
+static const struct snd_kcontrol_new mtk_dai_adda_controls[] = {
+       SOC_SINGLE_EXT("ADDA_DL_Gain", SND_SOC_NOPM, 0, 65535, 0,
+                      mt8195_adda_dl_gain_get, mt8195_adda_dl_gain_put),
+       SOC_SINGLE_BOOL_EXT("MTKAIF_DMIC", 0,
+                           mt8195_adda_dmic_get, mt8195_adda_dmic_set),
+       SOC_SINGLE_BOOL_EXT("MTKAIF_ADDA6_ONLY", 0,
+                           mt8195_adda6_only_get,
+                           mt8195_adda6_only_set),
+};
+
+static int mtk_dai_da_configure(struct mtk_base_afe *afe,
+                               unsigned int rate, int id)
+{
+       unsigned int val = 0;
+       unsigned int mask = 0;
+
+       /* set sampling rate */
+       mask |= DL_2_INPUT_MODE_CTL_MASK;
+       val |= DL_2_INPUT_MODE_CTL(afe_adda_dl_rate_transform(afe, rate));
+
+       /* turn off saturation */
+       mask |= DL_2_CH1_SATURATION_EN_CTL;
+       mask |= DL_2_CH2_SATURATION_EN_CTL;
+
+       /* turn off mute function */
+       mask |= DL_2_MUTE_CH1_OFF_CTL_PRE;
+       mask |= DL_2_MUTE_CH2_OFF_CTL_PRE;
+       val |= DL_2_MUTE_CH1_OFF_CTL_PRE;
+       val |= DL_2_MUTE_CH2_OFF_CTL_PRE;
+
+       /* set voice input data if input sample rate is 8k or 16k */
+       mask |= DL_2_VOICE_MODE_CTL_PRE;
+       if (rate == 8000 || rate == 16000)
+               val |= DL_2_VOICE_MODE_CTL_PRE;
+
+       regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON0, mask, val);
+
+       mask = 0;
+       val = 0;
+
+       /* new 2nd sdm */
+       mask |= DL_USE_NEW_2ND_SDM;
+       val |= DL_USE_NEW_2ND_SDM;
+       regmap_update_bits(afe->regmap, AFE_ADDA_DL_SDM_DCCOMP_CON, mask, val);
+
+       return 0;
+}
+
+static int mtk_dai_ad_configure(struct mtk_base_afe *afe,
+                               unsigned int rate, int id)
+{
+       unsigned int val = 0;
+       unsigned int mask = 0;
+
+       mask |= UL_VOICE_MODE_CTL_MASK;
+       val |= UL_VOICE_MODE_CTL(afe_adda_ul_rate_transform(afe, rate));
+
+       switch (id) {
+       case MT8195_AFE_IO_UL_SRC1:
+               regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,
+                                  mask, val);
+               break;
+       case MT8195_AFE_IO_UL_SRC2:
+               regmap_update_bits(afe->regmap, AFE_ADDA6_UL_SRC_CON0,
+                                  mask, val);
+               break;
+       default:
+               break;
+       }
+       return 0;
+}
+
+static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,
+                                 struct snd_pcm_hw_params *params,
+                                 struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_adda_priv *adda_priv = afe_priv->dai_priv[dai->id];
+       unsigned int rate = params_rate(params);
+       int id = dai->id;
+       int ret = 0;
+
+       dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",
+               __func__, id, substream->stream, rate);
+
+       if (rate > ADDA_HIRES_THRES)
+               adda_priv->hires_required = 1;
+       else
+               adda_priv->hires_required = 0;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               ret = mtk_dai_da_configure(afe, rate, id);
+       else
+               ret = mtk_dai_ad_configure(afe, rate, id);
+
+       return ret;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_adda_ops = {
+       .hw_params = mtk_dai_adda_hw_params,
+};
+
+/* dai driver */
+#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\
+                                SNDRV_PCM_RATE_96000 |\
+                                SNDRV_PCM_RATE_192000)
+
+#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
+                               SNDRV_PCM_RATE_16000 |\
+                               SNDRV_PCM_RATE_32000 |\
+                               SNDRV_PCM_RATE_48000 |\
+                               SNDRV_PCM_RATE_96000 |\
+                               SNDRV_PCM_RATE_192000)
+
+#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+                         SNDRV_PCM_FMTBIT_S24_LE |\
+                         SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {
+       {
+               .name = "DL_SRC",
+               .id = MT8195_AFE_IO_DL_SRC,
+               .playback = {
+                       .stream_name = "ADDA Playback",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = MTK_ADDA_PLAYBACK_RATES,
+                       .formats = MTK_ADDA_FORMATS,
+               },
+               .ops = &mtk_dai_adda_ops,
+       },
+       {
+               .name = "UL_SRC1",
+               .id = MT8195_AFE_IO_UL_SRC1,
+               .capture = {
+                       .stream_name = "ADDA Capture",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = MTK_ADDA_CAPTURE_RATES,
+                       .formats = MTK_ADDA_FORMATS,
+               },
+               .ops = &mtk_dai_adda_ops,
+       },
+       {
+               .name = "UL_SRC2",
+               .id = MT8195_AFE_IO_UL_SRC2,
+               .capture = {
+                       .stream_name = "ADDA6 Capture",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = MTK_ADDA_CAPTURE_RATES,
+                       .formats = MTK_ADDA_FORMATS,
+               },
+               .ops = &mtk_dai_adda_ops,
+       },
+};
+
+static int init_adda_priv_data(struct mtk_base_afe *afe)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_adda_priv *adda_priv;
+       int adda_dai_list[] = { MT8195_AFE_IO_DL_SRC,
+                               MT8195_AFE_IO_UL_SRC1,
+                               MT8195_AFE_IO_UL_SRC2};
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(adda_dai_list); i++) {
+               adda_priv = devm_kzalloc(afe->dev,
+                                        sizeof(struct mtk_dai_adda_priv),
+                                        GFP_KERNEL);
+               if (!adda_priv)
+                       return -ENOMEM;
+
+               afe_priv->dai_priv[adda_dai_list[i]] = adda_priv;
+       }
+
+       return 0;
+}
+
+int mt8195_dai_adda_register(struct mtk_base_afe *afe)
+{
+       struct mtk_base_afe_dai *dai;
+
+       dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+       if (!dai)
+               return -ENOMEM;
+
+       list_add(&dai->list, &afe->sub_dais);
+
+       dai->dai_drivers = mtk_dai_adda_driver;
+       dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver);
+
+       dai->dapm_widgets = mtk_dai_adda_widgets;
+       dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets);
+       dai->dapm_routes = mtk_dai_adda_routes;
+       dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes);
+       dai->controls = mtk_dai_adda_controls;
+       dai->num_controls = ARRAY_SIZE(mtk_dai_adda_controls);
+
+       return init_adda_priv_data(afe);
+}
diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c
new file mode 100644 (file)
index 0000000..7378e42
--- /dev/null
@@ -0,0 +1,2639 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek ALSA SoC Audio DAI eTDM Control
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ *         Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include "mt8195-afe-clk.h"
+#include "mt8195-afe-common.h"
+#include "mt8195-reg.h"
+
+#define MT8195_ETDM_MAX_CHANNELS 24
+#define MT8195_ETDM_NORMAL_MAX_BCK_RATE 24576000
+#define ETDM_TO_DAI_ID(x) ((x) + MT8195_AFE_IO_ETDM_START)
+#define ENUM_TO_STR(x) #x
+
+enum {
+       MTK_DAI_ETDM_FORMAT_I2S = 0,
+       MTK_DAI_ETDM_FORMAT_LJ,
+       MTK_DAI_ETDM_FORMAT_RJ,
+       MTK_DAI_ETDM_FORMAT_EIAJ,
+       MTK_DAI_ETDM_FORMAT_DSPA,
+       MTK_DAI_ETDM_FORMAT_DSPB,
+};
+
+enum {
+       MTK_DAI_ETDM_DATA_ONE_PIN = 0,
+       MTK_DAI_ETDM_DATA_MULTI_PIN,
+};
+
+enum {
+       ETDM_IN,
+       ETDM_OUT,
+};
+
+enum {
+       ETDM_IN_FROM_PAD,
+       ETDM_IN_FROM_ETDM_OUT1,
+       ETDM_IN_FROM_ETDM_OUT2,
+};
+
+enum {
+       ETDM_IN_SLAVE_FROM_PAD,
+       ETDM_IN_SLAVE_FROM_ETDM_OUT1,
+       ETDM_IN_SLAVE_FROM_ETDM_OUT2,
+};
+
+enum {
+       ETDM_OUT_SLAVE_FROM_PAD,
+       ETDM_OUT_SLAVE_FROM_ETDM_IN1,
+       ETDM_OUT_SLAVE_FROM_ETDM_IN2,
+};
+
+enum {
+       COWORK_ETDM_NONE = 0,
+       COWORK_ETDM_IN1_M = 2,
+       COWORK_ETDM_IN1_S = 3,
+       COWORK_ETDM_IN2_M = 4,
+       COWORK_ETDM_IN2_S = 5,
+       COWORK_ETDM_OUT1_M = 10,
+       COWORK_ETDM_OUT1_S = 11,
+       COWORK_ETDM_OUT2_M = 12,
+       COWORK_ETDM_OUT2_S = 13,
+       COWORK_ETDM_OUT3_M = 14,
+       COWORK_ETDM_OUT3_S = 15,
+};
+
+enum {
+       ETDM_RELATCH_TIMING_A1A2SYS,
+       ETDM_RELATCH_TIMING_A3SYS,
+       ETDM_RELATCH_TIMING_A4SYS,
+};
+
+enum {
+       ETDM_SYNC_NONE,
+       ETDM_SYNC_FROM_IN1,
+       ETDM_SYNC_FROM_IN2,
+       ETDM_SYNC_FROM_OUT1,
+       ETDM_SYNC_FROM_OUT2,
+       ETDM_SYNC_FROM_OUT3,
+};
+
+struct etdm_con_reg {
+       unsigned int con0;
+       unsigned int con1;
+       unsigned int con2;
+       unsigned int con3;
+       unsigned int con4;
+       unsigned int con5;
+};
+
+struct mtk_dai_etdm_rate {
+       unsigned int rate;
+       unsigned int reg_value;
+};
+
+struct mtk_dai_etdm_priv {
+       unsigned int clock_mode;
+       unsigned int data_mode;
+       bool slave_mode;
+       bool lrck_inv;
+       bool bck_inv;
+       unsigned int format;
+       unsigned int slots;
+       unsigned int lrck_width;
+       unsigned int mclk_freq;
+       unsigned int mclk_apll;
+       unsigned int mclk_dir;
+       int cowork_source_id; //dai id
+       unsigned int cowork_slv_count;
+       int cowork_slv_id[MT8195_AFE_IO_ETDM_NUM - 1]; //dai_id
+       bool in_disable_ch[MT8195_ETDM_MAX_CHANNELS];
+       unsigned int en_ref_cnt;
+};
+
+static const struct mtk_dai_etdm_rate mt8195_etdm_rates[] = {
+       { .rate = 8000, .reg_value = 0, },
+       { .rate = 12000, .reg_value = 1, },
+       { .rate = 16000, .reg_value = 2, },
+       { .rate = 24000, .reg_value = 3, },
+       { .rate = 32000, .reg_value = 4, },
+       { .rate = 48000, .reg_value = 5, },
+       { .rate = 96000, .reg_value = 7, },
+       { .rate = 192000, .reg_value = 9, },
+       { .rate = 384000, .reg_value = 11, },
+       { .rate = 11025, .reg_value = 16, },
+       { .rate = 22050, .reg_value = 17, },
+       { .rate = 44100, .reg_value = 18, },
+       { .rate = 88200, .reg_value = 19, },
+       { .rate = 176400, .reg_value = 20, },
+       { .rate = 352800, .reg_value = 21, },
+};
+
+static int get_etdm_fs_timing(unsigned int rate)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mt8195_etdm_rates); i++)
+               if (mt8195_etdm_rates[i].rate == rate)
+                       return mt8195_etdm_rates[i].reg_value;
+
+       return -EINVAL;
+}
+
+static unsigned int get_etdm_ch_fixup(unsigned int channels)
+{
+       if (channels > 16)
+               return 24;
+       else if (channels > 8)
+               return 16;
+       else if (channels > 4)
+               return 8;
+       else if (channels > 2)
+               return 4;
+       else
+               return 2;
+}
+
+static int get_etdm_reg(unsigned int dai_id, struct etdm_con_reg *etdm_reg)
+{
+       switch (dai_id) {
+       case MT8195_AFE_IO_ETDM1_IN:
+               etdm_reg->con0 = ETDM_IN1_CON0;
+               etdm_reg->con1 = ETDM_IN1_CON1;
+               etdm_reg->con2 = ETDM_IN1_CON2;
+               etdm_reg->con3 = ETDM_IN1_CON3;
+               etdm_reg->con4 = ETDM_IN1_CON4;
+               etdm_reg->con5 = ETDM_IN1_CON5;
+               break;
+       case MT8195_AFE_IO_ETDM2_IN:
+               etdm_reg->con0 = ETDM_IN2_CON0;
+               etdm_reg->con1 = ETDM_IN2_CON1;
+               etdm_reg->con2 = ETDM_IN2_CON2;
+               etdm_reg->con3 = ETDM_IN2_CON3;
+               etdm_reg->con4 = ETDM_IN2_CON4;
+               etdm_reg->con5 = ETDM_IN2_CON5;
+               break;
+       case MT8195_AFE_IO_ETDM1_OUT:
+               etdm_reg->con0 = ETDM_OUT1_CON0;
+               etdm_reg->con1 = ETDM_OUT1_CON1;
+               etdm_reg->con2 = ETDM_OUT1_CON2;
+               etdm_reg->con3 = ETDM_OUT1_CON3;
+               etdm_reg->con4 = ETDM_OUT1_CON4;
+               etdm_reg->con5 = ETDM_OUT1_CON5;
+               break;
+       case MT8195_AFE_IO_ETDM2_OUT:
+               etdm_reg->con0 = ETDM_OUT2_CON0;
+               etdm_reg->con1 = ETDM_OUT2_CON1;
+               etdm_reg->con2 = ETDM_OUT2_CON2;
+               etdm_reg->con3 = ETDM_OUT2_CON3;
+               etdm_reg->con4 = ETDM_OUT2_CON4;
+               etdm_reg->con5 = ETDM_OUT2_CON5;
+               break;
+       case MT8195_AFE_IO_ETDM3_OUT:
+       case MT8195_AFE_IO_DPTX:
+               etdm_reg->con0 = ETDM_OUT3_CON0;
+               etdm_reg->con1 = ETDM_OUT3_CON1;
+               etdm_reg->con2 = ETDM_OUT3_CON2;
+               etdm_reg->con3 = ETDM_OUT3_CON3;
+               etdm_reg->con4 = ETDM_OUT3_CON4;
+               etdm_reg->con5 = ETDM_OUT3_CON5;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int get_etdm_dir(unsigned int dai_id)
+{
+       switch (dai_id) {
+       case MT8195_AFE_IO_ETDM1_IN:
+       case MT8195_AFE_IO_ETDM2_IN:
+               return ETDM_IN;
+       case MT8195_AFE_IO_ETDM1_OUT:
+       case MT8195_AFE_IO_ETDM2_OUT:
+       case MT8195_AFE_IO_ETDM3_OUT:
+               return ETDM_OUT;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int get_etdm_wlen(unsigned int bitwidth)
+{
+       return bitwidth <= 16 ? 16 : 32;
+}
+
+static int is_cowork_mode(struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+
+       return (etdm_data->cowork_slv_count > 0 ||
+               etdm_data->cowork_source_id != COWORK_ETDM_NONE);
+}
+
+static int sync_to_dai_id(int source_sel)
+{
+       switch (source_sel) {
+       case ETDM_SYNC_FROM_IN1:
+               return MT8195_AFE_IO_ETDM1_IN;
+       case ETDM_SYNC_FROM_IN2:
+               return MT8195_AFE_IO_ETDM2_IN;
+       case ETDM_SYNC_FROM_OUT1:
+               return MT8195_AFE_IO_ETDM1_OUT;
+       case ETDM_SYNC_FROM_OUT2:
+               return MT8195_AFE_IO_ETDM2_OUT;
+       case ETDM_SYNC_FROM_OUT3:
+               return MT8195_AFE_IO_ETDM3_OUT;
+       default:
+               return 0;
+       }
+}
+
+static int get_etdm_cowork_master_id(struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+       int dai_id = etdm_data->cowork_source_id;
+
+       if (dai_id == COWORK_ETDM_NONE)
+               dai_id = dai->id;
+
+       return dai_id;
+}
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o048_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN48, 20, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN48, 22, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I046 Switch", AFE_CONN48_1, 14, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN48_2, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o049_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN49, 21, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN49, 23, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I047 Switch", AFE_CONN49_1, 15, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN49_2, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o050_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN50, 24, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I048 Switch", AFE_CONN50_1, 16, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o051_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN51, 25, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I049 Switch", AFE_CONN51_1, 17, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o052_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN52, 26, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I050 Switch", AFE_CONN52_1, 18, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o053_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN53, 27, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I051 Switch", AFE_CONN53_1, 19, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o054_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN54, 28, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I052 Switch", AFE_CONN54_1, 20, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o055_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN55, 29, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I053 Switch", AFE_CONN55_1, 21, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o056_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I030 Switch", AFE_CONN56, 30, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I054 Switch", AFE_CONN56_1, 22, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o057_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I031 Switch", AFE_CONN57, 31, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I055 Switch", AFE_CONN57_1, 23, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o058_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I032 Switch", AFE_CONN58_1, 0, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I056 Switch", AFE_CONN58_1, 24, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o059_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I033 Switch", AFE_CONN59_1, 1, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I057 Switch", AFE_CONN59_1, 25, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o060_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I034 Switch", AFE_CONN60_1, 2, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I058 Switch", AFE_CONN60_1, 26, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o061_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I035 Switch", AFE_CONN61_1, 3, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I059 Switch", AFE_CONN61_1, 27, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o062_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I036 Switch", AFE_CONN62_1, 4, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I060 Switch", AFE_CONN62_1, 28, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o063_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I037 Switch", AFE_CONN63_1, 5, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I061 Switch", AFE_CONN63_1, 29, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o064_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I038 Switch", AFE_CONN64_1, 6, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I062 Switch", AFE_CONN64_1, 30, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o065_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I039 Switch", AFE_CONN65_1, 7, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I063 Switch", AFE_CONN65_1, 31, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o066_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I040 Switch", AFE_CONN66_1, 8, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I064 Switch", AFE_CONN66_2, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o067_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I041 Switch", AFE_CONN67_1, 9, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I065 Switch", AFE_CONN67_2, 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o068_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I042 Switch", AFE_CONN68_1, 10, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I066 Switch", AFE_CONN68_2, 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o069_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I043 Switch", AFE_CONN69_1, 11, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I067 Switch", AFE_CONN69_2, 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o070_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I044 Switch", AFE_CONN70_1, 12, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I068 Switch", AFE_CONN70_2, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o071_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I045 Switch", AFE_CONN71_1, 13, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I069 Switch", AFE_CONN71_2, 5, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o072_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN72, 20, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN72, 22, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I046 Switch", AFE_CONN72_1, 14, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN72_2, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o073_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN73, 21, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN73, 23, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I047 Switch", AFE_CONN73_1, 15, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN73_2, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o074_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN74, 24, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I048 Switch", AFE_CONN74_1, 16, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o075_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN75, 25, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I049 Switch", AFE_CONN75_1, 17, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o076_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN76, 26, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I050 Switch", AFE_CONN76_1, 18, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o077_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN77, 27, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I051 Switch", AFE_CONN77_1, 19, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o078_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN78, 28, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I052 Switch", AFE_CONN78_1, 20, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o079_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN79, 29, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I053 Switch", AFE_CONN79_1, 21, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o080_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I030 Switch", AFE_CONN80, 30, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I054 Switch", AFE_CONN80_1, 22, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o081_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I031 Switch", AFE_CONN81, 31, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I055 Switch", AFE_CONN81_1, 23, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o082_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I032 Switch", AFE_CONN82_1, 0, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I056 Switch", AFE_CONN82_1, 24, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o083_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I033 Switch", AFE_CONN83_1, 1, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I057 Switch", AFE_CONN83_1, 25, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o084_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I034 Switch", AFE_CONN84_1, 2, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I058 Switch", AFE_CONN84_1, 26, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o085_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I035 Switch", AFE_CONN85_1, 3, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I059 Switch", AFE_CONN85_1, 27, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o086_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I036 Switch", AFE_CONN86_1, 4, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I060 Switch", AFE_CONN86_1, 28, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o087_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I037 Switch", AFE_CONN87_1, 5, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I061 Switch", AFE_CONN87_1, 29, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o088_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I038 Switch", AFE_CONN88_1, 6, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I062 Switch", AFE_CONN88_1, 30, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o089_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I039 Switch", AFE_CONN89_1, 7, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I063 Switch", AFE_CONN89_1, 31, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o090_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I040 Switch", AFE_CONN90_1, 8, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I064 Switch", AFE_CONN90_2, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o091_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I041 Switch", AFE_CONN91_1, 9, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I065 Switch", AFE_CONN91_2, 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o092_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I042 Switch", AFE_CONN92_1, 10, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I066 Switch", AFE_CONN92_2, 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o093_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I043 Switch", AFE_CONN93_1, 11, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I067 Switch", AFE_CONN93_2, 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o094_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I044 Switch", AFE_CONN94_1, 12, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I068 Switch", AFE_CONN94_2, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o095_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I045 Switch", AFE_CONN95_1, 13, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I069 Switch", AFE_CONN95_2, 5, 1, 0),
+};
+
+static const char * const mt8195_etdm_clk_src_sel_text[] = {
+       "26m",
+       "a1sys_a2sys",
+       "a3sys",
+       "a4sys",
+};
+
+static SOC_ENUM_SINGLE_EXT_DECL(etdmout_clk_src_enum,
+       mt8195_etdm_clk_src_sel_text);
+
+static const char * const hdmitx_dptx_mux_map[] = {
+       "Disconnect", "Connect",
+};
+
+static int hdmitx_dptx_mux_map_value[] = {
+       0, 1,
+};
+
+/* HDMI_OUT_MUX */
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(hdmi_out_mux_map_enum,
+                               SND_SOC_NOPM,
+                               0,
+                               1,
+                               hdmitx_dptx_mux_map,
+                               hdmitx_dptx_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_out_mux_control =
+       SOC_DAPM_ENUM("HDMI_OUT_MUX", hdmi_out_mux_map_enum);
+
+/* DPTX_OUT_MUX */
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(dptx_out_mux_map_enum,
+                               SND_SOC_NOPM,
+                               0,
+                               1,
+                               hdmitx_dptx_mux_map,
+                               hdmitx_dptx_mux_map_value);
+
+static const struct snd_kcontrol_new dptx_out_mux_control =
+       SOC_DAPM_ENUM("DPTX_OUT_MUX", dptx_out_mux_map_enum);
+
+/* HDMI_CH0_MUX ~ HDMI_CH7_MUX */
+static const char *const afe_conn_hdmi_mux_map[] = {
+       "CH0", "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7",
+};
+
+static int afe_conn_hdmi_mux_map_value[] = {
+       0, 1, 2, 3, 4, 5, 6, 7,
+};
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum,
+                               AFE_TDMOUT_CONN0,
+                               0,
+                               0xf,
+                               afe_conn_hdmi_mux_map,
+                               afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch0_mux_control =
+       SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum,
+                               AFE_TDMOUT_CONN0,
+                               4,
+                               0xf,
+                               afe_conn_hdmi_mux_map,
+                               afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch1_mux_control =
+       SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum,
+                               AFE_TDMOUT_CONN0,
+                               8,
+                               0xf,
+                               afe_conn_hdmi_mux_map,
+                               afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch2_mux_control =
+       SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum,
+                               AFE_TDMOUT_CONN0,
+                               12,
+                               0xf,
+                               afe_conn_hdmi_mux_map,
+                               afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch3_mux_control =
+       SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum,
+                               AFE_TDMOUT_CONN0,
+                               16,
+                               0xf,
+                               afe_conn_hdmi_mux_map,
+                               afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch4_mux_control =
+       SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum,
+                               AFE_TDMOUT_CONN0,
+                               20,
+                               0xf,
+                               afe_conn_hdmi_mux_map,
+                               afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch5_mux_control =
+       SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum,
+                               AFE_TDMOUT_CONN0,
+                               24,
+                               0xf,
+                               afe_conn_hdmi_mux_map,
+                               afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch6_mux_control =
+       SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum,
+                               AFE_TDMOUT_CONN0,
+                               28,
+                               0xf,
+                               afe_conn_hdmi_mux_map,
+                               afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch7_mux_control =
+       SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum);
+
+static int mt8195_etdm_clk_src_sel_put(struct snd_kcontrol *kcontrol,
+                                      struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+       unsigned int source = ucontrol->value.enumerated.item[0];
+       unsigned int val;
+       unsigned int mask;
+       unsigned int reg;
+
+       if (source >= e->items)
+               return -EINVAL;
+
+       reg = 0;
+       if (!strcmp(kcontrol->id.name, "ETDM_OUT1_Clock_Source")) {
+               reg = ETDM_OUT1_CON4;
+               mask = ETDM_OUT_CON4_CLOCK_MASK;
+               val = ETDM_OUT_CON4_CLOCK(source);
+       } else if (!strcmp(kcontrol->id.name, "ETDM_OUT2_Clock_Source")) {
+               reg = ETDM_OUT2_CON4;
+               mask = ETDM_OUT_CON4_CLOCK_MASK;
+               val = ETDM_OUT_CON4_CLOCK(source);
+       } else if (!strcmp(kcontrol->id.name, "ETDM_OUT3_Clock_Source")) {
+               reg = ETDM_OUT3_CON4;
+               mask = ETDM_OUT_CON4_CLOCK_MASK;
+               val = ETDM_OUT_CON4_CLOCK(source);
+       } else if (!strcmp(kcontrol->id.name, "ETDM_IN1_Clock_Source")) {
+               reg = ETDM_IN1_CON2;
+               mask = ETDM_IN_CON2_CLOCK_MASK;
+               val = ETDM_IN_CON2_CLOCK(source);
+       } else if (!strcmp(kcontrol->id.name, "ETDM_IN2_Clock_Source")) {
+               reg = ETDM_IN2_CON2;
+               mask = ETDM_IN_CON2_CLOCK_MASK;
+               val = ETDM_IN_CON2_CLOCK(source);
+       }
+
+       if (reg)
+               regmap_update_bits(afe->regmap, reg, mask, val);
+
+       return 0;
+}
+
+static int mt8195_etdm_clk_src_sel_get(struct snd_kcontrol *kcontrol,
+                                      struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component =
+               snd_soc_kcontrol_component(kcontrol);
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+       unsigned int value = 0;
+       unsigned int reg = 0;
+       unsigned int mask = 0;
+       unsigned int shift = 0;
+
+       if (!strcmp(kcontrol->id.name, "ETDM_OUT1_Clock_Source")) {
+               reg = ETDM_OUT1_CON4;
+               mask = ETDM_OUT_CON4_CLOCK_MASK;
+               shift = ETDM_OUT_CON4_CLOCK_SHIFT;
+       } else if (!strcmp(kcontrol->id.name, "ETDM_OUT2_Clock_Source")) {
+               reg = ETDM_OUT2_CON4;
+               mask = ETDM_OUT_CON4_CLOCK_MASK;
+               shift = ETDM_OUT_CON4_CLOCK_SHIFT;
+       } else if (!strcmp(kcontrol->id.name, "ETDM_OUT3_Clock_Source")) {
+               reg = ETDM_OUT3_CON4;
+               mask = ETDM_OUT_CON4_CLOCK_MASK;
+               shift = ETDM_OUT_CON4_CLOCK_SHIFT;
+       } else if (!strcmp(kcontrol->id.name, "ETDM_IN1_Clock_Source")) {
+               reg = ETDM_IN1_CON2;
+               mask = ETDM_IN_CON2_CLOCK_MASK;
+               shift = ETDM_IN_CON2_CLOCK_SHIFT;
+       } else if (!strcmp(kcontrol->id.name, "ETDM_IN2_Clock_Source")) {
+               reg = ETDM_IN2_CON2;
+               mask = ETDM_IN_CON2_CLOCK_MASK;
+               shift = ETDM_IN_CON2_CLOCK_SHIFT;
+       }
+
+       if (reg)
+               regmap_read(afe->regmap, reg, &value);
+
+       value &= mask;
+       value >>= shift;
+       ucontrol->value.enumerated.item[0] = value;
+       return 0;
+}
+
+static const struct snd_kcontrol_new mtk_dai_etdm_controls[] = {
+       SOC_ENUM_EXT("ETDM_OUT1_Clock_Source",
+                    etdmout_clk_src_enum,
+                    mt8195_etdm_clk_src_sel_get,
+                    mt8195_etdm_clk_src_sel_put),
+       SOC_ENUM_EXT("ETDM_OUT2_Clock_Source",
+                    etdmout_clk_src_enum,
+                    mt8195_etdm_clk_src_sel_get,
+                    mt8195_etdm_clk_src_sel_put),
+       SOC_ENUM_EXT("ETDM_OUT3_Clock_Source",
+                    etdmout_clk_src_enum,
+                    mt8195_etdm_clk_src_sel_get,
+                    mt8195_etdm_clk_src_sel_put),
+       SOC_ENUM_EXT("ETDM_IN1_Clock_Source",
+                    etdmout_clk_src_enum,
+                    mt8195_etdm_clk_src_sel_get,
+                    mt8195_etdm_clk_src_sel_put),
+       SOC_ENUM_EXT("ETDM_IN2_Clock_Source",
+                    etdmout_clk_src_enum,
+                    mt8195_etdm_clk_src_sel_get,
+                    mt8195_etdm_clk_src_sel_put),
+};
+
+static const struct snd_soc_dapm_widget mtk_dai_etdm_widgets[] = {
+       /* eTDM_IN2 */
+       SND_SOC_DAPM_MIXER("I012", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I013", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I014", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I015", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I016", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I017", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I018", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I019", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       /* eTDM_IN1 */
+       SND_SOC_DAPM_MIXER("I072", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I073", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I074", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I075", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I076", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I077", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I078", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I079", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I080", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I081", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I082", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I083", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I084", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I085", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I086", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I087", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I088", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I089", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I090", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I091", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I092", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I093", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I094", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I095", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       /* eTDM_OUT2 */
+       SND_SOC_DAPM_MIXER("O048", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o048_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o048_mix)),
+       SND_SOC_DAPM_MIXER("O049", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o049_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o049_mix)),
+       SND_SOC_DAPM_MIXER("O050", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o050_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o050_mix)),
+       SND_SOC_DAPM_MIXER("O051", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o051_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o051_mix)),
+       SND_SOC_DAPM_MIXER("O052", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o052_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o052_mix)),
+       SND_SOC_DAPM_MIXER("O053", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o053_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o053_mix)),
+       SND_SOC_DAPM_MIXER("O054", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o054_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o054_mix)),
+       SND_SOC_DAPM_MIXER("O055", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o055_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o055_mix)),
+       SND_SOC_DAPM_MIXER("O056", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o056_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o056_mix)),
+       SND_SOC_DAPM_MIXER("O057", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o057_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o057_mix)),
+       SND_SOC_DAPM_MIXER("O058", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o058_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o058_mix)),
+       SND_SOC_DAPM_MIXER("O059", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o059_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o059_mix)),
+       SND_SOC_DAPM_MIXER("O060", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o060_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o060_mix)),
+       SND_SOC_DAPM_MIXER("O061", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o061_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o061_mix)),
+       SND_SOC_DAPM_MIXER("O062", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o062_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o062_mix)),
+       SND_SOC_DAPM_MIXER("O063", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o063_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o063_mix)),
+       SND_SOC_DAPM_MIXER("O064", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o064_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o064_mix)),
+       SND_SOC_DAPM_MIXER("O065", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o065_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o065_mix)),
+       SND_SOC_DAPM_MIXER("O066", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o066_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o066_mix)),
+       SND_SOC_DAPM_MIXER("O067", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o067_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o067_mix)),
+       SND_SOC_DAPM_MIXER("O068", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o068_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o068_mix)),
+       SND_SOC_DAPM_MIXER("O069", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o069_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o069_mix)),
+       SND_SOC_DAPM_MIXER("O070", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o070_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o070_mix)),
+       SND_SOC_DAPM_MIXER("O071", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o071_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o071_mix)),
+
+       /* eTDM_OUT1 */
+       SND_SOC_DAPM_MIXER("O072", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o072_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o072_mix)),
+       SND_SOC_DAPM_MIXER("O073", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o073_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o073_mix)),
+       SND_SOC_DAPM_MIXER("O074", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o074_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o074_mix)),
+       SND_SOC_DAPM_MIXER("O075", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o075_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o075_mix)),
+       SND_SOC_DAPM_MIXER("O076", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o076_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o076_mix)),
+       SND_SOC_DAPM_MIXER("O077", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o077_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o077_mix)),
+       SND_SOC_DAPM_MIXER("O078", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o078_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o078_mix)),
+       SND_SOC_DAPM_MIXER("O079", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o079_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o079_mix)),
+       SND_SOC_DAPM_MIXER("O080", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o080_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o080_mix)),
+       SND_SOC_DAPM_MIXER("O081", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o081_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o081_mix)),
+       SND_SOC_DAPM_MIXER("O082", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o082_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o082_mix)),
+       SND_SOC_DAPM_MIXER("O083", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o083_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o083_mix)),
+       SND_SOC_DAPM_MIXER("O084", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o084_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o084_mix)),
+       SND_SOC_DAPM_MIXER("O085", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o085_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o085_mix)),
+       SND_SOC_DAPM_MIXER("O086", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o086_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o086_mix)),
+       SND_SOC_DAPM_MIXER("O087", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o087_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o087_mix)),
+       SND_SOC_DAPM_MIXER("O088", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o088_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o088_mix)),
+       SND_SOC_DAPM_MIXER("O089", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o089_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o089_mix)),
+       SND_SOC_DAPM_MIXER("O090", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o090_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o090_mix)),
+       SND_SOC_DAPM_MIXER("O091", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o091_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o091_mix)),
+       SND_SOC_DAPM_MIXER("O092", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o092_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o092_mix)),
+       SND_SOC_DAPM_MIXER("O093", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o093_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o093_mix)),
+       SND_SOC_DAPM_MIXER("O094", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o094_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o094_mix)),
+       SND_SOC_DAPM_MIXER("O095", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_etdm_o095_mix,
+                          ARRAY_SIZE(mtk_dai_etdm_o095_mix)),
+
+       /* eTDM_OUT3 */
+       SND_SOC_DAPM_MUX("HDMI_OUT_MUX", SND_SOC_NOPM, 0, 0,
+                        &hdmi_out_mux_control),
+       SND_SOC_DAPM_MUX("DPTX_OUT_MUX", SND_SOC_NOPM, 0, 0,
+                        &dptx_out_mux_control),
+
+       SND_SOC_DAPM_MUX("HDMI_CH0_MUX", SND_SOC_NOPM, 0, 0,
+                        &hdmi_ch0_mux_control),
+       SND_SOC_DAPM_MUX("HDMI_CH1_MUX", SND_SOC_NOPM, 0, 0,
+                        &hdmi_ch1_mux_control),
+       SND_SOC_DAPM_MUX("HDMI_CH2_MUX", SND_SOC_NOPM, 0, 0,
+                        &hdmi_ch2_mux_control),
+       SND_SOC_DAPM_MUX("HDMI_CH3_MUX", SND_SOC_NOPM, 0, 0,
+                        &hdmi_ch3_mux_control),
+       SND_SOC_DAPM_MUX("HDMI_CH4_MUX", SND_SOC_NOPM, 0, 0,
+                        &hdmi_ch4_mux_control),
+       SND_SOC_DAPM_MUX("HDMI_CH5_MUX", SND_SOC_NOPM, 0, 0,
+                        &hdmi_ch5_mux_control),
+       SND_SOC_DAPM_MUX("HDMI_CH6_MUX", SND_SOC_NOPM, 0, 0,
+                        &hdmi_ch6_mux_control),
+       SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM, 0, 0,
+                        &hdmi_ch7_mux_control),
+
+       SND_SOC_DAPM_INPUT("ETDM_INPUT"),
+       SND_SOC_DAPM_OUTPUT("ETDM_OUTPUT"),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_etdm_routes[] = {
+       {"I012", NULL, "ETDM2 Capture"},
+       {"I013", NULL, "ETDM2 Capture"},
+       {"I014", NULL, "ETDM2 Capture"},
+       {"I015", NULL, "ETDM2 Capture"},
+       {"I016", NULL, "ETDM2 Capture"},
+       {"I017", NULL, "ETDM2 Capture"},
+       {"I018", NULL, "ETDM2 Capture"},
+       {"I019", NULL, "ETDM2 Capture"},
+
+       {"I072", NULL, "ETDM1 Capture"},
+       {"I073", NULL, "ETDM1 Capture"},
+       {"I074", NULL, "ETDM1 Capture"},
+       {"I075", NULL, "ETDM1 Capture"},
+       {"I076", NULL, "ETDM1 Capture"},
+       {"I077", NULL, "ETDM1 Capture"},
+       {"I078", NULL, "ETDM1 Capture"},
+       {"I079", NULL, "ETDM1 Capture"},
+       {"I080", NULL, "ETDM1 Capture"},
+       {"I081", NULL, "ETDM1 Capture"},
+       {"I082", NULL, "ETDM1 Capture"},
+       {"I083", NULL, "ETDM1 Capture"},
+       {"I084", NULL, "ETDM1 Capture"},
+       {"I085", NULL, "ETDM1 Capture"},
+       {"I086", NULL, "ETDM1 Capture"},
+       {"I087", NULL, "ETDM1 Capture"},
+       {"I088", NULL, "ETDM1 Capture"},
+       {"I089", NULL, "ETDM1 Capture"},
+       {"I090", NULL, "ETDM1 Capture"},
+       {"I091", NULL, "ETDM1 Capture"},
+       {"I092", NULL, "ETDM1 Capture"},
+       {"I093", NULL, "ETDM1 Capture"},
+       {"I094", NULL, "ETDM1 Capture"},
+       {"I095", NULL, "ETDM1 Capture"},
+
+       {"UL8", NULL, "ETDM1 Capture"},
+       {"UL3", NULL, "ETDM2 Capture"},
+
+       {"ETDM2 Playback", NULL, "O048"},
+       {"ETDM2 Playback", NULL, "O049"},
+       {"ETDM2 Playback", NULL, "O050"},
+       {"ETDM2 Playback", NULL, "O051"},
+       {"ETDM2 Playback", NULL, "O052"},
+       {"ETDM2 Playback", NULL, "O053"},
+       {"ETDM2 Playback", NULL, "O054"},
+       {"ETDM2 Playback", NULL, "O055"},
+       {"ETDM2 Playback", NULL, "O056"},
+       {"ETDM2 Playback", NULL, "O057"},
+       {"ETDM2 Playback", NULL, "O058"},
+       {"ETDM2 Playback", NULL, "O059"},
+       {"ETDM2 Playback", NULL, "O060"},
+       {"ETDM2 Playback", NULL, "O061"},
+       {"ETDM2 Playback", NULL, "O062"},
+       {"ETDM2 Playback", NULL, "O063"},
+       {"ETDM2 Playback", NULL, "O064"},
+       {"ETDM2 Playback", NULL, "O065"},
+       {"ETDM2 Playback", NULL, "O066"},
+       {"ETDM2 Playback", NULL, "O067"},
+       {"ETDM2 Playback", NULL, "O068"},
+       {"ETDM2 Playback", NULL, "O069"},
+       {"ETDM2 Playback", NULL, "O070"},
+       {"ETDM2 Playback", NULL, "O071"},
+
+       {"ETDM1 Playback", NULL, "O072"},
+       {"ETDM1 Playback", NULL, "O073"},
+       {"ETDM1 Playback", NULL, "O074"},
+       {"ETDM1 Playback", NULL, "O075"},
+       {"ETDM1 Playback", NULL, "O076"},
+       {"ETDM1 Playback", NULL, "O077"},
+       {"ETDM1 Playback", NULL, "O078"},
+       {"ETDM1 Playback", NULL, "O079"},
+       {"ETDM1 Playback", NULL, "O080"},
+       {"ETDM1 Playback", NULL, "O081"},
+       {"ETDM1 Playback", NULL, "O082"},
+       {"ETDM1 Playback", NULL, "O083"},
+       {"ETDM1 Playback", NULL, "O084"},
+       {"ETDM1 Playback", NULL, "O085"},
+       {"ETDM1 Playback", NULL, "O086"},
+       {"ETDM1 Playback", NULL, "O087"},
+       {"ETDM1 Playback", NULL, "O088"},
+       {"ETDM1 Playback", NULL, "O089"},
+       {"ETDM1 Playback", NULL, "O090"},
+       {"ETDM1 Playback", NULL, "O091"},
+       {"ETDM1 Playback", NULL, "O092"},
+       {"ETDM1 Playback", NULL, "O093"},
+       {"ETDM1 Playback", NULL, "O094"},
+       {"ETDM1 Playback", NULL, "O095"},
+
+       {"O048", "I020 Switch", "I020"},
+       {"O049", "I021 Switch", "I021"},
+
+       {"O048", "I022 Switch", "I022"},
+       {"O049", "I023 Switch", "I023"},
+       {"O050", "I024 Switch", "I024"},
+       {"O051", "I025 Switch", "I025"},
+       {"O052", "I026 Switch", "I026"},
+       {"O053", "I027 Switch", "I027"},
+       {"O054", "I028 Switch", "I028"},
+       {"O055", "I029 Switch", "I029"},
+       {"O056", "I030 Switch", "I030"},
+       {"O057", "I031 Switch", "I031"},
+       {"O058", "I032 Switch", "I032"},
+       {"O059", "I033 Switch", "I033"},
+       {"O060", "I034 Switch", "I034"},
+       {"O061", "I035 Switch", "I035"},
+       {"O062", "I036 Switch", "I036"},
+       {"O063", "I037 Switch", "I037"},
+       {"O064", "I038 Switch", "I038"},
+       {"O065", "I039 Switch", "I039"},
+       {"O066", "I040 Switch", "I040"},
+       {"O067", "I041 Switch", "I041"},
+       {"O068", "I042 Switch", "I042"},
+       {"O069", "I043 Switch", "I043"},
+       {"O070", "I044 Switch", "I044"},
+       {"O071", "I045 Switch", "I045"},
+
+       {"O048", "I046 Switch", "I046"},
+       {"O049", "I047 Switch", "I047"},
+       {"O050", "I048 Switch", "I048"},
+       {"O051", "I049 Switch", "I049"},
+       {"O052", "I050 Switch", "I050"},
+       {"O053", "I051 Switch", "I051"},
+       {"O054", "I052 Switch", "I052"},
+       {"O055", "I053 Switch", "I053"},
+       {"O056", "I054 Switch", "I054"},
+       {"O057", "I055 Switch", "I055"},
+       {"O058", "I056 Switch", "I056"},
+       {"O059", "I057 Switch", "I057"},
+       {"O060", "I058 Switch", "I058"},
+       {"O061", "I059 Switch", "I059"},
+       {"O062", "I060 Switch", "I060"},
+       {"O063", "I061 Switch", "I061"},
+       {"O064", "I062 Switch", "I062"},
+       {"O065", "I063 Switch", "I063"},
+       {"O066", "I064 Switch", "I064"},
+       {"O067", "I065 Switch", "I065"},
+       {"O068", "I066 Switch", "I066"},
+       {"O069", "I067 Switch", "I067"},
+       {"O070", "I068 Switch", "I068"},
+       {"O071", "I069 Switch", "I069"},
+
+       {"O048", "I070 Switch", "I070"},
+       {"O049", "I071 Switch", "I071"},
+
+       {"O072", "I020 Switch", "I020"},
+       {"O073", "I021 Switch", "I021"},
+
+       {"O072", "I022 Switch", "I022"},
+       {"O073", "I023 Switch", "I023"},
+       {"O074", "I024 Switch", "I024"},
+       {"O075", "I025 Switch", "I025"},
+       {"O076", "I026 Switch", "I026"},
+       {"O077", "I027 Switch", "I027"},
+       {"O078", "I028 Switch", "I028"},
+       {"O079", "I029 Switch", "I029"},
+       {"O080", "I030 Switch", "I030"},
+       {"O081", "I031 Switch", "I031"},
+       {"O082", "I032 Switch", "I032"},
+       {"O083", "I033 Switch", "I033"},
+       {"O084", "I034 Switch", "I034"},
+       {"O085", "I035 Switch", "I035"},
+       {"O086", "I036 Switch", "I036"},
+       {"O087", "I037 Switch", "I037"},
+       {"O088", "I038 Switch", "I038"},
+       {"O089", "I039 Switch", "I039"},
+       {"O090", "I040 Switch", "I040"},
+       {"O091", "I041 Switch", "I041"},
+       {"O092", "I042 Switch", "I042"},
+       {"O093", "I043 Switch", "I043"},
+       {"O094", "I044 Switch", "I044"},
+       {"O095", "I045 Switch", "I045"},
+
+       {"O072", "I046 Switch", "I046"},
+       {"O073", "I047 Switch", "I047"},
+       {"O074", "I048 Switch", "I048"},
+       {"O075", "I049 Switch", "I049"},
+       {"O076", "I050 Switch", "I050"},
+       {"O077", "I051 Switch", "I051"},
+       {"O078", "I052 Switch", "I052"},
+       {"O079", "I053 Switch", "I053"},
+       {"O080", "I054 Switch", "I054"},
+       {"O081", "I055 Switch", "I055"},
+       {"O082", "I056 Switch", "I056"},
+       {"O083", "I057 Switch", "I057"},
+       {"O084", "I058 Switch", "I058"},
+       {"O085", "I059 Switch", "I059"},
+       {"O086", "I060 Switch", "I060"},
+       {"O087", "I061 Switch", "I061"},
+       {"O088", "I062 Switch", "I062"},
+       {"O089", "I063 Switch", "I063"},
+       {"O090", "I064 Switch", "I064"},
+       {"O091", "I065 Switch", "I065"},
+       {"O092", "I066 Switch", "I066"},
+       {"O093", "I067 Switch", "I067"},
+       {"O094", "I068 Switch", "I068"},
+       {"O095", "I069 Switch", "I069"},
+
+       {"O072", "I070 Switch", "I070"},
+       {"O073", "I071 Switch", "I071"},
+
+       {"HDMI_CH0_MUX", "CH0", "DL10"},
+       {"HDMI_CH0_MUX", "CH1", "DL10"},
+       {"HDMI_CH0_MUX", "CH2", "DL10"},
+       {"HDMI_CH0_MUX", "CH3", "DL10"},
+       {"HDMI_CH0_MUX", "CH4", "DL10"},
+       {"HDMI_CH0_MUX", "CH5", "DL10"},
+       {"HDMI_CH0_MUX", "CH6", "DL10"},
+       {"HDMI_CH0_MUX", "CH7", "DL10"},
+
+       {"HDMI_CH1_MUX", "CH0", "DL10"},
+       {"HDMI_CH1_MUX", "CH1", "DL10"},
+       {"HDMI_CH1_MUX", "CH2", "DL10"},
+       {"HDMI_CH1_MUX", "CH3", "DL10"},
+       {"HDMI_CH1_MUX", "CH4", "DL10"},
+       {"HDMI_CH1_MUX", "CH5", "DL10"},
+       {"HDMI_CH1_MUX", "CH6", "DL10"},
+       {"HDMI_CH1_MUX", "CH7", "DL10"},
+
+       {"HDMI_CH2_MUX", "CH0", "DL10"},
+       {"HDMI_CH2_MUX", "CH1", "DL10"},
+       {"HDMI_CH2_MUX", "CH2", "DL10"},
+       {"HDMI_CH2_MUX", "CH3", "DL10"},
+       {"HDMI_CH2_MUX", "CH4", "DL10"},
+       {"HDMI_CH2_MUX", "CH5", "DL10"},
+       {"HDMI_CH2_MUX", "CH6", "DL10"},
+       {"HDMI_CH2_MUX", "CH7", "DL10"},
+
+       {"HDMI_CH3_MUX", "CH0", "DL10"},
+       {"HDMI_CH3_MUX", "CH1", "DL10"},
+       {"HDMI_CH3_MUX", "CH2", "DL10"},
+       {"HDMI_CH3_MUX", "CH3", "DL10"},
+       {"HDMI_CH3_MUX", "CH4", "DL10"},
+       {"HDMI_CH3_MUX", "CH5", "DL10"},
+       {"HDMI_CH3_MUX", "CH6", "DL10"},
+       {"HDMI_CH3_MUX", "CH7", "DL10"},
+
+       {"HDMI_CH4_MUX", "CH0", "DL10"},
+       {"HDMI_CH4_MUX", "CH1", "DL10"},
+       {"HDMI_CH4_MUX", "CH2", "DL10"},
+       {"HDMI_CH4_MUX", "CH3", "DL10"},
+       {"HDMI_CH4_MUX", "CH4", "DL10"},
+       {"HDMI_CH4_MUX", "CH5", "DL10"},
+       {"HDMI_CH4_MUX", "CH6", "DL10"},
+       {"HDMI_CH4_MUX", "CH7", "DL10"},
+
+       {"HDMI_CH5_MUX", "CH0", "DL10"},
+       {"HDMI_CH5_MUX", "CH1", "DL10"},
+       {"HDMI_CH5_MUX", "CH2", "DL10"},
+       {"HDMI_CH5_MUX", "CH3", "DL10"},
+       {"HDMI_CH5_MUX", "CH4", "DL10"},
+       {"HDMI_CH5_MUX", "CH5", "DL10"},
+       {"HDMI_CH5_MUX", "CH6", "DL10"},
+       {"HDMI_CH5_MUX", "CH7", "DL10"},
+
+       {"HDMI_CH6_MUX", "CH0", "DL10"},
+       {"HDMI_CH6_MUX", "CH1", "DL10"},
+       {"HDMI_CH6_MUX", "CH2", "DL10"},
+       {"HDMI_CH6_MUX", "CH3", "DL10"},
+       {"HDMI_CH6_MUX", "CH4", "DL10"},
+       {"HDMI_CH6_MUX", "CH5", "DL10"},
+       {"HDMI_CH6_MUX", "CH6", "DL10"},
+       {"HDMI_CH6_MUX", "CH7", "DL10"},
+
+       {"HDMI_CH7_MUX", "CH0", "DL10"},
+       {"HDMI_CH7_MUX", "CH1", "DL10"},
+       {"HDMI_CH7_MUX", "CH2", "DL10"},
+       {"HDMI_CH7_MUX", "CH3", "DL10"},
+       {"HDMI_CH7_MUX", "CH4", "DL10"},
+       {"HDMI_CH7_MUX", "CH5", "DL10"},
+       {"HDMI_CH7_MUX", "CH6", "DL10"},
+       {"HDMI_CH7_MUX", "CH7", "DL10"},
+
+       {"HDMI_OUT_MUX", "Connect", "HDMI_CH0_MUX"},
+       {"HDMI_OUT_MUX", "Connect", "HDMI_CH1_MUX"},
+       {"HDMI_OUT_MUX", "Connect", "HDMI_CH2_MUX"},
+       {"HDMI_OUT_MUX", "Connect", "HDMI_CH3_MUX"},
+       {"HDMI_OUT_MUX", "Connect", "HDMI_CH4_MUX"},
+       {"HDMI_OUT_MUX", "Connect", "HDMI_CH5_MUX"},
+       {"HDMI_OUT_MUX", "Connect", "HDMI_CH6_MUX"},
+       {"HDMI_OUT_MUX", "Connect", "HDMI_CH7_MUX"},
+
+       {"DPTX_OUT_MUX", "Connect", "HDMI_CH0_MUX"},
+       {"DPTX_OUT_MUX", "Connect", "HDMI_CH1_MUX"},
+       {"DPTX_OUT_MUX", "Connect", "HDMI_CH2_MUX"},
+       {"DPTX_OUT_MUX", "Connect", "HDMI_CH3_MUX"},
+       {"DPTX_OUT_MUX", "Connect", "HDMI_CH4_MUX"},
+       {"DPTX_OUT_MUX", "Connect", "HDMI_CH5_MUX"},
+       {"DPTX_OUT_MUX", "Connect", "HDMI_CH6_MUX"},
+       {"DPTX_OUT_MUX", "Connect", "HDMI_CH7_MUX"},
+
+       {"ETDM3 Playback", NULL, "HDMI_OUT_MUX"},
+       {"DPTX Playback", NULL, "DPTX_OUT_MUX"},
+
+       {"ETDM_OUTPUT", NULL, "DPTX Playback"},
+       {"ETDM_OUTPUT", NULL, "ETDM1 Playback"},
+       {"ETDM_OUTPUT", NULL, "ETDM2 Playback"},
+       {"ETDM_OUTPUT", NULL, "ETDM3 Playback"},
+       {"ETDM1 Capture", NULL, "ETDM_INPUT"},
+       {"ETDM2 Capture", NULL, "ETDM_INPUT"},
+};
+
+static int mt8195_afe_enable_etdm(struct mtk_base_afe *afe, int dai_id)
+{
+       int ret = 0;
+       struct etdm_con_reg etdm_reg;
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+       unsigned long flags;
+
+       spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+       etdm_data->en_ref_cnt++;
+       if (etdm_data->en_ref_cnt == 1) {
+               ret = get_etdm_reg(dai_id, &etdm_reg);
+               if (ret < 0)
+                       goto out;
+
+               regmap_update_bits(afe->regmap, etdm_reg.con0,
+                                  ETDM_CON0_EN, ETDM_CON0_EN);
+       }
+out:
+       spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
+       return ret;
+}
+
+static int mt8195_afe_disable_etdm(struct mtk_base_afe *afe, int dai_id)
+{
+       int ret = 0;
+       struct etdm_con_reg etdm_reg;
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+       unsigned long flags;
+
+       spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+       if (etdm_data->en_ref_cnt > 0) {
+               etdm_data->en_ref_cnt--;
+               if (etdm_data->en_ref_cnt == 0) {
+                       ret = get_etdm_reg(dai_id, &etdm_reg);
+                       if (ret < 0)
+                               goto out;
+
+                       regmap_update_bits(afe->regmap, etdm_reg.con0,
+                                          ETDM_CON0_EN, 0);
+               }
+       }
+out:
+       spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
+       return 0;
+}
+
+static int etdm_cowork_slv_sel(int id, int slave_mode)
+{
+       if (slave_mode) {
+               switch (id) {
+               case MT8195_AFE_IO_ETDM1_IN:
+                       return COWORK_ETDM_IN1_S;
+               case MT8195_AFE_IO_ETDM2_IN:
+                       return COWORK_ETDM_IN2_S;
+               case MT8195_AFE_IO_ETDM1_OUT:
+                       return COWORK_ETDM_OUT1_S;
+               case MT8195_AFE_IO_ETDM2_OUT:
+                       return COWORK_ETDM_OUT2_S;
+               case MT8195_AFE_IO_ETDM3_OUT:
+                       return COWORK_ETDM_OUT3_S;
+               default:
+                       return -EINVAL;
+               }
+       } else {
+               switch (id) {
+               case MT8195_AFE_IO_ETDM1_IN:
+                       return COWORK_ETDM_IN1_M;
+               case MT8195_AFE_IO_ETDM2_IN:
+                       return COWORK_ETDM_IN2_M;
+               case MT8195_AFE_IO_ETDM1_OUT:
+                       return COWORK_ETDM_OUT1_M;
+               case MT8195_AFE_IO_ETDM2_OUT:
+                       return COWORK_ETDM_OUT2_M;
+               case MT8195_AFE_IO_ETDM3_OUT:
+                       return COWORK_ETDM_OUT3_M;
+               default:
+                       return -EINVAL;
+               }
+       }
+}
+
+static int mt8195_etdm_sync_mode_configure(struct mtk_base_afe *afe, int dai_id)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+       unsigned int reg = 0;
+       unsigned int mask;
+       unsigned int val;
+       int cowork_source_sel;
+
+       if (etdm_data->cowork_source_id == COWORK_ETDM_NONE)
+               return 0;
+
+       cowork_source_sel = etdm_cowork_slv_sel(etdm_data->cowork_source_id,
+                                               etdm_data->slave_mode);
+       if (cowork_source_sel < 0)
+               return cowork_source_sel;
+
+       switch (dai_id) {
+       case MT8195_AFE_IO_ETDM1_IN:
+               reg = ETDM_COWORK_CON1;
+               mask = ETDM_IN1_SLAVE_SEL_MASK;
+               val = ETDM_IN1_SLAVE_SEL(cowork_source_sel);
+               break;
+       case MT8195_AFE_IO_ETDM2_IN:
+               reg = ETDM_COWORK_CON2;
+               mask = ETDM_IN2_SLAVE_SEL_MASK;
+               val = ETDM_IN2_SLAVE_SEL(cowork_source_sel);
+               break;
+       case MT8195_AFE_IO_ETDM1_OUT:
+               reg = ETDM_COWORK_CON0;
+               mask = ETDM_OUT1_SLAVE_SEL_MASK;
+               val = ETDM_OUT1_SLAVE_SEL(cowork_source_sel);
+               break;
+       case MT8195_AFE_IO_ETDM2_OUT:
+               reg = ETDM_COWORK_CON2;
+               mask = ETDM_OUT2_SLAVE_SEL_MASK;
+               val = ETDM_OUT2_SLAVE_SEL(cowork_source_sel);
+               break;
+       case MT8195_AFE_IO_ETDM3_OUT:
+               reg = ETDM_COWORK_CON2;
+               mask = ETDM_OUT3_SLAVE_SEL_MASK;
+               val = ETDM_OUT3_SLAVE_SEL(cowork_source_sel);
+               break;
+       default:
+               return 0;
+       }
+
+       regmap_update_bits(afe->regmap, reg, mask, val);
+
+       return 0;
+}
+
+static int mtk_dai_etdm_get_cg_id_by_dai_id(int dai_id)
+{
+       int cg_id = -1;
+
+       switch (dai_id) {
+       case MT8195_AFE_IO_DPTX:
+               cg_id = MT8195_CLK_AUD_HDMI_OUT;
+               break;
+       case MT8195_AFE_IO_ETDM1_IN:
+               cg_id = MT8195_CLK_AUD_TDM_IN;
+               break;
+       case MT8195_AFE_IO_ETDM2_IN:
+               cg_id = MT8195_CLK_AUD_I2SIN;
+               break;
+       case MT8195_AFE_IO_ETDM1_OUT:
+               cg_id = MT8195_CLK_AUD_TDM_OUT;
+               break;
+       case MT8195_AFE_IO_ETDM2_OUT:
+               cg_id = MT8195_CLK_AUD_I2S_OUT;
+               break;
+       case MT8195_AFE_IO_ETDM3_OUT:
+               cg_id = MT8195_CLK_AUD_HDMI_OUT;
+               break;
+       default:
+               break;
+       }
+
+       return cg_id;
+}
+
+static int mtk_dai_etdm_get_clk_id_by_dai_id(int dai_id)
+{
+       int clk_id = -1;
+
+       switch (dai_id) {
+       case MT8195_AFE_IO_DPTX:
+               clk_id = MT8195_CLK_TOP_DPTX_M_SEL;
+               break;
+       case MT8195_AFE_IO_ETDM1_IN:
+               clk_id = MT8195_CLK_TOP_I2SI1_M_SEL;
+               break;
+       case MT8195_AFE_IO_ETDM2_IN:
+               clk_id = MT8195_CLK_TOP_I2SI2_M_SEL;
+               break;
+       case MT8195_AFE_IO_ETDM1_OUT:
+               clk_id = MT8195_CLK_TOP_I2SO1_M_SEL;
+               break;
+       case MT8195_AFE_IO_ETDM2_OUT:
+               clk_id = MT8195_CLK_TOP_I2SO2_M_SEL;
+               break;
+       case MT8195_AFE_IO_ETDM3_OUT:
+       default:
+               break;
+       }
+
+       return clk_id;
+}
+
+static int mtk_dai_etdm_get_clkdiv_id_by_dai_id(int dai_id)
+{
+       int clk_id = -1;
+
+       switch (dai_id) {
+       case MT8195_AFE_IO_DPTX:
+               clk_id = MT8195_CLK_TOP_APLL12_DIV9;
+               break;
+       case MT8195_AFE_IO_ETDM1_IN:
+               clk_id = MT8195_CLK_TOP_APLL12_DIV0;
+               break;
+       case MT8195_AFE_IO_ETDM2_IN:
+               clk_id = MT8195_CLK_TOP_APLL12_DIV1;
+               break;
+       case MT8195_AFE_IO_ETDM1_OUT:
+               clk_id = MT8195_CLK_TOP_APLL12_DIV2;
+               break;
+       case MT8195_AFE_IO_ETDM2_OUT:
+               clk_id = MT8195_CLK_TOP_APLL12_DIV3;
+               break;
+       case MT8195_AFE_IO_ETDM3_OUT:
+       default:
+               break;
+       }
+
+       return clk_id;
+}
+
+static int mtk_dai_etdm_enable_mclk(struct mtk_base_afe *afe, int dai_id)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id);
+
+       if (clkdiv_id < 0)
+               return -EINVAL;
+
+       mt8195_afe_enable_clk(afe, afe_priv->clk[clkdiv_id]);
+
+       return 0;
+}
+
+static int mtk_dai_etdm_disable_mclk(struct mtk_base_afe *afe, int dai_id)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id);
+
+       if (clkdiv_id < 0)
+               return -EINVAL;
+
+       mt8195_afe_disable_clk(afe, afe_priv->clk[clkdiv_id]);
+
+       return 0;
+}
+
+/* dai ops */
+static int mtk_dai_etdm_startup(struct snd_pcm_substream *substream,
+                               struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *mst_etdm_data;
+       int cg_id;
+       int mst_dai_id;
+       int slv_dai_id;
+       int i;
+
+       if (is_cowork_mode(dai)) {
+               mst_dai_id = get_etdm_cowork_master_id(dai);
+               mtk_dai_etdm_enable_mclk(afe, mst_dai_id);
+
+               cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(mst_dai_id);
+               if (cg_id >= 0)
+                       mt8195_afe_enable_clk(afe, afe_priv->clk[cg_id]);
+
+               mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
+
+               for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
+                       slv_dai_id = mst_etdm_data->cowork_slv_id[i];
+                       cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(slv_dai_id);
+                       if (cg_id >= 0)
+                               mt8195_afe_enable_clk(afe,
+                                                     afe_priv->clk[cg_id]);
+               }
+       } else {
+               mtk_dai_etdm_enable_mclk(afe, dai->id);
+
+               cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id);
+               if (cg_id >= 0)
+                       mt8195_afe_enable_clk(afe, afe_priv->clk[cg_id]);
+       }
+
+       return 0;
+}
+
+static void mtk_dai_etdm_shutdown(struct snd_pcm_substream *substream,
+                                 struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *mst_etdm_data;
+       int cg_id;
+       int mst_dai_id;
+       int slv_dai_id;
+       int i;
+
+       if (is_cowork_mode(dai)) {
+               mst_dai_id = get_etdm_cowork_master_id(dai);
+               cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(mst_dai_id);
+               if (cg_id >= 0)
+                       mt8195_afe_disable_clk(afe, afe_priv->clk[cg_id]);
+
+               mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
+               for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
+                       slv_dai_id = mst_etdm_data->cowork_slv_id[i];
+                       cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(slv_dai_id);
+                       if (cg_id >= 0)
+                               mt8195_afe_disable_clk(afe,
+                                                      afe_priv->clk[cg_id]);
+               }
+               mtk_dai_etdm_disable_mclk(afe, mst_dai_id);
+       } else {
+               cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id);
+               if (cg_id >= 0)
+                       mt8195_afe_disable_clk(afe, afe_priv->clk[cg_id]);
+
+               mtk_dai_etdm_disable_mclk(afe, dai->id);
+       }
+}
+
+static int mtk_dai_etdm_fifo_mode(struct mtk_base_afe *afe,
+                                 int dai_id, unsigned int rate)
+{
+       unsigned int mode = 0;
+       unsigned int reg = 0;
+       unsigned int val = 0;
+       unsigned int mask = (ETDM_IN_AFIFO_MODE_MASK | ETDM_IN_USE_AFIFO);
+
+       if (rate != 0)
+               mode = mt8195_afe_fs_timing(rate);
+
+       switch (dai_id) {
+       case MT8195_AFE_IO_ETDM1_IN:
+               reg = ETDM_IN1_AFIFO_CON;
+               if (rate == 0)
+                       mode = MT8195_ETDM_IN1_1X_EN;
+               break;
+       case MT8195_AFE_IO_ETDM2_IN:
+               reg = ETDM_IN2_AFIFO_CON;
+               if (rate == 0)
+                       mode = MT8195_ETDM_IN2_1X_EN;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       val = (mode | ETDM_IN_USE_AFIFO);
+
+       regmap_update_bits(afe->regmap, reg, mask, val);
+       return 0;
+}
+
+static int mtk_dai_etdm_in_configure(struct mtk_base_afe *afe,
+                                    unsigned int rate,
+                                    unsigned int channels,
+                                    int dai_id)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+       struct etdm_con_reg etdm_reg;
+       bool slave_mode = etdm_data->slave_mode;
+       unsigned int data_mode = etdm_data->data_mode;
+       unsigned int lrck_width = etdm_data->lrck_width;
+       unsigned int val = 0;
+       unsigned int mask = 0;
+       int i;
+       int ret;
+
+       dev_dbg(afe->dev, "%s rate %u channels %u, id %d\n",
+               __func__, rate, channels, dai_id);
+
+       ret = get_etdm_reg(dai_id, &etdm_reg);
+       if (ret < 0)
+               return ret;
+
+       if (etdm_data->cowork_source_id != COWORK_ETDM_NONE)
+               slave_mode = true;
+
+       /* afifo */
+       if (slave_mode)
+               mtk_dai_etdm_fifo_mode(afe, dai_id, 0);
+       else
+               mtk_dai_etdm_fifo_mode(afe, dai_id, rate);
+
+       /* con1 */
+       if (lrck_width > 0) {
+               mask |= (ETDM_IN_CON1_LRCK_AUTO_MODE |
+                       ETDM_IN_CON1_LRCK_WIDTH_MASK);
+               val |= ETDM_IN_CON1_LRCK_WIDTH(lrck_width);
+       }
+       regmap_update_bits(afe->regmap, etdm_reg.con1, mask, val);
+
+       mask = 0;
+       val = 0;
+
+       /* con2 */
+       if (!slave_mode) {
+               mask |= ETDM_IN_CON2_UPDATE_GAP_MASK;
+               if (rate == 352800 || rate == 384000)
+                       val |= ETDM_IN_CON2_UPDATE_GAP(4);
+               else
+                       val |= ETDM_IN_CON2_UPDATE_GAP(3);
+       }
+       mask |= (ETDM_IN_CON2_MULTI_IP_2CH_MODE |
+               ETDM_IN_CON2_MULTI_IP_TOTAL_CH_MASK);
+       if (data_mode == MTK_DAI_ETDM_DATA_MULTI_PIN) {
+               val |= ETDM_IN_CON2_MULTI_IP_2CH_MODE |
+                      ETDM_IN_CON2_MULTI_IP_TOTAL_CH(channels);
+       }
+       regmap_update_bits(afe->regmap, etdm_reg.con2, mask, val);
+
+       mask = 0;
+       val = 0;
+
+       /* con3 */
+       mask |= ETDM_IN_CON3_DISABLE_OUT_MASK;
+       for (i = 0; i < channels; i += 2) {
+               if (etdm_data->in_disable_ch[i] &&
+                   etdm_data->in_disable_ch[i + 1])
+                       val |= ETDM_IN_CON3_DISABLE_OUT(i >> 1);
+       }
+       if (!slave_mode) {
+               mask |= ETDM_IN_CON3_FS_MASK;
+               val |= ETDM_IN_CON3_FS(get_etdm_fs_timing(rate));
+       }
+       regmap_update_bits(afe->regmap, etdm_reg.con3, mask, val);
+
+       mask = 0;
+       val = 0;
+
+       /* con4 */
+       mask |= (ETDM_IN_CON4_MASTER_LRCK_INV | ETDM_IN_CON4_MASTER_BCK_INV |
+               ETDM_IN_CON4_SLAVE_LRCK_INV | ETDM_IN_CON4_SLAVE_BCK_INV);
+       if (slave_mode) {
+               if (etdm_data->lrck_inv)
+                       val |= ETDM_IN_CON4_SLAVE_LRCK_INV;
+               if (etdm_data->bck_inv)
+                       val |= ETDM_IN_CON4_SLAVE_BCK_INV;
+       } else {
+               if (etdm_data->lrck_inv)
+                       val |= ETDM_IN_CON4_MASTER_LRCK_INV;
+               if (etdm_data->bck_inv)
+                       val |= ETDM_IN_CON4_MASTER_BCK_INV;
+       }
+       regmap_update_bits(afe->regmap, etdm_reg.con4, mask, val);
+
+       mask = 0;
+       val = 0;
+
+       /* con5 */
+       mask |= ETDM_IN_CON5_LR_SWAP_MASK;
+       mask |= ETDM_IN_CON5_ENABLE_ODD_MASK;
+       for (i = 0; i < channels; i += 2) {
+               if (etdm_data->in_disable_ch[i] &&
+                   !etdm_data->in_disable_ch[i + 1]) {
+                       if (i == (channels - 2))
+                               val |= ETDM_IN_CON5_LR_SWAP(15);
+                       else
+                               val |= ETDM_IN_CON5_LR_SWAP(i >> 1);
+                       val |= ETDM_IN_CON5_ENABLE_ODD(i >> 1);
+               } else if (!etdm_data->in_disable_ch[i] &&
+                          etdm_data->in_disable_ch[i + 1]) {
+                       val |= ETDM_IN_CON5_ENABLE_ODD(i >> 1);
+               }
+       }
+       regmap_update_bits(afe->regmap, etdm_reg.con5, mask, val);
+       return 0;
+}
+
+static int mtk_dai_etdm_out_configure(struct mtk_base_afe *afe,
+                                     unsigned int rate,
+                                     unsigned int channels,
+                                     int dai_id)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+       struct etdm_con_reg etdm_reg;
+       bool slave_mode = etdm_data->slave_mode;
+       unsigned int lrck_width = etdm_data->lrck_width;
+       unsigned int val = 0;
+       unsigned int mask = 0;
+       int ret;
+       int fs = 0;
+
+       dev_dbg(afe->dev, "%s rate %u channels %u, id %d\n",
+               __func__, rate, channels, dai_id);
+
+       ret = get_etdm_reg(dai_id, &etdm_reg);
+       if (ret < 0)
+               return ret;
+
+       if (etdm_data->cowork_source_id != COWORK_ETDM_NONE)
+               slave_mode = true;
+
+       /* con0 */
+       mask = ETDM_OUT_CON0_RELATCH_DOMAIN_MASK;
+       val = ETDM_OUT_CON0_RELATCH_DOMAIN(ETDM_RELATCH_TIMING_A1A2SYS);
+       regmap_update_bits(afe->regmap, etdm_reg.con0, mask, val);
+
+       mask = 0;
+       val = 0;
+
+       /* con1 */
+       if (lrck_width > 0) {
+               mask |= (ETDM_OUT_CON1_LRCK_AUTO_MODE |
+                       ETDM_OUT_CON1_LRCK_WIDTH_MASK);
+               val |= ETDM_OUT_CON1_LRCK_WIDTH(lrck_width);
+       }
+       regmap_update_bits(afe->regmap, etdm_reg.con1, mask, val);
+
+       mask = 0;
+       val = 0;
+
+       if (slave_mode) {
+               /* con2 */
+               mask = (ETDM_OUT_CON2_LRCK_DELAY_BCK_INV |
+                       ETDM_OUT_CON2_LRCK_DELAY_0P5T_EN);
+               val = (ETDM_OUT_CON2_LRCK_DELAY_BCK_INV |
+                       ETDM_OUT_CON2_LRCK_DELAY_0P5T_EN);
+               regmap_update_bits(afe->regmap, etdm_reg.con2,
+                                  mask, val);
+               mask = 0;
+               val = 0;
+       } else {
+               /* con4 */
+               mask |= ETDM_OUT_CON4_FS_MASK;
+               val |= ETDM_OUT_CON4_FS(get_etdm_fs_timing(rate));
+       }
+
+       mask |= ETDM_OUT_CON4_RELATCH_EN_MASK;
+       if (dai_id == MT8195_AFE_IO_ETDM1_OUT)
+               fs = MT8195_ETDM_OUT1_1X_EN;
+       else if (dai_id == MT8195_AFE_IO_ETDM2_OUT)
+               fs = MT8195_ETDM_OUT2_1X_EN;
+
+       val |= ETDM_OUT_CON4_RELATCH_EN(fs);
+
+       regmap_update_bits(afe->regmap, etdm_reg.con4, mask, val);
+
+       mask = 0;
+       val = 0;
+
+       /* con5 */
+       mask |= (ETDM_OUT_CON5_MASTER_LRCK_INV | ETDM_OUT_CON5_MASTER_BCK_INV |
+               ETDM_OUT_CON5_SLAVE_LRCK_INV | ETDM_OUT_CON5_SLAVE_BCK_INV);
+       if (slave_mode) {
+               if (etdm_data->lrck_inv)
+                       val |= ETDM_OUT_CON5_SLAVE_LRCK_INV;
+               if (etdm_data->bck_inv)
+                       val |= ETDM_OUT_CON5_SLAVE_BCK_INV;
+       } else {
+               if (etdm_data->lrck_inv)
+                       val |= ETDM_OUT_CON5_MASTER_LRCK_INV;
+               if (etdm_data->bck_inv)
+                       val |= ETDM_OUT_CON5_MASTER_BCK_INV;
+       }
+       regmap_update_bits(afe->regmap, etdm_reg.con5, mask, val);
+
+       return 0;
+}
+
+static int mtk_dai_etdm_mclk_configure(struct mtk_base_afe *afe, int dai_id)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+       int clk_id = mtk_dai_etdm_get_clk_id_by_dai_id(dai_id);
+       int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id);
+       int apll;
+       int apll_clk_id;
+       struct etdm_con_reg etdm_reg;
+       unsigned int val = 0;
+       unsigned int mask = 0;
+       int ret = 0;
+
+       if (clk_id < 0 || clkdiv_id < 0)
+               return 0;
+
+       ret = get_etdm_reg(dai_id, &etdm_reg);
+       if (ret < 0)
+               return ret;
+
+       mask |= ETDM_CON1_MCLK_OUTPUT;
+       if (etdm_data->mclk_dir == SND_SOC_CLOCK_OUT)
+               val |= ETDM_CON1_MCLK_OUTPUT;
+       regmap_update_bits(afe->regmap, etdm_reg.con1, mask, val);
+
+       if (etdm_data->mclk_freq) {
+               apll = etdm_data->mclk_apll;
+               apll_clk_id = mt8195_afe_get_mclk_source_clk_id(apll);
+               if (apll_clk_id < 0)
+                       return apll_clk_id;
+
+               /* select apll */
+               ret = mt8195_afe_set_clk_parent(afe, afe_priv->clk[clk_id],
+                                               afe_priv->clk[apll_clk_id]);
+               if (ret)
+                       return ret;
+
+               /* set rate */
+               ret = mt8195_afe_set_clk_rate(afe, afe_priv->clk[clkdiv_id],
+                                             etdm_data->mclk_freq);
+       } else {
+               if (etdm_data->mclk_dir == SND_SOC_CLOCK_OUT)
+                       dev_dbg(afe->dev, "%s mclk freq = 0\n", __func__);
+       }
+       return ret;
+}
+
+static int mtk_dai_etdm_configure(struct mtk_base_afe *afe,
+                                 unsigned int rate,
+                                 unsigned int channels,
+                                 unsigned int bit_width,
+                                 int dai_id)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+       struct etdm_con_reg etdm_reg;
+       bool slave_mode = etdm_data->slave_mode;
+       unsigned int etdm_channels;
+       unsigned int val = 0;
+       unsigned int mask = 0;
+       unsigned int bck;
+       unsigned int wlen = get_etdm_wlen(bit_width);
+       int ret;
+
+       ret = get_etdm_reg(dai_id, &etdm_reg);
+       if (ret < 0)
+               return ret;
+
+       if (etdm_data->cowork_source_id != COWORK_ETDM_NONE)
+               slave_mode = true;
+
+       dev_dbg(afe->dev, "%s fmt %u data %u lrck %d-%u bck %d, clock %u slv %u\n",
+               __func__, etdm_data->format, etdm_data->data_mode,
+               etdm_data->lrck_inv, etdm_data->lrck_width, etdm_data->bck_inv,
+               etdm_data->clock_mode, etdm_data->slave_mode);
+       dev_dbg(afe->dev, "%s rate %u channels %u bitwidth %u, id %d\n",
+               __func__, rate, channels, bit_width, dai_id);
+
+       etdm_channels = (etdm_data->data_mode == MTK_DAI_ETDM_DATA_ONE_PIN) ?
+                       get_etdm_ch_fixup(channels) : 2;
+
+       bck = rate * etdm_channels * wlen;
+       if (bck > MT8195_ETDM_NORMAL_MAX_BCK_RATE) {
+               dev_info(afe->dev, "%s bck rate %u not support\n",
+                        __func__, bck);
+               return -EINVAL;
+       }
+
+       /* con0 */
+       mask |= ETDM_CON0_BIT_LEN_MASK;
+       val |= ETDM_CON0_BIT_LEN(bit_width);
+       mask |= ETDM_CON0_WORD_LEN_MASK;
+       val |= ETDM_CON0_WORD_LEN(wlen);
+       mask |= ETDM_CON0_FORMAT_MASK;
+       val |= ETDM_CON0_FORMAT(etdm_data->format);
+       mask |= ETDM_CON0_CH_NUM_MASK;
+       val |= ETDM_CON0_CH_NUM(etdm_channels);
+
+       mask |= ETDM_CON0_SLAVE_MODE;
+       if (slave_mode) {
+               if (dai_id == MT8195_AFE_IO_ETDM1_OUT &&
+                   etdm_data->cowork_source_id == COWORK_ETDM_NONE) {
+                       dev_info(afe->dev, "%s id %d only support master mode\n",
+                                __func__, dai_id);
+                       return -EINVAL;
+               }
+               val |= ETDM_CON0_SLAVE_MODE;
+       }
+       regmap_update_bits(afe->regmap, etdm_reg.con0, mask, val);
+
+       if (get_etdm_dir(dai_id) == ETDM_IN)
+               mtk_dai_etdm_in_configure(afe, rate, channels, dai_id);
+       else
+               mtk_dai_etdm_out_configure(afe, rate, channels, dai_id);
+
+       return 0;
+}
+
+static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream,
+                                 struct snd_pcm_hw_params *params,
+                                 struct snd_soc_dai *dai)
+{
+       int ret = 0;
+       unsigned int rate = params_rate(params);
+       unsigned int bit_width = params_width(params);
+       unsigned int channels = params_channels(params);
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *mst_etdm_data;
+       int mst_dai_id;
+       int slv_dai_id;
+       int i;
+
+       dev_dbg(afe->dev, "%s '%s' period %u-%u\n",
+               __func__, snd_pcm_stream_str(substream),
+               params_period_size(params), params_periods(params));
+
+       if (is_cowork_mode(dai)) {
+               mst_dai_id = get_etdm_cowork_master_id(dai);
+
+               ret = mtk_dai_etdm_mclk_configure(afe, mst_dai_id);
+               if (ret)
+                       return ret;
+
+               ret = mtk_dai_etdm_configure(afe, rate, channels,
+                                            bit_width, mst_dai_id);
+               if (ret)
+                       return ret;
+
+               mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
+               for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
+                       slv_dai_id = mst_etdm_data->cowork_slv_id[i];
+                       ret = mtk_dai_etdm_configure(afe, rate, channels,
+                                                    bit_width, slv_dai_id);
+                       if (ret)
+                               return ret;
+
+                       ret = mt8195_etdm_sync_mode_configure(afe, slv_dai_id);
+                       if (ret)
+                               return ret;
+               }
+       } else {
+               ret = mtk_dai_etdm_mclk_configure(afe, dai->id);
+               if (ret)
+                       return ret;
+
+               ret = mtk_dai_etdm_configure(afe, rate, channels,
+                                            bit_width, dai->id);
+       }
+
+       return ret;
+}
+
+static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd,
+                               struct snd_soc_dai *dai)
+{
+       int ret = 0;
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *mst_etdm_data;
+       int mst_dai_id;
+       int slv_dai_id;
+       int i;
+
+       dev_dbg(afe->dev, "%s(), cmd %d, dai id %d\n", __func__, cmd, dai->id);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+               if (is_cowork_mode(dai)) {
+                       mst_dai_id = get_etdm_cowork_master_id(dai);
+                       mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
+
+                       //open master first
+                       ret |= mt8195_afe_enable_etdm(afe, mst_dai_id);
+                       for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
+                               slv_dai_id = mst_etdm_data->cowork_slv_id[i];
+                               ret |= mt8195_afe_enable_etdm(afe, slv_dai_id);
+                       }
+               } else {
+                       ret = mt8195_afe_enable_etdm(afe, dai->id);
+               }
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               if (is_cowork_mode(dai)) {
+                       mst_dai_id = get_etdm_cowork_master_id(dai);
+                       mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
+
+                       for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
+                               slv_dai_id = mst_etdm_data->cowork_slv_id[i];
+                               ret |= mt8195_afe_disable_etdm(afe, slv_dai_id);
+                       }
+                       // close master at last
+                       ret |= mt8195_afe_disable_etdm(afe, mst_dai_id);
+               } else {
+                       ret = mt8195_afe_disable_etdm(afe, dai->id);
+               }
+               break;
+       default:
+               break;
+       }
+       return ret;
+}
+
+static int mtk_dai_etdm_cal_mclk(struct mtk_base_afe *afe, int freq, int dai_id)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+       int apll;
+       int apll_rate;
+
+       if (freq == 0) {
+               etdm_data->mclk_freq = freq;
+               return 0;
+       }
+
+       apll = mt8195_afe_get_default_mclk_source_by_rate(freq);
+       apll_rate = mt8195_afe_get_mclk_source_rate(afe, apll);
+
+       if (freq > apll_rate) {
+               dev_info(afe->dev, "freq %d > apll rate %d\n", freq, apll_rate);
+               return -EINVAL;
+       }
+
+       if (apll_rate % freq != 0) {
+               dev_info(afe->dev, "APLL%d cannot generate freq Hz\n", apll);
+               return -EINVAL;
+       }
+
+       etdm_data->mclk_apll = apll;
+       etdm_data->mclk_freq = freq;
+
+       return 0;
+}
+
+static int mtk_dai_etdm_set_sysclk(struct snd_soc_dai *dai,
+                                  int clk_id, unsigned int freq, int dir)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+       int dai_id;
+
+       dev_dbg(dai->dev, "%s id %d freq %u, dir %d\n",
+               __func__, dai->id, freq, dir);
+       if (is_cowork_mode(dai))
+               dai_id = get_etdm_cowork_master_id(dai);
+       else
+               dai_id = dai->id;
+
+       etdm_data = afe_priv->dai_priv[dai_id];
+       etdm_data->mclk_dir = dir;
+       return mtk_dai_etdm_cal_mclk(afe, freq, dai_id);
+}
+
+static int mtk_dai_etdm_set_tdm_slot(struct snd_soc_dai *dai,
+                                    unsigned int tx_mask, unsigned int rx_mask,
+                                    int slots, int slot_width)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+
+       dev_dbg(dai->dev, "%s id %d slot_width %d\n",
+               __func__, dai->id, slot_width);
+
+       etdm_data->slots = slots;
+       etdm_data->lrck_width = slot_width;
+       return 0;
+}
+
+static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               etdm_data->format = MTK_DAI_ETDM_FORMAT_I2S;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               etdm_data->format = MTK_DAI_ETDM_FORMAT_LJ;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               etdm_data->format = MTK_DAI_ETDM_FORMAT_RJ;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPA;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPB;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               etdm_data->bck_inv = false;
+               etdm_data->lrck_inv = false;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               etdm_data->bck_inv = false;
+               etdm_data->lrck_inv = true;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               etdm_data->bck_inv = true;
+               etdm_data->lrck_inv = false;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               etdm_data->bck_inv = true;
+               etdm_data->lrck_inv = true;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               etdm_data->slave_mode = true;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               etdm_data->slave_mode = false;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int mtk_dai_hdmitx_dptx_startup(struct snd_pcm_substream *substream,
+                                      struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       int cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id);
+
+       if (cg_id >= 0)
+               mt8195_afe_enable_clk(afe, afe_priv->clk[cg_id]);
+
+       mtk_dai_etdm_enable_mclk(afe, dai->id);
+
+       return 0;
+}
+
+static void mtk_dai_hdmitx_dptx_shutdown(struct snd_pcm_substream *substream,
+                                        struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       int cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id);
+
+       mtk_dai_etdm_disable_mclk(afe, dai->id);
+
+       if (cg_id >= 0)
+               mt8195_afe_disable_clk(afe, afe_priv->clk[cg_id]);
+}
+
+static unsigned int mtk_dai_get_dptx_ch_en(unsigned int channel)
+{
+       switch (channel) {
+       case 1 ... 2:
+               return AFE_DPTX_CON_CH_EN_2CH;
+       case 3 ... 4:
+               return AFE_DPTX_CON_CH_EN_4CH;
+       case 5 ... 6:
+               return AFE_DPTX_CON_CH_EN_6CH;
+       case 7 ... 8:
+               return AFE_DPTX_CON_CH_EN_8CH;
+       default:
+               return AFE_DPTX_CON_CH_EN_2CH;
+       }
+}
+
+static unsigned int mtk_dai_get_dptx_ch(unsigned int ch)
+{
+       return (ch > 2) ?
+               AFE_DPTX_CON_CH_NUM_8CH : AFE_DPTX_CON_CH_NUM_2CH;
+}
+
+static unsigned int mtk_dai_get_dptx_wlen(snd_pcm_format_t format)
+{
+       return snd_pcm_format_physical_width(format) <= 16 ?
+               AFE_DPTX_CON_16BIT : AFE_DPTX_CON_24BIT;
+}
+
+static int mtk_dai_hdmitx_dptx_hw_params(struct snd_pcm_substream *substream,
+                                        struct snd_pcm_hw_params *params,
+                                        struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+       unsigned int rate = params_rate(params);
+       unsigned int channels = params_channels(params);
+       snd_pcm_format_t format = params_format(params);
+       int width = snd_pcm_format_physical_width(format);
+       int ret = 0;
+
+       /* dptx configure */
+       if (dai->id == MT8195_AFE_IO_DPTX) {
+               regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+                                  AFE_DPTX_CON_CH_EN_MASK,
+                                  mtk_dai_get_dptx_ch_en(channels));
+               regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+                                  AFE_DPTX_CON_CH_NUM_MASK,
+                                  mtk_dai_get_dptx_ch(channels));
+               regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+                                  AFE_DPTX_CON_16BIT_MASK,
+                                  mtk_dai_get_dptx_wlen(format));
+
+               if (mtk_dai_get_dptx_ch(channels) == AFE_DPTX_CON_CH_NUM_8CH) {
+                       etdm_data->data_mode = MTK_DAI_ETDM_DATA_ONE_PIN;
+                       channels = 8;
+               } else {
+                       channels = 2;
+               }
+       } else {
+               etdm_data->data_mode = MTK_DAI_ETDM_DATA_MULTI_PIN;
+       }
+
+       ret = mtk_dai_etdm_mclk_configure(afe, dai->id);
+       if (ret)
+               return ret;
+
+       ret = mtk_dai_etdm_configure(afe, rate, channels, width, dai->id);
+
+       return ret;
+}
+
+static int mtk_dai_hdmitx_dptx_trigger(struct snd_pcm_substream *substream,
+                                      int cmd,
+                                      struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       int ret = 0;
+
+       dev_dbg(afe->dev, "%s(), cmd %d, dai id %d\n", __func__, cmd, dai->id);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+               /* enable dptx interface */
+               if (dai->id == MT8195_AFE_IO_DPTX)
+                       regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+                                          AFE_DPTX_CON_ON_MASK,
+                                          AFE_DPTX_CON_ON);
+
+               /* enable etdm_out3 */
+               ret = mt8195_afe_enable_etdm(afe, dai->id);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               /* disable etdm_out3 */
+               ret = mt8195_afe_disable_etdm(afe, dai->id);
+
+               /* disable dptx interface */
+               if (dai->id == MT8195_AFE_IO_DPTX)
+                       regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+                                          AFE_DPTX_CON_ON_MASK, 0);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+static int mtk_dai_hdmitx_dptx_set_sysclk(struct snd_soc_dai *dai,
+                                         int clk_id,
+                                         unsigned int freq,
+                                         int dir)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+
+       dev_dbg(dai->dev, "%s id %d freq %u, dir %d\n",
+               __func__, dai->id, freq, dir);
+
+       etdm_data->mclk_dir = dir;
+       return mtk_dai_etdm_cal_mclk(afe, freq, dai->id);
+}
+
+static const struct snd_soc_dai_ops mtk_dai_etdm_ops = {
+       .startup = mtk_dai_etdm_startup,
+       .shutdown = mtk_dai_etdm_shutdown,
+       .hw_params = mtk_dai_etdm_hw_params,
+       .trigger = mtk_dai_etdm_trigger,
+       .set_sysclk = mtk_dai_etdm_set_sysclk,
+       .set_fmt = mtk_dai_etdm_set_fmt,
+       .set_tdm_slot = mtk_dai_etdm_set_tdm_slot,
+};
+
+static const struct snd_soc_dai_ops mtk_dai_hdmitx_dptx_ops = {
+       .startup        = mtk_dai_hdmitx_dptx_startup,
+       .shutdown       = mtk_dai_hdmitx_dptx_shutdown,
+       .hw_params      = mtk_dai_hdmitx_dptx_hw_params,
+       .trigger        = mtk_dai_hdmitx_dptx_trigger,
+       .set_sysclk     = mtk_dai_hdmitx_dptx_set_sysclk,
+       .set_fmt        = mtk_dai_etdm_set_fmt,
+};
+
+/* dai driver */
+#define MTK_ETDM_RATES (SNDRV_PCM_RATE_8000_384000)
+
+#define MTK_ETDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+                         SNDRV_PCM_FMTBIT_S24_LE |\
+                         SNDRV_PCM_FMTBIT_S32_LE)
+
+static int mtk_dai_etdm_probe(struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+
+       dev_dbg(dai->dev, "%s id %d\n", __func__, dai->id);
+
+       if (etdm_data->mclk_freq) {
+               dev_dbg(afe->dev, "MCLK always on, rate %d\n",
+                       etdm_data->mclk_freq);
+               pm_runtime_get_sync(afe->dev);
+               mtk_dai_etdm_mclk_configure(afe, dai->id);
+               mtk_dai_etdm_enable_mclk(afe, dai->id);
+               pm_runtime_put_sync(afe->dev);
+       }
+       return 0;
+}
+
+static struct snd_soc_dai_driver mtk_dai_etdm_driver[] = {
+       {
+               .name = "DPTX",
+               .id = MT8195_AFE_IO_DPTX,
+               .playback = {
+                       .stream_name = "DPTX Playback",
+                       .channels_min = 1,
+                       .channels_max = 8,
+                       .rates = MTK_ETDM_RATES,
+                       .formats = MTK_ETDM_FORMATS,
+               },
+               .ops = &mtk_dai_hdmitx_dptx_ops,
+       },
+       {
+               .name = "ETDM1_IN",
+               .id = MT8195_AFE_IO_ETDM1_IN,
+               .capture = {
+                       .stream_name = "ETDM1 Capture",
+                       .channels_min = 1,
+                       .channels_max = 24,
+                       .rates = MTK_ETDM_RATES,
+                       .formats = MTK_ETDM_FORMATS,
+               },
+               .ops = &mtk_dai_etdm_ops,
+               .probe = mtk_dai_etdm_probe,
+       },
+       {
+               .name = "ETDM2_IN",
+               .id = MT8195_AFE_IO_ETDM2_IN,
+               .capture = {
+                       .stream_name = "ETDM2 Capture",
+                       .channels_min = 1,
+                       .channels_max = 16,
+                       .rates = MTK_ETDM_RATES,
+                       .formats = MTK_ETDM_FORMATS,
+               },
+               .ops = &mtk_dai_etdm_ops,
+               .probe = mtk_dai_etdm_probe,
+       },
+       {
+               .name = "ETDM1_OUT",
+               .id = MT8195_AFE_IO_ETDM1_OUT,
+               .playback = {
+                       .stream_name = "ETDM1 Playback",
+                       .channels_min = 1,
+                       .channels_max = 24,
+                       .rates = MTK_ETDM_RATES,
+                       .formats = MTK_ETDM_FORMATS,
+               },
+               .ops = &mtk_dai_etdm_ops,
+               .probe = mtk_dai_etdm_probe,
+       },
+       {
+               .name = "ETDM2_OUT",
+               .id = MT8195_AFE_IO_ETDM2_OUT,
+               .playback = {
+                       .stream_name = "ETDM2 Playback",
+                       .channels_min = 1,
+                       .channels_max = 24,
+                       .rates = MTK_ETDM_RATES,
+                       .formats = MTK_ETDM_FORMATS,
+               },
+               .ops = &mtk_dai_etdm_ops,
+               .probe = mtk_dai_etdm_probe,
+       },
+       {
+               .name = "ETDM3_OUT",
+               .id = MT8195_AFE_IO_ETDM3_OUT,
+               .playback = {
+                       .stream_name = "ETDM3 Playback",
+                       .channels_min = 1,
+                       .channels_max = 8,
+                       .rates = MTK_ETDM_RATES,
+                       .formats = MTK_ETDM_FORMATS,
+               },
+               .ops = &mtk_dai_hdmitx_dptx_ops,
+               .probe = mtk_dai_etdm_probe,
+       },
+};
+
+static void mt8195_etdm_update_sync_info(struct mtk_base_afe *afe)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data;
+       struct mtk_dai_etdm_priv *mst_data;
+       int i;
+       int mst_dai_id;
+
+       for (i = MT8195_AFE_IO_ETDM_START; i < MT8195_AFE_IO_ETDM_END; i++) {
+               etdm_data = afe_priv->dai_priv[i];
+               if (etdm_data->cowork_source_id != COWORK_ETDM_NONE) {
+                       mst_dai_id = etdm_data->cowork_source_id;
+                       mst_data = afe_priv->dai_priv[mst_dai_id];
+                       if (mst_data->cowork_source_id != COWORK_ETDM_NONE)
+                               dev_info(afe->dev, "%s [%d] wrong sync source\n"
+                                        , __func__, i);
+                       mst_data->cowork_slv_id[mst_data->cowork_slv_count] = i;
+                       mst_data->cowork_slv_count++;
+               }
+       }
+}
+
+static void mt8195_dai_etdm_parse_of(struct mtk_base_afe *afe)
+{
+       const struct device_node *of_node = afe->dev->of_node;
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_data;
+       int i, j;
+       char prop[48];
+       u8 disable_chn[MT8195_ETDM_MAX_CHANNELS];
+       int max_chn = MT8195_ETDM_MAX_CHANNELS;
+       u32 sel;
+       int ret;
+       int dai_id;
+       unsigned int sync_id;
+       struct {
+               const char *name;
+               const unsigned int sync_id;
+       } of_afe_etdms[MT8195_AFE_IO_ETDM_NUM] = {
+               {"etdm-in1", ETDM_SYNC_FROM_IN1},
+               {"etdm-in2", ETDM_SYNC_FROM_IN2},
+               {"etdm-out1", ETDM_SYNC_FROM_OUT1},
+               {"etdm-out2", ETDM_SYNC_FROM_OUT2},
+               {"etdm-out3", ETDM_SYNC_FROM_OUT3},
+       };
+
+       for (i = 0; i < MT8195_AFE_IO_ETDM_NUM; i++) {
+               dai_id = ETDM_TO_DAI_ID(i);
+               etdm_data = afe_priv->dai_priv[dai_id];
+
+               ret = snprintf(prop, sizeof(prop),
+                              "mediatek,%s-mclk-always-on-rate",
+                              of_afe_etdms[i].name);
+               if (ret < 0) {
+                       dev_info(afe->dev, "%s snprintf err=%d\n",
+                                __func__, ret);
+                       return;
+               }
+               ret = of_property_read_u32(of_node, prop, &sel);
+               if (ret == 0) {
+                       etdm_data->mclk_dir = SND_SOC_CLOCK_OUT;
+                       if (mtk_dai_etdm_cal_mclk(afe, sel, dai_id))
+                               dev_info(afe->dev, "%s unsupported mclk %uHz\n",
+                                        __func__, sel);
+               }
+
+               ret = snprintf(prop, sizeof(prop),
+                              "mediatek,%s-multi-pin-mode",
+                              of_afe_etdms[i].name);
+               if (ret < 0) {
+                       dev_info(afe->dev, "%s snprintf err=%d\n",
+                                __func__, ret);
+                       return;
+               }
+               etdm_data->data_mode = of_property_read_bool(of_node, prop);
+
+               ret = snprintf(prop, sizeof(prop),
+                              "mediatek,%s-cowork-source",
+                              of_afe_etdms[i].name);
+               if (ret < 0) {
+                       dev_info(afe->dev, "%s snprintf err=%d\n",
+                                __func__, ret);
+                       return;
+               }
+               ret = of_property_read_u32(of_node, prop, &sel);
+               if (ret == 0) {
+                       if (sel >= MT8195_AFE_IO_ETDM_NUM) {
+                               dev_info(afe->dev, "%s invalid id=%d\n",
+                                        __func__, sel);
+                               etdm_data->cowork_source_id = COWORK_ETDM_NONE;
+                       } else {
+                               sync_id = of_afe_etdms[sel].sync_id;
+                               etdm_data->cowork_source_id =
+                                       sync_to_dai_id(sync_id);
+                       }
+               } else {
+                       etdm_data->cowork_source_id = COWORK_ETDM_NONE;
+               }
+       }
+
+       /* etdm in only */
+       for (i = 0; i < 2; i++) {
+               ret = snprintf(prop, sizeof(prop),
+                              "mediatek,%s-chn-disabled",
+                              of_afe_etdms[i].name);
+               if (ret < 0) {
+                       dev_info(afe->dev, "%s snprintf err=%d\n",
+                                __func__, ret);
+                       return;
+               }
+               ret = of_property_read_variable_u8_array(of_node, prop,
+                                                        disable_chn,
+                                                        1, max_chn);
+               if (ret < 0)
+                       continue;
+
+               for (j = 0; j < ret; j++) {
+                       if (disable_chn[j] >= MT8195_ETDM_MAX_CHANNELS)
+                               dev_info(afe->dev, "%s [%d] invalid chn %u\n",
+                                        __func__, j, disable_chn[j]);
+                       else
+                               etdm_data->in_disable_ch[disable_chn[j]] = true;
+               }
+       }
+       mt8195_etdm_update_sync_info(afe);
+}
+
+static int init_etdm_priv_data(struct mtk_base_afe *afe)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_etdm_priv *etdm_priv;
+       int i;
+
+       for (i = MT8195_AFE_IO_ETDM_START; i < MT8195_AFE_IO_ETDM_END; i++) {
+               etdm_priv = devm_kzalloc(afe->dev,
+                                        sizeof(struct mtk_dai_etdm_priv),
+                                        GFP_KERNEL);
+               if (!etdm_priv)
+                       return -ENOMEM;
+
+               afe_priv->dai_priv[i] = etdm_priv;
+       }
+
+       afe_priv->dai_priv[MT8195_AFE_IO_DPTX] =
+               afe_priv->dai_priv[MT8195_AFE_IO_ETDM3_OUT];
+
+       mt8195_dai_etdm_parse_of(afe);
+       return 0;
+}
+
+int mt8195_dai_etdm_register(struct mtk_base_afe *afe)
+{
+       struct mtk_base_afe_dai *dai;
+
+       dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+       if (!dai)
+               return -ENOMEM;
+
+       list_add(&dai->list, &afe->sub_dais);
+
+       dai->dai_drivers = mtk_dai_etdm_driver;
+       dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_etdm_driver);
+
+       dai->dapm_widgets = mtk_dai_etdm_widgets;
+       dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_etdm_widgets);
+       dai->dapm_routes = mtk_dai_etdm_routes;
+       dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_etdm_routes);
+       dai->controls = mtk_dai_etdm_controls;
+       dai->num_controls = ARRAY_SIZE(mtk_dai_etdm_controls);
+
+       return init_etdm_priv_data(afe);
+}
diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c
new file mode 100644 (file)
index 0000000..5d10d2c
--- /dev/null
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek ALSA SoC Audio DAI PCM I/F Control
+ *
+ * Copyright (c) 2020 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ *         Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include "mt8195-afe-clk.h"
+#include "mt8195-afe-common.h"
+#include "mt8195-reg.h"
+
+enum {
+       MTK_DAI_PCM_FMT_I2S,
+       MTK_DAI_PCM_FMT_EIAJ,
+       MTK_DAI_PCM_FMT_MODEA,
+       MTK_DAI_PCM_FMT_MODEB,
+};
+
+enum {
+       MTK_DAI_PCM_CLK_A1SYS,
+       MTK_DAI_PCM_CLK_A2SYS,
+       MTK_DAI_PCM_CLK_26M_48K,
+       MTK_DAI_PCM_CLK_26M_441K,
+};
+
+struct mtk_dai_pcm_rate {
+       unsigned int rate;
+       unsigned int reg_value;
+};
+
+struct mtk_dai_pcmif_priv {
+       unsigned int slave_mode;
+       unsigned int lrck_inv;
+       unsigned int bck_inv;
+       unsigned int format;
+};
+
+static const struct mtk_dai_pcm_rate mtk_dai_pcm_rates[] = {
+       { .rate = 8000, .reg_value = 0, },
+       { .rate = 16000, .reg_value = 1, },
+       { .rate = 32000, .reg_value = 2, },
+       { .rate = 48000, .reg_value = 3, },
+       { .rate = 11025, .reg_value = 1, },
+       { .rate = 22050, .reg_value = 2, },
+       { .rate = 44100, .reg_value = 3, },
+};
+
+static int mtk_dai_pcm_mode(unsigned int rate)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mtk_dai_pcm_rates); i++)
+               if (mtk_dai_pcm_rates[i].rate == rate)
+                       return mtk_dai_pcm_rates[i].reg_value;
+
+       return -EINVAL;
+}
+
+static const struct snd_kcontrol_new mtk_dai_pcm_o000_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN0, 0, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN0_2, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_pcm_o001_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN1, 1, 1, 0),
+       SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN1_2, 7, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = {
+       SND_SOC_DAPM_MIXER("I002", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I003", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("O000", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_pcm_o000_mix,
+                          ARRAY_SIZE(mtk_dai_pcm_o000_mix)),
+       SND_SOC_DAPM_MIXER("O001", SND_SOC_NOPM, 0, 0,
+                          mtk_dai_pcm_o001_mix,
+                          ARRAY_SIZE(mtk_dai_pcm_o001_mix)),
+
+       SND_SOC_DAPM_INPUT("PCM1_INPUT"),
+       SND_SOC_DAPM_OUTPUT("PCM1_OUTPUT"),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = {
+       {"I002", NULL, "PCM1 Capture"},
+       {"I003", NULL, "PCM1 Capture"},
+
+       {"O000", "I000 Switch", "I000"},
+       {"O001", "I001 Switch", "I001"},
+
+       {"O000", "I070 Switch", "I070"},
+       {"O001", "I071 Switch", "I071"},
+
+       {"PCM1 Playback", NULL, "O000"},
+       {"PCM1 Playback", NULL, "O001"},
+
+       {"PCM1_OUTPUT", NULL, "PCM1 Playback"},
+       {"PCM1 Capture", NULL, "PCM1_INPUT"},
+};
+
+static void mtk_dai_pcm_enable(struct mtk_base_afe *afe)
+{
+       regmap_update_bits(afe->regmap, PCM_INTF_CON1,
+                          PCM_INTF_CON1_PCM_EN, PCM_INTF_CON1_PCM_EN);
+}
+
+static void mtk_dai_pcm_disable(struct mtk_base_afe *afe)
+{
+       regmap_update_bits(afe->regmap, PCM_INTF_CON1,
+                          PCM_INTF_CON1_PCM_EN, 0x0);
+}
+
+static int mtk_dai_pcm_configure(struct snd_pcm_substream *substream,
+                                struct snd_soc_dai *dai)
+{
+       struct snd_pcm_runtime * const runtime = substream->runtime;
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_pcmif_priv *pcmif_priv = afe_priv->dai_priv[dai->id];
+       unsigned int slave_mode = pcmif_priv->slave_mode;
+       unsigned int lrck_inv = pcmif_priv->lrck_inv;
+       unsigned int bck_inv = pcmif_priv->bck_inv;
+       unsigned int fmt = pcmif_priv->format;
+       unsigned int bit_width = dai->sample_bits;
+       unsigned int val = 0;
+       unsigned int mask = 0;
+       int fs = 0;
+       int mode = 0;
+
+       /* sync freq mode */
+       fs = mt8195_afe_fs_timing(runtime->rate);
+       if (fs < 0)
+               return -EINVAL;
+       val |= PCM_INTF_CON2_SYNC_FREQ_MODE(fs);
+       mask |= PCM_INTF_CON2_SYNC_FREQ_MODE_MASK;
+
+       /* clk domain sel */
+       if (runtime->rate % 8000)
+               val |= PCM_INTF_CON2_CLK_DOMAIN_SEL(MTK_DAI_PCM_CLK_26M_441K);
+       else
+               val |= PCM_INTF_CON2_CLK_DOMAIN_SEL(MTK_DAI_PCM_CLK_26M_48K);
+       mask |= PCM_INTF_CON2_CLK_DOMAIN_SEL_MASK;
+
+       regmap_update_bits(afe->regmap, PCM_INTF_CON2, mask, val);
+
+       val = 0;
+       mask = 0;
+
+       /* pcm mode */
+       mode = mtk_dai_pcm_mode(runtime->rate);
+       if (mode < 0)
+               return -EINVAL;
+       val |= PCM_INTF_CON1_PCM_MODE(mode);
+       mask |= PCM_INTF_CON1_PCM_MODE_MASK;
+
+       /* pcm format */
+       val |= PCM_INTF_CON1_PCM_FMT(fmt);
+       mask |= PCM_INTF_CON1_PCM_FMT_MASK;
+
+       /* pcm sync length */
+       if (fmt == MTK_DAI_PCM_FMT_MODEA ||
+           fmt == MTK_DAI_PCM_FMT_MODEB)
+               val |= PCM_INTF_CON1_SYNC_LENGTH(1);
+       else
+               val |= PCM_INTF_CON1_SYNC_LENGTH(bit_width);
+       mask |= PCM_INTF_CON1_SYNC_LENGTH_MASK;
+
+       /* pcm bits, word length */
+       if (bit_width > 16) {
+               val |= PCM_INTF_CON1_PCM_24BIT;
+               val |= PCM_INTF_CON1_PCM_WLEN_64BCK;
+       } else {
+               val |= PCM_INTF_CON1_PCM_16BIT;
+               val |= PCM_INTF_CON1_PCM_WLEN_32BCK;
+       }
+       mask |= PCM_INTF_CON1_PCM_BIT_MASK;
+       mask |= PCM_INTF_CON1_PCM_WLEN_MASK;
+
+       /* master/slave */
+       if (!slave_mode) {
+               val |= PCM_INTF_CON1_PCM_MASTER;
+
+               if (lrck_inv)
+                       val |= PCM_INTF_CON1_SYNC_OUT_INV;
+               if (bck_inv)
+                       val |= PCM_INTF_CON1_BCLK_OUT_INV;
+               mask |= PCM_INTF_CON1_CLK_OUT_INV_MASK;
+       } else {
+               val |= PCM_INTF_CON1_PCM_SLAVE;
+
+               if (lrck_inv)
+                       val |= PCM_INTF_CON1_SYNC_IN_INV;
+               if (bck_inv)
+                       val |= PCM_INTF_CON1_BCLK_IN_INV;
+               mask |= PCM_INTF_CON1_CLK_IN_INV_MASK;
+
+               /* TODO: add asrc setting for slave mode */
+       }
+       mask |= PCM_INTF_CON1_PCM_M_S_MASK;
+
+       regmap_update_bits(afe->regmap, PCM_INTF_CON1, mask, val);
+
+       return 0;
+}
+
+/* dai ops */
+static int mtk_dai_pcm_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+
+       if (dai->component->active)
+               return 0;
+
+       mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC11]);
+       mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC12]);
+       mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_PCMIF]);
+
+       return 0;
+}
+
+static void mtk_dai_pcm_shutdown(struct snd_pcm_substream *substream,
+                                struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+
+       if (dai->component->active)
+               return;
+
+       mtk_dai_pcm_disable(afe);
+
+       mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_PCMIF]);
+       mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC12]);
+       mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC11]);
+}
+
+static int mtk_dai_pcm_prepare(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       int ret = 0;
+
+       if (snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK) &&
+           snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE))
+               return 0;
+
+       ret = mtk_dai_pcm_configure(substream, dai);
+       if (ret)
+               return ret;
+
+       mtk_dai_pcm_enable(afe);
+
+       return 0;
+}
+
+static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_pcmif_priv *pcmif_priv = afe_priv->dai_priv[dai->id];
+
+       dev_dbg(dai->dev, "%s fmt 0x%x\n", __func__, fmt);
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               pcmif_priv->format = MTK_DAI_PCM_FMT_I2S;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               pcmif_priv->format = MTK_DAI_PCM_FMT_MODEA;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               pcmif_priv->format = MTK_DAI_PCM_FMT_MODEB;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               pcmif_priv->bck_inv = 0;
+               pcmif_priv->lrck_inv = 0;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               pcmif_priv->bck_inv = 0;
+               pcmif_priv->lrck_inv = 1;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               pcmif_priv->bck_inv = 1;
+               pcmif_priv->lrck_inv = 0;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               pcmif_priv->bck_inv = 1;
+               pcmif_priv->lrck_inv = 1;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               pcmif_priv->slave_mode = 1;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               pcmif_priv->slave_mode = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_pcm_ops = {
+       .startup        = mtk_dai_pcm_startup,
+       .shutdown       = mtk_dai_pcm_shutdown,
+       .prepare        = mtk_dai_pcm_prepare,
+       .set_fmt        = mtk_dai_pcm_set_fmt,
+};
+
+/* dai driver */
+#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000)
+
+#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+                        SNDRV_PCM_FMTBIT_S24_LE |\
+                        SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
+       {
+               .name = "PCM1",
+               .id = MT8195_AFE_IO_PCM,
+               .playback = {
+                       .stream_name = "PCM1 Playback",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .capture = {
+                       .stream_name = "PCM1 Capture",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = MTK_PCM_RATES,
+                       .formats = MTK_PCM_FORMATS,
+               },
+               .ops = &mtk_dai_pcm_ops,
+               .symmetric_rate = 1,
+               .symmetric_sample_bits = 1,
+       },
+};
+
+static int init_pcmif_priv_data(struct mtk_base_afe *afe)
+{
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtk_dai_pcmif_priv *pcmif_priv;
+
+       pcmif_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_pcmif_priv),
+                                 GFP_KERNEL);
+       if (!pcmif_priv)
+               return -ENOMEM;
+
+       afe_priv->dai_priv[MT8195_AFE_IO_PCM] = pcmif_priv;
+       return 0;
+}
+
+int mt8195_dai_pcm_register(struct mtk_base_afe *afe)
+{
+       struct mtk_base_afe_dai *dai;
+
+       dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+       if (!dai)
+               return -ENOMEM;
+
+       list_add(&dai->list, &afe->sub_dais);
+
+       dai->dai_drivers = mtk_dai_pcm_driver;
+       dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver);
+
+       dai->dapm_widgets = mtk_dai_pcm_widgets;
+       dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets);
+       dai->dapm_routes = mtk_dai_pcm_routes;
+       dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes);
+
+       return init_pcmif_priv_data(afe);
+}
diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c b/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c
new file mode 100644 (file)
index 0000000..5dc217f
--- /dev/null
@@ -0,0 +1,1087 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// mt8195-mt6359-rt1019-rt5682.c  --
+//     MT8195-MT6359-RT1019-RT6358 ALSA SoC machine driver
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Trevor Wu <trevor.wu@mediatek.com>
+//
+
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <sound/jack.h>
+#include <sound/pcm_params.h>
+#include <sound/rt5682.h>
+#include <sound/soc.h>
+#include "../../codecs/mt6359.h"
+#include "../../codecs/rt5682.h"
+#include "../common/mtk-afe-platform-driver.h"
+#include "mt8195-afe-common.h"
+
+#define RT1019_CODEC_DAI       "HiFi"
+#define RT1019_DEV0_NAME       "rt1019p"
+
+#define RT5682_CODEC_DAI       "rt5682-aif1"
+#define RT5682_DEV0_NAME       "rt5682.2-001a"
+
+struct mt8195_mt6359_rt1019_rt5682_priv {
+       struct snd_soc_jack headset_jack;
+       struct snd_soc_jack dp_jack;
+       struct snd_soc_jack hdmi_jack;
+};
+
+static const struct snd_soc_dapm_widget
+       mt8195_mt6359_rt1019_rt5682_widgets[] = {
+       SND_SOC_DAPM_SPK("Speakers", NULL),
+       SND_SOC_DAPM_HP("Headphone Jack", NULL),
+       SND_SOC_DAPM_MIC("Headset Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route mt8195_mt6359_rt1019_rt5682_routes[] = {
+       /* speaker */
+       { "Speakers", NULL, "Speaker" },
+       /* headset */
+       { "Headphone Jack", NULL, "HPOL" },
+       { "Headphone Jack", NULL, "HPOR" },
+       { "IN1P", NULL, "Headset Mic" },
+};
+
+static const struct snd_kcontrol_new mt8195_mt6359_rt1019_rt5682_controls[] = {
+       SOC_DAPM_PIN_SWITCH("Speakers"),
+       SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+       SOC_DAPM_PIN_SWITCH("Headset Mic"),
+};
+
+static int mt8195_rt5682_etdm_hw_params(struct snd_pcm_substream *substream,
+                                       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_card *card = rtd->card;
+       struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+       struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+       unsigned int rate = params_rate(params);
+       unsigned int mclk_fs_ratio = 128;
+       unsigned int mclk_fs = rate * mclk_fs_ratio;
+       int bitwidth;
+       int ret;
+
+       bitwidth = snd_pcm_format_width(params_format(params));
+       if (bitwidth < 0) {
+               dev_err(card->dev, "invalid bit width: %d\n", bitwidth);
+               return bitwidth;
+       }
+
+       ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth);
+       if (ret) {
+               dev_err(card->dev, "failed to set tdm slot\n");
+               return ret;
+       }
+
+       ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL1,
+                                 RT5682_PLL1_S_BCLK1,
+                                 params_rate(params) * 64,
+                                 params_rate(params) * 512);
+       if (ret) {
+               dev_err(card->dev, "failed to set pll\n");
+               return ret;
+       }
+
+       ret = snd_soc_dai_set_sysclk(codec_dai,
+                                    RT5682_SCLK_S_PLL1,
+                                    params_rate(params) * 512,
+                                    SND_SOC_CLOCK_IN);
+       if (ret) {
+               dev_err(card->dev, "failed to set sysclk\n");
+               return ret;
+       }
+
+       return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT);
+}
+
+static const struct snd_soc_ops mt8195_rt5682_etdm_ops = {
+       .hw_params = mt8195_rt5682_etdm_hw_params,
+};
+
+#define CKSYS_AUD_TOP_CFG 0x032c
+#define CKSYS_AUD_TOP_MON 0x0330
+
+static int mt8195_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_component *cmpnt_afe =
+               snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
+       struct snd_soc_component *cmpnt_codec =
+               asoc_rtd_to_codec(rtd, 0)->component;
+       struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
+       struct mt8195_afe_private *afe_priv = afe->platform_priv;
+       struct mtkaif_param *param = &afe_priv->mtkaif_params;
+       int phase;
+       unsigned int monitor;
+       int mtkaif_calibration_num_phase;
+       int test_done_1, test_done_2, test_done_3;
+       int cycle_1, cycle_2, cycle_3;
+       int prev_cycle_1, prev_cycle_2, prev_cycle_3;
+       int chosen_phase_1, chosen_phase_2, chosen_phase_3;
+       int counter;
+       bool mtkaif_calibration_ok;
+       int mtkaif_chosen_phase[MT8195_MTKAIF_MISO_NUM];
+       int mtkaif_phase_cycle[MT8195_MTKAIF_MISO_NUM];
+       int i;
+
+       dev_info(afe->dev, "%s(), start\n", __func__);
+
+       param->mtkaif_calibration_ok = false;
+       for (i = 0; i < MT8195_MTKAIF_MISO_NUM; i++) {
+               param->mtkaif_chosen_phase[i] = -1;
+               param->mtkaif_phase_cycle[i] = 0;
+               mtkaif_chosen_phase[i] = -1;
+               mtkaif_phase_cycle[i] = 0;
+       }
+
+       if (IS_ERR(afe_priv->topckgen)) {
+               dev_info(afe->dev, "%s() Cannot find topckgen controller\n",
+                        __func__);
+               return 0;
+       }
+
+       pm_runtime_get_sync(afe->dev);
+       mt6359_mtkaif_calibration_enable(cmpnt_codec);
+
+       /* set test type to synchronizer pulse */
+       regmap_update_bits(afe_priv->topckgen,
+                          CKSYS_AUD_TOP_CFG, 0xffff, 0x4);
+       mtkaif_calibration_num_phase = 42;      /* mt6359: 0 ~ 42 */
+       mtkaif_calibration_ok = true;
+
+       for (phase = 0;
+            phase <= mtkaif_calibration_num_phase && mtkaif_calibration_ok;
+            phase++) {
+               mt6359_set_mtkaif_calibration_phase(cmpnt_codec,
+                                                   phase, phase, phase);
+
+               regmap_update_bits(afe_priv->topckgen,
+                                  CKSYS_AUD_TOP_CFG, 0x1, 0x1);
+
+               test_done_1 = 0;
+               test_done_2 = 0;
+               test_done_3 = 0;
+               cycle_1 = -1;
+               cycle_2 = -1;
+               cycle_3 = -1;
+               counter = 0;
+               while (!(test_done_1 & test_done_2 & test_done_3)) {
+                       regmap_read(afe_priv->topckgen,
+                                   CKSYS_AUD_TOP_MON, &monitor);
+                       test_done_1 = (monitor >> 28) & 0x1;
+                       test_done_2 = (monitor >> 29) & 0x1;
+                       test_done_3 = (monitor >> 30) & 0x1;
+                       if (test_done_1 == 1)
+                               cycle_1 = monitor & 0xf;
+
+                       if (test_done_2 == 1)
+                               cycle_2 = (monitor >> 4) & 0xf;
+
+                       if (test_done_3 == 1)
+                               cycle_3 = (monitor >> 8) & 0xf;
+
+                       /* handle if never test done */
+                       if (++counter > 10000) {
+                               dev_info(afe->dev, "%s(), test fail, cycle_1 %d, cycle_2 %d, cycle_3 %d, monitor 0x%x\n",
+                                        __func__,
+                                        cycle_1, cycle_2, cycle_3, monitor);
+                               mtkaif_calibration_ok = false;
+                               break;
+                       }
+               }
+
+               if (phase == 0) {
+                       prev_cycle_1 = cycle_1;
+                       prev_cycle_2 = cycle_2;
+                       prev_cycle_3 = cycle_3;
+               }
+
+               if (cycle_1 != prev_cycle_1 &&
+                   mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] < 0) {
+                       mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] = phase - 1;
+                       mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0] = prev_cycle_1;
+               }
+
+               if (cycle_2 != prev_cycle_2 &&
+                   mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] < 0) {
+                       mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] = phase - 1;
+                       mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1] = prev_cycle_2;
+               }
+
+               if (cycle_3 != prev_cycle_3 &&
+                   mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] < 0) {
+                       mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] = phase - 1;
+                       mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2] = prev_cycle_3;
+               }
+
+               regmap_update_bits(afe_priv->topckgen,
+                                  CKSYS_AUD_TOP_CFG, 0x1, 0x0);
+
+               if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] >= 0 &&
+                   mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] >= 0 &&
+                   mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] >= 0)
+                       break;
+       }
+
+       if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] < 0) {
+               mtkaif_calibration_ok = false;
+               chosen_phase_1 = 0;
+       } else {
+               chosen_phase_1 = mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0];
+       }
+
+       if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] < 0) {
+               mtkaif_calibration_ok = false;
+               chosen_phase_2 = 0;
+       } else {
+               chosen_phase_2 = mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1];
+       }
+
+       if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] < 0) {
+               mtkaif_calibration_ok = false;
+               chosen_phase_3 = 0;
+       } else {
+               chosen_phase_3 = mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2];
+       }
+
+       mt6359_set_mtkaif_calibration_phase(cmpnt_codec,
+                                           chosen_phase_1,
+                                           chosen_phase_2,
+                                           chosen_phase_3);
+
+       mt6359_mtkaif_calibration_disable(cmpnt_codec);
+       pm_runtime_put(afe->dev);
+
+       param->mtkaif_calibration_ok = mtkaif_calibration_ok;
+       param->mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] = chosen_phase_1;
+       param->mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] = chosen_phase_2;
+       param->mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] = chosen_phase_3;
+       for (i = 0; i < MT8195_MTKAIF_MISO_NUM; i++)
+               param->mtkaif_phase_cycle[i] = mtkaif_phase_cycle[i];
+
+       dev_info(afe->dev, "%s(), end, calibration ok %d\n",
+                __func__, param->mtkaif_calibration_ok);
+
+       return 0;
+}
+
+static int mt8195_mt6359_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_component *cmpnt_codec =
+               asoc_rtd_to_codec(rtd, 0)->component;
+
+       /* set mtkaif protocol */
+       mt6359_set_mtkaif_protocol(cmpnt_codec,
+                                  MT6359_MTKAIF_PROTOCOL_2_CLK_P2);
+
+       /* mtkaif calibration */
+       mt8195_mt6359_mtkaif_calibration(rtd);
+
+       return 0;
+}
+
+static int mt8195_rt5682_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_component *cmpnt_codec =
+               asoc_rtd_to_codec(rtd, 0)->component;
+       struct mt8195_mt6359_rt1019_rt5682_priv *priv =
+               snd_soc_card_get_drvdata(rtd->card);
+       struct snd_soc_jack *jack = &priv->headset_jack;
+       int ret;
+
+       ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
+                                   SND_JACK_HEADSET | SND_JACK_BTN_0 |
+                                   SND_JACK_BTN_1 | SND_JACK_BTN_2 |
+                                   SND_JACK_BTN_3,
+                                   jack, NULL, 0);
+       if (ret) {
+               dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
+               return ret;
+       }
+
+       snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+       snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+       snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+       snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
+
+       ret = snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
+       if (ret) {
+               dev_err(rtd->dev, "Headset Jack set failed: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+};
+
+static int mt8195_etdm_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+                                      struct snd_pcm_hw_params *params)
+{
+       /* fix BE i2s format to 32bit, clean param mask first */
+       snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
+                            0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
+
+       params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+
+       return 0;
+}
+
+static int mt8195_hdmitx_dptx_startup(struct snd_pcm_substream *substream)
+{
+       static const unsigned int rates[] = {
+               48000
+       };
+       static const unsigned int channels[] = {
+               2, 4, 6, 8
+       };
+       static const struct snd_pcm_hw_constraint_list constraints_rates = {
+               .count = ARRAY_SIZE(rates),
+               .list  = rates,
+               .mask = 0,
+       };
+       static const struct snd_pcm_hw_constraint_list constraints_channels = {
+               .count = ARRAY_SIZE(channels),
+               .list  = channels,
+               .mask = 0,
+       };
+
+       struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int ret;
+
+       ret = snd_pcm_hw_constraint_list(runtime, 0,
+                                        SNDRV_PCM_HW_PARAM_RATE,
+                                        &constraints_rates);
+       if (ret < 0) {
+               dev_err(rtd->dev, "hw_constraint_list rate failed\n");
+               return ret;
+       }
+
+       ret = snd_pcm_hw_constraint_list(runtime, 0,
+                                        SNDRV_PCM_HW_PARAM_CHANNELS,
+                                        &constraints_channels);
+       if (ret < 0) {
+               dev_err(rtd->dev, "hw_constraint_list channel failed\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static const struct snd_soc_ops mt8195_hdmitx_dptx_playback_ops = {
+       .startup = mt8195_hdmitx_dptx_startup,
+};
+
+static int mt8195_dptx_hw_params(struct snd_pcm_substream *substream,
+                                struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+       unsigned int rate = params_rate(params);
+       unsigned int mclk_fs_ratio = 256;
+       unsigned int mclk_fs = rate * mclk_fs_ratio;
+
+       return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs,
+                                     SND_SOC_CLOCK_OUT);
+}
+
+static struct snd_soc_ops mt8195_dptx_ops = {
+       .hw_params = mt8195_dptx_hw_params,
+};
+
+static int mt8195_dptx_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct mt8195_mt6359_rt1019_rt5682_priv *priv =
+               snd_soc_card_get_drvdata(rtd->card);
+       struct snd_soc_component *cmpnt_codec =
+               asoc_rtd_to_codec(rtd, 0)->component;
+       int ret = 0;
+
+       ret = snd_soc_card_jack_new(rtd->card, "DP Jack", SND_JACK_LINEOUT,
+                                   &priv->dp_jack, NULL, 0);
+       if (ret)
+               return ret;
+
+       return snd_soc_component_set_jack(cmpnt_codec, &priv->dp_jack, NULL);
+}
+
+static int mt8195_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct mt8195_mt6359_rt1019_rt5682_priv *priv =
+               snd_soc_card_get_drvdata(rtd->card);
+       struct snd_soc_component *cmpnt_codec =
+               asoc_rtd_to_codec(rtd, 0)->component;
+       int ret = 0;
+
+       ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT,
+                                   &priv->hdmi_jack, NULL, 0);
+       if (ret)
+               return ret;
+
+       return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL);
+}
+
+static int mt8195_hdmitx_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+                                             struct snd_pcm_hw_params *params)
+
+{
+       /* fix BE i2s format to 32bit, clean param mask first */
+       snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
+                            0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
+
+       params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+
+       return 0;
+}
+
+static int mt8195_playback_startup(struct snd_pcm_substream *substream)
+{
+       static const unsigned int rates[] = {
+               48000
+       };
+       static const unsigned int channels[] = {
+               2
+       };
+       static const struct snd_pcm_hw_constraint_list constraints_rates = {
+               .count = ARRAY_SIZE(rates),
+               .list  = rates,
+               .mask = 0,
+       };
+       static const struct snd_pcm_hw_constraint_list constraints_channels = {
+               .count = ARRAY_SIZE(channels),
+               .list  = channels,
+               .mask = 0,
+       };
+
+       struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int ret;
+
+       ret = snd_pcm_hw_constraint_list(runtime, 0,
+                                        SNDRV_PCM_HW_PARAM_RATE,
+                                        &constraints_rates);
+       if (ret < 0) {
+               dev_err(rtd->dev, "hw_constraint_list rate failed\n");
+               return ret;
+       }
+
+       ret = snd_pcm_hw_constraint_list(runtime, 0,
+                                        SNDRV_PCM_HW_PARAM_CHANNELS,
+                                        &constraints_channels);
+       if (ret < 0) {
+               dev_err(rtd->dev, "hw_constraint_list channel failed\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static const struct snd_soc_ops mt8195_playback_ops = {
+       .startup = mt8195_playback_startup,
+};
+
+static int mt8195_capture_startup(struct snd_pcm_substream *substream)
+{
+       static const unsigned int rates[] = {
+               48000
+       };
+       static const unsigned int channels[] = {
+               1, 2
+       };
+       static const struct snd_pcm_hw_constraint_list constraints_rates = {
+               .count = ARRAY_SIZE(rates),
+               .list  = rates,
+               .mask = 0,
+       };
+       static const struct snd_pcm_hw_constraint_list constraints_channels = {
+               .count = ARRAY_SIZE(channels),
+               .list  = channels,
+               .mask = 0,
+       };
+
+       struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int ret;
+
+       ret = snd_pcm_hw_constraint_list(runtime, 0,
+                                        SNDRV_PCM_HW_PARAM_RATE,
+                                        &constraints_rates);
+       if (ret < 0) {
+               dev_err(rtd->dev, "hw_constraint_list rate failed\n");
+               return ret;
+       }
+
+       ret = snd_pcm_hw_constraint_list(runtime, 0,
+                                        SNDRV_PCM_HW_PARAM_CHANNELS,
+                                        &constraints_channels);
+       if (ret < 0) {
+               dev_err(rtd->dev, "hw_constraint_list channel failed\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static const struct snd_soc_ops mt8195_capture_ops = {
+       .startup = mt8195_capture_startup,
+};
+
+enum {
+       DAI_LINK_DL2_FE,
+       DAI_LINK_DL3_FE,
+       DAI_LINK_DL6_FE,
+       DAI_LINK_DL7_FE,
+       DAI_LINK_DL8_FE,
+       DAI_LINK_DL10_FE,
+       DAI_LINK_DL11_FE,
+       DAI_LINK_UL1_FE,
+       DAI_LINK_UL2_FE,
+       DAI_LINK_UL3_FE,
+       DAI_LINK_UL4_FE,
+       DAI_LINK_UL5_FE,
+       DAI_LINK_UL6_FE,
+       DAI_LINK_UL8_FE,
+       DAI_LINK_UL9_FE,
+       DAI_LINK_UL10_FE,
+       DAI_LINK_DL_SRC_BE,
+       DAI_LINK_DPTX_BE,
+       DAI_LINK_ETDM1_IN_BE,
+       DAI_LINK_ETDM2_IN_BE,
+       DAI_LINK_ETDM1_OUT_BE,
+       DAI_LINK_ETDM2_OUT_BE,
+       DAI_LINK_ETDM3_OUT_BE,
+       DAI_LINK_PCM1_BE,
+       DAI_LINK_UL_SRC1_BE,
+       DAI_LINK_UL_SRC2_BE,
+};
+
+/* FE */
+SND_SOC_DAILINK_DEFS(DL2_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL3_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL6_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("DL6")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL7_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("DL7")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL8_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("DL8")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL10_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("DL10")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL11_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("DL11")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL1_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL2_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL3_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL4_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("UL4")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL5_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("UL5")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL6_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("UL6")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL8_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("UL8")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL9_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("UL9")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL10_FE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("UL10")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+/* BE */
+SND_SOC_DAILINK_DEFS(DL_SRC_BE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("DL_SRC")),
+                    DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
+                                                  "mt6359-snd-codec-aif1")),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DPTX_BE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("DPTX")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM1_IN_BE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_IN")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM2_IN_BE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_IN")),
+                    DAILINK_COMP_ARRAY(COMP_CODEC(RT5682_DEV0_NAME,
+                                                  RT5682_CODEC_DAI)),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM1_OUT_BE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_OUT")),
+                    DAILINK_COMP_ARRAY(COMP_CODEC(RT5682_DEV0_NAME,
+                                                  RT5682_CODEC_DAI)),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM2_OUT_BE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_OUT")),
+                    DAILINK_COMP_ARRAY(COMP_CODEC(RT1019_DEV0_NAME,
+                                                  RT1019_CODEC_DAI)),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM3_OUT_BE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("ETDM3_OUT")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(PCM1_BE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("PCM1")),
+                    DAILINK_COMP_ARRAY(COMP_DUMMY()),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL_SRC1_BE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC1")),
+                    DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
+                                                  "mt6359-snd-codec-aif1"),
+                                       COMP_CODEC("dmic-codec",
+                                                  "dmic-hifi")),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL_SRC2_BE,
+                    DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC2")),
+                    DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
+                                                  "mt6359-snd-codec-aif2")),
+                    DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+static struct snd_soc_dai_link mt8195_mt6359_rt1019_rt5682_dai_links[] = {
+       /* FE */
+       [DAI_LINK_DL2_FE] = {
+               .name = "DL2_FE",
+               .stream_name = "DL2 Playback",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST,
+                       SND_SOC_DPCM_TRIGGER_POST,
+               },
+               .dynamic = 1,
+               .dpcm_playback = 1,
+               .ops = &mt8195_playback_ops,
+               SND_SOC_DAILINK_REG(DL2_FE),
+       },
+       [DAI_LINK_DL3_FE] = {
+               .name = "DL3_FE",
+               .stream_name = "DL3 Playback",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST,
+                       SND_SOC_DPCM_TRIGGER_POST,
+               },
+               .dynamic = 1,
+               .dpcm_playback = 1,
+               .ops = &mt8195_playback_ops,
+               SND_SOC_DAILINK_REG(DL3_FE),
+       },
+       [DAI_LINK_DL6_FE] = {
+               .name = "DL6_FE",
+               .stream_name = "DL6 Playback",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST,
+                       SND_SOC_DPCM_TRIGGER_POST,
+               },
+               .dynamic = 1,
+               .dpcm_playback = 1,
+               .ops = &mt8195_playback_ops,
+               SND_SOC_DAILINK_REG(DL6_FE),
+       },
+       [DAI_LINK_DL7_FE] = {
+               .name = "DL7_FE",
+               .stream_name = "DL7 Playback",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_PRE,
+                       SND_SOC_DPCM_TRIGGER_PRE,
+               },
+               .dynamic = 1,
+               .dpcm_playback = 1,
+               SND_SOC_DAILINK_REG(DL7_FE),
+       },
+       [DAI_LINK_DL8_FE] = {
+               .name = "DL8_FE",
+               .stream_name = "DL8 Playback",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST,
+                       SND_SOC_DPCM_TRIGGER_POST,
+               },
+               .dynamic = 1,
+               .dpcm_playback = 1,
+               .ops = &mt8195_playback_ops,
+               SND_SOC_DAILINK_REG(DL8_FE),
+       },
+       [DAI_LINK_DL10_FE] = {
+               .name = "DL10_FE",
+               .stream_name = "DL10 Playback",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST,
+                       SND_SOC_DPCM_TRIGGER_POST,
+               },
+               .dynamic = 1,
+               .dpcm_playback = 1,
+               .ops = &mt8195_hdmitx_dptx_playback_ops,
+               SND_SOC_DAILINK_REG(DL10_FE),
+       },
+       [DAI_LINK_DL11_FE] = {
+               .name = "DL11_FE",
+               .stream_name = "DL11 Playback",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST,
+                       SND_SOC_DPCM_TRIGGER_POST,
+               },
+               .dynamic = 1,
+               .dpcm_playback = 1,
+               .ops = &mt8195_playback_ops,
+               SND_SOC_DAILINK_REG(DL11_FE),
+       },
+       [DAI_LINK_UL1_FE] = {
+               .name = "UL1_FE",
+               .stream_name = "UL1 Capture",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_PRE,
+                       SND_SOC_DPCM_TRIGGER_PRE,
+               },
+               .dynamic = 1,
+               .dpcm_capture = 1,
+               SND_SOC_DAILINK_REG(UL1_FE),
+       },
+       [DAI_LINK_UL2_FE] = {
+               .name = "UL2_FE",
+               .stream_name = "UL2 Capture",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST,
+                       SND_SOC_DPCM_TRIGGER_POST,
+               },
+               .dynamic = 1,
+               .dpcm_capture = 1,
+               .ops = &mt8195_capture_ops,
+               SND_SOC_DAILINK_REG(UL2_FE),
+       },
+       [DAI_LINK_UL3_FE] = {
+               .name = "UL3_FE",
+               .stream_name = "UL3 Capture",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST,
+                       SND_SOC_DPCM_TRIGGER_POST,
+               },
+               .dynamic = 1,
+               .dpcm_capture = 1,
+               .ops = &mt8195_capture_ops,
+               SND_SOC_DAILINK_REG(UL3_FE),
+       },
+       [DAI_LINK_UL4_FE] = {
+               .name = "UL4_FE",
+               .stream_name = "UL4 Capture",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST,
+                       SND_SOC_DPCM_TRIGGER_POST,
+               },
+               .dynamic = 1,
+               .dpcm_capture = 1,
+               .ops = &mt8195_capture_ops,
+               SND_SOC_DAILINK_REG(UL4_FE),
+       },
+       [DAI_LINK_UL5_FE] = {
+               .name = "UL5_FE",
+               .stream_name = "UL5 Capture",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST,
+                       SND_SOC_DPCM_TRIGGER_POST,
+               },
+               .dynamic = 1,
+               .dpcm_capture = 1,
+               .ops = &mt8195_capture_ops,
+               SND_SOC_DAILINK_REG(UL5_FE),
+       },
+       [DAI_LINK_UL6_FE] = {
+               .name = "UL6_FE",
+               .stream_name = "UL6 Capture",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_PRE,
+                       SND_SOC_DPCM_TRIGGER_PRE,
+               },
+               .dynamic = 1,
+               .dpcm_capture = 1,
+               SND_SOC_DAILINK_REG(UL6_FE),
+       },
+       [DAI_LINK_UL8_FE] = {
+               .name = "UL8_FE",
+               .stream_name = "UL8 Capture",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST,
+                       SND_SOC_DPCM_TRIGGER_POST,
+               },
+               .dynamic = 1,
+               .dpcm_capture = 1,
+               .ops = &mt8195_capture_ops,
+               SND_SOC_DAILINK_REG(UL8_FE),
+       },
+       [DAI_LINK_UL9_FE] = {
+               .name = "UL9_FE",
+               .stream_name = "UL9 Capture",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST,
+                       SND_SOC_DPCM_TRIGGER_POST,
+               },
+               .dynamic = 1,
+               .dpcm_capture = 1,
+               .ops = &mt8195_capture_ops,
+               SND_SOC_DAILINK_REG(UL9_FE),
+       },
+       [DAI_LINK_UL10_FE] = {
+               .name = "UL10_FE",
+               .stream_name = "UL10 Capture",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST,
+                       SND_SOC_DPCM_TRIGGER_POST,
+               },
+               .dynamic = 1,
+               .dpcm_capture = 1,
+               .ops = &mt8195_capture_ops,
+               SND_SOC_DAILINK_REG(UL10_FE),
+       },
+       /* BE */
+       [DAI_LINK_DL_SRC_BE] = {
+               .name = "DL_SRC_BE",
+               .init = mt8195_mt6359_init,
+               .no_pcm = 1,
+               .dpcm_playback = 1,
+               SND_SOC_DAILINK_REG(DL_SRC_BE),
+       },
+       [DAI_LINK_DPTX_BE] = {
+               .name = "DPTX_BE",
+               .no_pcm = 1,
+               .dpcm_playback = 1,
+               .ops = &mt8195_dptx_ops,
+               .be_hw_params_fixup = mt8195_hdmitx_dptx_hw_params_fixup,
+               SND_SOC_DAILINK_REG(DPTX_BE),
+       },
+       [DAI_LINK_ETDM1_IN_BE] = {
+               .name = "ETDM1_IN_BE",
+               .no_pcm = 1,
+               .dai_fmt = SND_SOC_DAIFMT_I2S |
+                       SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBS_CFS,
+               .dpcm_capture = 1,
+               SND_SOC_DAILINK_REG(ETDM1_IN_BE),
+       },
+       [DAI_LINK_ETDM2_IN_BE] = {
+               .name = "ETDM2_IN_BE",
+               .no_pcm = 1,
+               .dai_fmt = SND_SOC_DAIFMT_I2S |
+                       SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBS_CFS,
+               .dpcm_capture = 1,
+               .init = mt8195_rt5682_init,
+               .ops = &mt8195_rt5682_etdm_ops,
+               .be_hw_params_fixup = mt8195_etdm_hw_params_fixup,
+               SND_SOC_DAILINK_REG(ETDM2_IN_BE),
+       },
+       [DAI_LINK_ETDM1_OUT_BE] = {
+               .name = "ETDM1_OUT_BE",
+               .no_pcm = 1,
+               .dai_fmt = SND_SOC_DAIFMT_I2S |
+                       SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBS_CFS,
+               .dpcm_playback = 1,
+               .ops = &mt8195_rt5682_etdm_ops,
+               .be_hw_params_fixup = mt8195_etdm_hw_params_fixup,
+               SND_SOC_DAILINK_REG(ETDM1_OUT_BE),
+       },
+       [DAI_LINK_ETDM2_OUT_BE] = {
+               .name = "ETDM2_OUT_BE",
+               .no_pcm = 1,
+               .dai_fmt = SND_SOC_DAIFMT_I2S |
+                       SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBS_CFS,
+               .dpcm_playback = 1,
+               SND_SOC_DAILINK_REG(ETDM2_OUT_BE),
+       },
+       [DAI_LINK_ETDM3_OUT_BE] = {
+               .name = "ETDM3_OUT_BE",
+               .no_pcm = 1,
+               .dai_fmt = SND_SOC_DAIFMT_I2S |
+                       SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBS_CFS,
+               .dpcm_playback = 1,
+               .be_hw_params_fixup = mt8195_hdmitx_dptx_hw_params_fixup,
+               SND_SOC_DAILINK_REG(ETDM3_OUT_BE),
+       },
+       [DAI_LINK_PCM1_BE] = {
+               .name = "PCM1_BE",
+               .no_pcm = 1,
+               .dai_fmt = SND_SOC_DAIFMT_I2S |
+                       SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBS_CFS,
+               .dpcm_capture = 1,
+               SND_SOC_DAILINK_REG(PCM1_BE),
+       },
+       [DAI_LINK_UL_SRC1_BE] = {
+               .name = "UL_SRC1_BE",
+               .no_pcm = 1,
+               .dpcm_capture = 1,
+               SND_SOC_DAILINK_REG(UL_SRC1_BE),
+       },
+       [DAI_LINK_UL_SRC2_BE] = {
+               .name = "UL_SRC2_BE",
+               .no_pcm = 1,
+               .dpcm_capture = 1,
+               SND_SOC_DAILINK_REG(UL_SRC2_BE),
+       },
+};
+
+static struct snd_soc_card mt8195_mt6359_rt1019_rt5682_soc_card = {
+       .name = "mt8195_r1019_5682",
+       .owner = THIS_MODULE,
+       .dai_link = mt8195_mt6359_rt1019_rt5682_dai_links,
+       .num_links = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_dai_links),
+       .controls = mt8195_mt6359_rt1019_rt5682_controls,
+       .num_controls = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_controls),
+       .dapm_widgets = mt8195_mt6359_rt1019_rt5682_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_widgets),
+       .dapm_routes = mt8195_mt6359_rt1019_rt5682_routes,
+       .num_dapm_routes = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_routes),
+};
+
+static int mt8195_mt6359_rt1019_rt5682_dev_probe(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = &mt8195_mt6359_rt1019_rt5682_soc_card;
+       struct device_node *platform_node;
+       struct snd_soc_dai_link *dai_link;
+       struct mt8195_mt6359_rt1019_rt5682_priv *priv = NULL;
+       int ret, i;
+
+       card->dev = &pdev->dev;
+
+       platform_node = of_parse_phandle(pdev->dev.of_node,
+                                        "mediatek,platform", 0);
+       if (!platform_node) {
+               dev_dbg(&pdev->dev, "Property 'platform' missing or invalid\n");
+               return -EINVAL;
+       }
+
+       for_each_card_prelinks(card, i, dai_link) {
+               if (!dai_link->platforms->name)
+                       dai_link->platforms->of_node = platform_node;
+
+               if (strcmp(dai_link->name, "DPTX_BE") == 0) {
+                       dai_link->codecs->of_node =
+                               of_parse_phandle(pdev->dev.of_node,
+                                                "mediatek,dptx-codec", 0);
+                       if (!dai_link->codecs->of_node) {
+                               dev_err(&pdev->dev, "Property 'dptx-codec' missing or invalid\n");
+                               return -EINVAL;
+                       }
+
+                       dai_link->codecs->name = NULL;
+                       dai_link->codecs->dai_name = "i2s-hifi";
+                       dai_link->init = mt8195_dptx_codec_init;
+               }
+
+               if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) {
+                       dai_link->codecs->of_node =
+                               of_parse_phandle(pdev->dev.of_node,
+                                                "mediatek,hdmi-codec", 0);
+                       if (!dai_link->codecs->of_node) {
+                               dev_err(&pdev->dev, "Property 'hdmi-codec' missing or invalid\n");
+                               return -EINVAL;
+                       }
+
+                       dai_link->codecs->name = NULL;
+                       dai_link->codecs->dai_name = "i2s-hifi";
+                       dai_link->init = mt8195_hdmi_codec_init;
+               }
+       }
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       snd_soc_card_set_drvdata(card, priv);
+
+       ret = devm_snd_soc_register_card(&pdev->dev, card);
+       if (ret)
+               dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
+                       __func__, ret);
+       return ret;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id mt8195_mt6359_rt1019_rt5682_dt_match[] = {
+       {.compatible = "mediatek,mt8195_mt6359_rt1019_rt5682",},
+       {}
+};
+#endif
+
+static const struct dev_pm_ops mt8195_mt6359_rt1019_rt5682_pm_ops = {
+       .poweroff = snd_soc_poweroff,
+       .restore = snd_soc_resume,
+};
+
+static struct platform_driver mt8195_mt6359_rt1019_rt5682_driver = {
+       .driver = {
+               .name = "mt8195_mt6359_rt1019_rt5682",
+#ifdef CONFIG_OF
+               .of_match_table = mt8195_mt6359_rt1019_rt5682_dt_match,
+#endif
+               .pm = &mt8195_mt6359_rt1019_rt5682_pm_ops,
+       },
+       .probe = mt8195_mt6359_rt1019_rt5682_dev_probe,
+};
+
+module_platform_driver(mt8195_mt6359_rt1019_rt5682_driver);
+
+/* Module information */
+MODULE_DESCRIPTION("MT8195-MT6359-RT1019-RT5682 ALSA SoC machine driver");
+MODULE_AUTHOR("Trevor Wu <trevor.wu@mediatek.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("mt8195_mt6359_rt1019_rt5682 soc card");
diff --git a/sound/soc/mediatek/mt8195/mt8195-reg.h b/sound/soc/mediatek/mt8195/mt8195-reg.h
new file mode 100644 (file)
index 0000000..d06f9cf
--- /dev/null
@@ -0,0 +1,2796 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8195-reg.h  --  Mediatek 8195 audio driver reg definition
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ *         Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#ifndef _MT8195_REG_H_
+#define _MT8195_REG_H_
+
+#define AFE_SRAM_BASE                     (0x10880000)
+#define AFE_SRAM_SIZE                     (0x10000)
+
+#define AUDIO_TOP_CON0                    (0x0000)
+#define AUDIO_TOP_CON1                    (0x0004)
+#define AUDIO_TOP_CON2                    (0x0008)
+#define AUDIO_TOP_CON3                    (0x000c)
+#define AUDIO_TOP_CON4                    (0x0010)
+#define AUDIO_TOP_CON5                    (0x0014)
+#define AUDIO_TOP_CON6                    (0x0018)
+#define AFE_MAS_HADDR_MSB                 (0x0020)
+#define PWR1_ASM_CON1                     (0x0108)
+#define ASYS_IRQ_CONFIG                   (0x0110)
+#define ASYS_IRQ1_CON                     (0x0114)
+#define ASYS_IRQ2_CON                     (0x0118)
+#define ASYS_IRQ3_CON                     (0x011c)
+#define ASYS_IRQ4_CON                     (0x0120)
+#define ASYS_IRQ5_CON                     (0x0124)
+#define ASYS_IRQ6_CON                     (0x0128)
+#define ASYS_IRQ7_CON                     (0x012c)
+#define ASYS_IRQ8_CON                     (0x0130)
+#define ASYS_IRQ9_CON                     (0x0134)
+#define ASYS_IRQ10_CON                    (0x0138)
+#define ASYS_IRQ11_CON                    (0x013c)
+#define ASYS_IRQ12_CON                    (0x0140)
+#define ASYS_IRQ13_CON                    (0x0144)
+#define ASYS_IRQ14_CON                    (0x0148)
+#define ASYS_IRQ15_CON                    (0x014c)
+#define ASYS_IRQ16_CON                    (0x0150)
+#define ASYS_IRQ_CLR                      (0x0154)
+#define ASYS_IRQ_STATUS                   (0x0158)
+#define ASYS_IRQ_MON1                     (0x015c)
+#define ASYS_IRQ_MON2                     (0x0160)
+#define AFE_IRQ1_CON                      (0x0164)
+#define AFE_IRQ2_CON                      (0x0168)
+#define AFE_IRQ3_CON                      (0x016c)
+#define AFE_IRQ_MCU_CLR                   (0x0170)
+#define AFE_IRQ_STATUS                    (0x0174)
+#define AFE_IRQ_MASK                      (0x0178)
+#define ASYS_IRQ_MASK                     (0x017c)
+#define AFE_IRQ3_CON_MON                  (0x01b0)
+#define AFE_IRQ_MCU_MON2                  (0x01b4)
+#define AFE_IRQ8_CON                      (0x01b8)
+#define AFE_IRQ9_CON                      (0x01bc)
+#define AFE_IRQ10_CON                     (0x01c0)
+#define AFE_IRQ9_CON_MON                  (0x01c4)
+#define ADSP_IRQ_MASK                     (0x01c8)
+#define ADSP_IRQ_STATUS                   (0x01cc)
+#define AFE_SINEGEN_CON0                  (0x01f0)
+#define AFE_SINEGEN_CON1                  (0x01f4)
+#define AFE_SINEGEN_CON2                  (0x01f8)
+#define AFE_SINEGEN_CON3                  (0x01fc)
+#define AFE_SPDIF_OUT_CON0                (0x0380)
+#define AFE_TDMOUT_CONN0                  (0x0390)
+#define PWR1_ASM_CON2                     (0x03b0)
+#define PWR1_ASM_CON3                     (0x03b4)
+#define PWR1_ASM_CON4                     (0x03b8)
+#define AFE_APLL_TUNER_CFG                (0x03f8)
+#define AFE_APLL_TUNER_CFG1               (0x03fc)
+#define AUDIO_TOP_STA0                    (0x0400)
+#define AUDIO_TOP_STA1                    (0x0404)
+#define AFE_GAIN1_CON0                    (0x0410)
+#define AFE_GAIN1_CON1                    (0x0414)
+#define AFE_GAIN1_CON2                    (0x0418)
+#define AFE_GAIN1_CON3                    (0x041c)
+#define AFE_GAIN1_CUR                     (0x0424)
+#define AFE_GAIN2_CON0                    (0x0428)
+#define AFE_GAIN2_CON1                    (0x042c)
+#define AFE_GAIN2_CON2                    (0x0430)
+#define AFE_GAIN2_CON3                    (0x0434)
+#define AFE_GAIN2_CUR                     (0x043c)
+#define AFE_IEC_CFG                       (0x0480)
+#define AFE_IEC_NSNUM                     (0x0484)
+#define AFE_IEC_BURST_INFO                (0x0488)
+#define AFE_IEC_BURST_LEN                 (0x048c)
+#define AFE_IEC_NSADR                     (0x0490)
+#define AFE_IEC_CHL_STAT0                 (0x04a0)
+#define AFE_IEC_CHL_STAT1                 (0x04a4)
+#define AFE_IEC_CHR_STAT0                 (0x04a8)
+#define AFE_IEC_CHR_STAT1                 (0x04ac)
+#define AFE_SPDIFIN_CFG0                  (0x0500)
+#define AFE_SPDIFIN_CFG1                  (0x0504)
+#define AFE_SPDIFIN_CHSTS1                (0x0508)
+#define AFE_SPDIFIN_CHSTS2                (0x050c)
+#define AFE_SPDIFIN_CHSTS3                (0x0510)
+#define AFE_SPDIFIN_CHSTS4                (0x0514)
+#define AFE_SPDIFIN_CHSTS5                (0x0518)
+#define AFE_SPDIFIN_CHSTS6                (0x051c)
+#define AFE_SPDIFIN_DEBUG1                (0x0520)
+#define AFE_SPDIFIN_DEBUG2                (0x0524)
+#define AFE_SPDIFIN_DEBUG3                (0x0528)
+#define AFE_SPDIFIN_DEBUG4                (0x052c)
+#define AFE_SPDIFIN_EC                    (0x0530)
+#define AFE_SPDIFIN_CKLOCK_CFG            (0x0534)
+#define AFE_SPDIFIN_BR                    (0x053c)
+#define AFE_SPDIFIN_BR_DBG1               (0x0540)
+#define AFE_SPDIFIN_CKFBDIV               (0x0544)
+#define AFE_SPDIFIN_INT_EXT               (0x0548)
+#define AFE_SPDIFIN_INT_EXT2              (0x054c)
+#define SPDIFIN_FREQ_INFO                 (0x0550)
+#define SPDIFIN_FREQ_INFO_2               (0x0554)
+#define SPDIFIN_FREQ_INFO_3               (0x0558)
+#define SPDIFIN_FREQ_STATUS               (0x055c)
+#define SPDIFIN_USERCODE1                 (0x0560)
+#define SPDIFIN_USERCODE2                 (0x0564)
+#define SPDIFIN_USERCODE3                 (0x0568)
+#define SPDIFIN_USERCODE4                 (0x056c)
+#define SPDIFIN_USERCODE5                 (0x0570)
+#define SPDIFIN_USERCODE6                 (0x0574)
+#define SPDIFIN_USERCODE7                 (0x0578)
+#define SPDIFIN_USERCODE8                 (0x057c)
+#define SPDIFIN_USERCODE9                 (0x0580)
+#define SPDIFIN_USERCODE10                (0x0584)
+#define SPDIFIN_USERCODE11                (0x0588)
+#define SPDIFIN_USERCODE12                (0x058c)
+#define AFE_SPDIFIN_APLL_TUNER_CFG        (0x0594)
+#define AFE_SPDIFIN_APLL_TUNER_CFG1       (0x0598)
+#define ASYS_TOP_CON                      (0x0600)
+#define AFE_LINEIN_APLL_TUNER_CFG         (0x0610)
+#define AFE_LINEIN_APLL_TUNER_MON         (0x0614)
+#define AFE_EARC_APLL_TUNER_CFG           (0x0618)
+#define AFE_EARC_APLL_TUNER_MON           (0x061c)
+#define PWR2_TOP_CON0                     (0x0634)
+#define PWR2_TOP_CON1                     (0x0638)
+#define PCM_INTF_CON1                     (0x063c)
+#define PCM_INTF_CON2                     (0x0640)
+#define AFE_CM0_CON                       (0x0660)
+#define AFE_CM1_CON                       (0x0664)
+#define AFE_CM2_CON                       (0x0668)
+#define AFE_CM0_MON                       (0x0670)
+#define AFE_CM1_MON                       (0x0674)
+#define AFE_CM2_MON                       (0x0678)
+#define AFE_MPHONE_MULTI_CON0             (0x06a4)
+#define AFE_MPHONE_MULTI_CON1             (0x06a8)
+#define AFE_MPHONE_MULTI_CON2             (0x06ac)
+#define AFE_MPHONE_MULTI_MON              (0x06b0)
+#define AFE_MPHONE_MULTI_DET_REG_CON0     (0x06b4)
+#define AFE_MPHONE_MULTI_DET_REG_CON1     (0x06b8)
+#define AFE_MPHONE_MULTI_DET_REG_CON2     (0x06bc)
+#define AFE_MPHONE_MULTI_DET_REG_CON3     (0x06c0)
+#define AFE_MPHONE_MULTI_DET_MON0         (0x06c4)
+#define AFE_MPHONE_MULTI_DET_MON1         (0x06c8)
+#define AFE_MPHONE_MULTI_DET_MON2         (0x06d0)
+#define AFE_MPHONE_MULTI2_CON0            (0x06d4)
+#define AFE_MPHONE_MULTI2_CON1            (0x06d8)
+#define AFE_MPHONE_MULTI2_CON2            (0x06dc)
+#define AFE_MPHONE_MULTI2_MON             (0x06e0)
+#define AFE_MPHONE_MULTI2_DET_REG_CON0    (0x06e4)
+#define AFE_MPHONE_MULTI2_DET_REG_CON1    (0x06e8)
+#define AFE_MPHONE_MULTI2_DET_REG_CON2    (0x06ec)
+#define AFE_MPHONE_MULTI2_DET_REG_CON3    (0x06f0)
+#define AFE_MPHONE_MULTI2_DET_MON0        (0x06f4)
+#define AFE_MPHONE_MULTI2_DET_MON1        (0x06f8)
+#define AFE_MPHONE_MULTI2_DET_MON2        (0x06fc)
+#define AFE_ADDA_IIR_COEF_02_01           (0x0700)
+#define AFE_ADDA_IIR_COEF_04_03           (0x0704)
+#define AFE_ADDA_IIR_COEF_06_05           (0x0708)
+#define AFE_ADDA_IIR_COEF_08_07           (0x070c)
+#define AFE_ADDA_IIR_COEF_10_09           (0x0710)
+#define AFE_ADDA_ULCF_CFG_02_01           (0x0714)
+#define AFE_ADDA_ULCF_CFG_04_03           (0x0718)
+#define AFE_ADDA_ULCF_CFG_06_05           (0x071c)
+#define AFE_ADDA_ULCF_CFG_08_07           (0x0720)
+#define AFE_ADDA_ULCF_CFG_10_09           (0x0724)
+#define AFE_ADDA_ULCF_CFG_12_11           (0x0728)
+#define AFE_ADDA_ULCF_CFG_14_13           (0x072c)
+#define AFE_ADDA_ULCF_CFG_16_15           (0x0730)
+#define AFE_ADDA_ULCF_CFG_18_17           (0x0734)
+#define AFE_ADDA_ULCF_CFG_20_19           (0x0738)
+#define AFE_ADDA_ULCF_CFG_22_21           (0x073c)
+#define AFE_ADDA_ULCF_CFG_24_23           (0x0740)
+#define AFE_ADDA_ULCF_CFG_26_25           (0x0744)
+#define AFE_ADDA_ULCF_CFG_28_27           (0x0748)
+#define AFE_ADDA_ULCF_CFG_30_29           (0x074c)
+#define AFE_ADDA6_IIR_COEF_02_01          (0x0750)
+#define AFE_ADDA6_IIR_COEF_04_03          (0x0754)
+#define AFE_ADDA6_IIR_COEF_06_05          (0x0758)
+#define AFE_ADDA6_IIR_COEF_08_07          (0x075c)
+#define AFE_ADDA6_IIR_COEF_10_09          (0x0760)
+#define AFE_ADDA6_ULCF_CFG_02_01          (0x0764)
+#define AFE_ADDA6_ULCF_CFG_04_03          (0x0768)
+#define AFE_ADDA6_ULCF_CFG_06_05          (0x076c)
+#define AFE_ADDA6_ULCF_CFG_08_07          (0x0770)
+#define AFE_ADDA6_ULCF_CFG_10_09          (0x0774)
+#define AFE_ADDA6_ULCF_CFG_12_11          (0x0778)
+#define AFE_ADDA6_ULCF_CFG_14_13          (0x077c)
+#define AFE_ADDA6_ULCF_CFG_16_15          (0x0780)
+#define AFE_ADDA6_ULCF_CFG_18_17          (0x0784)
+#define AFE_ADDA6_ULCF_CFG_20_19          (0x0788)
+#define AFE_ADDA6_ULCF_CFG_22_21          (0x078c)
+#define AFE_ADDA6_ULCF_CFG_24_23          (0x0790)
+#define AFE_ADDA6_ULCF_CFG_26_25          (0x0794)
+#define AFE_ADDA6_ULCF_CFG_28_27          (0x0798)
+#define AFE_ADDA6_ULCF_CFG_30_29          (0x079c)
+#define AFE_ADDA_MTKAIF_CFG0              (0x07a0)
+#define AFE_ADDA_MTKAIF_SYNCWORD_CFG      (0x07a8)
+#define AFE_ADDA_MTKAIF_RX_CFG0           (0x07b4)
+#define AFE_ADDA_MTKAIF_RX_CFG1           (0x07b8)
+#define AFE_ADDA_MTKAIF_RX_CFG2           (0x07bc)
+#define AFE_ADDA_MTKAIF_MON0              (0x07c8)
+#define AFE_ADDA_MTKAIF_MON1              (0x07cc)
+#define AFE_AUD_PAD_TOP                   (0x07d4)
+#define AFE_ADDA6_MTKAIF_MON0             (0x07d8)
+#define AFE_ADDA6_MTKAIF_MON1             (0x07dc)
+#define AFE_ADDA6_MTKAIF_CFG0             (0x07e0)
+#define AFE_ADDA6_MTKAIF_RX_CFG0          (0x07e4)
+#define AFE_ADDA6_MTKAIF_RX_CFG1          (0x07e8)
+#define AFE_ADDA6_MTKAIF_RX_CFG2          (0x07ec)
+#define AFE_ADDA6_TOP_CON0                (0x07f0)
+#define AFE_ADDA6_UL_SRC_CON0             (0x07f4)
+#define AFE_ADDA6_UL_SRC_CON1             (0x07f8)
+#define AFE_ADDA6_SRC_DEBUG               (0x0800)
+#define AFE_ADDA6_SRC_DEBUG_MON0          (0x0804)
+#define AFE_ADDA6_UL_SRC_MON0             (0x0818)
+#define AFE_ADDA6_UL_SRC_MON1             (0x081c)
+#define AFE_CONN0_5                       (0x0830)
+#define AFE_CONN1_5                       (0x0834)
+#define AFE_CONN2_5                       (0x0838)
+#define AFE_CONN3_5                       (0x083c)
+#define AFE_CONN4_5                       (0x0840)
+#define AFE_CONN5_5                       (0x0844)
+#define AFE_CONN6_5                       (0x0848)
+#define AFE_CONN7_5                       (0x084c)
+#define AFE_CONN8_5                       (0x0850)
+#define AFE_CONN9_5                       (0x0854)
+#define AFE_CONN10_5                      (0x0858)
+#define AFE_CONN11_5                      (0x085c)
+#define AFE_CONN12_5                      (0x0860)
+#define AFE_CONN13_5                      (0x0864)
+#define AFE_CONN14_5                      (0x0868)
+#define AFE_CONN15_5                      (0x086c)
+#define AFE_CONN16_5                      (0x0870)
+#define AFE_CONN17_5                      (0x0874)
+#define AFE_CONN18_5                      (0x0878)
+#define AFE_CONN19_5                      (0x087c)
+#define AFE_CONN20_5                      (0x0880)
+#define AFE_CONN21_5                      (0x0884)
+#define AFE_CONN22_5                      (0x0888)
+#define AFE_CONN23_5                      (0x088c)
+#define AFE_CONN24_5                      (0x0890)
+#define AFE_CONN25_5                      (0x0894)
+#define AFE_CONN26_5                      (0x0898)
+#define AFE_CONN27_5                      (0x089c)
+#define AFE_CONN28_5                      (0x08a0)
+#define AFE_CONN29_5                      (0x08a4)
+#define AFE_CONN30_5                      (0x08a8)
+#define AFE_CONN31_5                      (0x08ac)
+#define AFE_CONN32_5                      (0x08b0)
+#define AFE_CONN33_5                      (0x08b4)
+#define AFE_CONN34_5                      (0x08b8)
+#define AFE_CONN35_5                      (0x08bc)
+#define AFE_CONN36_5                      (0x08c0)
+#define AFE_CONN37_5                      (0x08c4)
+#define AFE_CONN38_5                      (0x08c8)
+#define AFE_CONN39_5                      (0x08cc)
+#define AFE_CONN40_5                      (0x08d0)
+#define AFE_CONN41_5                      (0x08d4)
+#define AFE_CONN42_5                      (0x08d8)
+#define AFE_CONN43_5                      (0x08dc)
+#define AFE_CONN44_5                      (0x08e0)
+#define AFE_CONN45_5                      (0x08e4)
+#define AFE_CONN46_5                      (0x08e8)
+#define AFE_CONN47_5                      (0x08ec)
+#define AFE_CONN48_5                      (0x08f0)
+#define AFE_CONN49_5                      (0x08f4)
+#define AFE_CONN50_5                      (0x08f8)
+#define AFE_CONN51_5                      (0x08fc)
+#define AFE_CONN52_5                      (0x0900)
+#define AFE_CONN53_5                      (0x0904)
+#define AFE_CONN54_5                      (0x0908)
+#define AFE_CONN55_5                      (0x090c)
+#define AFE_CONN56_5                      (0x0910)
+#define AFE_CONN57_5                      (0x0914)
+#define AFE_CONN58_5                      (0x0918)
+#define AFE_CONN59_5                      (0x091c)
+#define AFE_CONN60_5                      (0x0920)
+#define AFE_CONN61_5                      (0x0924)
+#define AFE_CONN62_5                      (0x0928)
+#define AFE_CONN63_5                      (0x092c)
+#define AFE_CONN64_5                      (0x0930)
+#define AFE_CONN65_5                      (0x0934)
+#define AFE_CONN66_5                      (0x0938)
+#define AFE_CONN67_5                      (0x093c)
+#define AFE_CONN68_5                      (0x0940)
+#define AFE_CONN69_5                      (0x0944)
+#define AFE_CONN70_5                      (0x0948)
+#define AFE_CONN71_5                      (0x094c)
+#define AFE_CONN72_5                      (0x0950)
+#define AFE_CONN73_5                      (0x0954)
+#define AFE_CONN74_5                      (0x0958)
+#define AFE_CONN75_5                      (0x095c)
+#define AFE_CONN76_5                      (0x0960)
+#define AFE_CONN77_5                      (0x0964)
+#define AFE_CONN78_5                      (0x0968)
+#define AFE_CONN79_5                      (0x096c)
+#define AFE_CONN80_5                      (0x0970)
+#define AFE_CONN81_5                      (0x0974)
+#define AFE_CONN82_5                      (0x0978)
+#define AFE_CONN83_5                      (0x097c)
+#define AFE_CONN84_5                      (0x0980)
+#define AFE_CONN85_5                      (0x0984)
+#define AFE_CONN86_5                      (0x0988)
+#define AFE_CONN87_5                      (0x098c)
+#define AFE_CONN88_5                      (0x0990)
+#define AFE_CONN89_5                      (0x0994)
+#define AFE_CONN90_5                      (0x0998)
+#define AFE_CONN91_5                      (0x099c)
+#define AFE_CONN92_5                      (0x09a0)
+#define AFE_CONN93_5                      (0x09a4)
+#define AFE_CONN94_5                      (0x09a8)
+#define AFE_CONN95_5                      (0x09ac)
+#define AFE_CONN96_5                      (0x09b0)
+#define AFE_CONN97_5                      (0x09b4)
+#define AFE_CONN98_5                      (0x09b8)
+#define AFE_CONN99_5                      (0x09bc)
+#define AFE_CONN100_5                     (0x09c0)
+#define AFE_CONN101_5                     (0x09c4)
+#define AFE_CONN102_5                     (0x09c8)
+#define AFE_CONN103_5                     (0x09cc)
+#define AFE_CONN104_5                     (0x09d0)
+#define AFE_CONN105_5                     (0x09d4)
+#define AFE_CONN106_5                     (0x09d8)
+#define AFE_CONN107_5                     (0x09dc)
+#define AFE_CONN108_5                     (0x09e0)
+#define AFE_CONN109_5                     (0x09e4)
+#define AFE_CONN110_5                     (0x09e8)
+#define AFE_CONN111_5                     (0x09ec)
+#define AFE_CONN112_5                     (0x09f0)
+#define AFE_CONN113_5                     (0x09f4)
+#define AFE_CONN114_5                     (0x09f8)
+#define AFE_CONN115_5                     (0x09fc)
+#define AFE_CONN116_5                     (0x0a00)
+#define AFE_CONN117_5                     (0x0a04)
+#define AFE_CONN118_5                     (0x0a08)
+#define AFE_CONN119_5                     (0x0a0c)
+#define AFE_CONN120_5                     (0x0a10)
+#define AFE_CONN121_5                     (0x0a14)
+#define AFE_CONN122_5                     (0x0a18)
+#define AFE_CONN123_5                     (0x0a1c)
+#define AFE_CONN124_5                     (0x0a20)
+#define AFE_CONN125_5                     (0x0a24)
+#define AFE_CONN126_5                     (0x0a28)
+#define AFE_CONN127_5                     (0x0a2c)
+#define AFE_CONN128_5                     (0x0a30)
+#define AFE_CONN129_5                     (0x0a34)
+#define AFE_CONN130_5                     (0x0a38)
+#define AFE_CONN131_5                     (0x0a3c)
+#define AFE_CONN132_5                     (0x0a40)
+#define AFE_CONN133_5                     (0x0a44)
+#define AFE_CONN134_5                     (0x0a48)
+#define AFE_CONN135_5                     (0x0a4c)
+#define AFE_CONN136_5                     (0x0a50)
+#define AFE_CONN137_5                     (0x0a54)
+#define AFE_CONN138_5                     (0x0a58)
+#define AFE_CONN139_5                     (0x0a5c)
+#define AFE_CONN_RS_5                     (0x0a60)
+#define AFE_CONN_DI_5                     (0x0a64)
+#define AFE_CONN_16BIT_5                  (0x0a68)
+#define AFE_CONN_24BIT_5                  (0x0a6c)
+#define AFE_ASRC11_NEW_CON0               (0x0d80)
+#define AFE_ASRC11_NEW_CON1               (0x0d84)
+#define AFE_ASRC11_NEW_CON2               (0x0d88)
+#define AFE_ASRC11_NEW_CON3               (0x0d8c)
+#define AFE_ASRC11_NEW_CON4               (0x0d90)
+#define AFE_ASRC11_NEW_CON5               (0x0d94)
+#define AFE_ASRC11_NEW_CON6               (0x0d98)
+#define AFE_ASRC11_NEW_CON7               (0x0d9c)
+#define AFE_ASRC11_NEW_CON8               (0x0da0)
+#define AFE_ASRC11_NEW_CON9               (0x0da4)
+#define AFE_ASRC11_NEW_CON10              (0x0da8)
+#define AFE_ASRC11_NEW_CON11              (0x0dac)
+#define AFE_ASRC11_NEW_CON13              (0x0db4)
+#define AFE_ASRC11_NEW_CON14              (0x0db8)
+#define AFE_ASRC12_NEW_CON0               (0x0dc0)
+#define AFE_ASRC12_NEW_CON1               (0x0dc4)
+#define AFE_ASRC12_NEW_CON2               (0x0dc8)
+#define AFE_ASRC12_NEW_CON3               (0x0dcc)
+#define AFE_ASRC12_NEW_CON4               (0x0dd0)
+#define AFE_ASRC12_NEW_CON5               (0x0dd4)
+#define AFE_ASRC12_NEW_CON6               (0x0dd8)
+#define AFE_ASRC12_NEW_CON7               (0x0ddc)
+#define AFE_ASRC12_NEW_CON8               (0x0de0)
+#define AFE_ASRC12_NEW_CON9               (0x0de4)
+#define AFE_ASRC12_NEW_CON10              (0x0de8)
+#define AFE_ASRC12_NEW_CON11              (0x0dec)
+#define AFE_ASRC12_NEW_CON13              (0x0df4)
+#define AFE_ASRC12_NEW_CON14              (0x0df8)
+#define AFE_LRCK_CNT                      (0x1018)
+#define AFE_DAC_CON0                      (0x1200)
+#define AFE_DAC_CON1                      (0x1204)
+#define AFE_DAC_CON2                      (0x1208)
+#define AFE_DAC_MON0                      (0x1218)
+#define AFE_DL2_BASE                      (0x1250)
+#define AFE_DL2_CUR                       (0x1254)
+#define AFE_DL2_END                       (0x1258)
+#define AFE_DL2_CON0                      (0x125c)
+#define AFE_DL3_BASE                      (0x1260)
+#define AFE_DL3_CUR                       (0x1264)
+#define AFE_DL3_END                       (0x1268)
+#define AFE_DL3_CON0                      (0x126c)
+#define AFE_DL6_BASE                      (0x1290)
+#define AFE_DL6_CUR                       (0x1294)
+#define AFE_DL6_END                       (0x1298)
+#define AFE_DL6_CON0                      (0x129c)
+#define AFE_DL7_BASE                      (0x12a0)
+#define AFE_DL7_CUR                       (0x12a4)
+#define AFE_DL7_END                       (0x12a8)
+#define AFE_DL7_CON0                      (0x12ac)
+#define AFE_DL8_BASE                      (0x12b0)
+#define AFE_DL8_CUR                       (0x12b4)
+#define AFE_DL8_END                       (0x12b8)
+#define AFE_DL8_CON0                      (0x12bc)
+#define AFE_DL10_BASE                     (0x12d0)
+#define AFE_DL10_CUR                      (0x12d4)
+#define AFE_DL10_END                      (0x12d8)
+#define AFE_DL10_CON0                     (0x12dc)
+#define AFE_DL11_BASE                     (0x12e0)
+#define AFE_DL11_CUR                      (0x12e4)
+#define AFE_DL11_END                      (0x12e8)
+#define AFE_DL11_CON0                     (0x12ec)
+#define AFE_UL1_BASE                      (0x1300)
+#define AFE_UL1_CUR                       (0x1304)
+#define AFE_UL1_END                       (0x1308)
+#define AFE_UL1_CON0                      (0x130c)
+#define AFE_UL2_BASE                      (0x1310)
+#define AFE_UL2_CUR                       (0x1314)
+#define AFE_UL2_END                       (0x1318)
+#define AFE_UL2_CON0                      (0x131c)
+#define AFE_UL3_BASE                      (0x1320)
+#define AFE_UL3_CUR                       (0x1324)
+#define AFE_UL3_END                       (0x1328)
+#define AFE_UL3_CON0                      (0x132c)
+#define AFE_UL4_BASE                      (0x1330)
+#define AFE_UL4_CUR                       (0x1334)
+#define AFE_UL4_END                       (0x1338)
+#define AFE_UL4_CON0                      (0x133c)
+#define AFE_UL5_BASE                      (0x1340)
+#define AFE_UL5_CUR                       (0x1344)
+#define AFE_UL5_END                       (0x1348)
+#define AFE_UL5_CON0                      (0x134c)
+#define AFE_UL6_BASE                      (0x1350)
+#define AFE_UL6_CUR                       (0x1354)
+#define AFE_UL6_END                       (0x1358)
+#define AFE_UL6_CON0                      (0x135c)
+#define AFE_UL8_BASE                      (0x1370)
+#define AFE_UL8_CUR                       (0x1374)
+#define AFE_UL8_END                       (0x1378)
+#define AFE_UL8_CON0                      (0x137c)
+#define AFE_UL9_BASE                      (0x1380)
+#define AFE_UL9_CUR                       (0x1384)
+#define AFE_UL9_END                       (0x1388)
+#define AFE_UL9_CON0                      (0x138c)
+#define AFE_UL10_BASE                     (0x13d0)
+#define AFE_UL10_CUR                      (0x13d4)
+#define AFE_UL10_END                      (0x13d8)
+#define AFE_UL10_CON0                     (0x13dc)
+#define AFE_DL8_CHK_SUM1                  (0x1400)
+#define AFE_DL8_CHK_SUM2                  (0x1404)
+#define AFE_DL8_CHK_SUM3                  (0x1408)
+#define AFE_DL8_CHK_SUM4                  (0x140c)
+#define AFE_DL8_CHK_SUM5                  (0x1410)
+#define AFE_DL8_CHK_SUM6                  (0x1414)
+#define AFE_DL10_CHK_SUM1                 (0x1418)
+#define AFE_DL10_CHK_SUM2                 (0x141c)
+#define AFE_DL10_CHK_SUM3                 (0x1420)
+#define AFE_DL10_CHK_SUM4                 (0x1424)
+#define AFE_DL10_CHK_SUM5                 (0x1428)
+#define AFE_DL10_CHK_SUM6                 (0x142c)
+#define AFE_DL11_CHK_SUM1                 (0x1430)
+#define AFE_DL11_CHK_SUM2                 (0x1434)
+#define AFE_DL11_CHK_SUM3                 (0x1438)
+#define AFE_DL11_CHK_SUM4                 (0x143c)
+#define AFE_DL11_CHK_SUM5                 (0x1440)
+#define AFE_DL11_CHK_SUM6                 (0x1444)
+#define AFE_UL1_CHK_SUM1                  (0x1450)
+#define AFE_UL1_CHK_SUM2                  (0x1454)
+#define AFE_UL2_CHK_SUM1                  (0x1458)
+#define AFE_UL2_CHK_SUM2                  (0x145c)
+#define AFE_UL3_CHK_SUM1                  (0x1460)
+#define AFE_UL3_CHK_SUM2                  (0x1464)
+#define AFE_UL4_CHK_SUM1                  (0x1468)
+#define AFE_UL4_CHK_SUM2                  (0x146c)
+#define AFE_UL5_CHK_SUM1                  (0x1470)
+#define AFE_UL5_CHK_SUM2                  (0x1474)
+#define AFE_UL6_CHK_SUM1                  (0x1478)
+#define AFE_UL6_CHK_SUM2                  (0x147c)
+#define AFE_UL8_CHK_SUM1                  (0x1488)
+#define AFE_UL8_CHK_SUM2                  (0x148c)
+#define AFE_DL2_CHK_SUM1                  (0x14a0)
+#define AFE_DL2_CHK_SUM2                  (0x14a4)
+#define AFE_DL3_CHK_SUM1                  (0x14b0)
+#define AFE_DL3_CHK_SUM2                  (0x14b4)
+#define AFE_DL6_CHK_SUM1                  (0x14e0)
+#define AFE_DL6_CHK_SUM2                  (0x14e4)
+#define AFE_DL7_CHK_SUM1                  (0x14f0)
+#define AFE_DL7_CHK_SUM2                  (0x14f4)
+#define AFE_UL9_CHK_SUM1                  (0x1528)
+#define AFE_UL9_CHK_SUM2                  (0x152c)
+#define AFE_BUS_MON1                      (0x1540)
+#define UL1_MOD2AGT_CNT_LAT               (0x1568)
+#define UL2_MOD2AGT_CNT_LAT               (0x156c)
+#define UL3_MOD2AGT_CNT_LAT               (0x1570)
+#define UL4_MOD2AGT_CNT_LAT               (0x1574)
+#define UL5_MOD2AGT_CNT_LAT               (0x1578)
+#define UL6_MOD2AGT_CNT_LAT               (0x157c)
+#define UL8_MOD2AGT_CNT_LAT               (0x1588)
+#define UL9_MOD2AGT_CNT_LAT               (0x158c)
+#define UL10_MOD2AGT_CNT_LAT              (0x1590)
+#define AFE_MEMIF_AGENT_FS_CON0           (0x15a0)
+#define AFE_MEMIF_AGENT_FS_CON1           (0x15a4)
+#define AFE_MEMIF_AGENT_FS_CON2           (0x15a8)
+#define AFE_MEMIF_AGENT_FS_CON3           (0x15ac)
+#define AFE_MEMIF_BURST_CFG               (0x1600)
+#define AFE_MEMIF_BUF_FULL_MON            (0x1610)
+#define AFE_MEMIF_BUF_MON1                (0x161c)
+#define AFE_MEMIF_BUF_MON3                (0x1624)
+#define AFE_MEMIF_BUF_MON4                (0x1628)
+#define AFE_MEMIF_BUF_MON5                (0x162c)
+#define AFE_MEMIF_BUF_MON6                (0x1630)
+#define AFE_MEMIF_BUF_MON7                (0x1634)
+#define AFE_MEMIF_BUF_MON8                (0x1638)
+#define AFE_MEMIF_BUF_MON9                (0x163c)
+#define AFE_MEMIF_BUF_MON10               (0x1640)
+#define DL2_AGENT2MODULE_CNT              (0x1678)
+#define DL3_AGENT2MODULE_CNT              (0x167c)
+#define DL6_AGENT2MODULE_CNT              (0x1688)
+#define DL7_AGENT2MODULE_CNT              (0x168c)
+#define DL8_AGENT2MODULE_CNT              (0x1690)
+#define DL10_AGENT2MODULE_CNT             (0x1698)
+#define DL11_AGENT2MODULE_CNT             (0x169c)
+#define UL1_MODULE2AGENT_CNT              (0x16a0)
+#define UL2_MODULE2AGENT_CNT              (0x16a4)
+#define UL3_MODULE2AGENT_CNT              (0x16a8)
+#define UL4_MODULE2AGENT_CNT              (0x16ac)
+#define UL5_MODULE2AGENT_CNT              (0x16b0)
+#define UL6_MODULE2AGENT_CNT              (0x16b4)
+#define UL8_MODULE2AGENT_CNT              (0x16bc)
+#define UL9_MODULE2AGENT_CNT              (0x16c0)
+#define UL10_MODULE2AGENT_CNT             (0x16c4)
+#define AFE_SECURE_CON2                   (0x1798)
+#define AFE_SECURE_CON1                   (0x179c)
+#define AFE_SECURE_CON                    (0x17a0)
+#define AFE_SRAM_BOUND                    (0x17a4)
+#define AFE_SE_SECURE_CON                 (0x17a8)
+#define AFE_SECURE_MASK_LOOPBACK          (0x17bc)
+#define AFE_SECURE_SIDEBAND0              (0x1908)
+#define AFE_SECURE_SIDEBAND1              (0x190c)
+#define AFE_SECURE_SIDEBAND2              (0x1910)
+#define AFE_SECURE_SIDEBAND3              (0x1914)
+#define AFE_SECURE_MASK_BASE_ADR_MSB      (0x1920)
+#define AFE_SECURE_MASK_END_ADR_MSB       (0x1924)
+#define AFE_NORMAL_BASE_ADR_MSB           (0x192c)
+#define AFE_NORMAL_END_ADR_MSB            (0x1930)
+#define AFE_SECURE_MASK_LOOPBACK0         (0x1940)
+#define AFE_SECURE_MASK_LOOPBACK1         (0x1944)
+#define AFE_SECURE_MASK_LOOPBACK2         (0x1948)
+#define AFE_LOOPBACK_CFG0                 (0x1950)
+#define AFE_LOOPBACK_CFG1                 (0x1954)
+#define AFE_LOOPBACK_CFG2                 (0x1958)
+#define AFE_DMIC0_UL_SRC_CON0             (0x1a00)
+#define AFE_DMIC0_UL_SRC_CON1             (0x1a04)
+#define AFE_DMIC0_SRC_DEBUG               (0x1a08)
+#define AFE_DMIC0_SRC_DEBUG_MON0          (0x1a0c)
+#define AFE_DMIC0_UL_SRC_MON0             (0x1a10)
+#define AFE_DMIC0_UL_SRC_MON1             (0x1a14)
+#define AFE_DMIC0_IIR_COEF_02_01          (0x1a18)
+#define AFE_DMIC0_IIR_COEF_04_03          (0x1a1c)
+#define AFE_DMIC0_IIR_COEF_06_05          (0x1a20)
+#define AFE_DMIC0_IIR_COEF_08_07          (0x1a24)
+#define AFE_DMIC0_IIR_COEF_10_09          (0x1a28)
+#define AFE_DMIC1_UL_SRC_CON0             (0x1a68)
+#define AFE_DMIC1_UL_SRC_CON1             (0x1a6c)
+#define AFE_DMIC1_SRC_DEBUG               (0x1a70)
+#define AFE_DMIC1_SRC_DEBUG_MON0          (0x1a74)
+#define AFE_DMIC1_UL_SRC_MON0             (0x1a78)
+#define AFE_DMIC1_UL_SRC_MON1             (0x1a7c)
+#define AFE_DMIC1_IIR_COEF_02_01          (0x1a80)
+#define AFE_DMIC1_IIR_COEF_04_03          (0x1a84)
+#define AFE_DMIC1_IIR_COEF_06_05          (0x1a88)
+#define AFE_DMIC1_IIR_COEF_08_07          (0x1a8c)
+#define AFE_DMIC1_IIR_COEF_10_09          (0x1a90)
+#define AFE_DMIC2_UL_SRC_CON0             (0x1ad0)
+#define AFE_DMIC2_UL_SRC_CON1             (0x1ad4)
+#define AFE_DMIC2_SRC_DEBUG               (0x1ad8)
+#define AFE_DMIC2_SRC_DEBUG_MON0          (0x1adc)
+#define AFE_DMIC2_UL_SRC_MON0             (0x1ae0)
+#define AFE_DMIC2_UL_SRC_MON1             (0x1ae4)
+#define AFE_DMIC2_IIR_COEF_02_01          (0x1ae8)
+#define AFE_DMIC2_IIR_COEF_04_03          (0x1aec)
+#define AFE_DMIC2_IIR_COEF_06_05          (0x1af0)
+#define AFE_DMIC2_IIR_COEF_08_07          (0x1af4)
+#define AFE_DMIC2_IIR_COEF_10_09          (0x1af8)
+#define AFE_DMIC3_UL_SRC_CON0             (0x1b38)
+#define AFE_DMIC3_UL_SRC_CON1             (0x1b3c)
+#define AFE_DMIC3_SRC_DEBUG               (0x1b40)
+#define AFE_DMIC3_SRC_DEBUG_MON0          (0x1b44)
+#define AFE_DMIC3_UL_SRC_MON0             (0x1b48)
+#define AFE_DMIC3_UL_SRC_MON1             (0x1b4c)
+#define AFE_DMIC3_IIR_COEF_02_01          (0x1b50)
+#define AFE_DMIC3_IIR_COEF_04_03          (0x1b54)
+#define AFE_DMIC3_IIR_COEF_06_05          (0x1b58)
+#define AFE_DMIC3_IIR_COEF_08_07          (0x1b5c)
+#define AFE_DMIC3_IIR_COEF_10_09          (0x1b60)
+#define DMIC_BYPASS_HW_GAIN               (0x1bf0)
+#define DMIC_GAIN1_CON0                   (0x1c00)
+#define DMIC_GAIN1_CON1                   (0x1c04)
+#define DMIC_GAIN1_CON2                   (0x1c08)
+#define DMIC_GAIN1_CON3                   (0x1c0c)
+#define DMIC_GAIN1_CUR                    (0x1c10)
+#define DMIC_GAIN2_CON0                   (0x1c20)
+#define DMIC_GAIN2_CON1                   (0x1c24)
+#define DMIC_GAIN2_CON2                   (0x1c28)
+#define DMIC_GAIN2_CON3                   (0x1c2c)
+#define DMIC_GAIN2_CUR                    (0x1c30)
+#define DMIC_GAIN3_CON0                   (0x1c40)
+#define DMIC_GAIN3_CON1                   (0x1c44)
+#define DMIC_GAIN3_CON2                   (0x1c48)
+#define DMIC_GAIN3_CON3                   (0x1c4c)
+#define DMIC_GAIN3_CUR                    (0x1c50)
+#define DMIC_GAIN4_CON0                   (0x1c60)
+#define DMIC_GAIN4_CON1                   (0x1c64)
+#define DMIC_GAIN4_CON2                   (0x1c68)
+#define DMIC_GAIN4_CON3                   (0x1c6c)
+#define DMIC_GAIN4_CUR                    (0x1c70)
+#define ETDM_OUT1_DSD_FADE_CON            (0x2260)
+#define ETDM_OUT1_DSD_FADE_CON1           (0x2264)
+#define ETDM_OUT3_DSD_FADE_CON            (0x2280)
+#define ETDM_OUT3_DSD_FADE_CON1           (0x2284)
+#define ETDM_IN1_AFIFO_CON                (0x2294)
+#define ETDM_IN2_AFIFO_CON                (0x2298)
+#define ETDM_IN1_MONITOR                  (0x22c0)
+#define ETDM_IN2_MONITOR                  (0x22c4)
+#define ETDM_OUT1_MONITOR                 (0x22d0)
+#define ETDM_OUT2_MONITOR                 (0x22d4)
+#define ETDM_OUT3_MONITOR                 (0x22d8)
+#define ETDM_COWORK_SEC_CON0              (0x22e0)
+#define ETDM_COWORK_SEC_CON1              (0x22e4)
+#define ETDM_COWORK_SEC_CON2              (0x22e8)
+#define ETDM_COWORK_SEC_CON3              (0x22ec)
+#define ETDM_COWORK_CON0                  (0x22f0)
+#define ETDM_COWORK_CON1                  (0x22f4)
+#define ETDM_COWORK_CON2                  (0x22f8)
+#define ETDM_COWORK_CON3                  (0x22fc)
+#define ETDM_IN1_CON0                     (0x2300)
+#define ETDM_IN1_CON1                     (0x2304)
+#define ETDM_IN1_CON2                     (0x2308)
+#define ETDM_IN1_CON3                     (0x230c)
+#define ETDM_IN1_CON4                     (0x2310)
+#define ETDM_IN1_CON5                     (0x2314)
+#define ETDM_IN1_CON6                     (0x2318)
+#define ETDM_IN1_CON7                     (0x231c)
+#define ETDM_IN2_CON0                     (0x2320)
+#define ETDM_IN2_CON1                     (0x2324)
+#define ETDM_IN2_CON2                     (0x2328)
+#define ETDM_IN2_CON3                     (0x232c)
+#define ETDM_IN2_CON4                     (0x2330)
+#define ETDM_IN2_CON5                     (0x2334)
+#define ETDM_IN2_CON6                     (0x2338)
+#define ETDM_IN2_CON7                     (0x233c)
+#define ETDM_OUT1_CON0                    (0x2380)
+#define ETDM_OUT1_CON1                    (0x2384)
+#define ETDM_OUT1_CON2                    (0x2388)
+#define ETDM_OUT1_CON3                    (0x238c)
+#define ETDM_OUT1_CON4                    (0x2390)
+#define ETDM_OUT1_CON5                    (0x2394)
+#define ETDM_OUT1_CON6                    (0x2398)
+#define ETDM_OUT1_CON7                    (0x239c)
+#define ETDM_OUT2_CON0                    (0x23a0)
+#define ETDM_OUT2_CON1                    (0x23a4)
+#define ETDM_OUT2_CON2                    (0x23a8)
+#define ETDM_OUT2_CON3                    (0x23ac)
+#define ETDM_OUT2_CON4                    (0x23b0)
+#define ETDM_OUT2_CON5                    (0x23b4)
+#define ETDM_OUT2_CON6                    (0x23b8)
+#define ETDM_OUT2_CON7                    (0x23bc)
+#define ETDM_OUT3_CON0                    (0x23c0)
+#define ETDM_OUT3_CON1                    (0x23c4)
+#define ETDM_OUT3_CON2                    (0x23c8)
+#define ETDM_OUT3_CON3                    (0x23cc)
+#define ETDM_OUT3_CON4                    (0x23d0)
+#define ETDM_OUT3_CON5                    (0x23d4)
+#define ETDM_OUT3_CON6                    (0x23d8)
+#define ETDM_OUT3_CON7                    (0x23dc)
+#define ETDM_OUT3_CON8                    (0x23e0)
+#define ETDM_OUT1_CON8                    (0x23e4)
+#define ETDM_OUT2_CON8                    (0x23e8)
+#define GASRC_TIMING_CON0                 (0x2414)
+#define GASRC_TIMING_CON1                 (0x2418)
+#define GASRC_TIMING_CON2                 (0x241c)
+#define GASRC_TIMING_CON3                 (0x2420)
+#define GASRC_TIMING_CON4                 (0x2424)
+#define GASRC_TIMING_CON5                 (0x2428)
+#define GASRC_TIMING_CON6                 (0x242c)
+#define GASRC_TIMING_CON7                 (0x2430)
+#define A3_A4_TIMING_SEL0                 (0x2440)
+#define A3_A4_TIMING_SEL1                 (0x2444)
+#define A3_A4_TIMING_SEL2                 (0x2448)
+#define A3_A4_TIMING_SEL3                 (0x244c)
+#define A3_A4_TIMING_SEL4                 (0x2450)
+#define A3_A4_TIMING_SEL5                 (0x2454)
+#define A3_A4_TIMING_SEL6                 (0x2458)
+#define ASYS_TOP_DEBUG                    (0x2500)
+#define AFE_DPTX_CON                      (0x2558)
+#define AFE_DPTX_MON                      (0x255c)
+#define AFE_ADDA_DL_SRC2_CON0             (0x2d00)
+#define AFE_ADDA_DL_SRC2_CON1             (0x2d04)
+#define AFE_ADDA_TOP_CON0                 (0x2d0c)
+#define AFE_ADDA_UL_DL_CON0               (0x2d10)
+#define AFE_ADDA_SRC_DEBUG                (0x2d14)
+#define AFE_ADDA_SRC_DEBUG_MON0           (0x2d18)
+#define AFE_ADDA_SRC_DEBUG_MON1           (0x2d20)
+#define AFE_ADDA_PREDIS_CON0              (0x2d24)
+#define AFE_ADDA_PREDIS_CON1              (0x2d28)
+#define AFE_ADDA_PREDIS_CON2              (0x2d2c)
+#define AFE_ADDA_PREDIS_CON3              (0x2d30)
+#define AFE_ADDA_DL_SDM_DCCOMP_CON        (0x2d34)
+#define AFE_ADDA_DL_SDM_TEST              (0x2d38)
+#define AFE_ADDA_DL_DC_COMP_CFG0          (0x2d3c)
+#define AFE_ADDA_DL_DC_COMP_CFG1          (0x2d40)
+#define AFE_ADDA_DL_SDM_FIFO_MON          (0x2d44)
+#define AFE_ADDA_DL_SRC_LCH_MON           (0x2d50)
+#define AFE_ADDA_DL_SRC_RCH_MON           (0x2d54)
+#define AFE_ADDA_DL_SDM_OUT_MON           (0x2d58)
+#define AFE_ADDA_DL_SDM_DITHER_CON        (0x2d5c)
+#define AFE_ADDA_DL_SDM_AUTO_RESET_CON    (0x2d60)
+#define AFE_ADDA_UL_SRC_CON0              (0x2e3c)
+#define AFE_ADDA_UL_SRC_CON1              (0x2e40)
+#define AFE_CONN0                         (0x3000)
+#define AFE_CONN0_1                       (0x3004)
+#define AFE_CONN0_2                       (0x3008)
+#define AFE_CONN0_3                       (0x300c)
+#define AFE_CONN0_4                       (0x3010)
+#define AFE_CONN1                         (0x3014)
+#define AFE_CONN1_1                       (0x3018)
+#define AFE_CONN1_2                       (0x301c)
+#define AFE_CONN1_3                       (0x3020)
+#define AFE_CONN1_4                       (0x3024)
+#define AFE_CONN2                         (0x3028)
+#define AFE_CONN2_1                       (0x302c)
+#define AFE_CONN2_2                       (0x3030)
+#define AFE_CONN2_3                       (0x3034)
+#define AFE_CONN2_4                       (0x3038)
+#define AFE_CONN3                         (0x303c)
+#define AFE_CONN3_1                       (0x3040)
+#define AFE_CONN3_2                       (0x3044)
+#define AFE_CONN3_3                       (0x3048)
+#define AFE_CONN3_4                       (0x304c)
+#define AFE_CONN4                         (0x3050)
+#define AFE_CONN4_1                       (0x3054)
+#define AFE_CONN4_2                       (0x3058)
+#define AFE_CONN4_3                       (0x305c)
+#define AFE_CONN4_4                       (0x3060)
+#define AFE_CONN5                         (0x3064)
+#define AFE_CONN5_1                       (0x3068)
+#define AFE_CONN5_2                       (0x306c)
+#define AFE_CONN5_3                       (0x3070)
+#define AFE_CONN5_4                       (0x3074)
+#define AFE_CONN6                         (0x3078)
+#define AFE_CONN6_1                       (0x307c)
+#define AFE_CONN6_2                       (0x3080)
+#define AFE_CONN6_3                       (0x3084)
+#define AFE_CONN6_4                       (0x3088)
+#define AFE_CONN7                         (0x308c)
+#define AFE_CONN7_1                       (0x3090)
+#define AFE_CONN7_2                       (0x3094)
+#define AFE_CONN7_3                       (0x3098)
+#define AFE_CONN7_4                       (0x309c)
+#define AFE_CONN8                         (0x30a0)
+#define AFE_CONN8_1                       (0x30a4)
+#define AFE_CONN8_2                       (0x30a8)
+#define AFE_CONN8_3                       (0x30ac)
+#define AFE_CONN8_4                       (0x30b0)
+#define AFE_CONN9                         (0x30b4)
+#define AFE_CONN9_1                       (0x30b8)
+#define AFE_CONN9_2                       (0x30bc)
+#define AFE_CONN9_3                       (0x30c0)
+#define AFE_CONN9_4                       (0x30c4)
+#define AFE_CONN10                        (0x30c8)
+#define AFE_CONN10_1                      (0x30cc)
+#define AFE_CONN10_2                      (0x30d0)
+#define AFE_CONN10_3                      (0x30d4)
+#define AFE_CONN10_4                      (0x30d8)
+#define AFE_CONN11                        (0x30dc)
+#define AFE_CONN11_1                      (0x30e0)
+#define AFE_CONN11_2                      (0x30e4)
+#define AFE_CONN11_3                      (0x30e8)
+#define AFE_CONN11_4                      (0x30ec)
+#define AFE_CONN12                        (0x30f0)
+#define AFE_CONN12_1                      (0x30f4)
+#define AFE_CONN12_2                      (0x30f8)
+#define AFE_CONN12_3                      (0x30fc)
+#define AFE_CONN12_4                      (0x3100)
+#define AFE_CONN13                        (0x3104)
+#define AFE_CONN13_1                      (0x3108)
+#define AFE_CONN13_2                      (0x310c)
+#define AFE_CONN13_3                      (0x3110)
+#define AFE_CONN13_4                      (0x3114)
+#define AFE_CONN14                        (0x3118)
+#define AFE_CONN14_1                      (0x311c)
+#define AFE_CONN14_2                      (0x3120)
+#define AFE_CONN14_3                      (0x3124)
+#define AFE_CONN14_4                      (0x3128)
+#define AFE_CONN15                        (0x312c)
+#define AFE_CONN15_1                      (0x3130)
+#define AFE_CONN15_2                      (0x3134)
+#define AFE_CONN15_3                      (0x3138)
+#define AFE_CONN15_4                      (0x313c)
+#define AFE_CONN16                        (0x3140)
+#define AFE_CONN16_1                      (0x3144)
+#define AFE_CONN16_2                      (0x3148)
+#define AFE_CONN16_3                      (0x314c)
+#define AFE_CONN16_4                      (0x3150)
+#define AFE_CONN17                        (0x3154)
+#define AFE_CONN17_1                      (0x3158)
+#define AFE_CONN17_2                      (0x315c)
+#define AFE_CONN17_3                      (0x3160)
+#define AFE_CONN17_4                      (0x3164)
+#define AFE_CONN18                        (0x3168)
+#define AFE_CONN18_1                      (0x316c)
+#define AFE_CONN18_2                      (0x3170)
+#define AFE_CONN18_3                      (0x3174)
+#define AFE_CONN18_4                      (0x3178)
+#define AFE_CONN19                        (0x317c)
+#define AFE_CONN19_1                      (0x3180)
+#define AFE_CONN19_2                      (0x3184)
+#define AFE_CONN19_3                      (0x3188)
+#define AFE_CONN19_4                      (0x318c)
+#define AFE_CONN20                        (0x3190)
+#define AFE_CONN20_1                      (0x3194)
+#define AFE_CONN20_2                      (0x3198)
+#define AFE_CONN20_3                      (0x319c)
+#define AFE_CONN20_4                      (0x31a0)
+#define AFE_CONN21                        (0x31a4)
+#define AFE_CONN21_1                      (0x31a8)
+#define AFE_CONN21_2                      (0x31ac)
+#define AFE_CONN21_3                      (0x31b0)
+#define AFE_CONN21_4                      (0x31b4)
+#define AFE_CONN22                        (0x31b8)
+#define AFE_CONN22_1                      (0x31bc)
+#define AFE_CONN22_2                      (0x31c0)
+#define AFE_CONN22_3                      (0x31c4)
+#define AFE_CONN22_4                      (0x31c8)
+#define AFE_CONN23                        (0x31cc)
+#define AFE_CONN23_1                      (0x31d0)
+#define AFE_CONN23_2                      (0x31d4)
+#define AFE_CONN23_3                      (0x31d8)
+#define AFE_CONN23_4                      (0x31dc)
+#define AFE_CONN24                        (0x31e0)
+#define AFE_CONN24_1                      (0x31e4)
+#define AFE_CONN24_2                      (0x31e8)
+#define AFE_CONN24_3                      (0x31ec)
+#define AFE_CONN24_4                      (0x31f0)
+#define AFE_CONN25                        (0x31f4)
+#define AFE_CONN25_1                      (0x31f8)
+#define AFE_CONN25_2                      (0x31fc)
+#define AFE_CONN25_3                      (0x3200)
+#define AFE_CONN25_4                      (0x3204)
+#define AFE_CONN26                        (0x3208)
+#define AFE_CONN26_1                      (0x320c)
+#define AFE_CONN26_2                      (0x3210)
+#define AFE_CONN26_3                      (0x3214)
+#define AFE_CONN26_4                      (0x3218)
+#define AFE_CONN27                        (0x321c)
+#define AFE_CONN27_1                      (0x3220)
+#define AFE_CONN27_2                      (0x3224)
+#define AFE_CONN27_3                      (0x3228)
+#define AFE_CONN27_4                      (0x322c)
+#define AFE_CONN28                        (0x3230)
+#define AFE_CONN28_1                      (0x3234)
+#define AFE_CONN28_2                      (0x3238)
+#define AFE_CONN28_3                      (0x323c)
+#define AFE_CONN28_4                      (0x3240)
+#define AFE_CONN29                        (0x3244)
+#define AFE_CONN29_1                      (0x3248)
+#define AFE_CONN29_2                      (0x324c)
+#define AFE_CONN29_3                      (0x3250)
+#define AFE_CONN29_4                      (0x3254)
+#define AFE_CONN30                        (0x3258)
+#define AFE_CONN30_1                      (0x325c)
+#define AFE_CONN30_2                      (0x3260)
+#define AFE_CONN30_3                      (0x3264)
+#define AFE_CONN30_4                      (0x3268)
+#define AFE_CONN31                        (0x326c)
+#define AFE_CONN31_1                      (0x3270)
+#define AFE_CONN31_2                      (0x3274)
+#define AFE_CONN31_3                      (0x3278)
+#define AFE_CONN31_4                      (0x327c)
+#define AFE_CONN32                        (0x3280)
+#define AFE_CONN32_1                      (0x3284)
+#define AFE_CONN32_2                      (0x3288)
+#define AFE_CONN32_3                      (0x328c)
+#define AFE_CONN32_4                      (0x3290)
+#define AFE_CONN33                        (0x3294)
+#define AFE_CONN33_1                      (0x3298)
+#define AFE_CONN33_2                      (0x329c)
+#define AFE_CONN33_3                      (0x32a0)
+#define AFE_CONN33_4                      (0x32a4)
+#define AFE_CONN34                        (0x32a8)
+#define AFE_CONN34_1                      (0x32ac)
+#define AFE_CONN34_2                      (0x32b0)
+#define AFE_CONN34_3                      (0x32b4)
+#define AFE_CONN34_4                      (0x32b8)
+#define AFE_CONN35                        (0x32bc)
+#define AFE_CONN35_1                      (0x32c0)
+#define AFE_CONN35_2                      (0x32c4)
+#define AFE_CONN35_3                      (0x32c8)
+#define AFE_CONN35_4                      (0x32cc)
+#define AFE_CONN36                        (0x32d0)
+#define AFE_CONN36_1                      (0x32d4)
+#define AFE_CONN36_2                      (0x32d8)
+#define AFE_CONN36_3                      (0x32dc)
+#define AFE_CONN36_4                      (0x32e0)
+#define AFE_CONN37                        (0x32e4)
+#define AFE_CONN37_1                      (0x32e8)
+#define AFE_CONN37_2                      (0x32ec)
+#define AFE_CONN37_3                      (0x32f0)
+#define AFE_CONN37_4                      (0x32f4)
+#define AFE_CONN38                        (0x32f8)
+#define AFE_CONN38_1                      (0x32fc)
+#define AFE_CONN38_2                      (0x3300)
+#define AFE_CONN38_3                      (0x3304)
+#define AFE_CONN38_4                      (0x3308)
+#define AFE_CONN39                        (0x330c)
+#define AFE_CONN39_1                      (0x3310)
+#define AFE_CONN39_2                      (0x3314)
+#define AFE_CONN39_3                      (0x3318)
+#define AFE_CONN39_4                      (0x331c)
+#define AFE_CONN40                        (0x3320)
+#define AFE_CONN40_1                      (0x3324)
+#define AFE_CONN40_2                      (0x3328)
+#define AFE_CONN40_3                      (0x332c)
+#define AFE_CONN40_4                      (0x3330)
+#define AFE_CONN41                        (0x3334)
+#define AFE_CONN41_1                      (0x3338)
+#define AFE_CONN41_2                      (0x333c)
+#define AFE_CONN41_3                      (0x3340)
+#define AFE_CONN41_4                      (0x3344)
+#define AFE_CONN42                        (0x3348)
+#define AFE_CONN42_1                      (0x334c)
+#define AFE_CONN42_2                      (0x3350)
+#define AFE_CONN42_3                      (0x3354)
+#define AFE_CONN42_4                      (0x3358)
+#define AFE_CONN43                        (0x335c)
+#define AFE_CONN43_1                      (0x3360)
+#define AFE_CONN43_2                      (0x3364)
+#define AFE_CONN43_3                      (0x3368)
+#define AFE_CONN43_4                      (0x336c)
+#define AFE_CONN44                        (0x3370)
+#define AFE_CONN44_1                      (0x3374)
+#define AFE_CONN44_2                      (0x3378)
+#define AFE_CONN44_3                      (0x337c)
+#define AFE_CONN44_4                      (0x3380)
+#define AFE_CONN45                        (0x3384)
+#define AFE_CONN45_1                      (0x3388)
+#define AFE_CONN45_2                      (0x338c)
+#define AFE_CONN45_3                      (0x3390)
+#define AFE_CONN45_4                      (0x3394)
+#define AFE_CONN46                        (0x3398)
+#define AFE_CONN46_1                      (0x339c)
+#define AFE_CONN46_2                      (0x33a0)
+#define AFE_CONN46_3                      (0x33a4)
+#define AFE_CONN46_4                      (0x33a8)
+#define AFE_CONN47                        (0x33ac)
+#define AFE_CONN47_1                      (0x33b0)
+#define AFE_CONN47_2                      (0x33b4)
+#define AFE_CONN47_3                      (0x33b8)
+#define AFE_CONN47_4                      (0x33bc)
+#define AFE_CONN48                        (0x33c0)
+#define AFE_CONN48_1                      (0x33c4)
+#define AFE_CONN48_2                      (0x33c8)
+#define AFE_CONN48_3                      (0x33cc)
+#define AFE_CONN48_4                      (0x33d0)
+#define AFE_CONN49                        (0x33d4)
+#define AFE_CONN49_1                      (0x33d8)
+#define AFE_CONN49_2                      (0x33dc)
+#define AFE_CONN49_3                      (0x33e0)
+#define AFE_CONN49_4                      (0x33e4)
+#define AFE_CONN50                        (0x33e8)
+#define AFE_CONN50_1                      (0x33ec)
+#define AFE_CONN50_2                      (0x33f0)
+#define AFE_CONN50_3                      (0x33f4)
+#define AFE_CONN50_4                      (0x33f8)
+#define AFE_CONN51                        (0x33fc)
+#define AFE_CONN51_1                      (0x3400)
+#define AFE_CONN51_2                      (0x3404)
+#define AFE_CONN51_3                      (0x3408)
+#define AFE_CONN51_4                      (0x340c)
+#define AFE_CONN52                        (0x3410)
+#define AFE_CONN52_1                      (0x3414)
+#define AFE_CONN52_2                      (0x3418)
+#define AFE_CONN52_3                      (0x341c)
+#define AFE_CONN52_4                      (0x3420)
+#define AFE_CONN53                        (0x3424)
+#define AFE_CONN53_1                      (0x3428)
+#define AFE_CONN53_2                      (0x342c)
+#define AFE_CONN53_3                      (0x3430)
+#define AFE_CONN53_4                      (0x3434)
+#define AFE_CONN54                        (0x3438)
+#define AFE_CONN54_1                      (0x343c)
+#define AFE_CONN54_2                      (0x3440)
+#define AFE_CONN54_3                      (0x3444)
+#define AFE_CONN54_4                      (0x3448)
+#define AFE_CONN55                        (0x344c)
+#define AFE_CONN55_1                      (0x3450)
+#define AFE_CONN55_2                      (0x3454)
+#define AFE_CONN55_3                      (0x3458)
+#define AFE_CONN55_4                      (0x345c)
+#define AFE_CONN56                        (0x3460)
+#define AFE_CONN56_1                      (0x3464)
+#define AFE_CONN56_2                      (0x3468)
+#define AFE_CONN56_3                      (0x346c)
+#define AFE_CONN56_4                      (0x3470)
+#define AFE_CONN57                        (0x3474)
+#define AFE_CONN57_1                      (0x3478)
+#define AFE_CONN57_2                      (0x347c)
+#define AFE_CONN57_3                      (0x3480)
+#define AFE_CONN57_4                      (0x3484)
+#define AFE_CONN58                        (0x3488)
+#define AFE_CONN58_1                      (0x348c)
+#define AFE_CONN58_2                      (0x3490)
+#define AFE_CONN58_3                      (0x3494)
+#define AFE_CONN58_4                      (0x3498)
+#define AFE_CONN59                        (0x349c)
+#define AFE_CONN59_1                      (0x34a0)
+#define AFE_CONN59_2                      (0x34a4)
+#define AFE_CONN59_3                      (0x34a8)
+#define AFE_CONN59_4                      (0x34ac)
+#define AFE_CONN60                        (0x34b0)
+#define AFE_CONN60_1                      (0x34b4)
+#define AFE_CONN60_2                      (0x34b8)
+#define AFE_CONN60_3                      (0x34bc)
+#define AFE_CONN60_4                      (0x34c0)
+#define AFE_CONN61                        (0x34c4)
+#define AFE_CONN61_1                      (0x34c8)
+#define AFE_CONN61_2                      (0x34cc)
+#define AFE_CONN61_3                      (0x34d0)
+#define AFE_CONN61_4                      (0x34d4)
+#define AFE_CONN62                        (0x34d8)
+#define AFE_CONN62_1                      (0x34dc)
+#define AFE_CONN62_2                      (0x34e0)
+#define AFE_CONN62_3                      (0x34e4)
+#define AFE_CONN62_4                      (0x34e8)
+#define AFE_CONN63                        (0x34ec)
+#define AFE_CONN63_1                      (0x34f0)
+#define AFE_CONN63_2                      (0x34f4)
+#define AFE_CONN63_3                      (0x34f8)
+#define AFE_CONN63_4                      (0x34fc)
+#define AFE_CONN64                        (0x3500)
+#define AFE_CONN64_1                      (0x3504)
+#define AFE_CONN64_2                      (0x3508)
+#define AFE_CONN64_3                      (0x350c)
+#define AFE_CONN64_4                      (0x3510)
+#define AFE_CONN65                        (0x3514)
+#define AFE_CONN65_1                      (0x3518)
+#define AFE_CONN65_2                      (0x351c)
+#define AFE_CONN65_3                      (0x3520)
+#define AFE_CONN65_4                      (0x3524)
+#define AFE_CONN66                        (0x3528)
+#define AFE_CONN66_1                      (0x352c)
+#define AFE_CONN66_2                      (0x3530)
+#define AFE_CONN66_3                      (0x3534)
+#define AFE_CONN66_4                      (0x3538)
+#define AFE_CONN67                        (0x353c)
+#define AFE_CONN67_1                      (0x3540)
+#define AFE_CONN67_2                      (0x3544)
+#define AFE_CONN67_3                      (0x3548)
+#define AFE_CONN67_4                      (0x354c)
+#define AFE_CONN68                        (0x3550)
+#define AFE_CONN68_1                      (0x3554)
+#define AFE_CONN68_2                      (0x3558)
+#define AFE_CONN68_3                      (0x355c)
+#define AFE_CONN68_4                      (0x3560)
+#define AFE_CONN69                        (0x3564)
+#define AFE_CONN69_1                      (0x3568)
+#define AFE_CONN69_2                      (0x356c)
+#define AFE_CONN69_3                      (0x3570)
+#define AFE_CONN69_4                      (0x3574)
+#define AFE_CONN70                        (0x3578)
+#define AFE_CONN70_1                      (0x357c)
+#define AFE_CONN70_2                      (0x3580)
+#define AFE_CONN70_3                      (0x3584)
+#define AFE_CONN70_4                      (0x3588)
+#define AFE_CONN71                        (0x358c)
+#define AFE_CONN71_1                      (0x3590)
+#define AFE_CONN71_2                      (0x3594)
+#define AFE_CONN71_3                      (0x3598)
+#define AFE_CONN71_4                      (0x359c)
+#define AFE_CONN72                        (0x35a0)
+#define AFE_CONN72_1                      (0x35a4)
+#define AFE_CONN72_2                      (0x35a8)
+#define AFE_CONN72_3                      (0x35ac)
+#define AFE_CONN72_4                      (0x35b0)
+#define AFE_CONN73                        (0x35b4)
+#define AFE_CONN73_1                      (0x35b8)
+#define AFE_CONN73_2                      (0x35bc)
+#define AFE_CONN73_3                      (0x35c0)
+#define AFE_CONN73_4                      (0x35c4)
+#define AFE_CONN74                        (0x35c8)
+#define AFE_CONN74_1                      (0x35cc)
+#define AFE_CONN74_2                      (0x35d0)
+#define AFE_CONN74_3                      (0x35d4)
+#define AFE_CONN74_4                      (0x35d8)
+#define AFE_CONN75                        (0x35dc)
+#define AFE_CONN75_1                      (0x35e0)
+#define AFE_CONN75_2                      (0x35e4)
+#define AFE_CONN75_3                      (0x35e8)
+#define AFE_CONN75_4                      (0x35ec)
+#define AFE_CONN76                        (0x35f0)
+#define AFE_CONN76_1                      (0x35f4)
+#define AFE_CONN76_2                      (0x35f8)
+#define AFE_CONN76_3                      (0x35fc)
+#define AFE_CONN76_4                      (0x3600)
+#define AFE_CONN77                        (0x3604)
+#define AFE_CONN77_1                      (0x3608)
+#define AFE_CONN77_2                      (0x360c)
+#define AFE_CONN77_3                      (0x3610)
+#define AFE_CONN77_4                      (0x3614)
+#define AFE_CONN78                        (0x3618)
+#define AFE_CONN78_1                      (0x361c)
+#define AFE_CONN78_2                      (0x3620)
+#define AFE_CONN78_3                      (0x3624)
+#define AFE_CONN78_4                      (0x3628)
+#define AFE_CONN79                        (0x362c)
+#define AFE_CONN79_1                      (0x3630)
+#define AFE_CONN79_2                      (0x3634)
+#define AFE_CONN79_3                      (0x3638)
+#define AFE_CONN79_4                      (0x363c)
+#define AFE_CONN80                        (0x3640)
+#define AFE_CONN80_1                      (0x3644)
+#define AFE_CONN80_2                      (0x3648)
+#define AFE_CONN80_3                      (0x364c)
+#define AFE_CONN80_4                      (0x3650)
+#define AFE_CONN81                        (0x3654)
+#define AFE_CONN81_1                      (0x3658)
+#define AFE_CONN81_2                      (0x365c)
+#define AFE_CONN81_3                      (0x3660)
+#define AFE_CONN81_4                      (0x3664)
+#define AFE_CONN82                        (0x3668)
+#define AFE_CONN82_1                      (0x366c)
+#define AFE_CONN82_2                      (0x3670)
+#define AFE_CONN82_3                      (0x3674)
+#define AFE_CONN82_4                      (0x3678)
+#define AFE_CONN83                        (0x367c)
+#define AFE_CONN83_1                      (0x3680)
+#define AFE_CONN83_2                      (0x3684)
+#define AFE_CONN83_3                      (0x3688)
+#define AFE_CONN83_4                      (0x368c)
+#define AFE_CONN84                        (0x3690)
+#define AFE_CONN84_1                      (0x3694)
+#define AFE_CONN84_2                      (0x3698)
+#define AFE_CONN84_3                      (0x369c)
+#define AFE_CONN84_4                      (0x36a0)
+#define AFE_CONN85                        (0x36a4)
+#define AFE_CONN85_1                      (0x36a8)
+#define AFE_CONN85_2                      (0x36ac)
+#define AFE_CONN85_3                      (0x36b0)
+#define AFE_CONN85_4                      (0x36b4)
+#define AFE_CONN86                        (0x36b8)
+#define AFE_CONN86_1                      (0x36bc)
+#define AFE_CONN86_2                      (0x36c0)
+#define AFE_CONN86_3                      (0x36c4)
+#define AFE_CONN86_4                      (0x36c8)
+#define AFE_CONN87                        (0x36cc)
+#define AFE_CONN87_1                      (0x36d0)
+#define AFE_CONN87_2                      (0x36d4)
+#define AFE_CONN87_3                      (0x36d8)
+#define AFE_CONN87_4                      (0x36dc)
+#define AFE_CONN88                        (0x36e0)
+#define AFE_CONN88_1                      (0x36e4)
+#define AFE_CONN88_2                      (0x36e8)
+#define AFE_CONN88_3                      (0x36ec)
+#define AFE_CONN88_4                      (0x36f0)
+#define AFE_CONN89                        (0x36f4)
+#define AFE_CONN89_1                      (0x36f8)
+#define AFE_CONN89_2                      (0x36fc)
+#define AFE_CONN89_3                      (0x3700)
+#define AFE_CONN89_4                      (0x3704)
+#define AFE_CONN90                        (0x3708)
+#define AFE_CONN90_1                      (0x370c)
+#define AFE_CONN90_2                      (0x3710)
+#define AFE_CONN90_3                      (0x3714)
+#define AFE_CONN90_4                      (0x3718)
+#define AFE_CONN91                        (0x371c)
+#define AFE_CONN91_1                      (0x3720)
+#define AFE_CONN91_2                      (0x3724)
+#define AFE_CONN91_3                      (0x3728)
+#define AFE_CONN91_4                      (0x372c)
+#define AFE_CONN92                        (0x3730)
+#define AFE_CONN92_1                      (0x3734)
+#define AFE_CONN92_2                      (0x3738)
+#define AFE_CONN92_3                      (0x373c)
+#define AFE_CONN92_4                      (0x3740)
+#define AFE_CONN93                        (0x3744)
+#define AFE_CONN93_1                      (0x3748)
+#define AFE_CONN93_2                      (0x374c)
+#define AFE_CONN93_3                      (0x3750)
+#define AFE_CONN93_4                      (0x3754)
+#define AFE_CONN94                        (0x3758)
+#define AFE_CONN94_1                      (0x375c)
+#define AFE_CONN94_2                      (0x3760)
+#define AFE_CONN94_3                      (0x3764)
+#define AFE_CONN94_4                      (0x3768)
+#define AFE_CONN95                        (0x376c)
+#define AFE_CONN95_1                      (0x3770)
+#define AFE_CONN95_2                      (0x3774)
+#define AFE_CONN95_3                      (0x3778)
+#define AFE_CONN95_4                      (0x377c)
+#define AFE_CONN96                        (0x3780)
+#define AFE_CONN96_1                      (0x3784)
+#define AFE_CONN96_2                      (0x3788)
+#define AFE_CONN96_3                      (0x378c)
+#define AFE_CONN96_4                      (0x3790)
+#define AFE_CONN97                        (0x3794)
+#define AFE_CONN97_1                      (0x3798)
+#define AFE_CONN97_2                      (0x379c)
+#define AFE_CONN97_3                      (0x37a0)
+#define AFE_CONN97_4                      (0x37a4)
+#define AFE_CONN98                        (0x37a8)
+#define AFE_CONN98_1                      (0x37ac)
+#define AFE_CONN98_2                      (0x37b0)
+#define AFE_CONN98_3                      (0x37b4)
+#define AFE_CONN98_4                      (0x37b8)
+#define AFE_CONN99                        (0x37bc)
+#define AFE_CONN99_1                      (0x37c0)
+#define AFE_CONN99_2                      (0x37c4)
+#define AFE_CONN99_3                      (0x37c8)
+#define AFE_CONN99_4                      (0x37cc)
+#define AFE_CONN100                       (0x37d0)
+#define AFE_CONN100_1                     (0x37d4)
+#define AFE_CONN100_2                     (0x37d8)
+#define AFE_CONN100_3                     (0x37dc)
+#define AFE_CONN100_4                     (0x37e0)
+#define AFE_CONN101                       (0x37e4)
+#define AFE_CONN101_1                     (0x37e8)
+#define AFE_CONN101_2                     (0x37ec)
+#define AFE_CONN101_3                     (0x37f0)
+#define AFE_CONN101_4                     (0x37f4)
+#define AFE_CONN102                       (0x37f8)
+#define AFE_CONN102_1                     (0x37fc)
+#define AFE_CONN102_2                     (0x3800)
+#define AFE_CONN102_3                     (0x3804)
+#define AFE_CONN102_4                     (0x3808)
+#define AFE_CONN103                       (0x380c)
+#define AFE_CONN103_1                     (0x3810)
+#define AFE_CONN103_2                     (0x3814)
+#define AFE_CONN103_3                     (0x3818)
+#define AFE_CONN103_4                     (0x381c)
+#define AFE_CONN104                       (0x3820)
+#define AFE_CONN104_1                     (0x3824)
+#define AFE_CONN104_2                     (0x3828)
+#define AFE_CONN104_3                     (0x382c)
+#define AFE_CONN104_4                     (0x3830)
+#define AFE_CONN105                       (0x3834)
+#define AFE_CONN105_1                     (0x3838)
+#define AFE_CONN105_2                     (0x383c)
+#define AFE_CONN105_3                     (0x3840)
+#define AFE_CONN105_4                     (0x3844)
+#define AFE_CONN106                       (0x3848)
+#define AFE_CONN106_1                     (0x384c)
+#define AFE_CONN106_2                     (0x3850)
+#define AFE_CONN106_3                     (0x3854)
+#define AFE_CONN106_4                     (0x3858)
+#define AFE_CONN107                       (0x385c)
+#define AFE_CONN107_1                     (0x3860)
+#define AFE_CONN107_2                     (0x3864)
+#define AFE_CONN107_3                     (0x3868)
+#define AFE_CONN107_4                     (0x386c)
+#define AFE_CONN108                       (0x3870)
+#define AFE_CONN108_1                     (0x3874)
+#define AFE_CONN108_2                     (0x3878)
+#define AFE_CONN108_3                     (0x387c)
+#define AFE_CONN108_4                     (0x3880)
+#define AFE_CONN109                       (0x3884)
+#define AFE_CONN109_1                     (0x3888)
+#define AFE_CONN109_2                     (0x388c)
+#define AFE_CONN109_3                     (0x3890)
+#define AFE_CONN109_4                     (0x3894)
+#define AFE_CONN110                       (0x3898)
+#define AFE_CONN110_1                     (0x389c)
+#define AFE_CONN110_2                     (0x38a0)
+#define AFE_CONN110_3                     (0x38a4)
+#define AFE_CONN110_4                     (0x38a8)
+#define AFE_CONN111                       (0x38ac)
+#define AFE_CONN111_1                     (0x38b0)
+#define AFE_CONN111_2                     (0x38b4)
+#define AFE_CONN111_3                     (0x38b8)
+#define AFE_CONN111_4                     (0x38bc)
+#define AFE_CONN112                       (0x38c0)
+#define AFE_CONN112_1                     (0x38c4)
+#define AFE_CONN112_2                     (0x38c8)
+#define AFE_CONN112_3                     (0x38cc)
+#define AFE_CONN112_4                     (0x38d0)
+#define AFE_CONN113                       (0x38d4)
+#define AFE_CONN113_1                     (0x38d8)
+#define AFE_CONN113_2                     (0x38dc)
+#define AFE_CONN113_3                     (0x38e0)
+#define AFE_CONN113_4                     (0x38e4)
+#define AFE_CONN114                       (0x38e8)
+#define AFE_CONN114_1                     (0x38ec)
+#define AFE_CONN114_2                     (0x38f0)
+#define AFE_CONN114_3                     (0x38f4)
+#define AFE_CONN114_4                     (0x38f8)
+#define AFE_CONN115                       (0x38fc)
+#define AFE_CONN115_1                     (0x3900)
+#define AFE_CONN115_2                     (0x3904)
+#define AFE_CONN115_3                     (0x3908)
+#define AFE_CONN115_4                     (0x390c)
+#define AFE_CONN116                       (0x3910)
+#define AFE_CONN116_1                     (0x3914)
+#define AFE_CONN116_2                     (0x3918)
+#define AFE_CONN116_3                     (0x391c)
+#define AFE_CONN116_4                     (0x3920)
+#define AFE_CONN117                       (0x3924)
+#define AFE_CONN117_1                     (0x3928)
+#define AFE_CONN117_2                     (0x392c)
+#define AFE_CONN117_3                     (0x3930)
+#define AFE_CONN117_4                     (0x3934)
+#define AFE_CONN118                       (0x3938)
+#define AFE_CONN118_1                     (0x393c)
+#define AFE_CONN118_2                     (0x3940)
+#define AFE_CONN118_3                     (0x3944)
+#define AFE_CONN118_4                     (0x3948)
+#define AFE_CONN119                       (0x394c)
+#define AFE_CONN119_1                     (0x3950)
+#define AFE_CONN119_2                     (0x3954)
+#define AFE_CONN119_3                     (0x3958)
+#define AFE_CONN119_4                     (0x395c)
+#define AFE_CONN120                       (0x3960)
+#define AFE_CONN120_1                     (0x3964)
+#define AFE_CONN120_2                     (0x3968)
+#define AFE_CONN120_3                     (0x396c)
+#define AFE_CONN120_4                     (0x3970)
+#define AFE_CONN121                       (0x3974)
+#define AFE_CONN121_1                     (0x3978)
+#define AFE_CONN121_2                     (0x397c)
+#define AFE_CONN121_3                     (0x3980)
+#define AFE_CONN121_4                     (0x3984)
+#define AFE_CONN122                       (0x3988)
+#define AFE_CONN122_1                     (0x398c)
+#define AFE_CONN122_2                     (0x3990)
+#define AFE_CONN122_3                     (0x3994)
+#define AFE_CONN122_4                     (0x3998)
+#define AFE_CONN123                       (0x399c)
+#define AFE_CONN123_1                     (0x39a0)
+#define AFE_CONN123_2                     (0x39a4)
+#define AFE_CONN123_3                     (0x39a8)
+#define AFE_CONN123_4                     (0x39ac)
+#define AFE_CONN124                       (0x39b0)
+#define AFE_CONN124_1                     (0x39b4)
+#define AFE_CONN124_2                     (0x39b8)
+#define AFE_CONN124_3                     (0x39bc)
+#define AFE_CONN124_4                     (0x39c0)
+#define AFE_CONN125                       (0x39c4)
+#define AFE_CONN125_1                     (0x39c8)
+#define AFE_CONN125_2                     (0x39cc)
+#define AFE_CONN125_3                     (0x39d0)
+#define AFE_CONN125_4                     (0x39d4)
+#define AFE_CONN126                       (0x39d8)
+#define AFE_CONN126_1                     (0x39dc)
+#define AFE_CONN126_2                     (0x39e0)
+#define AFE_CONN126_3                     (0x39e4)
+#define AFE_CONN126_4                     (0x39e8)
+#define AFE_CONN127                       (0x39ec)
+#define AFE_CONN127_1                     (0x39f0)
+#define AFE_CONN127_2                     (0x39f4)
+#define AFE_CONN127_3                     (0x39f8)
+#define AFE_CONN127_4                     (0x39fc)
+#define AFE_CONN128                       (0x3a00)
+#define AFE_CONN128_1                     (0x3a04)
+#define AFE_CONN128_2                     (0x3a08)
+#define AFE_CONN128_3                     (0x3a0c)
+#define AFE_CONN128_4                     (0x3a10)
+#define AFE_CONN129                       (0x3a14)
+#define AFE_CONN129_1                     (0x3a18)
+#define AFE_CONN129_2                     (0x3a1c)
+#define AFE_CONN129_3                     (0x3a20)
+#define AFE_CONN129_4                     (0x3a24)
+#define AFE_CONN130                       (0x3a28)
+#define AFE_CONN130_1                     (0x3a2c)
+#define AFE_CONN130_2                     (0x3a30)
+#define AFE_CONN130_3                     (0x3a34)
+#define AFE_CONN130_4                     (0x3a38)
+#define AFE_CONN131                       (0x3a3c)
+#define AFE_CONN131_1                     (0x3a40)
+#define AFE_CONN131_2                     (0x3a44)
+#define AFE_CONN131_3                     (0x3a48)
+#define AFE_CONN131_4                     (0x3a4c)
+#define AFE_CONN132                       (0x3a50)
+#define AFE_CONN132_1                     (0x3a54)
+#define AFE_CONN132_2                     (0x3a58)
+#define AFE_CONN132_3                     (0x3a5c)
+#define AFE_CONN132_4                     (0x3a60)
+#define AFE_CONN133                       (0x3a64)
+#define AFE_CONN133_1                     (0x3a68)
+#define AFE_CONN133_2                     (0x3a6c)
+#define AFE_CONN133_3                     (0x3a70)
+#define AFE_CONN133_4                     (0x3a74)
+#define AFE_CONN134                       (0x3a78)
+#define AFE_CONN134_1                     (0x3a7c)
+#define AFE_CONN134_2                     (0x3a80)
+#define AFE_CONN134_3                     (0x3a84)
+#define AFE_CONN134_4                     (0x3a88)
+#define AFE_CONN135                       (0x3a8c)
+#define AFE_CONN135_1                     (0x3a90)
+#define AFE_CONN135_2                     (0x3a94)
+#define AFE_CONN135_3                     (0x3a98)
+#define AFE_CONN135_4                     (0x3a9c)
+#define AFE_CONN136                       (0x3aa0)
+#define AFE_CONN136_1                     (0x3aa4)
+#define AFE_CONN136_2                     (0x3aa8)
+#define AFE_CONN136_3                     (0x3aac)
+#define AFE_CONN136_4                     (0x3ab0)
+#define AFE_CONN137                       (0x3ab4)
+#define AFE_CONN137_1                     (0x3ab8)
+#define AFE_CONN137_2                     (0x3abc)
+#define AFE_CONN137_3                     (0x3ac0)
+#define AFE_CONN137_4                     (0x3ac4)
+#define AFE_CONN138                       (0x3ac8)
+#define AFE_CONN138_1                     (0x3acc)
+#define AFE_CONN138_2                     (0x3ad0)
+#define AFE_CONN138_3                     (0x3ad4)
+#define AFE_CONN138_4                     (0x3ad8)
+#define AFE_CONN139                       (0x3adc)
+#define AFE_CONN139_1                     (0x3ae0)
+#define AFE_CONN139_2                     (0x3ae4)
+#define AFE_CONN139_3                     (0x3ae8)
+#define AFE_CONN139_4                     (0x3aec)
+#define AFE_CONN_RS                       (0x3af0)
+#define AFE_CONN_RS_1                     (0x3af4)
+#define AFE_CONN_RS_2                     (0x3af8)
+#define AFE_CONN_RS_3                     (0x3afc)
+#define AFE_CONN_RS_4                     (0x3b00)
+#define AFE_CONN_16BIT                    (0x3b04)
+#define AFE_CONN_16BIT_1                  (0x3b08)
+#define AFE_CONN_16BIT_2                  (0x3b0c)
+#define AFE_CONN_16BIT_3                  (0x3b10)
+#define AFE_CONN_16BIT_4                  (0x3b14)
+#define AFE_CONN_24BIT                    (0x3b18)
+#define AFE_CONN_24BIT_1                  (0x3b1c)
+#define AFE_CONN_24BIT_2                  (0x3b20)
+#define AFE_CONN_24BIT_3                  (0x3b24)
+#define AFE_CONN_24BIT_4                  (0x3b28)
+#define AFE_CONN_DI                       (0x3b2c)
+#define AFE_CONN_DI_1                     (0x3b30)
+#define AFE_CONN_DI_2                     (0x3b34)
+#define AFE_CONN_DI_3                     (0x3b38)
+#define AFE_CONN_DI_4                     (0x3b3c)
+#define AFE_CONN176                       (0x3ea0)
+#define AFE_CONN176_1                     (0x3ea4)
+#define AFE_CONN176_2                     (0x3ea8)
+#define AFE_CONN176_3                     (0x3eac)
+#define AFE_CONN176_4                     (0x3eb0)
+#define AFE_CONN176_5                     (0x3eb4)
+#define AFE_CONN177                       (0x3eb8)
+#define AFE_CONN177_1                     (0x3ebc)
+#define AFE_CONN177_2                     (0x3ec0)
+#define AFE_CONN177_3                     (0x3ec4)
+#define AFE_CONN177_4                     (0x3ec8)
+#define AFE_CONN177_5                     (0x3ecc)
+#define AFE_CONN182                       (0x3f30)
+#define AFE_CONN182_1                     (0x3f34)
+#define AFE_CONN182_2                     (0x3f38)
+#define AFE_CONN182_3                     (0x3f3c)
+#define AFE_CONN182_4                     (0x3f40)
+#define AFE_CONN182_5                     (0x3f44)
+#define AFE_CONN183                       (0x3f48)
+#define AFE_CONN183_1                     (0x3f4c)
+#define AFE_CONN183_2                     (0x3f50)
+#define AFE_CONN183_3                     (0x3f54)
+#define AFE_CONN183_4                     (0x3f58)
+#define AFE_CONN183_5                     (0x3f5c)
+#define AFE_SECURE_MASK_CONN0             (0x4000)
+#define AFE_SECURE_MASK_CONN0_1           (0x4004)
+#define AFE_SECURE_MASK_CONN0_2           (0x4008)
+#define AFE_SECURE_MASK_CONN0_3           (0x400c)
+#define AFE_SECURE_MASK_CONN0_4           (0x4010)
+#define AFE_SECURE_MASK_CONN1             (0x4014)
+#define AFE_SECURE_MASK_CONN1_1           (0x4018)
+#define AFE_SECURE_MASK_CONN1_2           (0x401c)
+#define AFE_SECURE_MASK_CONN1_3           (0x4020)
+#define AFE_SECURE_MASK_CONN1_4           (0x4024)
+#define AFE_SECURE_MASK_CONN2             (0x4028)
+#define AFE_SECURE_MASK_CONN2_1           (0x402c)
+#define AFE_SECURE_MASK_CONN2_2           (0x4030)
+#define AFE_SECURE_MASK_CONN2_3           (0x4034)
+#define AFE_SECURE_MASK_CONN2_4           (0x4038)
+#define AFE_SECURE_MASK_CONN3             (0x403c)
+#define AFE_SECURE_MASK_CONN3_1           (0x4040)
+#define AFE_SECURE_MASK_CONN3_2           (0x4044)
+#define AFE_SECURE_MASK_CONN3_3           (0x4048)
+#define AFE_SECURE_MASK_CONN3_4           (0x404c)
+#define AFE_SECURE_MASK_CONN4             (0x4050)
+#define AFE_SECURE_MASK_CONN4_1           (0x4054)
+#define AFE_SECURE_MASK_CONN4_2           (0x4058)
+#define AFE_SECURE_MASK_CONN4_3           (0x405c)
+#define AFE_SECURE_MASK_CONN4_4           (0x4060)
+#define AFE_SECURE_MASK_CONN5             (0x4064)
+#define AFE_SECURE_MASK_CONN5_1           (0x4068)
+#define AFE_SECURE_MASK_CONN5_2           (0x406c)
+#define AFE_SECURE_MASK_CONN5_3           (0x4070)
+#define AFE_SECURE_MASK_CONN5_4           (0x4074)
+#define AFE_SECURE_MASK_CONN6             (0x4078)
+#define AFE_SECURE_MASK_CONN6_1           (0x407c)
+#define AFE_SECURE_MASK_CONN6_2           (0x4080)
+#define AFE_SECURE_MASK_CONN6_3           (0x4084)
+#define AFE_SECURE_MASK_CONN6_4           (0x4088)
+#define AFE_SECURE_MASK_CONN7             (0x408c)
+#define AFE_SECURE_MASK_CONN7_1           (0x4090)
+#define AFE_SECURE_MASK_CONN7_2           (0x4094)
+#define AFE_SECURE_MASK_CONN7_3           (0x4098)
+#define AFE_SECURE_MASK_CONN7_4           (0x409c)
+#define AFE_SECURE_MASK_CONN8             (0x40a0)
+#define AFE_SECURE_MASK_CONN8_1           (0x40a4)
+#define AFE_SECURE_MASK_CONN8_2           (0x40a8)
+#define AFE_SECURE_MASK_CONN8_3           (0x40ac)
+#define AFE_SECURE_MASK_CONN8_4           (0x40b0)
+#define AFE_SECURE_MASK_CONN9             (0x40b4)
+#define AFE_SECURE_MASK_CONN9_1           (0x40b8)
+#define AFE_SECURE_MASK_CONN9_2           (0x40bc)
+#define AFE_SECURE_MASK_CONN9_3           (0x40c0)
+#define AFE_SECURE_MASK_CONN9_4           (0x40c4)
+#define AFE_SECURE_MASK_CONN10            (0x40c8)
+#define AFE_SECURE_MASK_CONN10_1          (0x40cc)
+#define AFE_SECURE_MASK_CONN10_2          (0x40d0)
+#define AFE_SECURE_MASK_CONN10_3          (0x40d4)
+#define AFE_SECURE_MASK_CONN10_4          (0x40d8)
+#define AFE_SECURE_MASK_CONN11            (0x40dc)
+#define AFE_SECURE_MASK_CONN11_1          (0x40e0)
+#define AFE_SECURE_MASK_CONN11_2          (0x40e4)
+#define AFE_SECURE_MASK_CONN11_3          (0x40e8)
+#define AFE_SECURE_MASK_CONN11_4          (0x40ec)
+#define AFE_SECURE_MASK_CONN12            (0x40f0)
+#define AFE_SECURE_MASK_CONN12_1          (0x40f4)
+#define AFE_SECURE_MASK_CONN12_2          (0x40f8)
+#define AFE_SECURE_MASK_CONN12_3          (0x40fc)
+#define AFE_SECURE_MASK_CONN12_4          (0x4100)
+#define AFE_SECURE_MASK_CONN13            (0x4104)
+#define AFE_SECURE_MASK_CONN13_1          (0x4108)
+#define AFE_SECURE_MASK_CONN13_2          (0x410c)
+#define AFE_SECURE_MASK_CONN13_3          (0x4110)
+#define AFE_SECURE_MASK_CONN13_4          (0x4114)
+#define AFE_SECURE_MASK_CONN14            (0x4118)
+#define AFE_SECURE_MASK_CONN14_1          (0x411c)
+#define AFE_SECURE_MASK_CONN14_2          (0x4120)
+#define AFE_SECURE_MASK_CONN14_3          (0x4124)
+#define AFE_SECURE_MASK_CONN14_4          (0x4128)
+#define AFE_SECURE_MASK_CONN15            (0x412c)
+#define AFE_SECURE_MASK_CONN15_1          (0x4130)
+#define AFE_SECURE_MASK_CONN15_2          (0x4134)
+#define AFE_SECURE_MASK_CONN15_3          (0x4138)
+#define AFE_SECURE_MASK_CONN15_4          (0x413c)
+#define AFE_SECURE_MASK_CONN16            (0x4140)
+#define AFE_SECURE_MASK_CONN16_1          (0x4144)
+#define AFE_SECURE_MASK_CONN16_2          (0x4148)
+#define AFE_SECURE_MASK_CONN16_3          (0x414c)
+#define AFE_SECURE_MASK_CONN16_4          (0x4150)
+#define AFE_SECURE_MASK_CONN17            (0x4154)
+#define AFE_SECURE_MASK_CONN17_1          (0x4158)
+#define AFE_SECURE_MASK_CONN17_2          (0x415c)
+#define AFE_SECURE_MASK_CONN17_3          (0x4160)
+#define AFE_SECURE_MASK_CONN17_4          (0x4164)
+#define AFE_SECURE_MASK_CONN18            (0x4168)
+#define AFE_SECURE_MASK_CONN18_1          (0x416c)
+#define AFE_SECURE_MASK_CONN18_2          (0x4170)
+#define AFE_SECURE_MASK_CONN18_3          (0x4174)
+#define AFE_SECURE_MASK_CONN18_4          (0x4178)
+#define AFE_SECURE_MASK_CONN19            (0x417c)
+#define AFE_SECURE_MASK_CONN19_1          (0x4180)
+#define AFE_SECURE_MASK_CONN19_2          (0x4184)
+#define AFE_SECURE_MASK_CONN19_3          (0x4188)
+#define AFE_SECURE_MASK_CONN19_4          (0x418c)
+#define AFE_SECURE_MASK_CONN20            (0x4190)
+#define AFE_SECURE_MASK_CONN20_1          (0x4194)
+#define AFE_SECURE_MASK_CONN20_2          (0x4198)
+#define AFE_SECURE_MASK_CONN20_3          (0x419c)
+#define AFE_SECURE_MASK_CONN20_4          (0x41a0)
+#define AFE_SECURE_MASK_CONN21            (0x41a4)
+#define AFE_SECURE_MASK_CONN21_1          (0x41a8)
+#define AFE_SECURE_MASK_CONN21_2          (0x41ac)
+#define AFE_SECURE_MASK_CONN21_3          (0x41b0)
+#define AFE_SECURE_MASK_CONN21_4          (0x41b4)
+#define AFE_SECURE_MASK_CONN22            (0x41b8)
+#define AFE_SECURE_MASK_CONN22_1          (0x41bc)
+#define AFE_SECURE_MASK_CONN22_2          (0x41c0)
+#define AFE_SECURE_MASK_CONN22_3          (0x41c4)
+#define AFE_SECURE_MASK_CONN22_4          (0x41c8)
+#define AFE_SECURE_MASK_CONN23            (0x41cc)
+#define AFE_SECURE_MASK_CONN23_1          (0x41d0)
+#define AFE_SECURE_MASK_CONN23_2          (0x41d4)
+#define AFE_SECURE_MASK_CONN23_3          (0x41d8)
+#define AFE_SECURE_MASK_CONN23_4          (0x41dc)
+#define AFE_SECURE_MASK_CONN24            (0x41e0)
+#define AFE_SECURE_MASK_CONN24_1          (0x41e4)
+#define AFE_SECURE_MASK_CONN24_2          (0x41e8)
+#define AFE_SECURE_MASK_CONN24_3          (0x41ec)
+#define AFE_SECURE_MASK_CONN24_4          (0x41f0)
+#define AFE_SECURE_MASK_CONN25            (0x41f4)
+#define AFE_SECURE_MASK_CONN25_1          (0x41f8)
+#define AFE_SECURE_MASK_CONN25_2          (0x41fc)
+#define AFE_SECURE_MASK_CONN25_3          (0x4200)
+#define AFE_SECURE_MASK_CONN25_4          (0x4204)
+#define AFE_SECURE_MASK_CONN26            (0x4208)
+#define AFE_SECURE_MASK_CONN26_1          (0x420c)
+#define AFE_SECURE_MASK_CONN26_2          (0x4210)
+#define AFE_SECURE_MASK_CONN26_3          (0x4214)
+#define AFE_SECURE_MASK_CONN26_4          (0x4218)
+#define AFE_SECURE_MASK_CONN27            (0x421c)
+#define AFE_SECURE_MASK_CONN27_1          (0x4220)
+#define AFE_SECURE_MASK_CONN27_2          (0x4224)
+#define AFE_SECURE_MASK_CONN27_3          (0x4228)
+#define AFE_SECURE_MASK_CONN27_4          (0x422c)
+#define AFE_SECURE_MASK_CONN28            (0x4230)
+#define AFE_SECURE_MASK_CONN28_1          (0x4234)
+#define AFE_SECURE_MASK_CONN28_2          (0x4238)
+#define AFE_SECURE_MASK_CONN28_3          (0x423c)
+#define AFE_SECURE_MASK_CONN28_4          (0x4240)
+#define AFE_SECURE_MASK_CONN29            (0x4244)
+#define AFE_SECURE_MASK_CONN29_1          (0x4248)
+#define AFE_SECURE_MASK_CONN29_2          (0x424c)
+#define AFE_SECURE_MASK_CONN29_3          (0x4250)
+#define AFE_SECURE_MASK_CONN29_4          (0x4254)
+#define AFE_SECURE_MASK_CONN30            (0x4258)
+#define AFE_SECURE_MASK_CONN30_1          (0x425c)
+#define AFE_SECURE_MASK_CONN30_2          (0x4260)
+#define AFE_SECURE_MASK_CONN30_3          (0x4264)
+#define AFE_SECURE_MASK_CONN30_4          (0x4268)
+#define AFE_SECURE_MASK_CONN31            (0x426c)
+#define AFE_SECURE_MASK_CONN31_1          (0x4270)
+#define AFE_SECURE_MASK_CONN31_2          (0x4274)
+#define AFE_SECURE_MASK_CONN31_3          (0x4278)
+#define AFE_SECURE_MASK_CONN31_4          (0x427c)
+#define AFE_SECURE_MASK_CONN32            (0x4280)
+#define AFE_SECURE_MASK_CONN32_1          (0x4284)
+#define AFE_SECURE_MASK_CONN32_2          (0x4288)
+#define AFE_SECURE_MASK_CONN32_3          (0x428c)
+#define AFE_SECURE_MASK_CONN32_4          (0x4290)
+#define AFE_SECURE_MASK_CONN33            (0x4294)
+#define AFE_SECURE_MASK_CONN33_1          (0x4298)
+#define AFE_SECURE_MASK_CONN33_2          (0x429c)
+#define AFE_SECURE_MASK_CONN33_3          (0x42a0)
+#define AFE_SECURE_MASK_CONN33_4          (0x42a4)
+#define AFE_SECURE_MASK_CONN34            (0x42a8)
+#define AFE_SECURE_MASK_CONN34_1          (0x42ac)
+#define AFE_SECURE_MASK_CONN34_2          (0x42b0)
+#define AFE_SECURE_MASK_CONN34_3          (0x42b4)
+#define AFE_SECURE_MASK_CONN34_4          (0x42b8)
+#define AFE_SECURE_MASK_CONN35            (0x42bc)
+#define AFE_SECURE_MASK_CONN35_1          (0x42c0)
+#define AFE_SECURE_MASK_CONN35_2          (0x42c4)
+#define AFE_SECURE_MASK_CONN35_3          (0x42c8)
+#define AFE_SECURE_MASK_CONN35_4          (0x42cc)
+#define AFE_SECURE_MASK_CONN36            (0x42d0)
+#define AFE_SECURE_MASK_CONN36_1          (0x42d4)
+#define AFE_SECURE_MASK_CONN36_2          (0x42d8)
+#define AFE_SECURE_MASK_CONN36_3          (0x42dc)
+#define AFE_SECURE_MASK_CONN36_4          (0x42e0)
+#define AFE_SECURE_MASK_CONN37            (0x42e4)
+#define AFE_SECURE_MASK_CONN37_1          (0x42e8)
+#define AFE_SECURE_MASK_CONN37_2          (0x42ec)
+#define AFE_SECURE_MASK_CONN37_3          (0x42f0)
+#define AFE_SECURE_MASK_CONN37_4          (0x42f4)
+#define AFE_SECURE_MASK_CONN38            (0x42f8)
+#define AFE_SECURE_MASK_CONN38_1          (0x42fc)
+#define AFE_SECURE_MASK_CONN38_2          (0x4300)
+#define AFE_SECURE_MASK_CONN38_3          (0x4304)
+#define AFE_SECURE_MASK_CONN38_4          (0x4308)
+#define AFE_SECURE_MASK_CONN39            (0x430c)
+#define AFE_SECURE_MASK_CONN39_1          (0x4310)
+#define AFE_SECURE_MASK_CONN39_2          (0x4314)
+#define AFE_SECURE_MASK_CONN39_3          (0x4318)
+#define AFE_SECURE_MASK_CONN39_4          (0x431c)
+#define AFE_SECURE_MASK_CONN40            (0x4320)
+#define AFE_SECURE_MASK_CONN40_1          (0x4324)
+#define AFE_SECURE_MASK_CONN40_2          (0x4328)
+#define AFE_SECURE_MASK_CONN40_3          (0x432c)
+#define AFE_SECURE_MASK_CONN40_4          (0x4330)
+#define AFE_SECURE_MASK_CONN41            (0x4334)
+#define AFE_SECURE_MASK_CONN41_1          (0x4338)
+#define AFE_SECURE_MASK_CONN41_2          (0x433c)
+#define AFE_SECURE_MASK_CONN41_3          (0x4340)
+#define AFE_SECURE_MASK_CONN41_4          (0x4344)
+#define AFE_SECURE_MASK_CONN42            (0x4348)
+#define AFE_SECURE_MASK_CONN42_1          (0x434c)
+#define AFE_SECURE_MASK_CONN42_2          (0x4350)
+#define AFE_SECURE_MASK_CONN42_3          (0x4354)
+#define AFE_SECURE_MASK_CONN42_4          (0x4358)
+#define AFE_SECURE_MASK_CONN43            (0x435c)
+#define AFE_SECURE_MASK_CONN43_1          (0x4360)
+#define AFE_SECURE_MASK_CONN43_2          (0x4364)
+#define AFE_SECURE_MASK_CONN43_3          (0x4368)
+#define AFE_SECURE_MASK_CONN43_4          (0x436c)
+#define AFE_SECURE_MASK_CONN44            (0x4370)
+#define AFE_SECURE_MASK_CONN44_1          (0x4374)
+#define AFE_SECURE_MASK_CONN44_2          (0x4378)
+#define AFE_SECURE_MASK_CONN44_3          (0x437c)
+#define AFE_SECURE_MASK_CONN44_4          (0x4380)
+#define AFE_SECURE_MASK_CONN45            (0x4384)
+#define AFE_SECURE_MASK_CONN45_1          (0x4388)
+#define AFE_SECURE_MASK_CONN45_2          (0x438c)
+#define AFE_SECURE_MASK_CONN45_3          (0x4390)
+#define AFE_SECURE_MASK_CONN45_4          (0x4394)
+#define AFE_SECURE_MASK_CONN46            (0x4398)
+#define AFE_SECURE_MASK_CONN46_1          (0x439c)
+#define AFE_SECURE_MASK_CONN46_2          (0x43a0)
+#define AFE_SECURE_MASK_CONN46_3          (0x43a4)
+#define AFE_SECURE_MASK_CONN46_4          (0x43a8)
+#define AFE_SECURE_MASK_CONN47            (0x43ac)
+#define AFE_SECURE_MASK_CONN47_1          (0x43b0)
+#define AFE_SECURE_MASK_CONN47_2          (0x43b4)
+#define AFE_SECURE_MASK_CONN47_3          (0x43b8)
+#define AFE_SECURE_MASK_CONN47_4          (0x43bc)
+#define AFE_SECURE_MASK_CONN48            (0x43c0)
+#define AFE_SECURE_MASK_CONN48_1          (0x43c4)
+#define AFE_SECURE_MASK_CONN48_2          (0x43c8)
+#define AFE_SECURE_MASK_CONN48_3          (0x43cc)
+#define AFE_SECURE_MASK_CONN48_4          (0x43d0)
+#define AFE_SECURE_MASK_CONN49            (0x43d4)
+#define AFE_SECURE_MASK_CONN49_1          (0x43d8)
+#define AFE_SECURE_MASK_CONN49_2          (0x43dc)
+#define AFE_SECURE_MASK_CONN49_3          (0x43e0)
+#define AFE_SECURE_MASK_CONN49_4          (0x43e4)
+#define AFE_SECURE_MASK_CONN50            (0x43e8)
+#define AFE_SECURE_MASK_CONN50_1          (0x43ec)
+#define AFE_SECURE_MASK_CONN50_2          (0x43f0)
+#define AFE_SECURE_MASK_CONN50_3          (0x43f4)
+#define AFE_SECURE_MASK_CONN50_4          (0x43f8)
+#define AFE_SECURE_MASK_CONN51            (0x43fc)
+#define AFE_SECURE_MASK_CONN51_1          (0x4400)
+#define AFE_SECURE_MASK_CONN51_2          (0x4404)
+#define AFE_SECURE_MASK_CONN51_3          (0x4408)
+#define AFE_SECURE_MASK_CONN51_4          (0x440c)
+#define AFE_SECURE_MASK_CONN52            (0x4410)
+#define AFE_SECURE_MASK_CONN52_1          (0x4414)
+#define AFE_SECURE_MASK_CONN52_2          (0x4418)
+#define AFE_SECURE_MASK_CONN52_3          (0x441c)
+#define AFE_SECURE_MASK_CONN52_4          (0x4420)
+#define AFE_SECURE_MASK_CONN53            (0x4424)
+#define AFE_SECURE_MASK_CONN53_1          (0x4428)
+#define AFE_SECURE_MASK_CONN53_2          (0x442c)
+#define AFE_SECURE_MASK_CONN53_3          (0x4430)
+#define AFE_SECURE_MASK_CONN53_4          (0x4434)
+#define AFE_SECURE_MASK_CONN54            (0x4438)
+#define AFE_SECURE_MASK_CONN54_1          (0x443c)
+#define AFE_SECURE_MASK_CONN54_2          (0x4440)
+#define AFE_SECURE_MASK_CONN54_3          (0x4444)
+#define AFE_SECURE_MASK_CONN54_4          (0x4448)
+#define AFE_SECURE_MASK_CONN55            (0x444c)
+#define AFE_SECURE_MASK_CONN55_1          (0x4450)
+#define AFE_SECURE_MASK_CONN55_2          (0x4454)
+#define AFE_SECURE_MASK_CONN55_3          (0x4458)
+#define AFE_SECURE_MASK_CONN55_4          (0x445c)
+#define AFE_SECURE_MASK_CONN56            (0x4460)
+#define AFE_SECURE_MASK_CONN56_1          (0x4464)
+#define AFE_SECURE_MASK_CONN56_2          (0x4468)
+#define AFE_SECURE_MASK_CONN56_3          (0x446c)
+#define AFE_SECURE_MASK_CONN56_4          (0x4470)
+#define AFE_SECURE_MASK_CONN57            (0x4474)
+#define AFE_SECURE_MASK_CONN57_1          (0x4478)
+#define AFE_SECURE_MASK_CONN57_2          (0x447c)
+#define AFE_SECURE_MASK_CONN57_3          (0x4480)
+#define AFE_SECURE_MASK_CONN57_4          (0x4484)
+#define AFE_SECURE_MASK_CONN58            (0x4488)
+#define AFE_SECURE_MASK_CONN58_1          (0x448c)
+#define AFE_SECURE_MASK_CONN58_2          (0x4490)
+#define AFE_SECURE_MASK_CONN58_3          (0x4494)
+#define AFE_SECURE_MASK_CONN58_4          (0x4498)
+#define AFE_SECURE_MASK_CONN59            (0x449c)
+#define AFE_SECURE_MASK_CONN59_1          (0x44a0)
+#define AFE_SECURE_MASK_CONN59_2          (0x44a4)
+#define AFE_SECURE_MASK_CONN59_3          (0x44a8)
+#define AFE_SECURE_MASK_CONN59_4          (0x44ac)
+#define AFE_SECURE_MASK_CONN60            (0x44b0)
+#define AFE_SECURE_MASK_CONN60_1          (0x44b4)
+#define AFE_SECURE_MASK_CONN60_2          (0x44b8)
+#define AFE_SECURE_MASK_CONN60_3          (0x44bc)
+#define AFE_SECURE_MASK_CONN60_4          (0x44c0)
+#define AFE_SECURE_MASK_CONN61            (0x44c4)
+#define AFE_SECURE_MASK_CONN61_1          (0x44c8)
+#define AFE_SECURE_MASK_CONN61_2          (0x44cc)
+#define AFE_SECURE_MASK_CONN61_3          (0x44d0)
+#define AFE_SECURE_MASK_CONN61_4          (0x44d4)
+#define AFE_SECURE_MASK_CONN62            (0x44d8)
+#define AFE_SECURE_MASK_CONN62_1          (0x44dc)
+#define AFE_SECURE_MASK_CONN62_2          (0x44e0)
+#define AFE_SECURE_MASK_CONN62_3          (0x44e4)
+#define AFE_SECURE_MASK_CONN62_4          (0x44e8)
+#define AFE_SECURE_MASK_CONN63            (0x44ec)
+#define AFE_SECURE_MASK_CONN63_1          (0x44f0)
+#define AFE_SECURE_MASK_CONN63_2          (0x44f4)
+#define AFE_SECURE_MASK_CONN63_3          (0x44f8)
+#define AFE_SECURE_MASK_CONN63_4          (0x44fc)
+#define AFE_SECURE_MASK_CONN64            (0x4500)
+#define AFE_SECURE_MASK_CONN64_1          (0x4504)
+#define AFE_SECURE_MASK_CONN64_2          (0x4508)
+#define AFE_SECURE_MASK_CONN64_3          (0x450c)
+#define AFE_SECURE_MASK_CONN64_4          (0x4510)
+#define AFE_SECURE_MASK_CONN65            (0x4514)
+#define AFE_SECURE_MASK_CONN65_1          (0x4518)
+#define AFE_SECURE_MASK_CONN65_2          (0x451c)
+#define AFE_SECURE_MASK_CONN65_3          (0x4520)
+#define AFE_SECURE_MASK_CONN65_4          (0x4524)
+#define AFE_SECURE_MASK_CONN66            (0x4528)
+#define AFE_SECURE_MASK_CONN66_1          (0x452c)
+#define AFE_SECURE_MASK_CONN66_2          (0x4530)
+#define AFE_SECURE_MASK_CONN66_3          (0x4534)
+#define AFE_SECURE_MASK_CONN66_4          (0x4538)
+#define AFE_SECURE_MASK_CONN67            (0x453c)
+#define AFE_SECURE_MASK_CONN67_1          (0x4540)
+#define AFE_SECURE_MASK_CONN67_2          (0x4544)
+#define AFE_SECURE_MASK_CONN67_3          (0x4548)
+#define AFE_SECURE_MASK_CONN67_4          (0x454c)
+#define AFE_SECURE_MASK_CONN68            (0x4550)
+#define AFE_SECURE_MASK_CONN68_1          (0x4554)
+#define AFE_SECURE_MASK_CONN68_2          (0x4558)
+#define AFE_SECURE_MASK_CONN68_3          (0x455c)
+#define AFE_SECURE_MASK_CONN68_4          (0x4560)
+#define AFE_SECURE_MASK_CONN69            (0x4564)
+#define AFE_SECURE_MASK_CONN69_1          (0x4568)
+#define AFE_SECURE_MASK_CONN69_2          (0x456c)
+#define AFE_SECURE_MASK_CONN69_3          (0x4570)
+#define AFE_SECURE_MASK_CONN69_4          (0x4574)
+#define AFE_SECURE_MASK_CONN70            (0x4578)
+#define AFE_SECURE_MASK_CONN70_1          (0x457c)
+#define AFE_SECURE_MASK_CONN70_2          (0x4580)
+#define AFE_SECURE_MASK_CONN70_3          (0x4584)
+#define AFE_SECURE_MASK_CONN70_4          (0x4588)
+#define AFE_SECURE_MASK_CONN71            (0x458c)
+#define AFE_SECURE_MASK_CONN71_1          (0x4590)
+#define AFE_SECURE_MASK_CONN71_2          (0x4594)
+#define AFE_SECURE_MASK_CONN71_3          (0x4598)
+#define AFE_SECURE_MASK_CONN71_4          (0x459c)
+#define AFE_SECURE_MASK_CONN72            (0x45a0)
+#define AFE_SECURE_MASK_CONN72_1          (0x45a4)
+#define AFE_SECURE_MASK_CONN72_2          (0x45a8)
+#define AFE_SECURE_MASK_CONN72_3          (0x45ac)
+#define AFE_SECURE_MASK_CONN72_4          (0x45b0)
+#define AFE_SECURE_MASK_CONN73            (0x45b4)
+#define AFE_SECURE_MASK_CONN73_1          (0x45b8)
+#define AFE_SECURE_MASK_CONN73_2          (0x45bc)
+#define AFE_SECURE_MASK_CONN73_3          (0x45c0)
+#define AFE_SECURE_MASK_CONN73_4          (0x45c4)
+#define AFE_SECURE_MASK_CONN74            (0x45c8)
+#define AFE_SECURE_MASK_CONN74_1          (0x45cc)
+#define AFE_SECURE_MASK_CONN74_2          (0x45d0)
+#define AFE_SECURE_MASK_CONN74_3          (0x45d4)
+#define AFE_SECURE_MASK_CONN74_4          (0x45d8)
+#define AFE_SECURE_MASK_CONN75            (0x45dc)
+#define AFE_SECURE_MASK_CONN75_1          (0x45e0)
+#define AFE_SECURE_MASK_CONN75_2          (0x45e4)
+#define AFE_SECURE_MASK_CONN75_3          (0x45e8)
+#define AFE_SECURE_MASK_CONN75_4          (0x45ec)
+#define AFE_SECURE_MASK_CONN76            (0x45f0)
+#define AFE_SECURE_MASK_CONN76_1          (0x45f4)
+#define AFE_SECURE_MASK_CONN76_2          (0x45f8)
+#define AFE_SECURE_MASK_CONN76_3          (0x45fc)
+#define AFE_SECURE_MASK_CONN76_4          (0x4600)
+#define AFE_SECURE_MASK_CONN77            (0x4604)
+#define AFE_SECURE_MASK_CONN77_1          (0x4608)
+#define AFE_SECURE_MASK_CONN77_2          (0x460c)
+#define AFE_SECURE_MASK_CONN77_3          (0x4610)
+#define AFE_SECURE_MASK_CONN77_4          (0x4614)
+#define AFE_SECURE_MASK_CONN78            (0x4618)
+#define AFE_SECURE_MASK_CONN78_1          (0x461c)
+#define AFE_SECURE_MASK_CONN78_2          (0x4620)
+#define AFE_SECURE_MASK_CONN78_3          (0x4624)
+#define AFE_SECURE_MASK_CONN78_4          (0x4628)
+#define AFE_SECURE_MASK_CONN79            (0x462c)
+#define AFE_SECURE_MASK_CONN79_1          (0x4630)
+#define AFE_SECURE_MASK_CONN79_2          (0x4634)
+#define AFE_SECURE_MASK_CONN79_3          (0x4638)
+#define AFE_SECURE_MASK_CONN79_4          (0x463c)
+#define AFE_SECURE_MASK_CONN80            (0x4640)
+#define AFE_SECURE_MASK_CONN80_1          (0x4644)
+#define AFE_SECURE_MASK_CONN80_2          (0x4648)
+#define AFE_SECURE_MASK_CONN80_3          (0x464c)
+#define AFE_SECURE_MASK_CONN80_4          (0x4650)
+#define AFE_SECURE_MASK_CONN81            (0x4654)
+#define AFE_SECURE_MASK_CONN81_1          (0x4658)
+#define AFE_SECURE_MASK_CONN81_2          (0x465c)
+#define AFE_SECURE_MASK_CONN81_3          (0x4660)
+#define AFE_SECURE_MASK_CONN81_4          (0x4664)
+#define AFE_SECURE_MASK_CONN82            (0x4668)
+#define AFE_SECURE_MASK_CONN82_1          (0x466c)
+#define AFE_SECURE_MASK_CONN82_2          (0x4670)
+#define AFE_SECURE_MASK_CONN82_3          (0x4674)
+#define AFE_SECURE_MASK_CONN82_4          (0x4678)
+#define AFE_SECURE_MASK_CONN83            (0x467c)
+#define AFE_SECURE_MASK_CONN83_1          (0x4680)
+#define AFE_SECURE_MASK_CONN83_2          (0x4684)
+#define AFE_SECURE_MASK_CONN83_3          (0x4688)
+#define AFE_SECURE_MASK_CONN83_4          (0x468c)
+#define AFE_SECURE_MASK_CONN84            (0x4690)
+#define AFE_SECURE_MASK_CONN84_1          (0x4694)
+#define AFE_SECURE_MASK_CONN84_2          (0x4698)
+#define AFE_SECURE_MASK_CONN84_3          (0x469c)
+#define AFE_SECURE_MASK_CONN84_4          (0x46a0)
+#define AFE_SECURE_MASK_CONN85            (0x46a4)
+#define AFE_SECURE_MASK_CONN85_1          (0x46a8)
+#define AFE_SECURE_MASK_CONN85_2          (0x46ac)
+#define AFE_SECURE_MASK_CONN85_3          (0x46b0)
+#define AFE_SECURE_MASK_CONN85_4          (0x46b4)
+#define AFE_SECURE_MASK_CONN86            (0x46b8)
+#define AFE_SECURE_MASK_CONN86_1          (0x46bc)
+#define AFE_SECURE_MASK_CONN86_2          (0x46c0)
+#define AFE_SECURE_MASK_CONN86_3          (0x46c4)
+#define AFE_SECURE_MASK_CONN86_4          (0x46c8)
+#define AFE_SECURE_MASK_CONN87            (0x46cc)
+#define AFE_SECURE_MASK_CONN87_1          (0x46d0)
+#define AFE_SECURE_MASK_CONN87_2          (0x46d4)
+#define AFE_SECURE_MASK_CONN87_3          (0x46d8)
+#define AFE_SECURE_MASK_CONN87_4          (0x46dc)
+#define AFE_SECURE_MASK_CONN88            (0x46e0)
+#define AFE_SECURE_MASK_CONN88_1          (0x46e4)
+#define AFE_SECURE_MASK_CONN88_2          (0x46e8)
+#define AFE_SECURE_MASK_CONN88_3          (0x46ec)
+#define AFE_SECURE_MASK_CONN88_4          (0x46f0)
+#define AFE_SECURE_MASK_CONN89            (0x46f4)
+#define AFE_SECURE_MASK_CONN89_1          (0x46f8)
+#define AFE_SECURE_MASK_CONN89_2          (0x46fc)
+#define AFE_SECURE_MASK_CONN89_3          (0x4700)
+#define AFE_SECURE_MASK_CONN89_4          (0x4704)
+#define AFE_SECURE_MASK_CONN90            (0x4708)
+#define AFE_SECURE_MASK_CONN90_1          (0x470c)
+#define AFE_SECURE_MASK_CONN90_2          (0x4710)
+#define AFE_SECURE_MASK_CONN90_3          (0x4714)
+#define AFE_SECURE_MASK_CONN90_4          (0x4718)
+#define AFE_SECURE_MASK_CONN91            (0x471c)
+#define AFE_SECURE_MASK_CONN91_1          (0x4720)
+#define AFE_SECURE_MASK_CONN91_2          (0x4724)
+#define AFE_SECURE_MASK_CONN91_3          (0x4728)
+#define AFE_SECURE_MASK_CONN91_4          (0x472c)
+#define AFE_SECURE_MASK_CONN92            (0x4730)
+#define AFE_SECURE_MASK_CONN92_1          (0x4734)
+#define AFE_SECURE_MASK_CONN92_2          (0x4738)
+#define AFE_SECURE_MASK_CONN92_3          (0x473c)
+#define AFE_SECURE_MASK_CONN92_4          (0x4740)
+#define AFE_SECURE_MASK_CONN93            (0x4744)
+#define AFE_SECURE_MASK_CONN93_1          (0x4748)
+#define AFE_SECURE_MASK_CONN93_2          (0x474c)
+#define AFE_SECURE_MASK_CONN93_3          (0x4750)
+#define AFE_SECURE_MASK_CONN93_4          (0x4754)
+#define AFE_SECURE_MASK_CONN94            (0x4758)
+#define AFE_SECURE_MASK_CONN94_1          (0x475c)
+#define AFE_SECURE_MASK_CONN94_2          (0x4760)
+#define AFE_SECURE_MASK_CONN94_3          (0x4764)
+#define AFE_SECURE_MASK_CONN94_4          (0x4768)
+#define AFE_SECURE_MASK_CONN95            (0x476c)
+#define AFE_SECURE_MASK_CONN95_1          (0x4770)
+#define AFE_SECURE_MASK_CONN95_2          (0x4774)
+#define AFE_SECURE_MASK_CONN95_3          (0x4778)
+#define AFE_SECURE_MASK_CONN95_4          (0x477c)
+#define AFE_SECURE_MASK_CONN96            (0x4780)
+#define AFE_SECURE_MASK_CONN96_1          (0x4784)
+#define AFE_SECURE_MASK_CONN96_2          (0x4788)
+#define AFE_SECURE_MASK_CONN96_3          (0x478c)
+#define AFE_SECURE_MASK_CONN96_4          (0x4790)
+#define AFE_SECURE_MASK_CONN97            (0x4794)
+#define AFE_SECURE_MASK_CONN97_1          (0x4798)
+#define AFE_SECURE_MASK_CONN97_2          (0x479c)
+#define AFE_SECURE_MASK_CONN97_3          (0x47a0)
+#define AFE_SECURE_MASK_CONN97_4          (0x47a4)
+#define AFE_SECURE_MASK_CONN98            (0x47a8)
+#define AFE_SECURE_MASK_CONN98_1          (0x47ac)
+#define AFE_SECURE_MASK_CONN98_2          (0x47b0)
+#define AFE_SECURE_MASK_CONN98_3          (0x47b4)
+#define AFE_SECURE_MASK_CONN98_4          (0x47b8)
+#define AFE_SECURE_MASK_CONN99            (0x47bc)
+#define AFE_SECURE_MASK_CONN99_1          (0x47c0)
+#define AFE_SECURE_MASK_CONN99_2          (0x47c4)
+#define AFE_SECURE_MASK_CONN99_3          (0x47c8)
+#define AFE_SECURE_MASK_CONN99_4          (0x47cc)
+#define AFE_SECURE_MASK_CONN100           (0x47d0)
+#define AFE_SECURE_MASK_CONN100_1         (0x47d4)
+#define AFE_SECURE_MASK_CONN100_2         (0x47d8)
+#define AFE_SECURE_MASK_CONN100_3         (0x47dc)
+#define AFE_SECURE_MASK_CONN100_4         (0x47e0)
+#define AFE_SECURE_MASK_CONN101           (0x47e4)
+#define AFE_SECURE_MASK_CONN101_1         (0x47e8)
+#define AFE_SECURE_MASK_CONN101_2         (0x47ec)
+#define AFE_SECURE_MASK_CONN101_3         (0x47f0)
+#define AFE_SECURE_MASK_CONN101_4         (0x47f4)
+#define AFE_SECURE_MASK_CONN102           (0x47f8)
+#define AFE_SECURE_MASK_CONN102_1         (0x47fc)
+#define AFE_SECURE_MASK_CONN102_2         (0x4800)
+#define AFE_SECURE_MASK_CONN102_3         (0x4804)
+#define AFE_SECURE_MASK_CONN102_4         (0x4808)
+#define AFE_SECURE_MASK_CONN103           (0x480c)
+#define AFE_SECURE_MASK_CONN103_1         (0x4810)
+#define AFE_SECURE_MASK_CONN103_2         (0x4814)
+#define AFE_SECURE_MASK_CONN103_3         (0x4818)
+#define AFE_SECURE_MASK_CONN103_4         (0x481c)
+#define AFE_SECURE_MASK_CONN104           (0x4820)
+#define AFE_SECURE_MASK_CONN104_1         (0x4824)
+#define AFE_SECURE_MASK_CONN104_2         (0x4828)
+#define AFE_SECURE_MASK_CONN104_3         (0x482c)
+#define AFE_SECURE_MASK_CONN104_4         (0x4830)
+#define AFE_SECURE_MASK_CONN105           (0x4834)
+#define AFE_SECURE_MASK_CONN105_1         (0x4838)
+#define AFE_SECURE_MASK_CONN105_2         (0x483c)
+#define AFE_SECURE_MASK_CONN105_3         (0x4840)
+#define AFE_SECURE_MASK_CONN105_4         (0x4844)
+#define AFE_SECURE_MASK_CONN106           (0x4848)
+#define AFE_SECURE_MASK_CONN106_1         (0x484c)
+#define AFE_SECURE_MASK_CONN106_2         (0x4850)
+#define AFE_SECURE_MASK_CONN106_3         (0x4854)
+#define AFE_SECURE_MASK_CONN106_4         (0x4858)
+#define AFE_SECURE_MASK_CONN107           (0x485c)
+#define AFE_SECURE_MASK_CONN107_1         (0x4860)
+#define AFE_SECURE_MASK_CONN107_2         (0x4864)
+#define AFE_SECURE_MASK_CONN107_3         (0x4868)
+#define AFE_SECURE_MASK_CONN107_4         (0x486c)
+#define AFE_SECURE_MASK_CONN108           (0x4870)
+#define AFE_SECURE_MASK_CONN108_1         (0x4874)
+#define AFE_SECURE_MASK_CONN108_2         (0x4878)
+#define AFE_SECURE_MASK_CONN108_3         (0x487c)
+#define AFE_SECURE_MASK_CONN108_4         (0x4880)
+#define AFE_SECURE_MASK_CONN109           (0x4884)
+#define AFE_SECURE_MASK_CONN109_1         (0x4888)
+#define AFE_SECURE_MASK_CONN109_2         (0x488c)
+#define AFE_SECURE_MASK_CONN109_3         (0x4890)
+#define AFE_SECURE_MASK_CONN109_4         (0x4894)
+#define AFE_SECURE_MASK_CONN110           (0x4898)
+#define AFE_SECURE_MASK_CONN110_1         (0x489c)
+#define AFE_SECURE_MASK_CONN110_2         (0x48a0)
+#define AFE_SECURE_MASK_CONN110_3         (0x48a4)
+#define AFE_SECURE_MASK_CONN110_4         (0x48a8)
+#define AFE_SECURE_MASK_CONN111           (0x48ac)
+#define AFE_SECURE_MASK_CONN111_1         (0x48b0)
+#define AFE_SECURE_MASK_CONN111_2         (0x48b4)
+#define AFE_SECURE_MASK_CONN111_3         (0x48b8)
+#define AFE_SECURE_MASK_CONN111_4         (0x48bc)
+#define AFE_SECURE_MASK_CONN112           (0x48c0)
+#define AFE_SECURE_MASK_CONN112_1         (0x48c4)
+#define AFE_SECURE_MASK_CONN112_2         (0x48c8)
+#define AFE_SECURE_MASK_CONN112_3         (0x48cc)
+#define AFE_SECURE_MASK_CONN112_4         (0x48d0)
+#define AFE_SECURE_MASK_CONN113           (0x48d4)
+#define AFE_SECURE_MASK_CONN113_1         (0x48d8)
+#define AFE_SECURE_MASK_CONN113_2         (0x48dc)
+#define AFE_SECURE_MASK_CONN113_3         (0x48e0)
+#define AFE_SECURE_MASK_CONN113_4         (0x48e4)
+#define AFE_SECURE_MASK_CONN114           (0x48e8)
+#define AFE_SECURE_MASK_CONN114_1         (0x48ec)
+#define AFE_SECURE_MASK_CONN114_2         (0x48f0)
+#define AFE_SECURE_MASK_CONN114_3         (0x48f4)
+#define AFE_SECURE_MASK_CONN114_4         (0x48f8)
+#define AFE_SECURE_MASK_CONN115           (0x48fc)
+#define AFE_SECURE_MASK_CONN115_1         (0x4900)
+#define AFE_SECURE_MASK_CONN115_2         (0x4904)
+#define AFE_SECURE_MASK_CONN115_3         (0x4908)
+#define AFE_SECURE_MASK_CONN115_4         (0x490c)
+#define AFE_SECURE_MASK_CONN116           (0x4910)
+#define AFE_SECURE_MASK_CONN116_1         (0x4914)
+#define AFE_SECURE_MASK_CONN116_2         (0x4918)
+#define AFE_SECURE_MASK_CONN116_3         (0x491c)
+#define AFE_SECURE_MASK_CONN116_4         (0x4920)
+#define AFE_SECURE_MASK_CONN117           (0x4924)
+#define AFE_SECURE_MASK_CONN117_1         (0x4928)
+#define AFE_SECURE_MASK_CONN117_2         (0x492c)
+#define AFE_SECURE_MASK_CONN117_3         (0x4930)
+#define AFE_SECURE_MASK_CONN117_4         (0x4934)
+#define AFE_SECURE_MASK_CONN118           (0x4938)
+#define AFE_SECURE_MASK_CONN118_1         (0x493c)
+#define AFE_SECURE_MASK_CONN118_2         (0x4940)
+#define AFE_SECURE_MASK_CONN118_3         (0x4944)
+#define AFE_SECURE_MASK_CONN118_4         (0x4948)
+#define AFE_SECURE_MASK_CONN119           (0x494c)
+#define AFE_SECURE_MASK_CONN119_1         (0x4950)
+#define AFE_SECURE_MASK_CONN119_2         (0x4954)
+#define AFE_SECURE_MASK_CONN119_3         (0x4958)
+#define AFE_SECURE_MASK_CONN119_4         (0x495c)
+#define AFE_SECURE_MASK_CONN120           (0x4960)
+#define AFE_SECURE_MASK_CONN120_1         (0x4964)
+#define AFE_SECURE_MASK_CONN120_2         (0x4968)
+#define AFE_SECURE_MASK_CONN120_3         (0x496c)
+#define AFE_SECURE_MASK_CONN120_4         (0x4970)
+#define AFE_SECURE_MASK_CONN121           (0x4974)
+#define AFE_SECURE_MASK_CONN121_1         (0x4978)
+#define AFE_SECURE_MASK_CONN121_2         (0x497c)
+#define AFE_SECURE_MASK_CONN121_3         (0x4980)
+#define AFE_SECURE_MASK_CONN121_4         (0x4984)
+#define AFE_SECURE_MASK_CONN122           (0x4988)
+#define AFE_SECURE_MASK_CONN122_1         (0x498c)
+#define AFE_SECURE_MASK_CONN122_2         (0x4990)
+#define AFE_SECURE_MASK_CONN122_3         (0x4994)
+#define AFE_SECURE_MASK_CONN122_4         (0x4998)
+#define AFE_SECURE_MASK_CONN123           (0x499c)
+#define AFE_SECURE_MASK_CONN123_1         (0x49a0)
+#define AFE_SECURE_MASK_CONN123_2         (0x49a4)
+#define AFE_SECURE_MASK_CONN123_3         (0x49a8)
+#define AFE_SECURE_MASK_CONN123_4         (0x49ac)
+#define AFE_SECURE_MASK_CONN124           (0x49b0)
+#define AFE_SECURE_MASK_CONN124_1         (0x49b4)
+#define AFE_SECURE_MASK_CONN124_2         (0x49b8)
+#define AFE_SECURE_MASK_CONN124_3         (0x49bc)
+#define AFE_SECURE_MASK_CONN124_4         (0x49c0)
+#define AFE_SECURE_MASK_CONN125           (0x49c4)
+#define AFE_SECURE_MASK_CONN125_1         (0x49c8)
+#define AFE_SECURE_MASK_CONN125_2         (0x49cc)
+#define AFE_SECURE_MASK_CONN125_3         (0x49d0)
+#define AFE_SECURE_MASK_CONN125_4         (0x49d4)
+#define AFE_SECURE_MASK_CONN126           (0x49d8)
+#define AFE_SECURE_MASK_CONN126_1         (0x49dc)
+#define AFE_SECURE_MASK_CONN126_2         (0x49e0)
+#define AFE_SECURE_MASK_CONN126_3         (0x49e4)
+#define AFE_SECURE_MASK_CONN126_4         (0x49e8)
+#define AFE_SECURE_MASK_CONN127           (0x49ec)
+#define AFE_SECURE_MASK_CONN127_1         (0x49f0)
+#define AFE_SECURE_MASK_CONN127_2         (0x49f4)
+#define AFE_SECURE_MASK_CONN127_3         (0x49f8)
+#define AFE_SECURE_MASK_CONN127_4         (0x49fc)
+#define AFE_SECURE_MASK_CONN128           (0x4a00)
+#define AFE_SECURE_MASK_CONN128_1         (0x4a04)
+#define AFE_SECURE_MASK_CONN128_2         (0x4a08)
+#define AFE_SECURE_MASK_CONN128_3         (0x4a0c)
+#define AFE_SECURE_MASK_CONN128_4         (0x4a10)
+#define AFE_SECURE_MASK_CONN129           (0x4a14)
+#define AFE_SECURE_MASK_CONN129_1         (0x4a18)
+#define AFE_SECURE_MASK_CONN129_2         (0x4a1c)
+#define AFE_SECURE_MASK_CONN129_3         (0x4a20)
+#define AFE_SECURE_MASK_CONN129_4         (0x4a24)
+#define AFE_SECURE_MASK_CONN130           (0x4a28)
+#define AFE_SECURE_MASK_CONN130_1         (0x4a2c)
+#define AFE_SECURE_MASK_CONN130_2         (0x4a30)
+#define AFE_SECURE_MASK_CONN130_3         (0x4a34)
+#define AFE_SECURE_MASK_CONN130_4         (0x4a38)
+#define AFE_SECURE_MASK_CONN131           (0x4a3c)
+#define AFE_SECURE_MASK_CONN131_1         (0x4a40)
+#define AFE_SECURE_MASK_CONN131_2         (0x4a44)
+#define AFE_SECURE_MASK_CONN131_3         (0x4a48)
+#define AFE_SECURE_MASK_CONN131_4         (0x4a4c)
+#define AFE_SECURE_MASK_CONN132           (0x4a50)
+#define AFE_SECURE_MASK_CONN132_1         (0x4a54)
+#define AFE_SECURE_MASK_CONN132_2         (0x4a58)
+#define AFE_SECURE_MASK_CONN132_3         (0x4a5c)
+#define AFE_SECURE_MASK_CONN132_4         (0x4a60)
+#define AFE_SECURE_MASK_CONN133           (0x4a64)
+#define AFE_SECURE_MASK_CONN133_1         (0x4a68)
+#define AFE_SECURE_MASK_CONN133_2         (0x4a6c)
+#define AFE_SECURE_MASK_CONN133_3         (0x4a70)
+#define AFE_SECURE_MASK_CONN133_4         (0x4a74)
+#define AFE_SECURE_MASK_CONN134           (0x4a78)
+#define AFE_SECURE_MASK_CONN134_1         (0x4a7c)
+#define AFE_SECURE_MASK_CONN134_2         (0x4a80)
+#define AFE_SECURE_MASK_CONN134_3         (0x4a84)
+#define AFE_SECURE_MASK_CONN134_4         (0x4a88)
+#define AFE_SECURE_MASK_CONN135           (0x4a8c)
+#define AFE_SECURE_MASK_CONN135_1         (0x4a90)
+#define AFE_SECURE_MASK_CONN135_2         (0x4a94)
+#define AFE_SECURE_MASK_CONN135_3         (0x4a98)
+#define AFE_SECURE_MASK_CONN135_4         (0x4a9c)
+#define AFE_SECURE_MASK_CONN136           (0x4aa0)
+#define AFE_SECURE_MASK_CONN136_1         (0x4aa4)
+#define AFE_SECURE_MASK_CONN136_2         (0x4aa8)
+#define AFE_SECURE_MASK_CONN136_3         (0x4aac)
+#define AFE_SECURE_MASK_CONN136_4         (0x4ab0)
+#define AFE_SECURE_MASK_CONN137           (0x4ab4)
+#define AFE_SECURE_MASK_CONN137_1         (0x4ab8)
+#define AFE_SECURE_MASK_CONN137_2         (0x4abc)
+#define AFE_SECURE_MASK_CONN137_3         (0x4ac0)
+#define AFE_SECURE_MASK_CONN137_4         (0x4ac4)
+#define AFE_SECURE_MASK_CONN138           (0x4ac8)
+#define AFE_SECURE_MASK_CONN138_1         (0x4acc)
+#define AFE_SECURE_MASK_CONN138_2         (0x4ad0)
+#define AFE_SECURE_MASK_CONN138_3         (0x4ad4)
+#define AFE_SECURE_MASK_CONN138_4         (0x4ad8)
+#define AFE_SECURE_MASK_CONN139           (0x4adc)
+#define AFE_SECURE_MASK_CONN139_1         (0x4ae0)
+#define AFE_SECURE_MASK_CONN139_2         (0x4ae4)
+#define AFE_SECURE_MASK_CONN139_3         (0x4ae8)
+#define AFE_SECURE_MASK_CONN139_4         (0x4aec)
+#define AFE_SECURE_MASK_CONN_RS           (0x4af0)
+#define AFE_SECURE_MASK_CONN_RS_1         (0x4af4)
+#define AFE_SECURE_MASK_CONN_RS_2         (0x4af8)
+#define AFE_SECURE_MASK_CONN_RS_3         (0x4afc)
+#define AFE_SECURE_MASK_CONN_RS_4         (0x4b00)
+#define AFE_SECURE_MASK_CONN_16BIT        (0x4b04)
+#define AFE_SECURE_MASK_CONN_16BIT_1      (0x4b08)
+#define AFE_SECURE_MASK_CONN_16BIT_2      (0x4b0c)
+#define AFE_SECURE_MASK_CONN_16BIT_3      (0x4b10)
+#define AFE_SECURE_MASK_CONN_16BIT_4      (0x4b14)
+#define AFE_SECURE_MASK_CONN_24BIT        (0x4b18)
+#define AFE_SECURE_MASK_CONN_24BIT_1      (0x4b1c)
+#define AFE_SECURE_MASK_CONN_24BIT_2      (0x4b20)
+#define AFE_SECURE_MASK_CONN_24BIT_3      (0x4b24)
+#define AFE_SECURE_MASK_CONN_24BIT_4      (0x4b28)
+#define AFE_GASRC0_NEW_CON0               (0x4c40)
+#define AFE_GASRC0_NEW_CON1               (0x4c44)
+#define AFE_GASRC0_NEW_CON2               (0x4c48)
+#define AFE_GASRC0_NEW_CON3               (0x4c4c)
+#define AFE_GASRC0_NEW_CON4               (0x4c50)
+#define AFE_GASRC0_NEW_CON5               (0x4c54)
+#define AFE_GASRC0_NEW_CON6               (0x4c58)
+#define AFE_GASRC0_NEW_CON7               (0x4c5c)
+#define AFE_GASRC0_NEW_CON8               (0x4c60)
+#define AFE_GASRC0_NEW_CON9               (0x4c64)
+#define AFE_GASRC0_NEW_CON10              (0x4c68)
+#define AFE_GASRC0_NEW_CON11              (0x4c6c)
+#define AFE_GASRC0_NEW_CON12              (0x4c70)
+#define AFE_GASRC0_NEW_CON13              (0x4c74)
+#define AFE_GASRC0_NEW_CON14              (0x4c78)
+#define AFE_GASRC1_NEW_CON0               (0x4c80)
+#define AFE_GASRC1_NEW_CON1               (0x4c84)
+#define AFE_GASRC1_NEW_CON2               (0x4c88)
+#define AFE_GASRC1_NEW_CON3               (0x4c8c)
+#define AFE_GASRC1_NEW_CON4               (0x4c90)
+#define AFE_GASRC1_NEW_CON5               (0x4c94)
+#define AFE_GASRC1_NEW_CON6               (0x4c98)
+#define AFE_GASRC1_NEW_CON7               (0x4c9c)
+#define AFE_GASRC1_NEW_CON8               (0x4ca0)
+#define AFE_GASRC1_NEW_CON9               (0x4ca4)
+#define AFE_GASRC1_NEW_CON10              (0x4ca8)
+#define AFE_GASRC1_NEW_CON11              (0x4cac)
+#define AFE_GASRC1_NEW_CON12              (0x4cb0)
+#define AFE_GASRC1_NEW_CON13              (0x4cb4)
+#define AFE_GASRC1_NEW_CON14              (0x4cb8)
+#define AFE_GASRC2_NEW_CON0               (0x4cc0)
+#define AFE_GASRC2_NEW_CON1               (0x4cc4)
+#define AFE_GASRC2_NEW_CON2               (0x4cc8)
+#define AFE_GASRC2_NEW_CON3               (0x4ccc)
+#define AFE_GASRC2_NEW_CON4               (0x4cd0)
+#define AFE_GASRC2_NEW_CON5               (0x4cd4)
+#define AFE_GASRC2_NEW_CON6               (0x4cd8)
+#define AFE_GASRC2_NEW_CON7               (0x4cdc)
+#define AFE_GASRC2_NEW_CON8               (0x4ce0)
+#define AFE_GASRC2_NEW_CON9               (0x4ce4)
+#define AFE_GASRC2_NEW_CON10              (0x4ce8)
+#define AFE_GASRC2_NEW_CON11              (0x4cec)
+#define AFE_GASRC2_NEW_CON12              (0x4cf0)
+#define AFE_GASRC2_NEW_CON13              (0x4cf4)
+#define AFE_GASRC2_NEW_CON14              (0x4cf8)
+#define AFE_GASRC3_NEW_CON0               (0x4d00)
+#define AFE_GASRC3_NEW_CON1               (0x4d04)
+#define AFE_GASRC3_NEW_CON2               (0x4d08)
+#define AFE_GASRC3_NEW_CON3               (0x4d0c)
+#define AFE_GASRC3_NEW_CON4               (0x4d10)
+#define AFE_GASRC3_NEW_CON5               (0x4d14)
+#define AFE_GASRC3_NEW_CON6               (0x4d18)
+#define AFE_GASRC3_NEW_CON7               (0x4d1c)
+#define AFE_GASRC3_NEW_CON8               (0x4d20)
+#define AFE_GASRC3_NEW_CON9               (0x4d24)
+#define AFE_GASRC3_NEW_CON10              (0x4d28)
+#define AFE_GASRC3_NEW_CON11              (0x4d2c)
+#define AFE_GASRC3_NEW_CON12              (0x4d30)
+#define AFE_GASRC3_NEW_CON13              (0x4d34)
+#define AFE_GASRC3_NEW_CON14              (0x4d38)
+#define AFE_GASRC4_NEW_CON0               (0x4d40)
+#define AFE_GASRC4_NEW_CON1               (0x4d44)
+#define AFE_GASRC4_NEW_CON2               (0x4d48)
+#define AFE_GASRC4_NEW_CON3               (0x4d4c)
+#define AFE_GASRC4_NEW_CON4               (0x4d50)
+#define AFE_GASRC4_NEW_CON5               (0x4d54)
+#define AFE_GASRC4_NEW_CON6               (0x4d58)
+#define AFE_GASRC4_NEW_CON7               (0x4d5c)
+#define AFE_GASRC4_NEW_CON8               (0x4d60)
+#define AFE_GASRC4_NEW_CON9               (0x4d64)
+#define AFE_GASRC4_NEW_CON10              (0x4d68)
+#define AFE_GASRC4_NEW_CON11              (0x4d6c)
+#define AFE_GASRC4_NEW_CON12              (0x4d70)
+#define AFE_GASRC4_NEW_CON13              (0x4d74)
+#define AFE_GASRC4_NEW_CON14              (0x4d78)
+#define AFE_GASRC5_NEW_CON0               (0x4d80)
+#define AFE_GASRC5_NEW_CON1               (0x4d84)
+#define AFE_GASRC5_NEW_CON2               (0x4d88)
+#define AFE_GASRC5_NEW_CON3               (0x4d8c)
+#define AFE_GASRC5_NEW_CON4               (0x4d90)
+#define AFE_GASRC5_NEW_CON5               (0x4d94)
+#define AFE_GASRC5_NEW_CON6               (0x4d98)
+#define AFE_GASRC5_NEW_CON7               (0x4d9c)
+#define AFE_GASRC5_NEW_CON8               (0x4da0)
+#define AFE_GASRC5_NEW_CON9               (0x4da4)
+#define AFE_GASRC5_NEW_CON10              (0x4da8)
+#define AFE_GASRC5_NEW_CON11              (0x4dac)
+#define AFE_GASRC5_NEW_CON12              (0x4db0)
+#define AFE_GASRC5_NEW_CON13              (0x4db4)
+#define AFE_GASRC5_NEW_CON14              (0x4db8)
+#define AFE_GASRC6_NEW_CON0               (0x4dc0)
+#define AFE_GASRC6_NEW_CON1               (0x4dc4)
+#define AFE_GASRC6_NEW_CON2               (0x4dc8)
+#define AFE_GASRC6_NEW_CON3               (0x4dcc)
+#define AFE_GASRC6_NEW_CON4               (0x4dd0)
+#define AFE_GASRC6_NEW_CON5               (0x4dd4)
+#define AFE_GASRC6_NEW_CON6               (0x4dd8)
+#define AFE_GASRC6_NEW_CON7               (0x4ddc)
+#define AFE_GASRC6_NEW_CON8               (0x4de0)
+#define AFE_GASRC6_NEW_CON9               (0x4de4)
+#define AFE_GASRC6_NEW_CON10              (0x4de8)
+#define AFE_GASRC6_NEW_CON11              (0x4dec)
+#define AFE_GASRC6_NEW_CON12              (0x4df0)
+#define AFE_GASRC6_NEW_CON13              (0x4df4)
+#define AFE_GASRC6_NEW_CON14              (0x4df8)
+#define AFE_GASRC7_NEW_CON0               (0x4e00)
+#define AFE_GASRC7_NEW_CON1               (0x4e04)
+#define AFE_GASRC7_NEW_CON2               (0x4e08)
+#define AFE_GASRC7_NEW_CON3               (0x4e0c)
+#define AFE_GASRC7_NEW_CON4               (0x4e10)
+#define AFE_GASRC7_NEW_CON5               (0x4e14)
+#define AFE_GASRC7_NEW_CON6               (0x4e18)
+#define AFE_GASRC7_NEW_CON7               (0x4e1c)
+#define AFE_GASRC7_NEW_CON8               (0x4e20)
+#define AFE_GASRC7_NEW_CON9               (0x4e24)
+#define AFE_GASRC7_NEW_CON10              (0x4e28)
+#define AFE_GASRC7_NEW_CON11              (0x4e2c)
+#define AFE_GASRC7_NEW_CON12              (0x4e30)
+#define AFE_GASRC7_NEW_CON13              (0x4e34)
+#define AFE_GASRC7_NEW_CON14              (0x4e38)
+#define AFE_GASRC8_NEW_CON0               (0x4e40)
+#define AFE_GASRC8_NEW_CON1               (0x4e44)
+#define AFE_GASRC8_NEW_CON2               (0x4e48)
+#define AFE_GASRC8_NEW_CON3               (0x4e4c)
+#define AFE_GASRC8_NEW_CON4               (0x4e50)
+#define AFE_GASRC8_NEW_CON5               (0x4e54)
+#define AFE_GASRC8_NEW_CON6               (0x4e58)
+#define AFE_GASRC8_NEW_CON7               (0x4e5c)
+#define AFE_GASRC8_NEW_CON8               (0x4e60)
+#define AFE_GASRC8_NEW_CON9               (0x4e64)
+#define AFE_GASRC8_NEW_CON10              (0x4e68)
+#define AFE_GASRC8_NEW_CON11              (0x4e6c)
+#define AFE_GASRC8_NEW_CON12              (0x4e70)
+#define AFE_GASRC8_NEW_CON13              (0x4e74)
+#define AFE_GASRC8_NEW_CON14              (0x4e78)
+#define AFE_GASRC9_NEW_CON0               (0x4e80)
+#define AFE_GASRC9_NEW_CON1               (0x4e84)
+#define AFE_GASRC9_NEW_CON2               (0x4e88)
+#define AFE_GASRC9_NEW_CON3               (0x4e8c)
+#define AFE_GASRC9_NEW_CON4               (0x4e90)
+#define AFE_GASRC9_NEW_CON5               (0x4e94)
+#define AFE_GASRC9_NEW_CON6               (0x4e98)
+#define AFE_GASRC9_NEW_CON7               (0x4e9c)
+#define AFE_GASRC9_NEW_CON8               (0x4ea0)
+#define AFE_GASRC9_NEW_CON9               (0x4ea4)
+#define AFE_GASRC9_NEW_CON10              (0x4ea8)
+#define AFE_GASRC9_NEW_CON11              (0x4eac)
+#define AFE_GASRC9_NEW_CON12              (0x4eb0)
+#define AFE_GASRC9_NEW_CON13              (0x4eb4)
+#define AFE_GASRC9_NEW_CON14              (0x4eb8)
+#define AFE_GASRC10_NEW_CON0              (0x4ec0)
+#define AFE_GASRC10_NEW_CON1              (0x4ec4)
+#define AFE_GASRC10_NEW_CON2              (0x4ec8)
+#define AFE_GASRC10_NEW_CON3              (0x4ecc)
+#define AFE_GASRC10_NEW_CON4              (0x4ed0)
+#define AFE_GASRC10_NEW_CON5              (0x4ed4)
+#define AFE_GASRC10_NEW_CON6              (0x4ed8)
+#define AFE_GASRC10_NEW_CON7              (0x4edc)
+#define AFE_GASRC10_NEW_CON8              (0x4ee0)
+#define AFE_GASRC10_NEW_CON9              (0x4ee4)
+#define AFE_GASRC10_NEW_CON10             (0x4ee8)
+#define AFE_GASRC10_NEW_CON11             (0x4eec)
+#define AFE_GASRC10_NEW_CON12             (0x4ef0)
+#define AFE_GASRC10_NEW_CON13             (0x4ef4)
+#define AFE_GASRC10_NEW_CON14             (0x4ef8)
+#define AFE_GASRC11_NEW_CON0              (0x4f00)
+#define AFE_GASRC11_NEW_CON1              (0x4f04)
+#define AFE_GASRC11_NEW_CON2              (0x4f08)
+#define AFE_GASRC11_NEW_CON3              (0x4f0c)
+#define AFE_GASRC11_NEW_CON4              (0x4f10)
+#define AFE_GASRC11_NEW_CON5              (0x4f14)
+#define AFE_GASRC11_NEW_CON6              (0x4f18)
+#define AFE_GASRC11_NEW_CON7              (0x4f1c)
+#define AFE_GASRC11_NEW_CON8              (0x4f20)
+#define AFE_GASRC11_NEW_CON9              (0x4f24)
+#define AFE_GASRC11_NEW_CON10             (0x4f28)
+#define AFE_GASRC11_NEW_CON11             (0x4f2c)
+#define AFE_GASRC11_NEW_CON12             (0x4f30)
+#define AFE_GASRC11_NEW_CON13             (0x4f34)
+#define AFE_GASRC11_NEW_CON14             (0x4f38)
+#define AFE_GASRC12_NEW_CON0              (0x4f40)
+#define AFE_GASRC12_NEW_CON1              (0x4f44)
+#define AFE_GASRC12_NEW_CON2              (0x4f48)
+#define AFE_GASRC12_NEW_CON3              (0x4f4c)
+#define AFE_GASRC12_NEW_CON4              (0x4f50)
+#define AFE_GASRC12_NEW_CON5              (0x4f54)
+#define AFE_GASRC12_NEW_CON6              (0x4f58)
+#define AFE_GASRC12_NEW_CON7              (0x4f5c)
+#define AFE_GASRC12_NEW_CON8              (0x4f60)
+#define AFE_GASRC12_NEW_CON9              (0x4f64)
+#define AFE_GASRC12_NEW_CON10             (0x4f68)
+#define AFE_GASRC12_NEW_CON11             (0x4f6c)
+#define AFE_GASRC12_NEW_CON12             (0x4f70)
+#define AFE_GASRC12_NEW_CON13             (0x4f74)
+#define AFE_GASRC12_NEW_CON14             (0x4f78)
+#define AFE_GASRC13_NEW_CON0              (0x4f80)
+#define AFE_GASRC13_NEW_CON1              (0x4f84)
+#define AFE_GASRC13_NEW_CON2              (0x4f88)
+#define AFE_GASRC13_NEW_CON3              (0x4f8c)
+#define AFE_GASRC13_NEW_CON4              (0x4f90)
+#define AFE_GASRC13_NEW_CON5              (0x4f94)
+#define AFE_GASRC13_NEW_CON6              (0x4f98)
+#define AFE_GASRC13_NEW_CON7              (0x4f9c)
+#define AFE_GASRC13_NEW_CON8              (0x4fa0)
+#define AFE_GASRC13_NEW_CON9              (0x4fa4)
+#define AFE_GASRC13_NEW_CON10             (0x4fa8)
+#define AFE_GASRC13_NEW_CON11             (0x4fac)
+#define AFE_GASRC13_NEW_CON12             (0x4fb0)
+#define AFE_GASRC13_NEW_CON13             (0x4fb4)
+#define AFE_GASRC13_NEW_CON14             (0x4fb8)
+#define AFE_GASRC14_NEW_CON0              (0x4fc0)
+#define AFE_GASRC14_NEW_CON1              (0x4fc4)
+#define AFE_GASRC14_NEW_CON2              (0x4fc8)
+#define AFE_GASRC14_NEW_CON3              (0x4fcc)
+#define AFE_GASRC14_NEW_CON4              (0x4fd0)
+#define AFE_GASRC14_NEW_CON5              (0x4fd4)
+#define AFE_GASRC14_NEW_CON6              (0x4fd8)
+#define AFE_GASRC14_NEW_CON7              (0x4fdc)
+#define AFE_GASRC14_NEW_CON8              (0x4fe0)
+#define AFE_GASRC14_NEW_CON9              (0x4fe4)
+#define AFE_GASRC14_NEW_CON10             (0x4fe8)
+#define AFE_GASRC14_NEW_CON11             (0x4fec)
+#define AFE_GASRC14_NEW_CON12             (0x4ff0)
+#define AFE_GASRC14_NEW_CON13             (0x4ff4)
+#define AFE_GASRC14_NEW_CON14             (0x4ff8)
+#define AFE_GASRC15_NEW_CON0              (0x5000)
+#define AFE_GASRC15_NEW_CON1              (0x5004)
+#define AFE_GASRC15_NEW_CON2              (0x5008)
+#define AFE_GASRC15_NEW_CON3              (0x500c)
+#define AFE_GASRC15_NEW_CON4              (0x5010)
+#define AFE_GASRC15_NEW_CON5              (0x5014)
+#define AFE_GASRC15_NEW_CON6              (0x5018)
+#define AFE_GASRC15_NEW_CON7              (0x501c)
+#define AFE_GASRC15_NEW_CON8              (0x5020)
+#define AFE_GASRC15_NEW_CON9              (0x5024)
+#define AFE_GASRC15_NEW_CON10             (0x5028)
+#define AFE_GASRC15_NEW_CON11             (0x502c)
+#define AFE_GASRC15_NEW_CON12             (0x5030)
+#define AFE_GASRC15_NEW_CON13             (0x5034)
+#define AFE_GASRC15_NEW_CON14             (0x5038)
+#define AFE_GASRC16_NEW_CON0              (0x5040)
+#define AFE_GASRC16_NEW_CON1              (0x5044)
+#define AFE_GASRC16_NEW_CON2              (0x5048)
+#define AFE_GASRC16_NEW_CON3              (0x504c)
+#define AFE_GASRC16_NEW_CON4              (0x5050)
+#define AFE_GASRC16_NEW_CON5              (0x5054)
+#define AFE_GASRC16_NEW_CON6              (0x5058)
+#define AFE_GASRC16_NEW_CON7              (0x505c)
+#define AFE_GASRC16_NEW_CON8              (0x5060)
+#define AFE_GASRC16_NEW_CON9              (0x5064)
+#define AFE_GASRC16_NEW_CON10             (0x5068)
+#define AFE_GASRC16_NEW_CON11             (0x506c)
+#define AFE_GASRC16_NEW_CON12             (0x5070)
+#define AFE_GASRC16_NEW_CON13             (0x5074)
+#define AFE_GASRC16_NEW_CON14             (0x5078)
+#define AFE_GASRC17_NEW_CON0              (0x5080)
+#define AFE_GASRC17_NEW_CON1              (0x5084)
+#define AFE_GASRC17_NEW_CON2              (0x5088)
+#define AFE_GASRC17_NEW_CON3              (0x508c)
+#define AFE_GASRC17_NEW_CON4              (0x5090)
+#define AFE_GASRC17_NEW_CON5              (0x5094)
+#define AFE_GASRC17_NEW_CON6              (0x5098)
+#define AFE_GASRC17_NEW_CON7              (0x509c)
+#define AFE_GASRC17_NEW_CON8              (0x50a0)
+#define AFE_GASRC17_NEW_CON9              (0x50a4)
+#define AFE_GASRC17_NEW_CON10             (0x50a8)
+#define AFE_GASRC17_NEW_CON11             (0x50ac)
+#define AFE_GASRC17_NEW_CON12             (0x50b0)
+#define AFE_GASRC17_NEW_CON13             (0x50b4)
+#define AFE_GASRC17_NEW_CON14             (0x50b8)
+#define AFE_GASRC18_NEW_CON0              (0x50c0)
+#define AFE_GASRC18_NEW_CON1              (0x50c4)
+#define AFE_GASRC18_NEW_CON2              (0x50c8)
+#define AFE_GASRC18_NEW_CON3              (0x50cc)
+#define AFE_GASRC18_NEW_CON4              (0x50d0)
+#define AFE_GASRC18_NEW_CON5              (0x50d4)
+#define AFE_GASRC18_NEW_CON6              (0x50d8)
+#define AFE_GASRC18_NEW_CON7              (0x50dc)
+#define AFE_GASRC18_NEW_CON8              (0x50e0)
+#define AFE_GASRC18_NEW_CON9              (0x50e4)
+#define AFE_GASRC18_NEW_CON10             (0x50e8)
+#define AFE_GASRC18_NEW_CON11             (0x50ec)
+#define AFE_GASRC18_NEW_CON12             (0x50f0)
+#define AFE_GASRC18_NEW_CON13             (0x50f4)
+#define AFE_GASRC18_NEW_CON14             (0x50f8)
+#define AFE_GASRC19_NEW_CON0              (0x5100)
+#define AFE_GASRC19_NEW_CON1              (0x5104)
+#define AFE_GASRC19_NEW_CON2              (0x5108)
+#define AFE_GASRC19_NEW_CON3              (0x510c)
+#define AFE_GASRC19_NEW_CON4              (0x5110)
+#define AFE_GASRC19_NEW_CON5              (0x5114)
+#define AFE_GASRC19_NEW_CON6              (0x5118)
+#define AFE_GASRC19_NEW_CON7              (0x511c)
+#define AFE_GASRC19_NEW_CON8              (0x5120)
+#define AFE_GASRC19_NEW_CON9              (0x5124)
+#define AFE_GASRC19_NEW_CON10             (0x5128)
+#define AFE_GASRC19_NEW_CON11             (0x512c)
+#define AFE_GASRC19_NEW_CON12             (0x5130)
+#define AFE_GASRC19_NEW_CON13             (0x5134)
+#define AFE_GASRC19_NEW_CON14             (0x5138)
+
+#define AFE_MAX_REGISTER                  (AFE_GASRC19_NEW_CON14)
+
+/* ASYS_TOP_CON */
+#define ASYS_TOP_CON_A1SYS_TIMING_ON       BIT(0)
+#define ASYS_TOP_CON_A2SYS_TIMING_ON       BIT(1)
+#define ASYS_TOP_CON_A3SYS_TIMING_ON       BIT(4)
+#define ASYS_TOP_CON_A4SYS_TIMING_ON       BIT(5)
+#define ASYS_TOP_CON_26M_TIMING_ON         BIT(2)
+
+/* PWR2_TOP_CON0 */
+#define PWR2_TOP_CON_DMIC8_SRC_SEL_MASK     GENMASK(31, 29)
+#define PWR2_TOP_CON_DMIC7_SRC_SEL_MASK     GENMASK(28, 26)
+#define PWR2_TOP_CON_DMIC6_SRC_SEL_MASK     GENMASK(25, 23)
+#define PWR2_TOP_CON_DMIC5_SRC_SEL_MASK     GENMASK(22, 20)
+#define PWR2_TOP_CON_DMIC4_SRC_SEL_MASK     GENMASK(19, 17)
+#define PWR2_TOP_CON_DMIC3_SRC_SEL_MASK     GENMASK(16, 14)
+#define PWR2_TOP_CON_DMIC2_SRC_SEL_MASK     GENMASK(13, 11)
+#define PWR2_TOP_CON_DMIC1_SRC_SEL_MASK     GENMASK(10, 8)
+#define PWR2_TOP_CON_DMIC8_SRC_SEL_VAL(x)   ((x) << 29)
+#define PWR2_TOP_CON_DMIC7_SRC_SEL_VAL(x)   ((x) << 26)
+#define PWR2_TOP_CON_DMIC6_SRC_SEL_VAL(x)   ((x) << 23)
+#define PWR2_TOP_CON_DMIC5_SRC_SEL_VAL(x)   ((x) << 20)
+#define PWR2_TOP_CON_DMIC4_SRC_SEL_VAL(x)   ((x) << 17)
+#define PWR2_TOP_CON_DMIC3_SRC_SEL_VAL(x)   ((x) << 14)
+#define PWR2_TOP_CON_DMIC2_SRC_SEL_VAL(x)   ((x) << 11)
+#define PWR2_TOP_CON_DMIC1_SRC_SEL_VAL(x)   ((x) << 8)
+
+/* PWR2_TOP_CON1 */
+#define PWR2_TOP_CON1_DMIC_CKDIV_ON        BIT(1)
+
+/* PCM_INTF_CON1 */
+#define PCM_INTF_CON1_SYNC_OUT_INV     BIT(23)
+#define PCM_INTF_CON1_BCLK_OUT_INV     BIT(22)
+#define PCM_INTF_CON1_CLK_OUT_INV_MASK GENMASK(23, 22)
+#define PCM_INTF_CON1_SYNC_IN_INV      BIT(21)
+#define PCM_INTF_CON1_BCLK_IN_INV      BIT(20)
+#define PCM_INTF_CON1_CLK_IN_INV_MASK  GENMASK(21, 20)
+#define PCM_INTF_CON1_PCM_24BIT        (0x1 << 16)
+#define PCM_INTF_CON1_PCM_16BIT        (0x0 << 16)
+#define PCM_INTF_CON1_PCM_BIT_MASK     BIT(16)
+#define PCM_INTF_CON1_PCM_WLEN_32BCK   (0x0 << 14)
+#define PCM_INTF_CON1_PCM_WLEN_64BCK   (0x1 << 14)
+#define PCM_INTF_CON1_PCM_WLEN_MASK    BIT(14)
+#define PCM_INTF_CON1_SYNC_LENGTH(x)   (((x) & 0x1f) << 9)
+#define PCM_INTF_CON1_SYNC_LENGTH_MASK (0x1f << 9)
+#define PCM_INTF_CON1_PCM_SLAVE        (0x1 << 5)
+#define PCM_INTF_CON1_PCM_MASTER       (0x0 << 5)
+#define PCM_INTF_CON1_PCM_M_S_MASK     BIT(5)
+#define PCM_INTF_CON1_PCM_MODE(x)      (((x) & 0x3) << 3)
+#define PCM_INTF_CON1_PCM_MODE_MASK    (0x3 << 3)
+#define PCM_INTF_CON1_PCM_FMT(x)       (((x) & 0x3) << 1)
+#define PCM_INTF_CON1_PCM_FMT_MASK     (0x3 << 1)
+#define PCM_INTF_CON1_PCM_EN           BIT(0)
+
+/* PCM_INTF_CON2 */
+#define PCM_INTF_CON2_CLK_DOMAIN_SEL(x)   (((x) & 0x3) << 23)
+#define PCM_INTF_CON2_CLK_DOMAIN_SEL_MASK (0x3 << 23)
+#define PCM_INTF_CON2_SYNC_FREQ_MODE(x)   (((x) & 0x1f) << 12)
+#define PCM_INTF_CON2_SYNC_FREQ_MODE_MASK (0x1f << 12)
+#define PCM_INTF_CON2_PCM_TX2RX_LPBK      BIT(8)
+
+/* AFE_MPHONE_MULTIx_CON0 */
+#define AFE_MPHONE_MULTI_CON0_16BIT_SWAP       BIT(3)
+#define AFE_MPHONE_MULTI_CON0_16BIT_SWAP_MASK  BIT(3)
+#define AFE_MPHONE_MULTI_CON0_24BIT_DATA       (0x1 << 1)
+#define AFE_MPHONE_MULTI_CON0_16BIT_DATA       (0x0 << 1)
+#define AFE_MPHONE_MULIT_CON0_24BIT_DATA_MASK  BIT(1)
+#define AFE_MPHONE_MULTI_CON0_EN               BIT(0)
+#define AFE_MPHONE_MULTI_CON0_EN_MASK          BIT(0)
+
+/* AFE_MPHONE_MULTIx_CON1 */
+#define AFE_MPHONE_MULTI_CON1_SYNC_ON                BIT(24)
+#define AFE_MPHONE_MULTI_CON1_SYNC_ON_MASK           BIT(24)
+#define AFE_MPHONE_MULTI_CON1_24BIT_SWAP_BYPASS      BIT(22)
+#define AFE_MPHONE_MULTI_CON1_24BIT_SWAP_BYPASS_MASK BIT(22)
+#define AFE_MPHONE_MULTI_CON1_NON_COMPACT_MODE       (0x1 << 19)
+#define AFE_MPHONE_MULTI_CON1_COMPACT_MODE           (0x0 << 19)
+#define AFE_MPHONE_MULTI_CON1_NON_COMPACT_MODE_MASK  BIT(19)
+#define AFE_MPHONE_MULTI_CON1_HBR_MODE               BIT(18)
+#define AFE_MPHONE_MULTI_CON1_HBR_MODE_MASK          BIT(18)
+#define AFE_MPHONE_MULTI_CON1_LRCK_32_CYCLE          (0x2 << 16)
+#define AFE_MPHONE_MULTI_CON1_LRCK_24_CYCLE          (0x1 << 16)
+#define AFE_MPHONE_MULTI_CON1_LRCK_16_CYCLE          (0x0 << 16)
+#define AFE_MPHONE_MULTI_CON1_LRCK_CYCLE_SEL_MASK    GENMASK(17, 16)
+#define AFE_MPHONE_MULTI_CON1_LRCK_INV               BIT(15)
+#define AFE_MPHONE_MULTI_CON1_LRCK_INV_MASK          BIT(15)
+#define AFE_MPHONE_MULTI_CON1_DELAY_DATA             BIT(14)
+#define AFE_MPHONE_MULTI_CON1_DELAY_DATA_MASK        BIT(14)
+#define AFE_MPHONE_MULTI_CON1_LEFT_ALIGN             BIT(13)
+#define AFE_MPHONE_MULTI_CON1_LEFT_ALIGN_MASK        BIT(13)
+#define AFE_MPHONE_MULTI_CON1_BIT_NUM(x)             ((((x) - 1) & 0x1f) << 8)
+#define AFE_MPHONE_MULTI_CON1_BIT_NUM_MASK           GENMASK(12, 8)
+#define AFE_MPHONE_MULTI_CON1_BCK_INV                BIT(6)
+#define AFE_MPHONE_MULTI_CON1_BCK_INV_MASK           BIT(6)
+#define AFE_MPHONE_MULTI_CON1_CH_NUM(x)              ((((x) >> 1) - 1) & 0x3)
+#define AFE_MPHONE_MULTI_CON1_CH_NUM_MASK            GENMASK(1, 0)
+
+/* AFE_MPHONE_MULTIx_CON2 */
+#define AFE_MPHONE_MULTI_CON2_SEL_SPDIFIN        BIT(19)
+#define AFE_MPHONE_MULTI_CON2_SEL_SPDIFIN_MASK   BIT(19)
+
+/* AFE_AUD_PAD_TOP */
+#define RG_RX_PROTOCOL2                        BIT(3)
+#define RG_RX_FIFO_ON                  BIT(0)
+
+/* AFE_ADDA_MTKAIF_CFG0 */
+#define MTKAIF_RXIF_CLKINV_ADC         BIT(31)
+#define MTKAIF_RXIF_PROTOCOL2          BIT(16)
+#define MTKAIF_TXIF_PROTOCOL2          BIT(4)
+#define MTKAIF_TXIF_8TO5               BIT(2)
+#define MTKAIF_RXIF_8TO5               BIT(1)
+#define MTKAIF_IF_LOOPBACK1            BIT(0)
+
+/* AFE_ADDA_MTKAIF_RX_CFG2 */
+#define MTKAIF_RXIF_DELAY_CYCLE(x)     ((x) << 12)
+#define MTKAIF_RXIF_DELAY_CYCLE_MASK   GENMASK(15, 12)
+#define MTKAIF_RXIF_DELAY_DATA         BIT(8)
+#define MTKAIF_RXIF_DELAY_DATA_SHIFT   8
+
+/* AFE_ADDA_MTKAIF_SYNCWORD_CFG */
+#define ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE     BIT(23)
+
+/* AFE_DMICx_UL_SRC_CON0 */
+#define AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_CH1(x)   (((x) & 0x7) << 27)
+#define AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_CH2(x)   (((x) & 0x7) << 24)
+#define AFE_DMIC_UL_SRC_CON0_UL_TWO_WIRE_MODE_CTL  BIT(23)
+#define AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH2_CTL BIT(22)
+#define AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH1_CTL BIT(21)
+#define AFE_DMIC_UL_VOICE_MODE(x)                  (((x) & 0x7) << 17)
+#define AFE_DMIC_UL_CON0_VOCIE_MODE_8K   AFE_DMIC_UL_VOICE_MODE(0)
+#define AFE_DMIC_UL_CON0_VOCIE_MODE_16K  AFE_DMIC_UL_VOICE_MODE(1)
+#define AFE_DMIC_UL_CON0_VOCIE_MODE_32K  AFE_DMIC_UL_VOICE_MODE(2)
+#define AFE_DMIC_UL_CON0_VOCIE_MODE_48K  AFE_DMIC_UL_VOICE_MODE(3)
+#define AFE_DMIC_UL_SRC_CON0_UL_IIR_MODE_CTL(x)    (((x) & 0x7) << 7)
+#define AFE_DMIC_UL_SRC_CON0_UL_IIR_ON_TMP_CTL     BIT(10)
+#define AFE_DMIC_UL_SRC_CON0_UL_SDM_3_LEVEL_CTL    BIT(1)
+#define AFE_DMIC_UL_SRC_CON0_UL_SRC_ON_TMP_CTL     BIT(0)
+
+/* ETDM_INx_AFIFO_CON */
+#define ETDM_IN_USE_AFIFO              BIT(8)
+#define ETDM_IN_AFIFO_CLOCK(x)         ((x) << 5)
+#define ETDM_IN_AFIFO_CLOCK_MASK       GENMASK(7, 5)
+#define ETDM_IN_AFIFO_MODE(x)          ((x) << 0)
+#define ETDM_IN_AFIFO_MODE_MASK                GENMASK(4, 0)
+
+/* ETDM_COWORK_CON0 */
+#define ETDM_OUT1_SLAVE_SEL(x)         ((x) << 20)
+#define ETDM_OUT1_SLAVE_SEL_MASK       GENMASK(23, 20)
+#define ETDM_OUT1_SLAVE_SEL_SHIFT      20
+
+/* ETDM_COWORK_CON1 */
+#define ETDM_IN1_SDATA_SEL(x)          ((x) << 20)
+#define ETDM_IN1_SDATA_SEL_MASK                GENMASK(23, 20)
+#define ETDM_IN1_SDATA_SEL_SHIFT       20
+#define ETDM_IN1_SDATA0_SEL(x)         ((x) << 16)
+#define ETDM_IN1_SDATA0_SEL_MASK       GENMASK(19, 16)
+#define ETDM_IN1_SDATA0_SEL_SHIFT      16
+#define ETDM_IN1_SLAVE_SEL(x)          ((x) << 8)
+#define ETDM_IN1_SLAVE_SEL_MASK                GENMASK(11, 8)
+#define ETDM_IN1_SLAVE_SEL_SHIFT       8
+
+/* ETDM_COWORK_CON2 */
+#define ETDM_IN2_SLAVE_SEL(x)          ((x) << 24)
+#define ETDM_IN2_SLAVE_SEL_MASK                GENMASK(27, 24)
+#define ETDM_IN2_SLAVE_SEL_SHIFT       24
+#define ETDM_OUT3_SLAVE_SEL(x)         ((x) << 20)
+#define ETDM_OUT3_SLAVE_SEL_MASK       GENMASK(23, 20)
+#define ETDM_OUT3_SLAVE_SEL_SHIFT      20
+#define ETDM_OUT2_SLAVE_SEL(x)         ((x) << 8)
+#define ETDM_OUT2_SLAVE_SEL_MASK       GENMASK(11, 8)
+#define ETDM_OUT2_SLAVE_SEL_SHIFT      8
+
+/* ETDM_COWORK_CON3 */
+#define ETDM_IN2_SDATA_SEL(x)          ((x) << 4)
+#define ETDM_IN2_SDATA_SEL_MASK                GENMASK(7, 4)
+#define ETDM_IN2_SDATA_SEL_SHIFT       4
+#define ETDM_IN2_SDATA0_SEL(x)         ((x) << 0)
+#define ETDM_IN2_SDATA0_SEL_MASK       GENMASK(3, 0)
+#define ETDM_IN2_SDATA0_SEL_SHIFT      0
+
+/* ETDM_x_CONx */
+#define ETDM_CON0_CH_NUM(x)            (((x) - 1) << 23)
+#define ETDM_CON0_CH_NUM_MASK          GENMASK(27, 23)
+#define ETDM_CON0_WORD_LEN(x)          (((x) - 1) << 16)
+#define ETDM_CON0_WORD_LEN_MASK                GENMASK(20, 16)
+#define ETDM_CON0_BIT_LEN(x)           (((x) - 1) << 11)
+#define ETDM_CON0_BIT_LEN_MASK         GENMASK(15, 11)
+#define ETDM_CON0_FORMAT(x)            ((x) << 6)
+#define ETDM_CON0_FORMAT_MASK          GENMASK(8, 6)
+#define ETDM_CON0_SLAVE_MODE           BIT(5)
+#define ETDM_CON0_EN                   BIT(0)
+
+#define ETDM_OUT_CON0_RELATCH_DOMAIN(x)                ((x) << 28)
+#define ETDM_OUT_CON0_RELATCH_DOMAIN_MASK      GENMASK(29, 28)
+
+#define ETDM_CON1_MCLK_OUTPUT                  BIT(16)
+#define ETDM_IN_CON1_LRCK_AUTO_MODE            BIT(31)
+#define ETDM_IN_CON1_LRCK_WIDTH(x)             (((x) - 1) << 20)
+#define ETDM_IN_CON1_LRCK_WIDTH_MASK           GENMASK(29, 20)
+#define ETDM_OUT_CON1_LRCK_AUTO_MODE           BIT(29)
+#define ETDM_OUT_CON1_LRCK_WIDTH(x)            (((x) - 1) << 19)
+#define ETDM_OUT_CON1_LRCK_WIDTH_MASK          GENMASK(28, 19)
+
+#define ETDM_IN_CON2_MULTI_IP_2CH_MODE         BIT(31)
+#define ETDM_IN_CON2_MULTI_IP_TOTAL_CH(x)      (((x) - 1) << 15)
+#define ETDM_IN_CON2_MULTI_IP_TOTAL_CH_MASK    GENMASK(19, 15)
+#define ETDM_IN_CON2_CLOCK(x)                  ((x) << 10)
+#define ETDM_IN_CON2_CLOCK_MASK                        GENMASK(12, 10)
+#define ETDM_IN_CON2_CLOCK_SHIFT               10
+#define ETDM_IN_CON2_UPDATE_GAP(x)             ((x) << 5)
+#define ETDM_IN_CON2_UPDATE_GAP_MASK           GENMASK(9, 5)
+
+#define ETDM_OUT_CON2_LRCK_DELAY_BCK_INV       BIT(30)
+#define ETDM_OUT_CON2_LRCK_DELAY_0P5T_EN       BIT(29)
+
+#define ETDM_IN_CON3_FS(x)                     ((x) << 26)
+#define ETDM_IN_CON3_FS_MASK                   GENMASK(30, 26)
+#define ETDM_IN_CON3_DISABLE_OUT(x)            BIT(((x) & 0xf))
+#define ETDM_IN_CON3_DISABLE_OUT_MASK          GENMASK(15, 0)
+
+#define ETDM_IN_CON4_MASTER_LRCK_INV           BIT(19)
+#define ETDM_IN_CON4_MASTER_BCK_INV            BIT(18)
+#define ETDM_IN_CON4_SLAVE_LRCK_INV            BIT(17)
+#define ETDM_IN_CON4_SLAVE_BCK_INV             BIT(16)
+
+#define ETDM_OUT_CON4_RELATCH_EN(x)            ((x) << 24)
+#define ETDM_OUT_CON4_RELATCH_EN_MASK          GENMASK(28, 24)
+#define ETDM_OUT_CON4_CLOCK(x)                 ((x) << 6)
+#define ETDM_OUT_CON4_CLOCK_MASK               GENMASK(8, 6)
+#define ETDM_OUT_CON4_CLOCK_SHIFT              6
+#define ETDM_OUT_CON4_FS(x)                    ((x) << 0)
+#define ETDM_OUT_CON4_FS_MASK                  GENMASK(4, 0)
+
+#define ETDM_IN_CON5_LR_SWAP(x)                        BIT(((x) & 0xf) + 16)
+#define ETDM_IN_CON5_LR_SWAP_MASK              GENMASK(31, 16)
+#define ETDM_IN_CON5_ENABLE_ODD(x)             BIT(((x) & 0xf))
+#define ETDM_IN_CON5_ENABLE_ODD_MASK           GENMASK(15, 0)
+
+#define ETDM_OUT_CON5_MASTER_LRCK_INV          BIT(10)
+#define ETDM_OUT_CON5_MASTER_BCK_INV           BIT(9)
+#define ETDM_OUT_CON5_SLAVE_LRCK_INV           BIT(8)
+#define ETDM_OUT_CON5_SLAVE_BCK_INV            BIT(7)
+
+/* AFE_DPTX_CON */
+#define AFE_DPTX_CON_CH_EN(x)     (((x) & 0xff) << 8)
+#define AFE_DPTX_CON_CH_EN_2CH    (AFE_DPTX_CON_CH_EN(GENMASK(1, 0)))
+#define AFE_DPTX_CON_CH_EN_4CH    (AFE_DPTX_CON_CH_EN(GENMASK(3, 0)))
+#define AFE_DPTX_CON_CH_EN_6CH    (AFE_DPTX_CON_CH_EN(GENMASK(5, 0)))
+#define AFE_DPTX_CON_CH_EN_8CH    (AFE_DPTX_CON_CH_EN(GENMASK(7, 0)))
+#define AFE_DPTX_CON_CH_EN_MASK   GENMASK(15, 8)
+#define AFE_DPTX_CON_16BIT        (0x1 << 2)
+#define AFE_DPTX_CON_24BIT        (0x0 << 2)
+#define AFE_DPTX_CON_16BIT_MASK   BIT(2)
+#define AFE_DPTX_CON_CH_NUM(x)    (((x) & 0x1) << 1)
+#define AFE_DPTX_CON_CH_NUM_2CH   (AFE_DPTX_CON_CH_NUM(0))
+#define AFE_DPTX_CON_CH_NUM_8CH   (AFE_DPTX_CON_CH_NUM(1))
+#define AFE_DPTX_CON_CH_NUM_MASK  (0x1 << 1)
+#define AFE_DPTX_CON_ON           BIT(0)
+#define AFE_DPTX_CON_ON_MASK      BIT(0)
+
+/* AFE_ADDA_UL_DL_CON0 */
+#define ADDA_AFE_ON_SHIFT              0
+
+/* AFE_ADDA_DL_SRC2_CON0 */
+#define DL_2_INPUT_MODE_CTL(x)         ((x) << 28)
+#define DL_2_INPUT_MODE_CTL_MASK       GENMASK(31, 28)
+#define DL_2_CH1_SATURATION_EN_CTL     BIT(27)
+#define DL_2_CH2_SATURATION_EN_CTL     BIT(26)
+#define DL_2_MUTE_CH1_OFF_CTL_PRE      BIT(12)
+#define DL_2_MUTE_CH2_OFF_CTL_PRE      BIT(11)
+#define DL_2_VOICE_MODE_CTL_PRE                BIT(5)
+#define DL_2_GAIN_ON_CTL_PRE_SHIFT     1
+#define DL_2_SRC_ON_TMP_CTRL_PRE_SHIFT 0
+
+/* AFE_ADDA_DL_SRC2_CON1 */
+#define DL_2_GAIN_CTL_PRE(x)           ((x) << 16)
+#define DL_2_GAIN_CTL_PRE_MASK         GENMASK(31, 16)
+#define DL_2_GAIN_CTL_PRE_SHIFT                16
+
+/* AFE_ADDA_TOP_CON0 */
+#define C_LOOPBACK_MODE_CTL_MASK       GENMASK(15, 12)
+#define DL_INPUT_FROM_SINEGEN          (4 << 12)
+
+/* AFE_ADDA_DL_SDM_DCCOMP_CON */
+#define DL_USE_NEW_2ND_SDM             BIT(30)
+#define ATTGAIN_CTL_MASK               GENMASK(5, 0)
+
+/* AFE_ADDA_UL_SRC_CON0 */
+#define UL_MODE_3P25M_CH2_CTL          BIT(22)
+#define UL_MODE_3P25M_CH1_CTL          BIT(21)
+#define UL_VOICE_MODE_CTL(x)           ((x) << 17)
+#define UL_VOICE_MODE_CTL_MASK         GENMASK(19, 17)
+#define UL_LOOPBACK_MODE_CTL           BIT(2)
+#define UL_SDM3_LEVEL_CTL              BIT(1)
+#define UL_SRC_ON_TMP_CTL_SHIFT                0
+
+#endif
index 939e7e2..7f13a35 100644 (file)
@@ -850,15 +850,12 @@ static struct snd_soc_dai_driver pxa_ssp_dai = {
 static const struct snd_soc_component_driver pxa_ssp_component = {
        .name           = "pxa-ssp",
        .pcm_construct  = pxa2xx_soc_pcm_new,
-       .pcm_destruct   = pxa2xx_soc_pcm_free,
        .open           = pxa2xx_soc_pcm_open,
        .close          = pxa2xx_soc_pcm_close,
        .hw_params      = pxa2xx_soc_pcm_hw_params,
-       .hw_free        = pxa2xx_soc_pcm_hw_free,
        .prepare        = pxa2xx_soc_pcm_prepare,
        .trigger        = pxa2xx_soc_pcm_trigger,
        .pointer        = pxa2xx_soc_pcm_pointer,
-       .mmap           = pxa2xx_soc_pcm_mmap,
        .suspend        = pxa_ssp_suspend,
        .resume         = pxa_ssp_resume,
 };
index 4240fde..58f8541 100644 (file)
@@ -202,15 +202,12 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
 static const struct snd_soc_component_driver pxa_ac97_component = {
        .name           = "pxa-ac97",
        .pcm_construct  = pxa2xx_soc_pcm_new,
-       .pcm_destruct   = pxa2xx_soc_pcm_free,
        .open           = pxa2xx_soc_pcm_open,
        .close          = pxa2xx_soc_pcm_close,
        .hw_params      = pxa2xx_soc_pcm_hw_params,
-       .hw_free        = pxa2xx_soc_pcm_hw_free,
        .prepare        = pxa2xx_soc_pcm_prepare,
        .trigger        = pxa2xx_soc_pcm_trigger,
        .pointer        = pxa2xx_soc_pcm_pointer,
-       .mmap           = pxa2xx_soc_pcm_mmap,
 };
 
 #ifdef CONFIG_OF
index bcde4a9..5bfc1a9 100644 (file)
@@ -359,15 +359,12 @@ static struct snd_soc_dai_driver pxa_i2s_dai = {
 static const struct snd_soc_component_driver pxa_i2s_component = {
        .name           = "pxa-i2s",
        .pcm_construct  = pxa2xx_soc_pcm_new,
-       .pcm_destruct   = pxa2xx_soc_pcm_free,
        .open           = pxa2xx_soc_pcm_open,
        .close          = pxa2xx_soc_pcm_close,
        .hw_params      = pxa2xx_soc_pcm_hw_params,
-       .hw_free        = pxa2xx_soc_pcm_hw_free,
        .prepare        = pxa2xx_soc_pcm_prepare,
        .trigger        = pxa2xx_soc_pcm_trigger,
        .pointer        = pxa2xx_soc_pcm_pointer,
-       .mmap           = pxa2xx_soc_pcm_mmap,
        .suspend        = pxa2xx_soc_pcm_suspend,
        .resume         = pxa2xx_soc_pcm_resume,
 };
index 2b78397..9d6c41f 100644 (file)
 
 static const struct snd_soc_component_driver pxa2xx_soc_platform = {
        .pcm_construct  = pxa2xx_soc_pcm_new,
-       .pcm_destruct   = pxa2xx_soc_pcm_free,
        .open           = pxa2xx_soc_pcm_open,
        .close          = pxa2xx_soc_pcm_close,
        .hw_params      = pxa2xx_soc_pcm_hw_params,
-       .hw_free        = pxa2xx_soc_pcm_hw_free,
        .prepare        = pxa2xx_soc_pcm_prepare,
        .trigger        = pxa2xx_soc_pcm_trigger,
        .pointer        = pxa2xx_soc_pcm_pointer,
-       .mmap           = pxa2xx_soc_pcm_mmap,
 };
 
 static int pxa2xx_soc_platform_probe(struct platform_device *pdev)
index 08a05f0..ba2a982 100644 (file)
@@ -30,6 +30,13 @@ struct apq8016_sbc_data {
 #define MIC_CTRL_QUA_WS_SLAVE_SEL_10   BIT(17)
 #define MIC_CTRL_TLMM_SCLK_EN          BIT(1)
 #define        SPKR_CTL_PRI_WS_SLAVE_SEL_11    (BIT(17) | BIT(16))
+#define SPKR_CTL_TLMM_MCLK_EN          BIT(1)
+#define SPKR_CTL_TLMM_SCLK_EN          BIT(2)
+#define SPKR_CTL_TLMM_DATA1_EN         BIT(3)
+#define SPKR_CTL_TLMM_WS_OUT_SEL_MASK  GENMASK(7, 6)
+#define SPKR_CTL_TLMM_WS_OUT_SEL_SEC   BIT(6)
+#define SPKR_CTL_TLMM_WS_EN_SEL_MASK   GENMASK(19, 18)
+#define SPKR_CTL_TLMM_WS_EN_SEL_SEC    BIT(18)
 #define DEFAULT_MCLK_RATE              9600000
 
 static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd)
@@ -40,6 +47,7 @@ static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_card *card = rtd->card;
        struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card);
        int i, rval;
+       u32 value;
 
        switch (cpu_dai->id) {
        case MI2S_PRIMARY:
@@ -53,6 +61,15 @@ static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd)
                        MIC_CTRL_TLMM_SCLK_EN,
                        pdata->mic_iomux);
                break;
+       case MI2S_SECONDARY:
+               /* Clear TLMM_WS_OUT_SEL and TLMM_WS_EN_SEL fields */
+               value = readl(pdata->spkr_iomux) &
+                       ~(SPKR_CTL_TLMM_WS_OUT_SEL_MASK | SPKR_CTL_TLMM_WS_EN_SEL_MASK);
+               /* Configure the Sec MI2S to TLMM */
+               writel(value | SPKR_CTL_TLMM_MCLK_EN | SPKR_CTL_TLMM_SCLK_EN |
+                       SPKR_CTL_TLMM_DATA1_EN | SPKR_CTL_TLMM_WS_OUT_SEL_SEC |
+                       SPKR_CTL_TLMM_WS_EN_SEL_SEC, pdata->spkr_iomux);
+               break;
        case MI2S_TERTIARY:
                writel(readl(pdata->mic_iomux) | MIC_CTRL_TER_WS_SLAVE_SEL |
                        MIC_CTRL_TLMM_SCLK_EN,
index f9df76d..a59e9d2 100644 (file)
@@ -156,8 +156,6 @@ static int lpass_platform_pcmops_open(struct snd_soc_component *component,
                return -EINVAL;
        }
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
        return 0;
 }
 
@@ -630,16 +628,6 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
        return bytes_to_frames(substream->runtime, curr_addr - base_addr);
 }
 
-static int lpass_platform_pcmops_mmap(struct snd_soc_component *component,
-                                     struct snd_pcm_substream *substream,
-                                     struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       return dma_mmap_coherent(component->dev, vma, runtime->dma_area,
-                                runtime->dma_addr, runtime->dma_bytes);
-}
-
 static irqreturn_t lpass_dma_interrupt_handler(
                        struct snd_pcm_substream *substream,
                        struct lpass_data *drvdata,
@@ -787,52 +775,10 @@ static int lpass_platform_pcm_new(struct snd_soc_component *component,
                                  struct snd_soc_pcm_runtime *soc_runtime)
 {
        struct snd_pcm *pcm = soc_runtime->pcm;
-       struct snd_pcm_substream *psubstream, *csubstream;
-       int ret;
        size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
 
-       psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-       if (psubstream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-                                       component->dev,
-                                       size, &psubstream->dma_buffer);
-               if (ret) {
-                       dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n");
-                       return ret;
-               }
-       }
-
-       csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
-       if (csubstream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-                                       component->dev,
-                                       size, &csubstream->dma_buffer);
-               if (ret) {
-                       dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n");
-                       if (psubstream)
-                               snd_dma_free_pages(&psubstream->dma_buffer);
-                       return ret;
-               }
-
-       }
-
-       return 0;
-}
-
-static void lpass_platform_pcm_free(struct snd_soc_component *component,
-                                   struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       int i;
-
-       for_each_pcm_streams(i) {
-               substream = pcm->streams[i].substream;
-               if (substream) {
-                       snd_dma_free_pages(&substream->dma_buffer);
-                       substream->dma_buffer.area = NULL;
-                       substream->dma_buffer.addr = 0;
-               }
-       }
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                           component->dev, size);
 }
 
 static int lpass_platform_pcmops_suspend(struct snd_soc_component *component)
@@ -877,9 +823,7 @@ static const struct snd_soc_component_driver lpass_component_driver = {
        .prepare        = lpass_platform_pcmops_prepare,
        .trigger        = lpass_platform_pcmops_trigger,
        .pointer        = lpass_platform_pcmops_pointer,
-       .mmap           = lpass_platform_pcmops_mmap,
        .pcm_construct  = lpass_platform_pcm_new,
-       .pcm_destruct   = lpass_platform_pcm_free,
        .suspend                = lpass_platform_pcmops_suspend,
        .resume                 = lpass_platform_pcmops_resume,
 
index 1855b80..3d831b6 100644 (file)
@@ -465,7 +465,7 @@ int q6adm_matrix_map(struct device *dev, int path,
        struct apr_pkt *pkt;
        uint16_t *copps_list;
        int pkt_size, ret, i, copp_idx;
-       void *matrix_map = NULL;
+       void *matrix_map;
        struct q6copp *copp;
 
        /* Assumes port_ids have already been validated during adm_open */
index 5ff56a7..46f3655 100644 (file)
@@ -429,8 +429,6 @@ static int q6asm_dai_open(struct snd_soc_component *component,
        else
                prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32);
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
        return 0;
 }
 
@@ -470,18 +468,6 @@ static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_soc_component *component,
        return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
 }
 
-static int q6asm_dai_mmap(struct snd_soc_component *component,
-                         struct snd_pcm_substream *substream,
-                         struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct device *dev = component->dev;
-
-       return dma_mmap_coherent(dev, vma,
-                       runtime->dma_area, runtime->dma_addr,
-                       runtime->dma_bytes);
-}
-
 static int q6asm_dai_hw_params(struct snd_soc_component *component,
                               struct snd_pcm_substream *substream,
                               struct snd_pcm_hw_params *params)
@@ -1185,52 +1171,11 @@ static const struct snd_compress_ops q6asm_dai_compress_ops = {
 static int q6asm_dai_pcm_new(struct snd_soc_component *component,
                             struct snd_soc_pcm_runtime *rtd)
 {
-       struct snd_pcm_substream *psubstream, *csubstream;
        struct snd_pcm *pcm = rtd->pcm;
-       struct device *dev;
-       int size, ret;
-
-       dev = component->dev;
-       size = q6asm_dai_hardware_playback.buffer_bytes_max;
-       psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-       if (psubstream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
-                                         &psubstream->dma_buffer);
-               if (ret) {
-                       dev_err(dev, "Cannot allocate buffer(s)\n");
-                       return ret;
-               }
-       }
+       size_t size = q6asm_dai_hardware_playback.buffer_bytes_max;
 
-       csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
-       if (csubstream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
-                                         &csubstream->dma_buffer);
-               if (ret) {
-                       dev_err(dev, "Cannot allocate buffer(s)\n");
-                       if (psubstream)
-                               snd_dma_free_pages(&psubstream->dma_buffer);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-static void q6asm_dai_pcm_free(struct snd_soc_component *component,
-                              struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
-               substream = pcm->streams[i].substream;
-               if (substream) {
-                       snd_dma_free_pages(&substream->dma_buffer);
-                       substream->dma_buffer.area = NULL;
-                       substream->dma_buffer.addr = 0;
-               }
-       }
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                           component->dev, size);
 }
 
 static const struct snd_soc_dapm_widget q6asm_dapm_widgets[] = {
@@ -1260,9 +1205,7 @@ static const struct snd_soc_component_driver q6asm_fe_dai_component = {
        .prepare        = q6asm_dai_prepare,
        .trigger        = q6asm_dai_trigger,
        .pointer        = q6asm_dai_pointer,
-       .mmap           = q6asm_dai_mmap,
        .pcm_construct  = q6asm_dai_pcm_new,
-       .pcm_destruct   = q6asm_dai_pcm_free,
        .compress_ops   = &q6asm_dai_compress_ops,
        .dapm_widgets   = q6asm_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(q6asm_dapm_widgets),
index 36bf8bd..9251d85 100644 (file)
@@ -1624,7 +1624,7 @@ EXPORT_SYMBOL_GPL(q6asm_write_async);
 
 static void q6asm_reset_buf_state(struct audio_client *ac)
 {
-       struct audio_port_data *port = NULL;
+       struct audio_port_data *port;
        unsigned long flags;
 
        spin_lock_irqsave(&ac->lock, flags);
index c7dc350..53e0b4a 100644 (file)
@@ -40,6 +40,9 @@ struct rk_i2s_dev {
        struct regmap *regmap;
        struct regmap *grf;
 
+       bool has_capture;
+       bool has_playback;
+
 /*
  * Used to indicate the tx/rx status.
  * I2S controller hopes to start the tx and rx together,
@@ -49,6 +52,7 @@ struct rk_i2s_dev {
        bool rx_start;
        bool is_master_mode;
        const struct rk_i2s_pins *pins;
+       unsigned int bclk_ratio;
 };
 
 static int i2s_runtime_suspend(struct device *dev)
@@ -186,7 +190,9 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
 {
        struct rk_i2s_dev *i2s = to_info(cpu_dai);
        unsigned int mask = 0, val = 0;
+       int ret = 0;
 
+       pm_runtime_get_sync(cpu_dai->dev);
        mask = I2S_CKR_MSS_MASK;
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
@@ -199,21 +205,37 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
                i2s->is_master_mode = false;
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_pm_put;
        }
 
        regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
 
-       mask = I2S_CKR_CKP_MASK;
+       mask = I2S_CKR_CKP_MASK | I2S_CKR_TLP_MASK | I2S_CKR_RLP_MASK;
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
-               val = I2S_CKR_CKP_NEG;
+               val = I2S_CKR_CKP_NORMAL |
+                     I2S_CKR_TLP_NORMAL |
+                     I2S_CKR_RLP_NORMAL;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               val = I2S_CKR_CKP_NORMAL |
+                     I2S_CKR_TLP_INVERTED |
+                     I2S_CKR_RLP_INVERTED;
                break;
        case SND_SOC_DAIFMT_IB_NF:
-               val = I2S_CKR_CKP_POS;
+               val = I2S_CKR_CKP_INVERTED |
+                     I2S_CKR_TLP_NORMAL |
+                     I2S_CKR_RLP_NORMAL;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               val = I2S_CKR_CKP_INVERTED |
+                     I2S_CKR_TLP_INVERTED |
+                     I2S_CKR_RLP_INVERTED;
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_pm_put;
        }
 
        regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
@@ -229,14 +251,15 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
        case SND_SOC_DAIFMT_I2S:
                val = I2S_TXCR_IBM_NORMAL;
                break;
-       case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */
-               val = I2S_TXCR_TFS_PCM;
-               break;
-       case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */
+       case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */
                val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1);
                break;
+       case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */
+               val = I2S_TXCR_TFS_PCM;
+               break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_pm_put;
        }
 
        regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val);
@@ -252,19 +275,23 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
        case SND_SOC_DAIFMT_I2S:
                val = I2S_RXCR_IBM_NORMAL;
                break;
-       case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */
-               val = I2S_RXCR_TFS_PCM;
-               break;
-       case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */
+       case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */
                val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1);
                break;
+       case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */
+               val = I2S_RXCR_TFS_PCM;
+               break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_pm_put;
        }
 
        regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val);
 
-       return 0;
+err_pm_put:
+       pm_runtime_put(cpu_dai->dev);
+
+       return ret;
 }
 
 static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
@@ -278,11 +305,11 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
 
        if (i2s->is_master_mode) {
                mclk_rate = clk_get_rate(i2s->mclk);
-               bclk_rate = 2 * 32 * params_rate(params);
-               if (bclk_rate == 0 || mclk_rate % bclk_rate)
+               bclk_rate = i2s->bclk_ratio * params_rate(params);
+               if (!bclk_rate)
                        return -EINVAL;
 
-               div_bclk = mclk_rate / bclk_rate;
+               div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate);
                div_lrck = bclk_rate / params_rate(params);
                regmap_update_bits(i2s->regmap, I2S_CKR,
                                   I2S_CKR_MDIV_MASK,
@@ -413,6 +440,16 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream,
        return ret;
 }
 
+static int rockchip_i2s_set_bclk_ratio(struct snd_soc_dai *dai,
+                                      unsigned int ratio)
+{
+       struct rk_i2s_dev *i2s = to_info(dai);
+
+       i2s->bclk_ratio = ratio;
+
+       return 0;
+}
+
 static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
                                   unsigned int freq, int dir)
 {
@@ -433,14 +470,16 @@ static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai)
 {
        struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai);
 
-       dai->capture_dma_data = &i2s->capture_dma_data;
-       dai->playback_dma_data = &i2s->playback_dma_data;
+       snd_soc_dai_init_dma_data(dai,
+               i2s->has_playback ? &i2s->playback_dma_data : NULL,
+               i2s->has_capture  ? &i2s->capture_dma_data  : NULL);
 
        return 0;
 }
 
 static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
        .hw_params = rockchip_i2s_hw_params,
+       .set_bclk_ratio = rockchip_i2s_set_bclk_ratio,
        .set_sysclk = rockchip_i2s_set_sysclk,
        .set_fmt = rockchip_i2s_set_fmt,
        .trigger = rockchip_i2s_trigger,
@@ -448,28 +487,6 @@ static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
 
 static struct snd_soc_dai_driver rockchip_i2s_dai = {
        .probe = rockchip_i2s_dai_probe,
-       .playback = {
-               .stream_name = "Playback",
-               .channels_min = 2,
-               .channels_max = 8,
-               .rates = SNDRV_PCM_RATE_8000_192000,
-               .formats = (SNDRV_PCM_FMTBIT_S8 |
-                           SNDRV_PCM_FMTBIT_S16_LE |
-                           SNDRV_PCM_FMTBIT_S20_3LE |
-                           SNDRV_PCM_FMTBIT_S24_LE |
-                           SNDRV_PCM_FMTBIT_S32_LE),
-       },
-       .capture = {
-               .stream_name = "Capture",
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000,
-               .formats = (SNDRV_PCM_FMTBIT_S8 |
-                           SNDRV_PCM_FMTBIT_S16_LE |
-                           SNDRV_PCM_FMTBIT_S20_3LE |
-                           SNDRV_PCM_FMTBIT_S24_LE |
-                           SNDRV_PCM_FMTBIT_S32_LE),
-       },
        .ops = &rockchip_i2s_dai_ops,
        .symmetric_rate = 1,
 };
@@ -567,23 +584,101 @@ static const struct rk_i2s_pins rk3399_i2s_pins = {
 };
 
 static const struct of_device_id rockchip_i2s_match[] __maybe_unused = {
+       { .compatible = "rockchip,px30-i2s", },
+       { .compatible = "rockchip,rk1808-i2s", },
+       { .compatible = "rockchip,rk3036-i2s", },
        { .compatible = "rockchip,rk3066-i2s", },
+       { .compatible = "rockchip,rk3128-i2s", },
        { .compatible = "rockchip,rk3188-i2s", },
+       { .compatible = "rockchip,rk3228-i2s", },
        { .compatible = "rockchip,rk3288-i2s", },
+       { .compatible = "rockchip,rk3308-i2s", },
+       { .compatible = "rockchip,rk3328-i2s", },
+       { .compatible = "rockchip,rk3366-i2s", },
+       { .compatible = "rockchip,rk3368-i2s", },
        { .compatible = "rockchip,rk3399-i2s", .data = &rk3399_i2s_pins },
+       { .compatible = "rockchip,rv1126-i2s", },
        {},
 };
 
+static int rockchip_i2s_init_dai(struct rk_i2s_dev *i2s, struct resource *res,
+                                struct snd_soc_dai_driver **dp)
+{
+       struct device_node *node = i2s->dev->of_node;
+       struct snd_soc_dai_driver *dai;
+       struct property *dma_names;
+       const char *dma_name;
+       unsigned int val;
+
+       of_property_for_each_string(node, "dma-names", dma_names, dma_name) {
+               if (!strcmp(dma_name, "tx"))
+                       i2s->has_playback = true;
+               if (!strcmp(dma_name, "rx"))
+                       i2s->has_capture = true;
+       }
+
+       dai = devm_kmemdup(i2s->dev, &rockchip_i2s_dai,
+                          sizeof(*dai), GFP_KERNEL);
+       if (!dai)
+               return -ENOMEM;
+
+       if (i2s->has_playback) {
+               dai->playback.stream_name = "Playback";
+               dai->playback.channels_min = 2;
+               dai->playback.channels_max = 8;
+               dai->playback.rates = SNDRV_PCM_RATE_8000_192000;
+               dai->playback.formats = SNDRV_PCM_FMTBIT_S8 |
+                                       SNDRV_PCM_FMTBIT_S16_LE |
+                                       SNDRV_PCM_FMTBIT_S20_3LE |
+                                       SNDRV_PCM_FMTBIT_S24_LE |
+                                       SNDRV_PCM_FMTBIT_S32_LE;
+
+               i2s->playback_dma_data.addr = res->start + I2S_TXDR;
+               i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+               i2s->playback_dma_data.maxburst = 8;
+
+               if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) {
+                       if (val >= 2 && val <= 8)
+                               dai->playback.channels_max = val;
+               }
+       }
+
+       if (i2s->has_capture) {
+               dai->capture.stream_name = "Capture";
+               dai->capture.channels_min = 2;
+               dai->capture.channels_max = 8;
+               dai->capture.rates = SNDRV_PCM_RATE_8000_192000;
+               dai->capture.formats = SNDRV_PCM_FMTBIT_S8 |
+                                      SNDRV_PCM_FMTBIT_S16_LE |
+                                      SNDRV_PCM_FMTBIT_S20_3LE |
+                                      SNDRV_PCM_FMTBIT_S24_LE |
+                                      SNDRV_PCM_FMTBIT_S32_LE;
+
+               i2s->capture_dma_data.addr = res->start + I2S_RXDR;
+               i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+               i2s->capture_dma_data.maxburst = 8;
+
+               if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {
+                       if (val >= 2 && val <= 8)
+                               dai->capture.channels_max = val;
+               }
+       }
+
+       if (dp)
+               *dp = dai;
+
+       return 0;
+}
+
 static int rockchip_i2s_probe(struct platform_device *pdev)
 {
        struct device_node *node = pdev->dev.of_node;
        const struct of_device_id *of_id;
        struct rk_i2s_dev *i2s;
-       struct snd_soc_dai_driver *soc_dai;
+       struct snd_soc_dai_driver *dai;
        struct resource *res;
        void __iomem *regs;
        int ret;
-       int val;
 
        i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
        if (!i2s)
@@ -630,13 +725,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
                return PTR_ERR(i2s->regmap);
        }
 
-       i2s->playback_dma_data.addr = res->start + I2S_TXDR;
-       i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       i2s->playback_dma_data.maxburst = 4;
-
-       i2s->capture_dma_data.addr = res->start + I2S_RXDR;
-       i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       i2s->capture_dma_data.maxburst = 4;
+       i2s->bclk_ratio = 64;
 
        dev_set_drvdata(&pdev->dev, i2s);
 
@@ -647,26 +736,13 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
                        goto err_pm_disable;
        }
 
-       soc_dai = devm_kmemdup(&pdev->dev, &rockchip_i2s_dai,
-                              sizeof(*soc_dai), GFP_KERNEL);
-       if (!soc_dai) {
-               ret = -ENOMEM;
+       ret = rockchip_i2s_init_dai(i2s, res, &dai);
+       if (ret)
                goto err_pm_disable;
-       }
-
-       if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) {
-               if (val >= 2 && val <= 8)
-                       soc_dai->playback.channels_max = val;
-       }
-
-       if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {
-               if (val >= 2 && val <= 8)
-                       soc_dai->capture.channels_max = val;
-       }
 
        ret = devm_snd_soc_register_component(&pdev->dev,
                                              &rockchip_i2s_component,
-                                             soc_dai, 1);
+                                             dai, 1);
 
        if (ret) {
                dev_err(&pdev->dev, "Could not register DAI\n");
index fcaae24..251851b 100644 (file)
 #define I2S_CKR_MSS_SLAVE      (1 << I2S_CKR_MSS_SHIFT)
 #define I2S_CKR_MSS_MASK       (1 << I2S_CKR_MSS_SHIFT)
 #define I2S_CKR_CKP_SHIFT      26
-#define I2S_CKR_CKP_NEG                (0 << I2S_CKR_CKP_SHIFT)
-#define I2S_CKR_CKP_POS                (1 << I2S_CKR_CKP_SHIFT)
+#define I2S_CKR_CKP_NORMAL     (0 << I2S_CKR_CKP_SHIFT)
+#define I2S_CKR_CKP_INVERTED   (1 << I2S_CKR_CKP_SHIFT)
 #define I2S_CKR_CKP_MASK       (1 << I2S_CKR_CKP_SHIFT)
 #define I2S_CKR_RLP_SHIFT      25
 #define I2S_CKR_RLP_NORMAL     (0 << I2S_CKR_RLP_SHIFT)
-#define I2S_CKR_RLP_OPPSITE    (1 << I2S_CKR_RLP_SHIFT)
+#define I2S_CKR_RLP_INVERTED   (1 << I2S_CKR_RLP_SHIFT)
+#define I2S_CKR_RLP_MASK       (1 << I2S_CKR_RLP_SHIFT)
 #define I2S_CKR_TLP_SHIFT      24
 #define I2S_CKR_TLP_NORMAL     (0 << I2S_CKR_TLP_SHIFT)
-#define I2S_CKR_TLP_OPPSITE    (1 << I2S_CKR_TLP_SHIFT)
+#define I2S_CKR_TLP_INVERTED   (1 << I2S_CKR_TLP_SHIFT)
+#define I2S_CKR_TLP_MASK       (1 << I2S_CKR_TLP_SHIFT)
 #define I2S_CKR_MDIV_SHIFT     16
 #define I2S_CKR_MDIV(x)                ((x - 1) << I2S_CKR_MDIV_SHIFT)
 #define I2S_CKR_MDIV_MASK      (0xff << I2S_CKR_MDIV_SHIFT)
index 73226a4..d027ca4 100644 (file)
@@ -58,6 +58,8 @@ static const struct of_device_id rk_spdif_match[] __maybe_unused = {
          .data = (void *)RK_SPDIF_RK3366 },
        { .compatible = "rockchip,rk3399-spdif",
          .data = (void *)RK_SPDIF_RK3366 },
+       { .compatible = "rockchip,rk3568-spdif",
+         .data = (void *)RK_SPDIF_RK3366 },
        {},
 };
 MODULE_DEVICE_TABLE(of, rk_spdif_match);
@@ -103,8 +105,8 @@ static int __maybe_unused rk_spdif_runtime_resume(struct device *dev)
 }
 
 static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
-                                 struct snd_pcm_hw_params *params,
-                                 struct snd_soc_dai *dai)
+                             struct snd_pcm_hw_params *params,
+                             struct snd_soc_dai *dai)
 {
        struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai);
        unsigned int val = SPDIF_CFGR_HALFWORD_ENABLE;
@@ -137,15 +139,15 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
        }
 
        ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR,
-               SPDIF_CFGR_CLK_DIV_MASK | SPDIF_CFGR_HALFWORD_ENABLE |
-               SDPIF_CFGR_VDW_MASK,
-               val);
+                                SPDIF_CFGR_CLK_DIV_MASK |
+                                SPDIF_CFGR_HALFWORD_ENABLE |
+                                SDPIF_CFGR_VDW_MASK, val);
 
        return ret;
 }
 
 static int rk_spdif_trigger(struct snd_pcm_substream *substream,
-                               int cmd, struct snd_soc_dai *dai)
+                           int cmd, struct snd_soc_dai *dai)
 {
        struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai);
        int ret;
@@ -155,31 +157,31 @@ static int rk_spdif_trigger(struct snd_pcm_substream *substream,
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                ret = regmap_update_bits(spdif->regmap, SPDIF_DMACR,
-                                  SPDIF_DMACR_TDE_ENABLE |
-                                  SPDIF_DMACR_TDL_MASK,
-                                  SPDIF_DMACR_TDE_ENABLE |
-                                  SPDIF_DMACR_TDL(16));
+                                        SPDIF_DMACR_TDE_ENABLE |
+                                        SPDIF_DMACR_TDL_MASK,
+                                        SPDIF_DMACR_TDE_ENABLE |
+                                        SPDIF_DMACR_TDL(16));
 
                if (ret != 0)
                        return ret;
 
                ret = regmap_update_bits(spdif->regmap, SPDIF_XFER,
-                                  SPDIF_XFER_TXS_START,
-                                  SPDIF_XFER_TXS_START);
+                                        SPDIF_XFER_TXS_START,
+                                        SPDIF_XFER_TXS_START);
                break;
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                ret = regmap_update_bits(spdif->regmap, SPDIF_DMACR,
-                                  SPDIF_DMACR_TDE_ENABLE,
-                                  SPDIF_DMACR_TDE_DISABLE);
+                                        SPDIF_DMACR_TDE_ENABLE,
+                                        SPDIF_DMACR_TDE_DISABLE);
 
                if (ret != 0)
                        return ret;
 
                ret = regmap_update_bits(spdif->regmap, SPDIF_XFER,
-                                  SPDIF_XFER_TXS_START,
-                                  SPDIF_XFER_TXS_STOP);
+                                        SPDIF_XFER_TXS_START,
+                                        SPDIF_XFER_TXS_STOP);
                break;
        default:
                ret = -EINVAL;
@@ -247,6 +249,7 @@ static bool rk_spdif_rd_reg(struct device *dev, unsigned int reg)
        case SPDIF_INTCR:
        case SPDIF_INTSR:
        case SPDIF_XFER:
+       case SPDIF_SMPDR:
                return true;
        default:
                return false;
@@ -258,6 +261,7 @@ static bool rk_spdif_volatile_reg(struct device *dev, unsigned int reg)
        switch (reg) {
        case SPDIF_INTSR:
        case SPDIF_SDBLR:
+       case SPDIF_SMPDR:
                return true;
        default:
                return false;
@@ -291,7 +295,7 @@ static int rk_spdif_probe(struct platform_device *pdev)
                grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
                if (IS_ERR(grf)) {
                        dev_err(&pdev->dev,
-                               "rockchip_spdif missing 'rockchip,grf' \n");
+                               "rockchip_spdif missing 'rockchip,grf'\n");
                        return PTR_ERR(grf);
                }
 
index 0ac5956..313ab65 100644 (file)
@@ -310,7 +310,7 @@ static int aries_hw_free(struct snd_pcm_substream *substream)
 /*
  * Main DAI operations
  */
-static struct snd_soc_ops aries_ops = {
+static const struct snd_soc_ops aries_ops = {
        .hw_params = aries_hw_params,
        .hw_free = aries_hw_free,
 };
index 2858737..606ac5e 100644 (file)
@@ -48,7 +48,7 @@ static int arndale_rt5631_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_ops arndale_rt5631_ops = {
+static const struct snd_soc_ops arndale_rt5631_ops = {
        .hw_params = arndale_rt5631_hw_params,
 };
 
@@ -80,7 +80,7 @@ static int arndale_wm1811_hw_params(struct snd_pcm_substream *substream,
                                        rclk + 1, SND_SOC_CLOCK_IN);
 }
 
-static struct snd_soc_ops arndale_wm1811_ops = {
+static const struct snd_soc_ops arndale_wm1811_ops = {
        .hw_params = arndale_wm1811_hw_params,
 };
 
index 8aa78ff..c994e67 100644 (file)
@@ -112,7 +112,7 @@ static int h1940_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_ops h1940_ops = {
+static const struct snd_soc_ops h1940_ops = {
        .startup        = h1940_startup,
        .hw_params      = h1940_hw_params,
 };
index a1ff140..390f2dd 100644 (file)
@@ -130,7 +130,7 @@ static int littlemill_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_ops littlemill_ops = {
+static const struct snd_soc_ops littlemill_ops = {
        .hw_params = littlemill_hw_params,
 };
 
index 1f9a553..a201953 100644 (file)
@@ -129,7 +129,7 @@ static int midas_aif1_hw_params(struct snd_pcm_substream *substream,
        return midas_start_fll1(rtd, pll_out);
 }
 
-static struct snd_soc_ops midas_aif1_ops = {
+static const struct snd_soc_ops midas_aif1_ops = {
        .hw_params = midas_aif1_hw_params,
 };
 
index 9266070..c98b685 100644 (file)
@@ -106,7 +106,7 @@ static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
 /*
  * Neo1973 WM8753 HiFi DAI opserations.
  */
-static struct snd_soc_ops neo1973_hifi_ops = {
+static const struct snd_soc_ops neo1973_hifi_ops = {
        .hw_params = neo1973_hifi_hw_params,
        .hw_free = neo1973_hifi_hw_free,
 };
@@ -158,7 +158,7 @@ static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
        return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
 }
 
-static struct snd_soc_ops neo1973_voice_ops = {
+static const struct snd_soc_ops neo1973_voice_ops = {
        .hw_params = neo1973_voice_hw_params,
        .hw_free = neo1973_voice_hw_free,
 };
index 400a7f7..6ea1c8c 100644 (file)
@@ -62,7 +62,7 @@ static struct snd_soc_jack_gpio hp_jack_gpios[] = {
        },
 };
 
-static struct snd_soc_ops rx1950_ops = {
+static const struct snd_soc_ops rx1950_ops = {
        .startup        = rx1950_startup,
        .hw_params      = rx1950_hw_params,
 };
index c95629b..cee39ad 100644 (file)
@@ -70,7 +70,7 @@ static int smartq_hifi_hw_params(struct snd_pcm_substream *substream,
 /*
  * SmartQ WM8987 HiFi DAI operations.
  */
-static struct snd_soc_ops smartq_hifi_ops = {
+static const struct snd_soc_ops smartq_hifi_ops = {
        .hw_params = smartq_hifi_hw_params,
 };
 
index ed753a2..78703d0 100644 (file)
@@ -86,7 +86,7 @@ static int smdk_hw_params(struct snd_pcm_substream *substream,
 /*
  * SMDK WM8580 DAI operations.
  */
-static struct snd_soc_ops smdk_ops = {
+static const struct snd_soc_ops smdk_ops = {
        .hw_params = smdk_hw_params,
 };
 
index 39a7a44..7661b63 100644 (file)
@@ -73,7 +73,7 @@ static int smdk_hw_params(struct snd_pcm_substream *substream,
 /*
  * SMDK WM8994 DAI operations.
  */
-static struct snd_soc_ops smdk_ops = {
+static const struct snd_soc_ops smdk_ops = {
        .hw_params = smdk_hw_params,
 };
 
index a016405..029448f 100644 (file)
@@ -85,7 +85,7 @@ static int smdk_wm8994_pcm_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_ops smdk_wm8994_pcm_ops = {
+static const struct snd_soc_ops smdk_wm8994_pcm_ops = {
        .hw_params = smdk_wm8994_pcm_hw_params,
 };
 
index 84c2c63..a2c77e6 100644 (file)
@@ -126,7 +126,7 @@ static int tm2_aif1_hw_params(struct snd_pcm_substream *substream,
        return tm2_start_sysclk(rtd->card);
 }
 
-static struct snd_soc_ops tm2_aif1_ops = {
+static const struct snd_soc_ops tm2_aif1_ops = {
        .hw_params = tm2_aif1_hw_params,
 };
 
@@ -200,7 +200,7 @@ static int tm2_aif2_hw_free(struct snd_pcm_substream *substream)
        return ret;
 }
 
-static struct snd_soc_ops tm2_aif2_ops = {
+static const struct snd_soc_ops tm2_aif2_ops = {
        .hw_params = tm2_aif2_hw_params,
        .hw_free = tm2_aif2_hw_free,
 };
@@ -254,7 +254,7 @@ static int tm2_hdmi_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_ops tm2_hdmi_ops = {
+static const struct snd_soc_ops tm2_hdmi_ops = {
        .hw_params = tm2_hdmi_hw_params,
 };
 
index c962d2c..15223d8 100644 (file)
@@ -105,7 +105,7 @@ static int tobermory_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_ops tobermory_ops = {
+static const struct snd_soc_ops tobermory_ops = {
        .hw_params = tobermory_hw_params,
 };
 
index 346c806..ae46f18 100644 (file)
@@ -45,6 +45,12 @@ config SND_SOC_RCAR
        help
          This option enables R-Car SRU/SCU/SSIU/SSI sound support
 
+config SND_SOC_RZ
+       tristate "RZ/G2L series SSIF-2 support"
+       depends on ARCH_R9A07G044 || COMPILE_TEST
+       help
+         This option enables RZ/G2L SSIF-2 sound support.
+
 ##
 ## Boards
 ##
index 51bd7c8..f6fd799 100644 (file)
@@ -22,3 +22,7 @@ snd-soc-migor-objs            := migor.o
 
 obj-$(CONFIG_SND_SH7760_AC97)  += snd-soc-sh7760-ac97.o
 obj-$(CONFIG_SND_SIU_MIGOR)    += snd-soc-migor.o
+
+# RZ/G2L
+snd-soc-rz-ssi-objs            := rz-ssi.o
+obj-$(CONFIG_SND_SOC_RZ)       += snd-soc-rz-ssi.o
index 0ebee1e..5f1e72e 100644 (file)
@@ -391,9 +391,9 @@ static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv,
        struct clk *clk;
 
        clk = clk_register_fixed_rate(dev, name, parent, 0, 0);
-       if (IS_ERR(clk)) {
+       if (IS_ERR_OR_NULL(clk)) {
                dev_err(dev, "create null clk error\n");
-               return NULL;
+               return ERR_CAST(clk);
        }
 
        return clk;
@@ -430,9 +430,9 @@ static int rsnd_adg_get_clkin(struct rsnd_priv *priv)
        for (i = 0; i < CLKMAX; i++) {
                clk = devm_clk_get(dev, clk_name[i]);
 
-               if (IS_ERR(clk))
+               if (IS_ERR_OR_NULL(clk))
                        clk = rsnd_adg_null_clk_get(priv);
-               if (IS_ERR(clk))
+               if (IS_ERR_OR_NULL(clk))
                        goto err;
 
                adg->clk[i] = clk;
@@ -582,7 +582,7 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
        if (!count) {
                clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT],
                                              parent_clk_name, 0, req_rate[0]);
-               if (IS_ERR(clk))
+               if (IS_ERR_OR_NULL(clk))
                        goto err;
 
                adg->clkout[CLKOUT] = clk;
@@ -596,7 +596,7 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
                        clk = clk_register_fixed_rate(dev, clkout_name[i],
                                                      parent_clk_name, 0,
                                                      req_rate[0]);
-                       if (IS_ERR(clk))
+                       if (IS_ERR_OR_NULL(clk))
                                goto err;
 
                        adg->clkout[i] = clk;
index 5e382b5..978bd04 100644 (file)
@@ -426,19 +426,19 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
 
 u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod)
 {
-       enum rsnd_mod_type playback_mods[] = {
+       static const enum rsnd_mod_type playback_mods[] = {
                RSND_MOD_SRC,
                RSND_MOD_CMD,
                RSND_MOD_SSIU,
        };
-       enum rsnd_mod_type capture_mods[] = {
+       static const enum rsnd_mod_type capture_mods[] = {
                RSND_MOD_CMD,
                RSND_MOD_SRC,
                RSND_MOD_SSIU,
        };
        struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
        struct rsnd_mod *tmod = NULL;
-       enum rsnd_mod_type *mods =
+       const enum rsnd_mod_type *mods =
                rsnd_io_is_play(io) ?
                playback_mods : capture_mods;
        int i;
index 82d16e0..16c6e02 100644 (file)
@@ -102,7 +102,7 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod,
        struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
 
        if (dmaen->chan)
-               dmaengine_terminate_all(dmaen->chan);
+               dmaengine_terminate_sync(dmaen->chan);
 
        return 0;
 }
index 27f34ca..87e606f 100644 (file)
@@ -165,7 +165,7 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod,
 
 static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io)
 {
-       enum rsnd_mod_type types[] = {
+       static const enum rsnd_mod_type types[] = {
                RSND_MOD_SSIM1,
                RSND_MOD_SSIM2,
                RSND_MOD_SSIM3,
@@ -228,7 +228,7 @@ unsigned int rsnd_ssi_clk_query(struct rsnd_dai *rdai,
                       int param1, int param2, int *idx)
 {
        struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
-       int ssi_clk_mul_table[] = {
+       static const int ssi_clk_mul_table[] = {
                1, 2, 4, 8, 16, 6, 12,
        };
        int j, ret;
@@ -1079,7 +1079,7 @@ static void rsnd_ssi_connect(struct rsnd_mod *mod,
                             struct rsnd_dai_stream *io)
 {
        struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
-       enum rsnd_mod_type types[] = {
+       static const enum rsnd_mod_type types[] = {
                RSND_MOD_SSI,
                RSND_MOD_SSIM1,
                RSND_MOD_SSIM2,
diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
new file mode 100644 (file)
index 0000000..fa0cc08
--- /dev/null
@@ -0,0 +1,1074 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Renesas RZ/G2L ASoC Serial Sound Interface (SSIF-2) Driver
+//
+// Copyright (C) 2021 Renesas Electronics Corp.
+// Copyright (C) 2019 Chris Brandt.
+//
+
+#include <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <sound/soc.h>
+
+/* REGISTER OFFSET */
+#define SSICR                  0x000
+#define SSISR                  0x004
+#define SSIFCR                 0x010
+#define SSIFSR                 0x014
+#define SSIFTDR                        0x018
+#define SSIFRDR                        0x01c
+#define SSIOFR                 0x020
+#define SSISCR                 0x024
+
+/* SSI REGISTER BITS */
+#define SSICR_DWL(x)           (((x) & 0x7) << 19)
+#define SSICR_SWL(x)           (((x) & 0x7) << 16)
+#define SSICR_MST              BIT(14)
+#define SSICR_CKDV(x)          (((x) & 0xf) << 4)
+
+#define SSICR_CKS              BIT(30)
+#define SSICR_TUIEN            BIT(29)
+#define SSICR_TOIEN            BIT(28)
+#define SSICR_RUIEN            BIT(27)
+#define SSICR_ROIEN            BIT(26)
+#define SSICR_MST              BIT(14)
+#define SSICR_BCKP             BIT(13)
+#define SSICR_LRCKP            BIT(12)
+#define SSICR_CKDV(x)          (((x) & 0xf) << 4)
+#define SSICR_TEN              BIT(1)
+#define SSICR_REN              BIT(0)
+
+#define SSISR_TUIRQ            BIT(29)
+#define SSISR_TOIRQ            BIT(28)
+#define SSISR_RUIRQ            BIT(27)
+#define SSISR_ROIRQ            BIT(26)
+#define SSISR_IIRQ             BIT(25)
+
+#define SSIFCR_AUCKE           BIT(31)
+#define SSIFCR_SSIRST          BIT(16)
+#define SSIFCR_TIE             BIT(3)
+#define SSIFCR_RIE             BIT(2)
+#define SSIFCR_TFRST           BIT(1)
+#define SSIFCR_RFRST           BIT(0)
+
+#define SSIFSR_TDC_MASK                0x3f
+#define SSIFSR_TDC_SHIFT       24
+#define SSIFSR_RDC_MASK                0x3f
+#define SSIFSR_RDC_SHIFT       8
+
+#define SSIFSR_TDC(x)          (((x) & 0x1f) << 24)
+#define SSIFSR_TDE             BIT(16)
+#define SSIFSR_RDC(x)          (((x) & 0x1f) << 8)
+#define SSIFSR_RDF             BIT(0)
+
+#define SSIOFR_LRCONT          BIT(8)
+
+#define SSISCR_TDES(x)         (((x) & 0x1f) << 8)
+#define SSISCR_RDFS(x)         (((x) & 0x1f) << 0)
+
+/* Pre allocated buffers sizes */
+#define PREALLOC_BUFFER                (SZ_32K)
+#define PREALLOC_BUFFER_MAX    (SZ_32K)
+
+#define SSI_RATES              SNDRV_PCM_RATE_8000_48000 /* 8k-44.1kHz */
+#define SSI_FMTS               SNDRV_PCM_FMTBIT_S16_LE
+#define SSI_CHAN_MIN           2
+#define SSI_CHAN_MAX           2
+#define SSI_FIFO_DEPTH         32
+
+struct rz_ssi_priv;
+
+struct rz_ssi_stream {
+       struct rz_ssi_priv *priv;
+       struct snd_pcm_substream *substream;
+       int fifo_sample_size;   /* sample capacity of SSI FIFO */
+       int dma_buffer_pos;     /* The address for the next DMA descriptor */
+       int period_counter;     /* for keeping track of periods transferred */
+       int sample_width;
+       int buffer_pos;         /* current frame position in the buffer */
+       int running;            /* 0=stopped, 1=running */
+
+       int uerr_num;
+       int oerr_num;
+
+       struct dma_chan *dma_ch;
+
+       int (*transfer)(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm);
+};
+
+struct rz_ssi_priv {
+       void __iomem *base;
+       struct platform_device *pdev;
+       struct reset_control *rstc;
+       struct device *dev;
+       struct clk *sfr_clk;
+       struct clk *clk;
+
+       phys_addr_t phys;
+       int irq_int;
+       int irq_tx;
+       int irq_rx;
+
+       spinlock_t lock;
+
+       /*
+        * The SSI supports full-duplex transmission and reception.
+        * However, if an error occurs, channel reset (both transmission
+        * and reception reset) is required.
+        * So it is better to use as half-duplex (playing and recording
+        * should be done on separate channels).
+        */
+       struct rz_ssi_stream playback;
+       struct rz_ssi_stream capture;
+
+       /* clock */
+       unsigned long audio_mck;
+       unsigned long audio_clk_1;
+       unsigned long audio_clk_2;
+
+       bool lrckp_fsync_fall;  /* LR clock polarity (SSICR.LRCKP) */
+       bool bckp_rise; /* Bit clock polarity (SSICR.BCKP) */
+       bool dma_rt;
+};
+
+static void rz_ssi_dma_complete(void *data);
+
+static void rz_ssi_reg_writel(struct rz_ssi_priv *priv, uint reg, u32 data)
+{
+       writel(data, (priv->base + reg));
+}
+
+static u32 rz_ssi_reg_readl(struct rz_ssi_priv *priv, uint reg)
+{
+       return readl(priv->base + reg);
+}
+
+static void rz_ssi_reg_mask_setl(struct rz_ssi_priv *priv, uint reg,
+                                u32 bclr, u32 bset)
+{
+       u32 val;
+
+       val = readl(priv->base + reg);
+       val = (val & ~bclr) | bset;
+       writel(val, (priv->base + reg));
+}
+
+static inline struct snd_soc_dai *
+rz_ssi_get_dai(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+
+       return asoc_rtd_to_cpu(rtd, 0);
+}
+
+static inline bool rz_ssi_stream_is_play(struct rz_ssi_priv *ssi,
+                                        struct snd_pcm_substream *substream)
+{
+       return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+}
+
+static inline struct rz_ssi_stream *
+rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream)
+{
+       struct rz_ssi_stream *stream = &ssi->playback;
+
+       if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+               stream = &ssi->capture;
+
+       return stream;
+}
+
+static inline bool rz_ssi_is_dma_enabled(struct rz_ssi_priv *ssi)
+{
+       return (ssi->playback.dma_ch && (ssi->dma_rt || ssi->capture.dma_ch));
+}
+
+static int rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi,
+                                 struct rz_ssi_stream *strm)
+{
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&ssi->lock, flags);
+       ret = !!(strm->substream && strm->substream->runtime);
+       spin_unlock_irqrestore(&ssi->lock, flags);
+
+       return ret;
+}
+
+static int rz_ssi_stream_init(struct rz_ssi_priv *ssi,
+                             struct rz_ssi_stream *strm,
+                             struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       strm->substream = substream;
+       strm->sample_width = samples_to_bytes(runtime, 1);
+       strm->dma_buffer_pos = 0;
+       strm->period_counter = 0;
+       strm->buffer_pos = 0;
+
+       strm->oerr_num = 0;
+       strm->uerr_num = 0;
+       strm->running = 0;
+
+       /* fifo init */
+       strm->fifo_sample_size = SSI_FIFO_DEPTH;
+
+       return 0;
+}
+
+static void rz_ssi_stream_quit(struct rz_ssi_priv *ssi,
+                              struct rz_ssi_stream *strm)
+{
+       struct snd_soc_dai *dai = rz_ssi_get_dai(strm->substream);
+       unsigned long flags;
+
+       spin_lock_irqsave(&ssi->lock, flags);
+       strm->substream = NULL;
+       spin_unlock_irqrestore(&ssi->lock, flags);
+
+       if (strm->oerr_num > 0)
+               dev_info(dai->dev, "overrun = %d\n", strm->oerr_num);
+
+       if (strm->uerr_num > 0)
+               dev_info(dai->dev, "underrun = %d\n", strm->uerr_num);
+}
+
+static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate,
+                           unsigned int channels)
+{
+       static s8 ckdv[16] = { 1,  2,  4,  8, 16, 32, 64, 128,
+                              6, 12, 24, 48, 96, -1, -1, -1 };
+       unsigned int channel_bits = 32; /* System Word Length */
+       unsigned long bclk_rate = rate * channels * channel_bits;
+       unsigned int div;
+       unsigned int i;
+       u32 ssicr = 0;
+       u32 clk_ckdv;
+
+       /* Clear AUCKE so we can set MST */
+       rz_ssi_reg_writel(ssi, SSIFCR, 0);
+
+       /* Continue to output LRCK pin even when idle */
+       rz_ssi_reg_writel(ssi, SSIOFR, SSIOFR_LRCONT);
+       if (ssi->audio_clk_1 && ssi->audio_clk_2) {
+               if (ssi->audio_clk_1 % bclk_rate)
+                       ssi->audio_mck = ssi->audio_clk_2;
+               else
+                       ssi->audio_mck = ssi->audio_clk_1;
+       }
+
+       /* Clock setting */
+       ssicr |= SSICR_MST;
+       if (ssi->audio_mck == ssi->audio_clk_1)
+               ssicr |= SSICR_CKS;
+       if (ssi->bckp_rise)
+               ssicr |= SSICR_BCKP;
+       if (ssi->lrckp_fsync_fall)
+               ssicr |= SSICR_LRCKP;
+
+       /* Determine the clock divider */
+       clk_ckdv = 0;
+       div = ssi->audio_mck / bclk_rate;
+       /* try to find an match */
+       for (i = 0; i < ARRAY_SIZE(ckdv); i++) {
+               if (ckdv[i] == div) {
+                       clk_ckdv = i;
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(ckdv)) {
+               dev_err(ssi->dev, "Rate not divisible by audio clock source\n");
+               return -EINVAL;
+       }
+
+       /*
+        * DWL: Data Word Length = 16 bits
+        * SWL: System Word Length = 32 bits
+        */
+       ssicr |= SSICR_CKDV(clk_ckdv);
+       ssicr |= SSICR_DWL(1) | SSICR_SWL(3);
+       rz_ssi_reg_writel(ssi, SSICR, ssicr);
+       rz_ssi_reg_writel(ssi, SSIFCR,
+                         (SSIFCR_AUCKE | SSIFCR_TFRST | SSIFCR_RFRST));
+
+       return 0;
+}
+
+static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
+{
+       bool is_play = rz_ssi_stream_is_play(ssi, strm->substream);
+       u32 ssicr, ssifcr;
+
+       ssicr = rz_ssi_reg_readl(ssi, SSICR);
+       ssifcr = rz_ssi_reg_readl(ssi, SSIFCR) & ~0xF;
+
+       /* FIFO interrupt thresholds */
+       if (rz_ssi_is_dma_enabled(ssi))
+               rz_ssi_reg_writel(ssi, SSISCR, 0);
+       else
+               rz_ssi_reg_writel(ssi, SSISCR,
+                                 SSISCR_TDES(strm->fifo_sample_size / 2 - 1) |
+                                 SSISCR_RDFS(0));
+
+       /* enable IRQ */
+       if (is_play) {
+               ssicr |= SSICR_TUIEN | SSICR_TOIEN;
+               ssifcr |= SSIFCR_TIE | SSIFCR_RFRST;
+       } else {
+               ssicr |= SSICR_RUIEN | SSICR_ROIEN;
+               ssifcr |= SSIFCR_RIE | SSIFCR_TFRST;
+       }
+
+       rz_ssi_reg_writel(ssi, SSICR, ssicr);
+       rz_ssi_reg_writel(ssi, SSIFCR, ssifcr);
+
+       /* Clear all error flags */
+       rz_ssi_reg_mask_setl(ssi, SSISR,
+                            (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ |
+                             SSISR_RUIRQ), 0);
+
+       strm->running = 1;
+       ssicr |= is_play ? SSICR_TEN : SSICR_REN;
+       rz_ssi_reg_writel(ssi, SSICR, ssicr);
+
+       return 0;
+}
+
+static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
+{
+       int timeout;
+
+       strm->running = 0;
+
+       /* Disable TX/RX */
+       rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0);
+
+       /* Cancel all remaining DMA transactions */
+       if (rz_ssi_is_dma_enabled(ssi))
+               dmaengine_terminate_async(strm->dma_ch);
+
+       /* Disable irqs */
+       rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN |
+                            SSICR_RUIEN | SSICR_ROIEN, 0);
+       rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_TIE | SSIFCR_RIE, 0);
+
+       /* Clear all error flags */
+       rz_ssi_reg_mask_setl(ssi, SSISR,
+                            (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ |
+                             SSISR_RUIRQ), 0);
+
+       /* Wait for idle */
+       timeout = 100;
+       while (--timeout) {
+               if (rz_ssi_reg_readl(ssi, SSISR) & SSISR_IIRQ)
+                       break;
+               udelay(1);
+       }
+
+       if (!timeout)
+               dev_info(ssi->dev, "timeout waiting for SSI idle\n");
+
+       /* Hold FIFOs in reset */
+       rz_ssi_reg_mask_setl(ssi, SSIFCR, 0,
+                            SSIFCR_TFRST | SSIFCR_RFRST);
+
+       return 0;
+}
+
+static void rz_ssi_pointer_update(struct rz_ssi_stream *strm, int frames)
+{
+       struct snd_pcm_substream *substream = strm->substream;
+       struct snd_pcm_runtime *runtime;
+       int current_period;
+
+       if (!strm->running || !substream || !substream->runtime)
+               return;
+
+       runtime = substream->runtime;
+       strm->buffer_pos += frames;
+       WARN_ON(strm->buffer_pos > runtime->buffer_size);
+
+       /* ring buffer */
+       if (strm->buffer_pos == runtime->buffer_size)
+               strm->buffer_pos = 0;
+
+       current_period = strm->buffer_pos / runtime->period_size;
+       if (strm->period_counter != current_period) {
+               snd_pcm_period_elapsed(strm->substream);
+               strm->period_counter = current_period;
+       }
+}
+
+static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
+{
+       struct snd_pcm_substream *substream = strm->substream;
+       struct snd_pcm_runtime *runtime;
+       u16 *buf;
+       int fifo_samples;
+       int frames_left;
+       int samples = 0;
+       int i;
+
+       if (!rz_ssi_stream_is_valid(ssi, strm))
+               return -EINVAL;
+
+       runtime = substream->runtime;
+       /* frames left in this period */
+       frames_left = runtime->period_size - (strm->buffer_pos %
+                                             runtime->period_size);
+       if (frames_left == 0)
+               frames_left = runtime->period_size;
+
+       /* Samples in RX FIFO */
+       fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >>
+                       SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK;
+
+       /* Only read full frames at a time */
+       while (frames_left && (fifo_samples >= runtime->channels)) {
+               samples += runtime->channels;
+               fifo_samples -= runtime->channels;
+               frames_left--;
+       }
+
+       /* not enough samples yet */
+       if (samples == 0)
+               return 0;
+
+       /* calculate new buffer index */
+       buf = (u16 *)(runtime->dma_area);
+       buf += strm->buffer_pos * runtime->channels;
+
+       /* Note, only supports 16-bit samples */
+       for (i = 0; i < samples; i++)
+               *buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16);
+
+       rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
+       rz_ssi_pointer_update(strm, samples / runtime->channels);
+
+       /*
+        * If we finished this period, but there are more samples in
+        * the RX FIFO, call this function again
+        */
+       if (frames_left == 0 && fifo_samples >= runtime->channels)
+               rz_ssi_pio_recv(ssi, strm);
+
+       return 0;
+}
+
+static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
+{
+       struct snd_pcm_substream *substream = strm->substream;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int sample_space;
+       int samples = 0;
+       int frames_left;
+       int i;
+       u32 ssifsr;
+       u16 *buf;
+
+       if (!rz_ssi_stream_is_valid(ssi, strm))
+               return -EINVAL;
+
+       /* frames left in this period */
+       frames_left = runtime->period_size - (strm->buffer_pos %
+                                             runtime->period_size);
+       if (frames_left == 0)
+               frames_left = runtime->period_size;
+
+       sample_space = strm->fifo_sample_size;
+       ssifsr = rz_ssi_reg_readl(ssi, SSIFSR);
+       sample_space -= (ssifsr >> SSIFSR_TDC_SHIFT) & SSIFSR_TDC_MASK;
+
+       /* Only add full frames at a time */
+       while (frames_left && (sample_space >= runtime->channels)) {
+               samples += runtime->channels;
+               sample_space -= runtime->channels;
+               frames_left--;
+       }
+
+       /* no space to send anything right now */
+       if (samples == 0)
+               return 0;
+
+       /* calculate new buffer index */
+       buf = (u16 *)(runtime->dma_area);
+       buf += strm->buffer_pos * runtime->channels;
+
+       /* Note, only supports 16-bit samples */
+       for (i = 0; i < samples; i++)
+               rz_ssi_reg_writel(ssi, SSIFTDR, ((u32)(*buf++) << 16));
+
+       rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_TDE, 0);
+       rz_ssi_pointer_update(strm, samples / runtime->channels);
+
+       return 0;
+}
+
+static irqreturn_t rz_ssi_interrupt(int irq, void *data)
+{
+       struct rz_ssi_stream *strm = NULL;
+       struct rz_ssi_priv *ssi = data;
+       u32 ssisr = rz_ssi_reg_readl(ssi, SSISR);
+
+       if (ssi->playback.substream)
+               strm = &ssi->playback;
+       else if (ssi->capture.substream)
+               strm = &ssi->capture;
+       else
+               return IRQ_HANDLED; /* Left over TX/RX interrupt */
+
+       if (irq == ssi->irq_int) { /* error or idle */
+               if (ssisr & SSISR_TUIRQ)
+                       strm->uerr_num++;
+               if (ssisr & SSISR_TOIRQ)
+                       strm->oerr_num++;
+               if (ssisr & SSISR_RUIRQ)
+                       strm->uerr_num++;
+               if (ssisr & SSISR_ROIRQ)
+                       strm->oerr_num++;
+
+               if (ssisr & (SSISR_TUIRQ | SSISR_TOIRQ | SSISR_RUIRQ |
+                            SSISR_ROIRQ)) {
+                       /* Error handling */
+                       /* You must reset (stop/restart) after each interrupt */
+                       rz_ssi_stop(ssi, strm);
+
+                       /* Clear all flags */
+                       rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ |
+                                            SSISR_TUIRQ | SSISR_ROIRQ |
+                                            SSISR_RUIRQ, 0);
+
+                       /* Add/remove more data */
+                       strm->transfer(ssi, strm);
+
+                       /* Resume */
+                       rz_ssi_start(ssi, strm);
+               }
+       }
+
+       if (!strm->running)
+               return IRQ_HANDLED;
+
+       /* tx data empty */
+       if (irq == ssi->irq_tx)
+               strm->transfer(ssi, &ssi->playback);
+
+       /* rx data full */
+       if (irq == ssi->irq_rx) {
+               strm->transfer(ssi, &ssi->capture);
+               rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int rz_ssi_dma_slave_config(struct rz_ssi_priv *ssi,
+                                  struct dma_chan *dma_ch, bool is_play)
+{
+       struct dma_slave_config cfg;
+
+       memset(&cfg, 0, sizeof(cfg));
+
+       cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+       cfg.dst_addr = ssi->phys + SSIFTDR;
+       cfg.src_addr = ssi->phys + SSIFRDR;
+       cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+       cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+
+       return dmaengine_slave_config(dma_ch, &cfg);
+}
+
+static int rz_ssi_dma_transfer(struct rz_ssi_priv *ssi,
+                              struct rz_ssi_stream *strm)
+{
+       struct snd_pcm_substream *substream = strm->substream;
+       struct dma_async_tx_descriptor *desc;
+       struct snd_pcm_runtime *runtime;
+       enum dma_transfer_direction dir;
+       u32 dma_paddr, dma_size;
+       int amount;
+
+       if (!rz_ssi_stream_is_valid(ssi, strm))
+               return -EINVAL;
+
+       runtime = substream->runtime;
+       if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+               /*
+                * Stream is ending, so do not queue up any more DMA
+                * transfers otherwise we play partial sound clips
+                * because we can't shut off the DMA quick enough.
+                */
+               return 0;
+
+       dir = rz_ssi_stream_is_play(ssi, substream) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+
+       /* Always transfer 1 period */
+       amount = runtime->period_size;
+
+       /* DMA physical address and size */
+       dma_paddr = runtime->dma_addr + frames_to_bytes(runtime,
+                                                       strm->dma_buffer_pos);
+       dma_size = frames_to_bytes(runtime, amount);
+       desc = dmaengine_prep_slave_single(strm->dma_ch, dma_paddr, dma_size,
+                                          dir,
+                                          DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+       if (!desc) {
+               dev_err(ssi->dev, "dmaengine_prep_slave_single() fail\n");
+               return -ENOMEM;
+       }
+
+       desc->callback = rz_ssi_dma_complete;
+       desc->callback_param = strm;
+
+       if (dmaengine_submit(desc) < 0) {
+               dev_err(ssi->dev, "dmaengine_submit() fail\n");
+               return -EIO;
+       }
+
+       /* Update DMA pointer */
+       strm->dma_buffer_pos += amount;
+       if (strm->dma_buffer_pos >= runtime->buffer_size)
+               strm->dma_buffer_pos = 0;
+
+       /* Start DMA */
+       dma_async_issue_pending(strm->dma_ch);
+
+       return 0;
+}
+
+static void rz_ssi_dma_complete(void *data)
+{
+       struct rz_ssi_stream *strm = (struct rz_ssi_stream *)data;
+
+       if (!strm->running || !strm->substream || !strm->substream->runtime)
+               return;
+
+       /* Note that next DMA transaction has probably already started */
+       rz_ssi_pointer_update(strm, strm->substream->runtime->period_size);
+
+       /* Queue up another DMA transaction */
+       rz_ssi_dma_transfer(strm->priv, strm);
+}
+
+static void rz_ssi_release_dma_channels(struct rz_ssi_priv *ssi)
+{
+       if (ssi->playback.dma_ch) {
+               dma_release_channel(ssi->playback.dma_ch);
+               ssi->playback.dma_ch = NULL;
+               if (ssi->dma_rt)
+                       ssi->dma_rt = false;
+       }
+
+       if (ssi->capture.dma_ch) {
+               dma_release_channel(ssi->capture.dma_ch);
+               ssi->capture.dma_ch = NULL;
+       }
+}
+
+static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev)
+{
+       ssi->playback.dma_ch = dma_request_chan(dev, "tx");
+       if (IS_ERR(ssi->playback.dma_ch))
+               ssi->playback.dma_ch = NULL;
+
+       ssi->capture.dma_ch = dma_request_chan(dev, "rx");
+       if (IS_ERR(ssi->capture.dma_ch))
+               ssi->capture.dma_ch = NULL;
+
+       if (!ssi->playback.dma_ch && !ssi->capture.dma_ch) {
+               ssi->playback.dma_ch = dma_request_chan(dev, "rt");
+               if (IS_ERR(ssi->playback.dma_ch)) {
+                       ssi->playback.dma_ch = NULL;
+                       goto no_dma;
+               }
+
+               ssi->dma_rt = true;
+       }
+
+       if (!rz_ssi_is_dma_enabled(ssi))
+               goto no_dma;
+
+       if (ssi->playback.dma_ch &&
+           (rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, true) < 0))
+               goto no_dma;
+
+       if (ssi->capture.dma_ch &&
+           (rz_ssi_dma_slave_config(ssi, ssi->capture.dma_ch, false) < 0))
+               goto no_dma;
+
+       return 0;
+
+no_dma:
+       rz_ssi_release_dma_channels(ssi);
+
+       return -ENODEV;
+}
+
+static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+                             struct snd_soc_dai *dai)
+{
+       struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+       struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
+       int ret = 0, i, num_transfer = 1;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               /* Soft Reset */
+               rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST);
+               rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0);
+               udelay(5);
+
+               ret = rz_ssi_stream_init(ssi, strm, substream);
+               if (ret)
+                       goto done;
+
+               if (ssi->dma_rt) {
+                       bool is_playback;
+
+                       is_playback = rz_ssi_stream_is_play(ssi, substream);
+                       ret = rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch,
+                                                     is_playback);
+                       /* Fallback to pio */
+                       if (ret < 0) {
+                               ssi->playback.transfer = rz_ssi_pio_send;
+                               ssi->capture.transfer = rz_ssi_pio_recv;
+                               rz_ssi_release_dma_channels(ssi);
+                       }
+               }
+
+               /* For DMA, queue up multiple DMA descriptors */
+               if (rz_ssi_is_dma_enabled(ssi))
+                       num_transfer = 4;
+
+               for (i = 0; i < num_transfer; i++) {
+                       ret = strm->transfer(ssi, strm);
+                       if (ret)
+                               goto done;
+               }
+
+               ret = rz_ssi_start(ssi, strm);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               rz_ssi_stop(ssi, strm);
+               rz_ssi_stream_quit(ssi, strm);
+               break;
+       }
+
+done:
+       return ret;
+}
+
+static int rz_ssi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+
+       switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
+       case SND_SOC_DAIFMT_CBC_CFC:
+               break;
+       default:
+               dev_err(ssi->dev, "Codec should be clk and frame consumer\n");
+               return -EINVAL;
+       }
+
+       /*
+        * set clock polarity
+        *
+        * "normal" BCLK = Signal is available at rising edge of BCLK
+        * "normal" FSYNC = (I2S) Left ch starts with falling FSYNC edge
+        */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               ssi->bckp_rise = false;
+               ssi->lrckp_fsync_fall = false;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               ssi->bckp_rise = false;
+               ssi->lrckp_fsync_fall = true;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               ssi->bckp_rise = true;
+               ssi->lrckp_fsync_fall = false;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               ssi->bckp_rise = true;
+               ssi->lrckp_fsync_fall = true;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* only i2s support */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               break;
+       default:
+               dev_err(ssi->dev, "Only I2S mode is supported.\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params,
+                               struct snd_soc_dai *dai)
+{
+       struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+       unsigned int sample_bits = hw_param_interval(params,
+                                       SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
+       unsigned int channels = params_channels(params);
+
+       if (sample_bits != 16) {
+               dev_err(ssi->dev, "Unsupported sample width: %d\n",
+                       sample_bits);
+               return -EINVAL;
+       }
+
+       if (channels != 2) {
+               dev_err(ssi->dev, "Number of channels not matched: %d\n",
+                       channels);
+               return -EINVAL;
+       }
+
+       return rz_ssi_clk_setup(ssi, params_rate(params),
+                               params_channels(params));
+}
+
+static const struct snd_soc_dai_ops rz_ssi_dai_ops = {
+       .trigger        = rz_ssi_dai_trigger,
+       .set_fmt        = rz_ssi_dai_set_fmt,
+       .hw_params      = rz_ssi_dai_hw_params,
+};
+
+static const struct snd_pcm_hardware rz_ssi_pcm_hardware = {
+       .info                   = SNDRV_PCM_INFO_INTERLEAVED    |
+                                 SNDRV_PCM_INFO_MMAP           |
+                                 SNDRV_PCM_INFO_MMAP_VALID,
+       .buffer_bytes_max       = PREALLOC_BUFFER,
+       .period_bytes_min       = 32,
+       .period_bytes_max       = 8192,
+       .channels_min           = SSI_CHAN_MIN,
+       .channels_max           = SSI_CHAN_MAX,
+       .periods_min            = 1,
+       .periods_max            = 32,
+       .fifo_size              = 32 * 2,
+};
+
+static int rz_ssi_pcm_open(struct snd_soc_component *component,
+                          struct snd_pcm_substream *substream)
+{
+       snd_soc_set_runtime_hwparams(substream, &rz_ssi_pcm_hardware);
+
+       return snd_pcm_hw_constraint_integer(substream->runtime,
+                                           SNDRV_PCM_HW_PARAM_PERIODS);
+}
+
+static snd_pcm_uframes_t rz_ssi_pcm_pointer(struct snd_soc_component *component,
+                                           struct snd_pcm_substream *substream)
+{
+       struct snd_soc_dai *dai = rz_ssi_get_dai(substream);
+       struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+       struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
+
+       return strm->buffer_pos;
+}
+
+static int rz_ssi_pcm_new(struct snd_soc_component *component,
+                         struct snd_soc_pcm_runtime *rtd)
+{
+       snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+                                      rtd->card->snd_card->dev,
+                                      PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
+       return 0;
+}
+
+static struct snd_soc_dai_driver rz_ssi_soc_dai[] = {
+       {
+               .name                   = "rz-ssi-dai",
+               .playback = {
+                       .rates          = SSI_RATES,
+                       .formats        = SSI_FMTS,
+                       .channels_min   = SSI_CHAN_MIN,
+                       .channels_max   = SSI_CHAN_MAX,
+               },
+               .capture = {
+                       .rates          = SSI_RATES,
+                       .formats        = SSI_FMTS,
+                       .channels_min   = SSI_CHAN_MIN,
+                       .channels_max   = SSI_CHAN_MAX,
+               },
+               .ops = &rz_ssi_dai_ops,
+       },
+};
+
+static const struct snd_soc_component_driver rz_ssi_soc_component = {
+       .name           = "rz-ssi",
+       .open           = rz_ssi_pcm_open,
+       .pointer        = rz_ssi_pcm_pointer,
+       .pcm_construct  = rz_ssi_pcm_new,
+};
+
+static int rz_ssi_probe(struct platform_device *pdev)
+{
+       struct rz_ssi_priv *ssi;
+       struct clk *audio_clk;
+       struct resource *res;
+       int ret;
+
+       ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL);
+       if (!ssi)
+               return -ENOMEM;
+
+       ssi->pdev = pdev;
+       ssi->dev = &pdev->dev;
+       ssi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+       if (IS_ERR(ssi->base))
+               return PTR_ERR(ssi->base);
+
+       ssi->phys = res->start;
+       ssi->clk = devm_clk_get(&pdev->dev, "ssi");
+       if (IS_ERR(ssi->clk))
+               return PTR_ERR(ssi->clk);
+
+       ssi->sfr_clk = devm_clk_get(&pdev->dev, "ssi_sfr");
+       if (IS_ERR(ssi->sfr_clk))
+               return PTR_ERR(ssi->sfr_clk);
+
+       audio_clk = devm_clk_get(&pdev->dev, "audio_clk1");
+       if (IS_ERR(audio_clk))
+               return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk),
+                                    "no audio clk1");
+
+       ssi->audio_clk_1 = clk_get_rate(audio_clk);
+       audio_clk = devm_clk_get(&pdev->dev, "audio_clk2");
+       if (IS_ERR(audio_clk))
+               return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk),
+                                    "no audio clk2");
+
+       ssi->audio_clk_2 = clk_get_rate(audio_clk);
+       if (!(ssi->audio_clk_1 || ssi->audio_clk_2))
+               return dev_err_probe(&pdev->dev, -EINVAL,
+                                    "no audio clk1 or audio clk2");
+
+       ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2;
+
+       /* Detect DMA support */
+       ret = rz_ssi_dma_request(ssi, &pdev->dev);
+       if (ret < 0) {
+               dev_warn(&pdev->dev, "DMA not available, using PIO\n");
+               ssi->playback.transfer = rz_ssi_pio_send;
+               ssi->capture.transfer = rz_ssi_pio_recv;
+       } else {
+               dev_info(&pdev->dev, "DMA enabled");
+               ssi->playback.transfer = rz_ssi_dma_transfer;
+               ssi->capture.transfer = rz_ssi_dma_transfer;
+       }
+
+       ssi->playback.priv = ssi;
+       ssi->capture.priv = ssi;
+
+       /* Error Interrupt */
+       ssi->irq_int = platform_get_irq_byname(pdev, "int_req");
+       if (ssi->irq_int < 0)
+               return dev_err_probe(&pdev->dev, -ENODEV,
+                                    "Unable to get SSI int_req IRQ\n");
+
+       ret = devm_request_irq(&pdev->dev, ssi->irq_int, &rz_ssi_interrupt,
+                              0, dev_name(&pdev->dev), ssi);
+       if (ret < 0)
+               return dev_err_probe(&pdev->dev, ret,
+                                    "irq request error (int_req)\n");
+
+       if (!rz_ssi_is_dma_enabled(ssi)) {
+               /* Tx and Rx interrupts (pio only) */
+               ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx");
+               if (ssi->irq_tx < 0)
+                       return dev_err_probe(&pdev->dev, -ENODEV,
+                                            "Unable to get SSI dma_tx IRQ\n");
+
+               ret = devm_request_irq(&pdev->dev, ssi->irq_tx,
+                                      &rz_ssi_interrupt, 0,
+                                      dev_name(&pdev->dev), ssi);
+               if (ret < 0)
+                       return dev_err_probe(&pdev->dev, ret,
+                                            "irq request error (dma_tx)\n");
+
+               ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx");
+               if (ssi->irq_rx < 0)
+                       return dev_err_probe(&pdev->dev, -ENODEV,
+                                            "Unable to get SSI dma_rx IRQ\n");
+
+               ret = devm_request_irq(&pdev->dev, ssi->irq_rx,
+                                      &rz_ssi_interrupt, 0,
+                                      dev_name(&pdev->dev), ssi);
+               if (ret < 0)
+                       return dev_err_probe(&pdev->dev, ret,
+                                            "irq request error (dma_rx)\n");
+       }
+
+       ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+       if (IS_ERR(ssi->rstc))
+               return PTR_ERR(ssi->rstc);
+
+       reset_control_deassert(ssi->rstc);
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_resume_and_get(&pdev->dev);
+
+       spin_lock_init(&ssi->lock);
+       dev_set_drvdata(&pdev->dev, ssi);
+       ret = devm_snd_soc_register_component(&pdev->dev, &rz_ssi_soc_component,
+                                             rz_ssi_soc_dai,
+                                             ARRAY_SIZE(rz_ssi_soc_dai));
+       if (ret < 0) {
+               rz_ssi_release_dma_channels(ssi);
+
+               pm_runtime_put(ssi->dev);
+               pm_runtime_disable(ssi->dev);
+               reset_control_assert(ssi->rstc);
+               dev_err(&pdev->dev, "failed to register snd component\n");
+       }
+
+       return ret;
+}
+
+static int rz_ssi_remove(struct platform_device *pdev)
+{
+       struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev);
+
+       rz_ssi_release_dma_channels(ssi);
+
+       pm_runtime_put(ssi->dev);
+       pm_runtime_disable(ssi->dev);
+       reset_control_assert(ssi->rstc);
+
+       return 0;
+}
+
+static const struct of_device_id rz_ssi_of_match[] = {
+       { .compatible = "renesas,rz-ssi", },
+       {/* Sentinel */},
+};
+MODULE_DEVICE_TABLE(of, rz_ssi_of_match);
+
+static struct platform_driver rz_ssi_driver = {
+       .driver = {
+               .name   = "rz-ssi-pcm-audio",
+               .of_match_table = rz_ssi_of_match,
+       },
+       .probe          = rz_ssi_probe,
+       .remove         = rz_ssi_remove,
+};
+
+module_platform_driver(rz_ssi_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas RZ/G2L ASoC Serial Sound Interface Driver");
+MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
index 65db083..5f49e3d 100644 (file)
@@ -34,14 +34,6 @@ struct snd_ac97_reset_cfg {
        int gpio_reset;
 };
 
-struct snd_ac97_gpio_priv {
-#ifdef CONFIG_GPIOLIB
-       struct gpio_chip gpio_chip;
-#endif
-       unsigned int gpios_set;
-       struct snd_soc_component *component;
-};
-
 static struct snd_ac97_bus soc_ac97_bus = {
        .ops = NULL, /* Gets initialized in snd_soc_set_ac97_ops() */
 };
@@ -52,6 +44,12 @@ static void soc_ac97_device_release(struct device *dev)
 }
 
 #ifdef CONFIG_GPIOLIB
+struct snd_ac97_gpio_priv {
+       struct gpio_chip gpio_chip;
+       unsigned int gpios_set;
+       struct snd_soc_component *component;
+};
+
 static inline struct snd_soc_component *gpio_to_component(struct gpio_chip *chip)
 {
        struct snd_ac97_gpio_priv *gpio_priv = gpiochip_get_data(chip);
index c8dfd0d..8e8d917 100644 (file)
@@ -1171,10 +1171,10 @@ int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,
                                         void *stream)
 {
        struct snd_soc_component *component;
-       int i, ret;
+       int i;
 
        for_each_rtd_components(rtd, i, component) {
-               ret = pm_runtime_get_sync(component->dev);
+               int ret = pm_runtime_get_sync(component->dev);
                if (ret < 0 && ret != -EACCES) {
                        pm_runtime_put_noidle(component->dev);
                        return soc_component_ret(component, ret);
index b4f5935..3606080 100644 (file)
@@ -604,7 +604,6 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
                break;
        }
 
-       mutex_init(&compr->lock);
        ret = snd_compress_new(rtd->card->snd_card, num, direction,
                                new_name, compr);
        if (ret < 0) {
index 583f238..c830e96 100644 (file)
@@ -1718,7 +1718,7 @@ static void append_dmi_string(struct snd_soc_card *card, const char *str)
  */
 int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
 {
-       const char *vendor, *product, *product_version, *board;
+       const char *vendor, *product, *board;
 
        if (card->long_name)
                return 0; /* long name already set by driver or from DMI */
@@ -1738,13 +1738,14 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
 
        product = dmi_get_system_info(DMI_PRODUCT_NAME);
        if (product && is_dmi_valid(product)) {
+               const char *product_version = dmi_get_system_info(DMI_PRODUCT_VERSION);
+
                append_dmi_string(card, product);
 
                /*
                 * some vendors like Lenovo may only put a self-explanatory
                 * name in the product version field
                 */
-               product_version = dmi_get_system_info(DMI_PRODUCT_VERSION);
                if (product_version && is_dmi_valid(product_version))
                        append_dmi_string(card, product_version);
        }
@@ -2236,13 +2237,12 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
        const struct snd_kcontrol_new *controls, int num_controls,
        const char *prefix, void *data)
 {
-       int err, i;
+       int i;
 
        for (i = 0; i < num_controls; i++) {
                const struct snd_kcontrol_new *control = &controls[i];
-
-               err = snd_ctl_add(card, snd_soc_cnew(control, data,
-                                                    control->name, prefix));
+               int err = snd_ctl_add(card, snd_soc_cnew(control, data,
+                                                        control->name, prefix));
                if (err < 0) {
                        dev_err(dev, "ASoC: Failed to add %s: %d\n",
                                control->name, err);
@@ -2716,11 +2716,10 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_component_by_driver);
  */
 void snd_soc_unregister_component(struct device *dev)
 {
-       struct snd_soc_component *component;
-
        mutex_lock(&client_mutex);
        while (1) {
-               component = snd_soc_lookup_component_nolocked(dev, NULL);
+               struct snd_soc_component *component = snd_soc_lookup_component_nolocked(dev, NULL);
+
                if (!component)
                        break;
 
@@ -2774,7 +2773,7 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
        struct device_node *np = card->dev->of_node;
        struct snd_soc_dapm_widget *widgets;
        const char *template, *wname;
-       int i, j, num_widgets, ret;
+       int i, j, num_widgets;
 
        num_widgets = of_property_count_strings(np, propname);
        if (num_widgets < 0) {
@@ -2804,8 +2803,8 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
        }
 
        for (i = 0; i < num_widgets; i++) {
-               ret = of_property_read_string_index(np, propname,
-                       2 * i, &template);
+               int ret = of_property_read_string_index(np, propname,
+                                                       2 * i, &template);
                if (ret) {
                        dev_err(card->dev,
                                "ASoC: Property '%s' index %d read error:%d\n",
@@ -2928,7 +2927,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
        struct device_node *np = card->dev->of_node;
        int num_routes;
        struct snd_soc_dapm_route *routes;
-       int i, ret;
+       int i;
 
        num_routes = of_property_count_strings(np, propname);
        if (num_routes < 0 || num_routes & 1) {
@@ -2948,8 +2947,8 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
        }
 
        for (i = 0; i < num_routes; i++) {
-               ret = of_property_read_string_index(np, propname,
-                       2 * i, &routes[i].sink);
+               int ret = of_property_read_string_index(np, propname,
+                                                       2 * i, &routes[i].sink);
                if (ret) {
                        dev_err(card->dev,
                                "ASoC: Property '%s' index %d could not be read: %d\n",
@@ -3053,7 +3052,7 @@ EXPORT_SYMBOL_GPL(snd_soc_daifmt_clock_provider_from_bitmap);
 unsigned int snd_soc_daifmt_parse_format(struct device_node *np,
                                         const char *prefix)
 {
-       int ret, i;
+       int ret;
        char prop[128];
        unsigned int format = 0;
        int bit, frame;
@@ -3087,6 +3086,8 @@ unsigned int snd_soc_daifmt_parse_format(struct device_node *np,
                ret = of_property_read_string(np, prop, &str);
        }
        if (ret == 0) {
+               int i;
+
                for (i = 0; i < ARRAY_SIZE(of_fmt_table); i++) {
                        if (strcmp(str, of_fmt_table[i].name) == 0) {
                                format |= of_fmt_table[i].val;
@@ -3200,12 +3201,11 @@ int snd_soc_get_dai_name(const struct of_phandle_args *args,
                                const char **dai_name)
 {
        struct snd_soc_component *pos;
-       struct device_node *component_of_node;
        int ret = -EPROBE_DEFER;
 
        mutex_lock(&client_mutex);
        for_each_component(pos) {
-               component_of_node = soc_component_to_node(pos);
+               struct device_node *component_of_node = soc_component_to_node(pos);
 
                if (component_of_node != args->np)
                        continue;
index a56dcc8..3db0fcf 100644 (file)
@@ -492,18 +492,16 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir)
  */
 void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link)
 {
-       struct snd_soc_dai_link_component *cpu;
-       struct snd_soc_dai_link_component *codec;
-       struct snd_soc_dai *dai;
        bool supported[SNDRV_PCM_STREAM_LAST + 1];
-       bool supported_cpu;
-       bool supported_codec;
        int direction;
-       int i;
 
        for_each_pcm_streams(direction) {
-               supported_cpu = false;
-               supported_codec = false;
+               struct snd_soc_dai_link_component *cpu;
+               struct snd_soc_dai_link_component *codec;
+               struct snd_soc_dai *dai;
+               bool supported_cpu = false;
+               bool supported_codec = false;
+               int i;
 
                for_each_link_cpus(dai_link, i, cpu) {
                        dai = snd_soc_find_dai_with_mutex(cpu);
@@ -597,11 +595,11 @@ int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order)
 int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_dai *dai;
-       int i, ret = 0;
+       int i;
 
        for_each_rtd_dais(rtd, i, dai) {
                if (dai->driver->pcm_new) {
-                       ret = dai->driver->pcm_new(rtd, dai);
+                       int ret = dai->driver->pcm_new(rtd, dai);
                        if (ret < 0)
                                return soc_dai_ret(dai, ret);
                }
index 91bf939..7b67f1e 100644 (file)
@@ -650,12 +650,11 @@ static struct snd_soc_dapm_widget *
 dapm_wcache_lookup(struct snd_soc_dapm_wcache *wcache, const char *name)
 {
        struct snd_soc_dapm_widget *w = wcache->widget;
-       struct list_head *wlist;
-       const int depth = 2;
-       int i = 0;
 
        if (w) {
-               wlist = &w->dapm->card->widgets;
+               struct list_head *wlist = &w->dapm->card->widgets;
+               const int depth = 2;
+               int i = 0;
 
                list_for_each_entry_from(w, wlist, list) {
                        if (!strcmp(name, w->name))
@@ -748,10 +747,11 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
 {
        const struct snd_kcontrol_new *kcontrol = &w->kcontrol_news[0];
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-       unsigned int val, item;
+       unsigned int item;
        int i;
 
        if (e->reg != SND_SOC_NOPM) {
+               unsigned int val;
                val = soc_dapm_read(dapm, e->reg);
                val = (val >> e->shift_l) & e->mask;
                item = snd_soc_enum_val_to_item(e, val);
@@ -782,14 +782,14 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i,
        struct soc_mixer_control *mc = (struct soc_mixer_control *)
                p->sink->kcontrol_news[i].private_value;
        unsigned int reg = mc->reg;
-       unsigned int shift = mc->shift;
-       unsigned int max = mc->max;
-       unsigned int mask = (1 << fls(max)) - 1;
        unsigned int invert = mc->invert;
-       unsigned int val;
 
        if (reg != SND_SOC_NOPM) {
-               val = soc_dapm_read(p->sink->dapm, reg);
+               unsigned int shift = mc->shift;
+               unsigned int max = mc->max;
+               unsigned int mask = (1 << fls(max)) - 1;
+               unsigned int val = soc_dapm_read(p->sink->dapm, reg);
+
                /*
                 * The nth_path argument allows this function to know
                 * which path of a kcontrol it is setting the initial
@@ -1060,10 +1060,10 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
 /* create new dapm volume control */
 static int dapm_new_pga(struct snd_soc_dapm_widget *w)
 {
-       int i, ret;
+       int i;
 
        for (i = 0; i < w->num_kcontrols; i++) {
-               ret = dapm_create_or_share_kcontrol(w, i);
+               int ret = dapm_create_or_share_kcontrol(w, i);
                if (ret < 0)
                        return ret;
        }
@@ -1074,10 +1074,7 @@ static int dapm_new_pga(struct snd_soc_dapm_widget *w)
 /* create new dapm dai link control */
 static int dapm_new_dai_link(struct snd_soc_dapm_widget *w)
 {
-       int i, ret;
-       struct snd_kcontrol *kcontrol;
-       struct snd_soc_dapm_context *dapm = w->dapm;
-       struct snd_card *card = dapm->card->snd_card;
+       int i;
        struct snd_soc_pcm_runtime *rtd = w->priv;
 
        /* create control for links with > 1 config */
@@ -1086,9 +1083,12 @@ static int dapm_new_dai_link(struct snd_soc_dapm_widget *w)
 
        /* add kcontrol */
        for (i = 0; i < w->num_kcontrols; i++) {
-               kcontrol = snd_soc_cnew(&w->kcontrol_news[i], w,
-                                       w->name, NULL);
-               ret = snd_ctl_add(card, kcontrol);
+               struct snd_soc_dapm_context *dapm = w->dapm;
+               struct snd_card *card = dapm->card->snd_card;
+               struct snd_kcontrol *kcontrol = snd_soc_cnew(&w->kcontrol_news[i],
+                                                            w, w->name, NULL);
+               int ret = snd_ctl_add(card, kcontrol);
+
                if (ret < 0) {
                        dev_err(dapm->dev,
                                "ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
@@ -1528,7 +1528,7 @@ static void dapm_seq_check_event(struct snd_soc_card *card,
                                 struct snd_soc_dapm_widget *w, int event)
 {
        const char *ev_name;
-       int power, ret;
+       int power;
 
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
@@ -1564,6 +1564,8 @@ static void dapm_seq_check_event(struct snd_soc_card *card,
                return;
 
        if (w->event && (w->event_flags & event)) {
+               int ret;
+
                pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
                        w->name, ev_name);
                soc_dapm_async_complete(w->dapm);
@@ -1645,7 +1647,7 @@ static void dapm_seq_run(struct snd_soc_card *card,
        int cur_subseq = -1;
        int cur_reg = SND_SOC_NOPM;
        struct snd_soc_dapm_context *cur_dapm = NULL;
-       int ret, i;
+       int i;
        int *sort;
 
        if (power_up)
@@ -1654,7 +1656,7 @@ static void dapm_seq_run(struct snd_soc_card *card,
                sort = dapm_down_seq;
 
        list_for_each_entry_safe(w, n, list, power_list) {
-               ret = 0;
+               int ret = 0;
 
                /* Do we need to apply any queued changes? */
                if (sort[w->id] != cur_sort || w->reg != cur_reg ||
@@ -3004,7 +3006,6 @@ err:
 static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
                                  const struct snd_soc_dapm_route *route)
 {
-       struct snd_soc_dapm_widget *wsource, *wsink;
        struct snd_soc_dapm_path *path, *p;
        const char *sink;
        const char *source;
@@ -3042,8 +3043,8 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
        }
 
        if (path) {
-               wsource = path->source;
-               wsink = path->sink;
+               struct snd_soc_dapm_widget *wsource = path->source;
+               struct snd_soc_dapm_widget *wsink = path->sink;
 
                dapm_mark_dirty(wsource, "Route removed");
                dapm_mark_dirty(wsink, "Route removed");
@@ -3079,11 +3080,11 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
 int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
                            const struct snd_soc_dapm_route *route, int num)
 {
-       int i, r, ret = 0;
+       int i, ret = 0;
 
        mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
        for (i = 0; i < num; i++) {
-               r = snd_soc_dapm_add_route(dapm, route);
+               int r = snd_soc_dapm_add_route(dapm, route);
                if (r < 0) {
                        dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n",
                                route->source,
@@ -3187,12 +3188,12 @@ static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,
 int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
                             const struct snd_soc_dapm_route *route, int num)
 {
-       int i, err;
+       int i;
        int ret = 0;
 
        mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
        for (i = 0; i < num; i++) {
-               err = snd_soc_dapm_weak_route(dapm, route);
+               int err = snd_soc_dapm_weak_route(dapm, route);
                if (err)
                        ret = err;
                route++;
@@ -3783,13 +3784,12 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
        const struct snd_soc_dapm_widget *widget,
        int num)
 {
-       struct snd_soc_dapm_widget *w;
        int i;
        int ret = 0;
 
        mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
        for (i = 0; i < num; i++) {
-               w = snd_soc_dapm_new_control_unlocked(dapm, widget);
+               struct snd_soc_dapm_widget *w = snd_soc_dapm_new_control_unlocked(dapm, widget);
                if (IS_ERR(w)) {
                        ret = PTR_ERR(w);
                        break;
@@ -4365,11 +4365,12 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
        int event)
 {
        struct snd_soc_dapm_widget *w;
-       unsigned int ep;
 
        w = snd_soc_dai_get_widget(dai, stream);
 
        if (w) {
+               unsigned int ep;
+
                dapm_mark_dirty(w, "stream event");
 
                if (w->id == snd_soc_dapm_dai_in) {
index 9ef80a4..4aa48c7 100644 (file)
@@ -79,7 +79,6 @@ static int dmaengine_pcm_hw_params(struct snd_soc_component *component,
                        struct snd_pcm_hw_params *params,
                        struct dma_slave_config *slave_config);
        struct dma_slave_config slave_config;
-       int ret;
 
        memset(&slave_config, 0, sizeof(slave_config));
 
@@ -89,7 +88,7 @@ static int dmaengine_pcm_hw_params(struct snd_soc_component *component,
                prepare_slave_config = pcm->config->prepare_slave_config;
 
        if (prepare_slave_config) {
-               ret = prepare_slave_config(substream, params, &slave_config);
+               int ret = prepare_slave_config(substream, params, &slave_config);
                if (ret)
                        return ret;
 
@@ -230,7 +229,6 @@ static int dmaengine_pcm_new(struct snd_soc_component *component,
        struct dmaengine_pcm *pcm = soc_component_to_pcm(component);
        const struct snd_dmaengine_pcm_config *config = pcm->config;
        struct device *dev = component->dev;
-       struct snd_pcm_substream *substream;
        size_t prealloc_buffer_size;
        size_t max_buffer_size;
        unsigned int i;
@@ -244,7 +242,7 @@ static int dmaengine_pcm_new(struct snd_soc_component *component,
        }
 
        for_each_pcm_streams(i) {
-               substream = rtd->pcm->streams[i].substream;
+               struct snd_pcm_substream *substream = rtd->pcm->streams[i].substream;
                if (!substream)
                        continue;
 
@@ -307,14 +305,13 @@ static int dmaengine_copy_user(struct snd_soc_component *component,
        bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
        void *dma_ptr = runtime->dma_area + hwoff +
                        channel * (runtime->dma_bytes / runtime->channels);
-       int ret;
 
        if (is_playback)
                if (copy_from_user(dma_ptr, buf, bytes))
                        return -EFAULT;
 
        if (process) {
-               ret = process(substream, channel, hwoff, (__force void *)buf, bytes);
+               int ret = process(substream, channel, hwoff, (__force void *)buf, bytes);
                if (ret < 0)
                        return ret;
        }
index 0f1820f..d798765 100644 (file)
 #include <linux/suspend.h>
 #include <trace/events/asoc.h>
 
-struct jack_gpio_tbl {
-       int count;
-       struct snd_soc_jack *jack;
-       struct snd_soc_jack_gpio *gpios;
-};
-
 /**
  * snd_soc_jack_report - Report the current status for a jack
  *
@@ -42,7 +36,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
        struct snd_soc_dapm_context *dapm;
        struct snd_soc_jack_pin *pin;
        unsigned int sync = 0;
-       int enable;
 
        if (!jack)
                return;
@@ -58,7 +51,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
        trace_snd_soc_jack_notify(jack, status);
 
        list_for_each_entry(pin, &jack->pins, list) {
-               enable = pin->mask & jack->status;
+               int enable = pin->mask & jack->status;
 
                if (pin->invert)
                        enable = !enable;
@@ -208,6 +201,12 @@ void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack,
 EXPORT_SYMBOL_GPL(snd_soc_jack_notifier_unregister);
 
 #ifdef CONFIG_GPIOLIB
+struct jack_gpio_tbl {
+       int count;
+       struct snd_soc_jack *jack;
+       struct snd_soc_jack_gpio *gpios;
+};
+
 /* gpio detect */
 static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
 {
index 5852724..08eaa9d 100644 (file)
@@ -407,7 +407,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
        int min = mc->min;
        unsigned int mask = (1U << (fls(min + max) - 1)) - 1;
        int err = 0;
-       unsigned int val, val_mask, val2;
+       unsigned int val, val_mask;
 
        val_mask = mask << shift;
        val = (ucontrol->value.integer.value[0] + min) & mask;
@@ -418,6 +418,8 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
                return err;
 
        if (snd_soc_volsw_is_stereo(mc)) {
+               unsigned int val2;
+
                val_mask = mask << rshift;
                val2 = (ucontrol->value.integer.value[1] + min) & mask;
                val2 = val2 << rshift;
@@ -573,7 +575,6 @@ int snd_soc_limit_volume(struct snd_soc_card *card,
        const char *name, int max)
 {
        struct snd_kcontrol *kctl;
-       struct soc_mixer_control *mc;
        int ret = -EINVAL;
 
        /* Sanity check for name and max */
@@ -582,7 +583,7 @@ int snd_soc_limit_volume(struct snd_soc_card *card,
 
        kctl = snd_soc_card_get_kcontrol(card, name);
        if (kctl) {
-               mc = (struct soc_mixer_control *)kctl->private_value;
+               struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
                if (max <= mc->max) {
                        mc->platform_max = max;
                        ret = 0;
@@ -811,11 +812,10 @@ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
        long min = mc->min;
        long max = mc->max;
        long val = 0;
-       unsigned int regval;
        unsigned int i;
 
        for (i = 0; i < regcount; i++) {
-               regval = snd_soc_component_read(component, regbase+i);
+               unsigned int regval = snd_soc_component_read(component, regbase+i);
                val |= (regval & regwmask) << (regwshift*(regcount-i-1));
        }
        val &= mask;
@@ -856,17 +856,16 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
        unsigned long mask = (1UL<<mc->nbits)-1;
        long max = mc->max;
        long val = ucontrol->value.integer.value[0];
-       unsigned int i, regval, regmask;
-       int err;
+       unsigned int i;
 
        if (invert)
                val = max - val;
        val &= mask;
        for (i = 0; i < regcount; i++) {
-               regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
-               regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
-               err = snd_soc_component_update_bits(component, regbase+i,
-                               regmask, regval);
+               unsigned int regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
+               unsigned int regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
+               int err = snd_soc_component_update_bits(component, regbase+i,
+                                                       regmask, regval);
                if (err < 0)
                        return err;
        }
index d1c570c..48f71bb 100644 (file)
@@ -449,13 +449,12 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
        struct snd_soc_dai *cpu_dai;
        struct snd_soc_dai *codec_dai;
-       struct snd_soc_pcm_stream *pcm_codec, *pcm_cpu;
        int stream = substream->stream;
        int i;
        unsigned int bits = 0, cpu_bits = 0;
 
        for_each_rtd_codec_dais(rtd, i, codec_dai) {
-               pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream);
+               struct snd_soc_pcm_stream *pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream);
 
                if (pcm_codec->sig_bits == 0) {
                        bits = 0;
@@ -465,7 +464,7 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
        }
 
        for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
-               pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream);
+               struct snd_soc_pcm_stream *pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream);
 
                if (pcm_cpu->sig_bits == 0) {
                        cpu_bits = 0;
@@ -634,10 +633,10 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
        struct snd_soc_component *component;
-       int i, r, ret = 0;
+       int i, ret = 0;
 
        for_each_rtd_components(rtd, i, component) {
-               r = snd_soc_component_close(component, substream, rollback);
+               int r = snd_soc_component_close(component, substream, rollback);
                if (r < 0)
                        ret = r; /* use last ret */
 
@@ -1318,13 +1317,12 @@ void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
 static bool dpcm_be_is_active(struct snd_soc_dpcm *dpcm, int stream,
                              struct snd_soc_dapm_widget_list *list)
 {
-       struct snd_soc_dapm_widget *widget;
        struct snd_soc_dai *dai;
        unsigned int i;
 
        /* is there a valid DAI widget for this BE */
        for_each_rtd_dais(dpcm->be, i, dai) {
-               widget = snd_soc_dai_get_widget(dai, stream);
+               struct snd_soc_dapm_widget *widget = snd_soc_dai_get_widget(dai, stream);
 
                /*
                 * The BE is pruned only if none of the dai
@@ -1637,7 +1635,6 @@ static void dpcm_runtime_setup_be_chan(struct snd_pcm_substream *substream)
 
        for_each_dpcm_be(fe, stream, dpcm) {
                struct snd_soc_pcm_runtime *be = dpcm->be;
-               struct snd_soc_pcm_stream *codec_stream;
                struct snd_soc_pcm_stream *cpu_stream;
                struct snd_soc_dai *dai;
                int i;
@@ -1660,7 +1657,8 @@ static void dpcm_runtime_setup_be_chan(struct snd_pcm_substream *substream)
                 * DAIs connected to a single CPU DAI, use CPU DAI's directly
                 */
                if (be->num_codecs == 1) {
-                       codec_stream = snd_soc_dai_get_pcm_stream(asoc_rtd_to_codec(be, 0), stream);
+                       struct snd_soc_pcm_stream *codec_stream = snd_soc_dai_get_pcm_stream(
+                               asoc_rtd_to_codec(be, 0), stream);
 
                        soc_pcm_hw_update_chan(hw, codec_stream);
                }
@@ -2591,9 +2589,7 @@ open_end:
 static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
                                    int *playback, int *capture)
 {
-       struct snd_soc_dai *codec_dai;
        struct snd_soc_dai *cpu_dai;
-       int stream;
        int i;
 
        if (rtd->dai_link->dynamic && rtd->num_cpus > 1) {
@@ -2603,6 +2599,8 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
        }
 
        if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
+               int stream;
+
                if (rtd->dai_link->dpcm_playback) {
                        stream = SNDRV_PCM_STREAM_PLAYBACK;
 
@@ -2637,6 +2635,8 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
                        }
                }
        } else {
+               struct snd_soc_dai *codec_dai;
+
                /* Adapt stream for codec2codec links */
                int cpu_capture = rtd->dai_link->params ?
                        SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
index 0a24d0d..f6e5ac3 100644 (file)
@@ -1035,7 +1035,6 @@ err_denum:
 static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
        struct snd_soc_tplg_hdr *hdr)
 {
-       struct snd_soc_tplg_ctl_hdr *control_hdr;
        int ret;
        int i;
 
@@ -1043,8 +1042,7 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
                soc_tplg_get_offset(tplg));
 
        for (i = 0; i < le32_to_cpu(hdr->count); i++) {
-
-               control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
+               struct snd_soc_tplg_ctl_hdr *control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
 
                if (le32_to_cpu(control_hdr->size) != sizeof(*control_hdr)) {
                        dev_err(tplg->dev, "ASoC: invalid control size\n");
@@ -1583,15 +1581,16 @@ err:
 static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg,
        struct snd_soc_tplg_hdr *hdr)
 {
-       struct snd_soc_tplg_dapm_widget *widget;
-       int ret, count, i;
+       int count, i;
 
        count = le32_to_cpu(hdr->count);
 
        dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count);
 
        for (i = 0; i < count; i++) {
-               widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos;
+               struct snd_soc_tplg_dapm_widget *widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos;
+               int ret;
+
                if (le32_to_cpu(widget->size) != sizeof(*widget)) {
                        dev_err(tplg->dev, "ASoC: invalid widget size\n");
                        return -EINVAL;
@@ -2125,10 +2124,9 @@ static struct snd_soc_dai_link *snd_soc_find_dai_link(struct snd_soc_card *card,
                                                      const char *stream_name)
 {
        struct snd_soc_pcm_runtime *rtd;
-       struct snd_soc_dai_link *link;
 
        for_each_card_rtds(card, rtd) {
-               link = rtd->dai_link;
+               struct snd_soc_dai_link *link = rtd->dai_link;
 
                if (link->id != id)
                        continue;
@@ -2346,15 +2344,16 @@ err:
 static int soc_tplg_dai_elems_load(struct soc_tplg *tplg,
                                   struct snd_soc_tplg_hdr *hdr)
 {
-       struct snd_soc_tplg_dai *dai;
        int count;
-       int i, ret;
+       int i;
 
        count = le32_to_cpu(hdr->count);
 
        /* config the existing BE DAIs */
        for (i = 0; i < count; i++) {
-               dai = (struct snd_soc_tplg_dai *)tplg->pos;
+               struct snd_soc_tplg_dai *dai = (struct snd_soc_tplg_dai *)tplg->pos;
+               int ret;
+
                if (le32_to_cpu(dai->size) != sizeof(*dai)) {
                        dev_err(tplg->dev, "ASoC: invalid physical DAI size\n");
                        return -EINVAL;
@@ -2572,13 +2571,13 @@ static int soc_tplg_load_header(struct soc_tplg *tplg,
 /* process the topology file headers */
 static int soc_tplg_process_headers(struct soc_tplg *tplg)
 {
-       struct snd_soc_tplg_hdr *hdr;
        int ret;
 
        tplg->pass = SOC_TPLG_PASS_START;
 
        /* process the header types from start to end */
        while (tplg->pass <= SOC_TPLG_PASS_END) {
+               struct snd_soc_tplg_hdr *hdr;
 
                tplg->hdr_pos = tplg->fw->data;
                hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos;
index 4447f51..88b6176 100644 (file)
@@ -249,16 +249,6 @@ config SND_SOC_SOF_HDA_PROBES
          Say Y if you want to enable probes.
          If unsure, select "N".
 
-config SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1
-       bool "SOF enable DMI Link L1"
-       help
-         This option enables DMI L1 for both playback and capture
-         and disables known workarounds for specific HDAudio platforms.
-         Only use to look into power optimizations on platforms not
-         affected by DMI L1 issues. This option is not recommended.
-         Say Y if you want to enable DMI Link L1.
-         If unsure, select "N".
-
 endif ## SND_SOC_SOF_HDA_COMMON
 
 config SND_SOC_SOF_HDA_LINK_BASELINE
index 821f25f..e115e12 100644 (file)
@@ -347,6 +347,9 @@ const struct sof_intel_dsp_desc cnl_chip_info = {
        .rom_init_timeout       = 300,
        .ssp_count = CNL_SSP_COUNT,
        .ssp_base_offset = CNL_SSP_BASE_OFFSET,
+       .sdw_shim_base = SDW_SHIM_BASE,
+       .sdw_alh_base = SDW_ALH_BASE,
+       .check_sdw_irq  = hda_common_check_sdw_irq,
 };
 EXPORT_SYMBOL_NS(cnl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
 
@@ -363,5 +366,8 @@ const struct sof_intel_dsp_desc jsl_chip_info = {
        .rom_init_timeout       = 300,
        .ssp_count = ICL_SSP_COUNT,
        .ssp_base_offset = CNL_SSP_BASE_OFFSET,
+       .sdw_shim_base = SDW_SHIM_BASE,
+       .sdw_alh_base = SDW_ALH_BASE,
+       .check_sdw_irq  = hda_common_check_sdw_irq,
 };
 EXPORT_SYMBOL_NS(jsl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
index df00db8..cc8ddef 100644 (file)
@@ -15,6 +15,7 @@
  * Hardware interface for generic Intel audio DSP HDA IP
  */
 
+#include <linux/moduleparam.h>
 #include <sound/hda_register.h>
 #include <sound/pcm_params.h>
 #include "../sof-audio.h"
 #define SDnFMT_BITS(x) ((x) << 4)
 #define SDnFMT_CHAN(x) ((x) << 0)
 
+static bool hda_always_enable_dmi_l1;
+module_param_named(always_enable_dmi_l1, hda_always_enable_dmi_l1, bool, 0444);
+MODULE_PARM_DESC(always_enable_dmi_l1, "SOF HDA always enable DMI l1");
+
 u32 hda_dsp_get_mult_div(struct snd_sof_dev *sdev, int rate)
 {
        switch (rate) {
@@ -216,6 +221,7 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
                     struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_component *scomp = sdev->component;
        struct hdac_ext_stream *dsp_stream;
        struct snd_sof_pcm *spcm;
@@ -228,8 +234,14 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
                return -EINVAL;
        }
 
-       /* All playback and D0i3 compatible streams are DMI L1 capable */
-       if (direction == SNDRV_PCM_STREAM_PLAYBACK ||
+       /*
+        * All playback streams are DMI L1 capable, capture streams need
+        * pause push/release to be disabled
+        */
+       if (hda_always_enable_dmi_l1 && direction == SNDRV_PCM_STREAM_CAPTURE)
+               runtime->hw.info &= ~SNDRV_PCM_INFO_PAUSE;
+
+       if (hda_always_enable_dmi_l1 ||
            spcm->stream[substream->stream].d0i3_compatible)
                flags |= SOF_HDA_STREAM_DMI_L1_COMPATIBLE;
 
index 40a3993..63c3674 100644 (file)
@@ -197,11 +197,10 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags)
         * Workaround to address a known issue with host DMA that results
         * in xruns during pause/release in capture scenarios.
         */
-       if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
-               if (stream && !(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE))
-                       snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
-                                               HDA_VS_INTEL_EM2,
-                                               HDA_VS_INTEL_EM2_L1SEN, 0);
+       if (!(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE))
+               snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
+                                       HDA_VS_INTEL_EM2,
+                                       HDA_VS_INTEL_EM2_L1SEN, 0);
 
        return stream;
 }
@@ -240,7 +239,7 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag)
        spin_unlock_irq(&bus->reg_lock);
 
        /* Enable DMI L1 if permitted */
-       if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1) && dmi_l1_enable)
+       if (dmi_l1_enable)
                snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2,
                                        HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN);
 
index 891e6e1..f60e2c5 100644 (file)
 #define EXCEPT_MAX_HDR_SIZE    0x400
 #define HDA_EXT_ROM_STATUS_SIZE 8
 
+static const struct sof_intel_dsp_desc
+       *get_chip_info(struct snd_sof_pdata *pdata)
+{
+       const struct sof_dev_desc *desc = pdata->desc;
+       const struct sof_intel_dsp_desc *chip_info;
+
+       chip_info = desc->chip_info;
+
+       return chip_info;
+}
+
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
 
 /*
@@ -155,6 +166,8 @@ static int hda_sdw_probe(struct snd_sof_dev *sdev)
        memset(&res, 0, sizeof(res));
 
        res.mmio_base = sdev->bar[HDA_DSP_BAR];
+       res.shim_base = hdev->desc->sdw_shim_base;
+       res.alh_base = hdev->desc->sdw_alh_base;
        res.irq = sdev->ipc_irq;
        res.handle = hdev->info.handle;
        res.parent = sdev->dev;
@@ -215,7 +228,7 @@ static int hda_sdw_exit(struct snd_sof_dev *sdev)
        return 0;
 }
 
-static bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
+bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev)
 {
        struct sof_intel_hda_dev *hdev;
        bool ret = false;
@@ -241,6 +254,17 @@ out:
        return ret;
 }
 
+static bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
+{
+       const struct sof_intel_dsp_desc *chip;
+
+       chip = get_chip_info(sdev->pdata);
+       if (chip && chip->check_sdw_irq)
+               return chip->check_sdw_irq(sdev);
+
+       return false;
+}
+
 static irqreturn_t hda_dsp_sdw_thread(int irq, void *context)
 {
        return sdw_intel_thread(irq, context);
@@ -253,7 +277,7 @@ static bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev)
        hdev = sdev->pdata->hw_pdata;
        if (hdev->sdw &&
            snd_sof_dsp_read(sdev, HDA_DSP_BAR,
-                            HDA_DSP_REG_SNDW_WAKE_STS))
+                            hdev->desc->sdw_shim_base + SDW_SHIM_WAKESTS))
                return true;
 
        return false;
@@ -672,17 +696,6 @@ skip_soundwire:
        return 0;
 }
 
-static const struct sof_intel_dsp_desc
-       *get_chip_info(struct snd_sof_pdata *pdata)
-{
-       const struct sof_dev_desc *desc = pdata->desc;
-       const struct sof_intel_dsp_desc *chip_info;
-
-       chip_info = desc->chip_info;
-
-       return chip_info;
-}
-
 static irqreturn_t hda_dsp_interrupt_handler(int irq, void *context)
 {
        struct snd_sof_dev *sdev = context;
index 4d44f89..4fdfb10 100644 (file)
 #define HDA_DSP_REG_ADSPIS2            (HDA_DSP_GEN_BASE + 0x14)
 
 #define HDA_DSP_REG_ADSPIS2_SNDW       BIT(5)
-#define HDA_DSP_REG_SNDW_WAKE_STS      0x2C192
 
 /* Intel HD Audio Inter-Processor Communication Registers */
 #define HDA_DSP_IPC_BASE               0x40
@@ -692,6 +691,7 @@ int hda_dsp_trace_trigger(struct snd_sof_dev *sdev, int cmd);
 int hda_sdw_startup(struct snd_sof_dev *sdev);
 void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable);
 void hda_sdw_process_wakeen(struct snd_sof_dev *sdev);
+bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev);
 
 #else
 
@@ -737,6 +737,12 @@ static inline bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev)
 static inline void hda_sdw_process_wakeen(struct snd_sof_dev *sdev)
 {
 }
+
+static inline bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev)
+{
+       return false;
+}
+
 #endif
 
 /* common dai driver */
index 88a74be..ee095b8 100644 (file)
@@ -142,5 +142,8 @@ const struct sof_intel_dsp_desc icl_chip_info = {
        .rom_init_timeout       = 300,
        .ssp_count = ICL_SSP_COUNT,
        .ssp_base_offset = CNL_SSP_BASE_OFFSET,
+       .sdw_shim_base = SDW_SHIM_BASE,
+       .sdw_alh_base = SDW_ALH_BASE,
+       .check_sdw_irq  = hda_common_check_sdw_irq,
 };
 EXPORT_SYMBOL_NS(icl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
index 4ee1da3..4bded66 100644 (file)
@@ -15,7 +15,6 @@
 #include <sound/sof.h>
 #include "../ops.h"
 #include "atom.h"
-#include "shim.h"
 #include "../sof-pci-dev.h"
 #include "../sof-audio.h"
 
index 529f68d..e9f7d4d 100644 (file)
@@ -164,6 +164,9 @@ struct sof_intel_dsp_desc {
        int rom_init_timeout;
        int ssp_count;                  /* ssp count of the platform */
        int ssp_base_offset;            /* base address of the SSPs */
+       u32 sdw_shim_base;
+       u32 sdw_alh_base;
+       bool (*check_sdw_irq)(struct snd_sof_dev *sdev);
 };
 
 extern const struct snd_sof_dsp_ops sof_tng_ops;
index 2ed7883..199d41a 100644 (file)
@@ -137,6 +137,9 @@ const struct sof_intel_dsp_desc tgl_chip_info = {
        .rom_init_timeout       = 300,
        .ssp_count = ICL_SSP_COUNT,
        .ssp_base_offset = CNL_SSP_BASE_OFFSET,
+       .sdw_shim_base = SDW_SHIM_BASE,
+       .sdw_alh_base = SDW_ALH_BASE,
+       .check_sdw_irq  = hda_common_check_sdw_irq,
 };
 EXPORT_SYMBOL_NS(tgl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
 
@@ -153,6 +156,9 @@ const struct sof_intel_dsp_desc tglh_chip_info = {
        .rom_init_timeout       = 300,
        .ssp_count = ICL_SSP_COUNT,
        .ssp_base_offset = CNL_SSP_BASE_OFFSET,
+       .sdw_shim_base = SDW_SHIM_BASE,
+       .sdw_alh_base = SDW_ALH_BASE,
+       .check_sdw_irq  = hda_common_check_sdw_irq,
 };
 EXPORT_SYMBOL_NS(tglh_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
 
@@ -169,6 +175,9 @@ const struct sof_intel_dsp_desc ehl_chip_info = {
        .rom_init_timeout       = 300,
        .ssp_count = ICL_SSP_COUNT,
        .ssp_base_offset = CNL_SSP_BASE_OFFSET,
+       .sdw_shim_base = SDW_SHIM_BASE,
+       .sdw_alh_base = SDW_ALH_BASE,
+       .check_sdw_irq  = hda_common_check_sdw_irq,
 };
 EXPORT_SYMBOL_NS(ehl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
 
@@ -185,5 +194,8 @@ const struct sof_intel_dsp_desc adls_chip_info = {
        .rom_init_timeout       = 300,
        .ssp_count = ICL_SSP_COUNT,
        .ssp_base_offset = CNL_SSP_BASE_OFFSET,
+       .sdw_shim_base = SDW_SHIM_BASE,
+       .sdw_alh_base = SDW_ALH_BASE,
+       .check_sdw_irq  = hda_common_check_sdw_irq,
 };
 EXPORT_SYMBOL_NS(adls_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
index 510883c..989912f 100644 (file)
@@ -433,11 +433,10 @@ struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp,
        return NULL;
 }
 
-/*
- * Helper to get SSP MCLK from a pcm_runtime.
- * Return 0 if not exist.
- */
-int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd)
+#define SOF_DAI_CLK_INTEL_SSP_MCLK     0
+#define SOF_DAI_CLK_INTEL_SSP_BCLK     1
+
+static int sof_dai_get_clk(struct snd_soc_pcm_runtime *rtd, int clk_type)
 {
        struct snd_soc_component *component =
                snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
@@ -450,16 +449,45 @@ int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd)
 
        switch (dai->dai_config->type) {
        case SOF_DAI_INTEL_SSP:
-               return dai->dai_config->ssp.mclk_rate;
+               switch (clk_type) {
+               case SOF_DAI_CLK_INTEL_SSP_MCLK:
+                       return dai->dai_config->ssp.mclk_rate;
+               case SOF_DAI_CLK_INTEL_SSP_BCLK:
+                       return dai->dai_config->ssp.bclk_rate;
+               default:
+                       dev_err(rtd->dev, "fail to get SSP clk %d rate\n",
+                               clk_type);
+                       return -EINVAL;
+               }
+               break;
        default:
                /* not yet implemented for platforms other than the above */
-               dev_err(rtd->dev, "mclk for dai_config->type %d not supported yet!\n",
+               dev_err(rtd->dev, "DAI type %d not supported yet!\n",
                        dai->dai_config->type);
                return -EINVAL;
        }
 }
+
+/*
+ * Helper to get SSP MCLK from a pcm_runtime.
+ * Return 0 if not exist.
+ */
+int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd)
+{
+       return sof_dai_get_clk(rtd, SOF_DAI_CLK_INTEL_SSP_MCLK);
+}
 EXPORT_SYMBOL(sof_dai_get_mclk);
 
+/*
+ * Helper to get SSP BCLK from a pcm_runtime.
+ * Return 0 if not exist.
+ */
+int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd)
+{
+       return sof_dai_get_clk(rtd, SOF_DAI_CLK_INTEL_SSP_BCLK);
+}
+EXPORT_SYMBOL(sof_dai_get_bclk);
+
 /*
  * SOF Driver enumeration.
  */
index 0311946..bc9e707 100644 (file)
@@ -50,6 +50,15 @@ static const struct dmi_system_id sof_tplg_table[] = {
                },
                .driver_data = "sof-tgl-rt5682-ssp0-max98373-ssp2.tplg",
        },
+       {
+               .callback = sof_tplg_cb,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
+                       DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"),
+               },
+               .driver_data = "sof-adl-rt5682-ssp0-max98373-ssp2.tplg",
+       },
        {}
 };
 
index 5e3a96d..48d9061 100644 (file)
@@ -204,8 +204,6 @@ static int sprd_pcm_hw_params(struct snd_soc_component *component,
        if (!dma_params) {
                dev_warn(component->dev, "no dma parameters setting\n");
                dma_private->params = NULL;
-               snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-               runtime->dma_bytes = totsize;
                return 0;
        }
 
@@ -217,9 +215,6 @@ static int sprd_pcm_hw_params(struct snd_soc_component *component,
                        return ret;
        }
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
-       runtime->dma_bytes = totsize;
        sg_num = totsize / period;
        dma_private->dma_addr_offset = totsize / channels;
 
@@ -310,7 +305,6 @@ sg_err:
 static int sprd_pcm_hw_free(struct snd_soc_component *component,
                            struct snd_pcm_substream *substream)
 {
-       snd_pcm_set_runtime_buffer(substream, NULL);
        sprd_pcm_release_dma_channel(substream);
 
        return 0;
@@ -435,73 +429,20 @@ static snd_pcm_uframes_t sprd_pcm_pointer(struct snd_soc_component *component,
        return x;
 }
 
-static int sprd_pcm_mmap(struct snd_soc_component *component,
-                        struct snd_pcm_substream *substream,
-                        struct vm_area_struct *vma)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-       return remap_pfn_range(vma, vma->vm_start,
-                              runtime->dma_addr >> PAGE_SHIFT,
-                              vma->vm_end - vma->vm_start,
-                              vma->vm_page_prot);
-}
-
 static int sprd_pcm_new(struct snd_soc_component *component,
                        struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
-       struct snd_pcm_substream *substream;
        int ret;
 
        ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
        if (ret)
                return ret;
 
-       substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-       if (substream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
-                                         sprd_pcm_hardware.buffer_bytes_max,
-                                         &substream->dma_buffer);
-               if (ret) {
-                       dev_err(card->dev,
-                               "can't alloc playback dma buffer: %d\n", ret);
-                       return ret;
-               }
-       }
-
-       substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
-       if (substream) {
-               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
-                                         sprd_pcm_hardware.buffer_bytes_max,
-                                         &substream->dma_buffer);
-               if (ret) {
-                       dev_err(card->dev,
-                               "can't alloc capture dma buffer: %d\n", ret);
-                       snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-static void sprd_pcm_free(struct snd_soc_component *component,
-                         struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
-               substream = pcm->streams[i].substream;
-               if (substream) {
-                       snd_dma_free_pages(&substream->dma_buffer);
-                       substream->dma_buffer.area = NULL;
-                       substream->dma_buffer.addr = 0;
-               }
-       }
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                           card->dev,
+                                           sprd_pcm_hardware.buffer_bytes_max);
 }
 
 static const struct snd_soc_component_driver sprd_soc_component = {
@@ -512,9 +453,7 @@ static const struct snd_soc_component_driver sprd_soc_component = {
        .hw_free        = sprd_pcm_hw_free,
        .trigger        = sprd_pcm_trigger,
        .pointer        = sprd_pcm_pointer,
-       .mmap           = sprd_pcm_mmap,
        .pcm_construct  = sprd_pcm_new,
-       .pcm_destruct   = sprd_pcm_free,
        .compress_ops   = &sprd_platform_compress_ops,
 };
 
index 0f9beef..bcccdf3 100644 (file)
@@ -612,12 +612,9 @@ static const struct snd_soc_component_driver tegra210_admaif_cmpnt = {
        .controls               = tegra210_admaif_controls,
        .num_controls           = ARRAY_SIZE(tegra210_admaif_controls),
        .pcm_construct          = tegra_pcm_construct,
-       .pcm_destruct           = tegra_pcm_destruct,
        .open                   = tegra_pcm_open,
        .close                  = tegra_pcm_close,
        .hw_params              = tegra_pcm_hw_params,
-       .hw_free                = tegra_pcm_hw_free,
-       .mmap                   = tegra_pcm_mmap,
        .pointer                = tegra_pcm_pointer,
 };
 
@@ -625,12 +622,9 @@ static const struct snd_soc_component_driver tegra186_admaif_cmpnt = {
        .controls               = tegra186_admaif_controls,
        .num_controls           = ARRAY_SIZE(tegra186_admaif_controls),
        .pcm_construct          = tegra_pcm_construct,
-       .pcm_destruct           = tegra_pcm_destruct,
        .open                   = tegra_pcm_open,
        .close                  = tegra_pcm_close,
        .hw_params              = tegra_pcm_hw_params,
-       .hw_free                = tegra_pcm_hw_free,
-       .mmap                   = tegra_pcm_mmap,
        .pointer                = tegra_pcm_pointer,
 };
 
index b3e1df6..ef011a4 100644 (file)
@@ -512,16 +512,14 @@ static const struct of_device_id tegra30_ahub_of_match[] = {
 
 static int tegra30_ahub_probe(struct platform_device *pdev)
 {
-       const struct of_device_id *match;
        const struct tegra30_ahub_soc_data *soc_data;
        struct resource *res0;
        void __iomem *regs_apbif, *regs_ahub;
        int ret = 0;
 
-       match = of_match_device(tegra30_ahub_of_match, &pdev->dev);
-       if (!match)
+       soc_data = of_device_get_match_data(&pdev->dev);
+       if (!soc_data)
                return -EINVAL;
-       soc_data = match->data;
 
        ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub),
                            GFP_KERNEL);
index 36344f0..084a533 100644 (file)
@@ -406,7 +406,7 @@ static const struct of_device_id tegra30_i2s_of_match[] = {
 static int tegra30_i2s_platform_probe(struct platform_device *pdev)
 {
        struct tegra30_i2s *i2s;
-       const struct of_device_id *match;
+       const struct tegra30_i2s_soc_data *soc_data;
        u32 cif_ids[2];
        void __iomem *regs;
        int ret;
@@ -418,13 +418,13 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
        }
        dev_set_drvdata(&pdev->dev, i2s);
 
-       match = of_match_device(tegra30_i2s_of_match, &pdev->dev);
-       if (!match) {
+       soc_data = of_device_get_match_data(&pdev->dev);
+       if (!soc_data) {
                dev_err(&pdev->dev, "Error: No device match found\n");
                ret = -ENODEV;
                goto err;
        }
-       i2s->soc_data = (struct tegra30_i2s_soc_data *)match->data;
+       i2s->soc_data = soc_data;
 
        i2s->dai = tegra30_i2s_dai_template;
        i2s->dai.name = dev_name(&pdev->dev);
index d3276b4..ef1e74d 100644 (file)
@@ -171,41 +171,10 @@ int tegra_pcm_hw_params(struct snd_soc_component *component,
                return ret;
        }
 
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
        return 0;
 }
 EXPORT_SYMBOL_GPL(tegra_pcm_hw_params);
 
-int tegra_pcm_hw_free(struct snd_soc_component *component,
-                     struct snd_pcm_substream *substream)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
-       if (rtd->dai_link->no_pcm)
-               return 0;
-
-       snd_pcm_set_runtime_buffer(substream, NULL);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(tegra_pcm_hw_free);
-
-int tegra_pcm_mmap(struct snd_soc_component *component,
-                  struct snd_pcm_substream *substream,
-                  struct vm_area_struct *vma)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       if (rtd->dai_link->no_pcm)
-               return 0;
-
-       return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
-                          runtime->dma_addr, runtime->dma_bytes);
-}
-EXPORT_SYMBOL_GPL(tegra_pcm_mmap);
-
 snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
                                    struct snd_pcm_substream *substream)
 {
@@ -213,41 +182,6 @@ snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
 }
 EXPORT_SYMBOL_GPL(tegra_pcm_pointer);
 
-static int tegra_pcm_preallocate_dma_buffer(struct device *dev, struct snd_pcm *pcm, int stream,
-                                           size_t size)
-{
-       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-       struct snd_dma_buffer *buf = &substream->dma_buffer;
-
-       buf->area = dma_alloc_wc(dev, size, &buf->addr, GFP_KERNEL);
-       if (!buf->area)
-               return -ENOMEM;
-
-       buf->private_data = NULL;
-       buf->dev.type = SNDRV_DMA_TYPE_DEV;
-       buf->dev.dev = dev;
-       buf->bytes = size;
-
-       return 0;
-}
-
-static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
-       struct snd_pcm_substream *substream;
-       struct snd_dma_buffer *buf;
-
-       substream = pcm->streams[stream].substream;
-       if (!substream)
-               return;
-
-       buf = &substream->dma_buffer;
-       if (!buf->area)
-               return;
-
-       dma_free_wc(buf->dev.dev, buf->bytes, buf->area, buf->addr);
-       buf->area = NULL;
-}
-
 static int tegra_pcm_dma_allocate(struct device *dev, struct snd_soc_pcm_runtime *rtd,
                                  size_t size)
 {
@@ -258,24 +192,7 @@ static int tegra_pcm_dma_allocate(struct device *dev, struct snd_soc_pcm_runtime
        if (ret < 0)
                return ret;
 
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = tegra_pcm_preallocate_dma_buffer(dev, pcm, SNDRV_PCM_STREAM_PLAYBACK, size);
-               if (ret)
-                       goto err;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = tegra_pcm_preallocate_dma_buffer(dev, pcm, SNDRV_PCM_STREAM_CAPTURE, size);
-               if (ret)
-                       goto err_free_play;
-       }
-
-       return 0;
-
-err_free_play:
-       tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
-err:
-       return ret;
+       return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC, dev, size);
 }
 
 int tegra_pcm_construct(struct snd_soc_component *component,
@@ -294,14 +211,6 @@ int tegra_pcm_construct(struct snd_soc_component *component,
 }
 EXPORT_SYMBOL_GPL(tegra_pcm_construct);
 
-void tegra_pcm_destruct(struct snd_soc_component *component,
-                       struct snd_pcm *pcm)
-{
-       tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE);
-       tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
-}
-EXPORT_SYMBOL_GPL(tegra_pcm_destruct);
-
 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 MODULE_DESCRIPTION("Tegra PCM ASoC driver");
 MODULE_LICENSE("GPL");
index 4838cdc..d602126 100644 (file)
@@ -22,8 +22,6 @@
 
 int tegra_pcm_construct(struct snd_soc_component *component,
                        struct snd_soc_pcm_runtime *rtd);
-void tegra_pcm_destruct(struct snd_soc_component *component,
-                       struct snd_pcm *pcm);
 int tegra_pcm_open(struct snd_soc_component *component,
                   struct snd_pcm_substream *substream);
 int tegra_pcm_close(struct snd_soc_component *component,
@@ -31,11 +29,6 @@ int tegra_pcm_close(struct snd_soc_component *component,
 int tegra_pcm_hw_params(struct snd_soc_component *component,
                        struct snd_pcm_substream *substream,
                        struct snd_pcm_hw_params *params);
-int tegra_pcm_hw_free(struct snd_soc_component *component,
-                     struct snd_pcm_substream *substream);
-int tegra_pcm_mmap(struct snd_soc_component *component,
-                  struct snd_pcm_substream *substream,
-                  struct vm_area_struct *vma);
 snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
                                    struct snd_pcm_substream *substream);
 int tegra_pcm_platform_register(struct device *dev);
index 698d7bc..1d9fe3f 100644 (file)
@@ -35,6 +35,7 @@ config SND_SOC_DAVINCI_MCASP
          various Texas Instruments SoCs like:
          - daVinci devices
          - Sitara line of SoCs (AM335x, AM438x, etc)
+         - OMAP4
          - DRA7x devices
          - Keystone devices
          - K3 devices (am654, j721e)
index 017a5a5..56a19ee 100644 (file)
@@ -83,6 +83,8 @@ struct davinci_mcasp {
        struct snd_pcm_substream *substreams[2];
        unsigned int dai_fmt;
 
+       u32 iec958_status;
+
        /* Audio can not be enabled due to missing parameter(s) */
        bool    missing_audio_param;
 
@@ -757,6 +759,9 @@ static int davinci_mcasp_set_tdm_slot(struct snd_soc_dai *dai,
 {
        struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
 
+       if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
+               return 0;
+
        dev_dbg(mcasp->dev,
                 "%s() tx_mask 0x%08x rx_mask 0x%08x slots %d width %d\n",
                 __func__, tx_mask, rx_mask, slots, slot_width);
@@ -827,6 +832,20 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
                mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate),
                               RXROT(7));
                mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask);
+       } else {
+               /*
+                * according to the TRM it should be TXROT=0, this one works:
+                * 16 bit to 23-8 (TXROT=6, rotate 24 bits)
+                * 24 bit to 23-0 (TXROT=0, rotate 0 bits)
+                *
+                * TXROT = 0 only works with 24bit samples
+                */
+               tx_rotate = (sample_width / 4 + 2) & 0x7;
+
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate),
+                              TXROT(7));
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(15),
+                              TXSSZ(0x0F));
        }
 
        mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask);
@@ -842,10 +861,16 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
        u8 tx_ser = 0;
        u8 rx_ser = 0;
        u8 slots = mcasp->tdm_slots;
-       u8 max_active_serializers = (channels + slots - 1) / slots;
-       u8 max_rx_serializers, max_tx_serializers;
+       u8 max_active_serializers, max_rx_serializers, max_tx_serializers;
        int active_serializers, numevt;
        u32 reg;
+
+       /* In DIT mode we only allow maximum of one serializers for now */
+       if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
+               max_active_serializers = 1;
+       else
+               max_active_serializers = (channels + slots - 1) / slots;
+
        /* Default configuration */
        if (mcasp->version < MCASP_VERSION_3)
                mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
@@ -1031,16 +1056,18 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream,
 static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
                              unsigned int rate)
 {
-       u32 cs_value = 0;
-       u8 *cs_bytes = (u8*) &cs_value;
+       u8 *cs_bytes = (u8 *)&mcasp->iec958_status;
 
-       /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
-          and LSB first */
-       mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15));
+       if (!mcasp->dat_port)
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSEL);
+       else
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSEL);
 
        /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */
        mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE | FSXMOD(0x180));
 
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, 0xFFFF);
+
        /* Set the TX tdm : for all the slots */
        mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);
 
@@ -1049,16 +1076,8 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
 
        mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
 
-       /* Only 44100 and 48000 are valid, both have the same setting */
-       mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));
-
-       /* Enable the DIT */
-       mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN);
-
        /* Set S/PDIF channel status bits */
-       cs_bytes[0] = IEC958_AES0_CON_NOT_COPYRIGHT;
-       cs_bytes[1] = IEC958_AES1_CON_PCM_CODER;
-
+       cs_bytes[3] &= ~IEC958_AES3_CON_FS;
        switch (rate) {
        case 22050:
                cs_bytes[3] |= IEC958_AES3_CON_FS_22050;
@@ -1088,12 +1107,15 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
                cs_bytes[3] |= IEC958_AES3_CON_FS_192000;
                break;
        default:
-               printk(KERN_WARNING "unsupported sampling rate: %d\n", rate);
+               dev_err(mcasp->dev, "unsupported sampling rate: %d\n", rate);
                return -EINVAL;
        }
 
-       mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRA_REG, cs_value);
-       mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRB_REG, cs_value);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRA_REG, mcasp->iec958_status);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRB_REG, mcasp->iec958_status);
+
+       /* Enable the DIT */
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN);
 
        return 0;
 }
@@ -1237,12 +1259,18 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
                int slots = mcasp->tdm_slots;
                int rate = params_rate(params);
                int sbits = params_width(params);
+               unsigned int bclk_target;
 
                if (mcasp->slot_width)
                        sbits = mcasp->slot_width;
 
+               if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE)
+                       bclk_target = rate * sbits * slots;
+               else
+                       bclk_target = rate * 128;
+
                davinci_mcasp_calc_clk_div(mcasp, mcasp->sysclk_freq,
-                                          rate * sbits * slots, true);
+                                          bclk_target, true);
        }
 
        ret = mcasp_common_hw_param(mcasp, substream->stream,
@@ -1598,6 +1626,77 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
        .set_tdm_slot   = davinci_mcasp_set_tdm_slot,
 };
 
+static int davinci_mcasp_iec958_info(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+       uinfo->count = 1;
+
+       return 0;
+}
+
+static int davinci_mcasp_iec958_get(struct snd_kcontrol *kcontrol,
+                                   struct snd_ctl_elem_value *uctl)
+{
+       struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
+
+       memcpy(uctl->value.iec958.status, &mcasp->iec958_status,
+              sizeof(mcasp->iec958_status));
+
+       return 0;
+}
+
+static int davinci_mcasp_iec958_put(struct snd_kcontrol *kcontrol,
+                                   struct snd_ctl_elem_value *uctl)
+{
+       struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
+
+       memcpy(&mcasp->iec958_status, uctl->value.iec958.status,
+              sizeof(mcasp->iec958_status));
+
+       return 0;
+}
+
+static int davinci_mcasp_iec958_con_mask_get(struct snd_kcontrol *kcontrol,
+                                            struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
+
+       memset(ucontrol->value.iec958.status, 0xff, sizeof(mcasp->iec958_status));
+       return 0;
+}
+
+static const struct snd_kcontrol_new davinci_mcasp_iec958_ctls[] = {
+       {
+               .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                          SNDRV_CTL_ELEM_ACCESS_VOLATILE),
+               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+               .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
+               .info = davinci_mcasp_iec958_info,
+               .get = davinci_mcasp_iec958_get,
+               .put = davinci_mcasp_iec958_put,
+       }, {
+               .access = SNDRV_CTL_ELEM_ACCESS_READ,
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
+               .info = davinci_mcasp_iec958_info,
+               .get = davinci_mcasp_iec958_con_mask_get,
+       },
+};
+
+static void davinci_mcasp_init_iec958_status(struct davinci_mcasp *mcasp)
+{
+       unsigned char *cs = (u8 *)&mcasp->iec958_status;
+
+       cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
+       cs[1] = IEC958_AES1_CON_PCM_CODER;
+       cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
+       cs[3] = IEC958_AES3_CON_CLOCK_1000PPM;
+}
+
 static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai)
 {
        struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
@@ -1605,6 +1704,12 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai)
        dai->playback_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
        dai->capture_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE];
 
+       if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) {
+               davinci_mcasp_init_iec958_status(mcasp);
+               snd_soc_add_dai_controls(dai, davinci_mcasp_iec958_ctls,
+                                        ARRAY_SIZE(davinci_mcasp_iec958_ctls));
+       }
+
        return 0;
 }
 
@@ -1651,7 +1756,8 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
                        .channels_min   = 1,
                        .channels_max   = 384,
                        .rates          = DAVINCI_MCASP_RATES,
-                       .formats        = DAVINCI_MCASP_PCM_FMTS,
+                       .formats        = SNDRV_PCM_FMTBIT_S16_LE |
+                                         SNDRV_PCM_FMTBIT_S24_LE,
                },
                .ops            = &davinci_mcasp_dai_ops,
        },
@@ -1688,6 +1794,12 @@ static struct davinci_mcasp_pdata dra7_mcasp_pdata = {
        .version = MCASP_VERSION_4,
 };
 
+static struct davinci_mcasp_pdata omap_mcasp_pdata = {
+       .tx_dma_offset = 0x200,
+       .rx_dma_offset = 0,
+       .version = MCASP_VERSION_OMAP,
+};
+
 static const struct of_device_id mcasp_dt_ids[] = {
        {
                .compatible = "ti,dm646x-mcasp-audio",
@@ -1705,6 +1817,10 @@ static const struct of_device_id mcasp_dt_ids[] = {
                .compatible = "ti,dra7-mcasp-audio",
                .data = &dra7_mcasp_pdata,
        },
+       {
+               .compatible = "ti,omap4-mcasp-audio",
+               .data = &omap_mcasp_pdata,
+       },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mcasp_dt_ids);
@@ -1871,6 +1987,8 @@ out:
                } else {
                        mcasp->tdm_slots = pdata->tdm_slots;
                }
+       } else {
+               mcasp->tdm_slots = 32;
        }
 
        mcasp->num_serializer = pdata->num_serializer;
@@ -2242,10 +2360,17 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 
        dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
        dma_data->filter_data = "tx";
-       if (dat)
+       if (dat) {
                dma_data->addr = dat->start;
-       else
+               /*
+                * According to the TRM there should be 0x200 offset added to
+                * the DAT port address
+                */
+               if (mcasp->version == MCASP_VERSION_OMAP)
+                       dma_data->addr += davinci_mcasp_txdma_offset(mcasp->pdata);
+       } else {
                dma_data->addr = mem->start + davinci_mcasp_txdma_offset(mcasp->pdata);
+       }
 
 
        /* RX is not valid in DIT mode */
@@ -2310,7 +2435,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
                ret = edma_pcm_platform_register(&pdev->dev);
                break;
        case PCM_SDMA:
-               ret = sdma_pcm_platform_register(&pdev->dev, "tx", "rx");
+               if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE)
+                       ret = sdma_pcm_platform_register(&pdev->dev, "tx", "rx");
+               else
+                       ret = sdma_pcm_platform_register(&pdev->dev, "tx", NULL);
                break;
        case PCM_UDMA:
                ret = udma_pcm_platform_register(&pdev->dev);
index 265bbc5..9347f98 100644 (file)
  */
 #define J721E_CODEC_CONF_COUNT 5
 
-#define J721E_AUDIO_DOMAIN_CPB 0
-#define J721E_AUDIO_DOMAIN_IVI 1
+enum j721e_audio_domain_id {
+       J721E_AUDIO_DOMAIN_CPB = 0,
+       J721E_AUDIO_DOMAIN_IVI,
+       J721E_AUDIO_DOMAIN_LAST,
+};
 
 #define J721E_CLK_PARENT_48000 0
 #define J721E_CLK_PARENT_44100 1
@@ -78,7 +81,7 @@ struct j721e_priv {
        u32 pll_rates[2];
        unsigned int hsdiv_rates[2];
 
-       struct j721e_audio_domain audio_domains[2];
+       struct j721e_audio_domain audio_domains[J721E_AUDIO_DOMAIN_LAST];
 
        struct mutex mutex;
 };
@@ -199,9 +202,8 @@ static int j721e_configure_refclk(struct j721e_priv *priv,
 
        if (domain->parent_clk_id == -1 || priv->hsdiv_rates[domain->parent_clk_id] != scki) {
                dev_dbg(priv->dev,
-                       "%s configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n",
-                       audio_domain == J721E_AUDIO_DOMAIN_CPB ? "CPB" : "IVI",
-                       rate,
+                       "domain%u configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n",
+                       audio_domain, rate,
                        clk_id == J721E_CLK_PARENT_48000 ? "PLL4" : "PLL15",
                        ratios_for_pcm3168a[i], scki);
 
@@ -263,10 +265,11 @@ static int j721e_audio_startup(struct snd_pcm_substream *substream)
 
        domain->active++;
 
-       if (priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].rate)
-               active_rate = priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].rate;
-       else
-               active_rate = priv->audio_domains[J721E_AUDIO_DOMAIN_IVI].rate;
+       for (i = 0; i < J721E_AUDIO_DOMAIN_LAST; i++) {
+               active_rate = priv->audio_domains[i].rate;
+               if (active_rate)
+                       break;
+       }
 
        if (active_rate)
                ret = snd_pcm_hw_constraint_single(substream->runtime,
@@ -825,7 +828,7 @@ static int j721e_soc_probe(struct platform_device *pdev)
        struct snd_soc_card *card;
        const struct of_device_id *match;
        struct j721e_priv *priv;
-       int link_cnt, conf_cnt, ret;
+       int link_cnt, conf_cnt, ret, i;
 
        if (!node) {
                dev_err(&pdev->dev, "of node is missing.\n");
@@ -849,8 +852,9 @@ static int j721e_soc_probe(struct platform_device *pdev)
        if (!priv->dai_links)
                return -ENOMEM;
 
-       priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].parent_clk_id = -1;
-       priv->audio_domains[J721E_AUDIO_DOMAIN_IVI].parent_clk_id = -1;
+       for (i = 0; i < J721E_AUDIO_DOMAIN_LAST; i++)
+               priv->audio_domains[i].parent_clk_id = -1;
+
        priv->dev = &pdev->dev;
        card = &priv->card;
        card->dev = &pdev->dev;
index 91cc9a4..2e3d1ee 100644 (file)
@@ -292,11 +292,6 @@ static int omap_abe_probe(struct platform_device *pdev)
 
        card->fully_routed = 1;
 
-       if (!priv->mclk_freq) {
-               dev_err(&pdev->dev, "MCLK frequency missing\n");
-               return -ENODEV;
-       }
-
        card->dai_link = priv->dai_links;
        card->num_links = num_links;
 
index cf98141..4e8d5f7 100644 (file)
@@ -128,8 +128,8 @@ static const struct uniphier_aio_spec *find_spec(struct uniphier_aio *aio,
 static int find_divider(struct uniphier_aio *aio, int pll_id, unsigned int freq)
 {
        struct uniphier_aio_pll *pll;
-       int mul[] = { 1, 1, 1, 2, };
-       int div[] = { 2, 3, 1, 3, };
+       static const int mul[] = { 1, 1, 1, 2, };
+       static const int div[] = { 2, 3, 1, 3, };
        int i;
 
        if (!is_valid_pll(aio->chip, pll_id))
index a1f8c3a..fd570a4 100644 (file)
@@ -68,9 +68,11 @@ static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
 static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
 static bool ignore_ctl_error;
 static bool autoclock = true;
+static bool lowlatency = true;
 static char *quirk_alias[SNDRV_CARDS];
 static char *delayed_register[SNDRV_CARDS];
 static bool implicit_fb[SNDRV_CARDS];
+static unsigned int quirk_flags[SNDRV_CARDS];
 
 bool snd_usb_use_vmalloc = true;
 bool snd_usb_skip_validation;
@@ -92,12 +94,16 @@ MODULE_PARM_DESC(ignore_ctl_error,
                 "Ignore errors from USB controller for mixer interfaces.");
 module_param(autoclock, bool, 0444);
 MODULE_PARM_DESC(autoclock, "Enable auto-clock selection for UAC2 devices (default: yes).");
+module_param(lowlatency, bool, 0444);
+MODULE_PARM_DESC(lowlatency, "Enable low latency playback (default: yes).");
 module_param_array(quirk_alias, charp, NULL, 0444);
 MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef.");
 module_param_array(delayed_register, charp, NULL, 0444);
 MODULE_PARM_DESC(delayed_register, "Quirk for delayed registration, given by id:iface, e.g. 0123abcd:4.");
 module_param_array(implicit_fb, bool, NULL, 0444);
 MODULE_PARM_DESC(implicit_fb, "Apply generic implicit feedback sync mode.");
+module_param_array(quirk_flags, uint, NULL, 0444);
+MODULE_PARM_DESC(quirk_flags, "Driver quirk bit flags.");
 module_param_named(use_vmalloc, snd_usb_use_vmalloc, bool, 0444);
 MODULE_PARM_DESC(use_vmalloc, "Use vmalloc for PCM intermediate buffers (default: yes).");
 module_param_named(skip_validation, snd_usb_skip_validation, bool, 0444);
@@ -378,6 +384,9 @@ static const struct usb_audio_device_name usb_audio_names[] = {
 
        DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"),
 
+       DEVICE_NAME(0x05e1, 0x0408, "Syntek", "STK1160"),
+       DEVICE_NAME(0x05e1, 0x0480, "Hauppauge", "Woodbury"),
+
        /* ASUS ROG Strix */
        PROFILE_NAME(0x0b05, 0x1917,
                     "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
@@ -406,6 +415,8 @@ static const struct usb_audio_device_name usb_audio_names[] = {
        PROFILE_NAME(0x0db0, 0x543d,
                     "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
 
+       DEVICE_NAME(0x0fd9, 0x0008, "Hauppauge", "HVR-950Q"),
+
        /* Stanton/N2IT Final Scratch v1 device ('Scratchamp') */
        DEVICE_NAME(0x103d, 0x0100, "Stanton", "ScratchAmp"),
        DEVICE_NAME(0x103d, 0x0101, "Stanton", "ScratchAmp"),
@@ -424,6 +435,22 @@ static const struct usb_audio_device_name usb_audio_names[] = {
        PROFILE_NAME(0x26ce, 0x0a01,
                     "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
 
+       DEVICE_NAME(0x2040, 0x7200, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7201, "Hauppauge", "HVR-950Q-MXL"),
+       DEVICE_NAME(0x2040, 0x7210, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7211, "Hauppauge", "HVR-950Q-MXL"),
+       DEVICE_NAME(0x2040, 0x7213, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7217, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x721b, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x721e, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x721f, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7240, "Hauppauge", "HVR-850"),
+       DEVICE_NAME(0x2040, 0x7260, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7280, "Hauppauge", "HVR-950Q"),
+       DEVICE_NAME(0x2040, 0x7281, "Hauppauge", "HVR-950Q-MXL"),
+       DEVICE_NAME(0x2040, 0x8200, "Hauppauge", "Woodbury"),
+
        { } /* terminator */
 };
 
@@ -599,6 +626,7 @@ static int snd_usb_audio_create(struct usb_interface *intf,
        chip->setup = device_setup[idx];
        chip->generic_implicit_fb = implicit_fb[idx];
        chip->autoclock = autoclock;
+       chip->lowlatency = lowlatency;
        atomic_set(&chip->active, 1); /* avoid autopm during probing */
        atomic_set(&chip->usage_count, 0);
        atomic_set(&chip->shutdown, 0);
@@ -610,6 +638,11 @@ static int snd_usb_audio_create(struct usb_interface *intf,
        INIT_LIST_HEAD(&chip->midi_list);
        INIT_LIST_HEAD(&chip->mixer_list);
 
+       if (quirk_flags[idx])
+               chip->quirk_flags = quirk_flags[idx];
+       else
+               snd_usb_init_quirk_flags(chip);
+
        card->private_free = snd_usb_audio_free;
 
        strcpy(card->driver, "USB-Audio");
@@ -781,6 +814,12 @@ static int usb_audio_probe(struct usb_interface *intf,
 
        dev_set_drvdata(&dev->dev, chip);
 
+       if (ignore_ctl_error)
+               chip->quirk_flags |= QUIRK_FLAG_IGNORE_CTL_ERROR;
+
+       if (chip->quirk_flags & QUIRK_FLAG_DISABLE_AUTOSUSPEND)
+               usb_disable_autosuspend(interface_to_usbdev(intf));
+
        /*
         * For devices with more than one control interface, we assume the
         * first contains the audio controls. We might need a more specific
@@ -789,7 +828,6 @@ static int usb_audio_probe(struct usb_interface *intf,
        if (!chip->ctrl_intf)
                chip->ctrl_intf = alts;
 
-       chip->txfr_quirk = 0;
        err = 1; /* continue */
        if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
                /* need some special handlings */
@@ -803,7 +841,7 @@ static int usb_audio_probe(struct usb_interface *intf,
                err = snd_usb_create_streams(chip, ifnum);
                if (err < 0)
                        goto __error;
-               err = snd_usb_create_mixer(chip, ifnum, ignore_ctl_error);
+               err = snd_usb_create_mixer(chip, ifnum);
                if (err < 0)
                        goto __error;
        }
@@ -825,7 +863,7 @@ static int usb_audio_probe(struct usb_interface *intf,
                        goto __error;
        }
 
-       if (quirk && quirk->shares_media_device) {
+       if (chip->quirk_flags & QUIRK_FLAG_SHARE_MEDIA_DEVICE) {
                /* don't want to fail when snd_media_device_create() fails */
                snd_media_device_create(chip, intf);
        }
@@ -907,7 +945,7 @@ static void usb_audio_disconnect(struct usb_interface *intf)
                }
        }
 
-       if (chip->quirk_type == QUIRK_SETUP_DISABLE_AUTOSUSPEND)
+       if (chip->quirk_flags & QUIRK_FLAG_DISABLE_AUTOSUSPEND)
                usb_enable_autosuspend(interface_to_usbdev(intf));
 
        chip->num_interfaces--;
index 6c0a052..5b19901 100644 (file)
@@ -94,6 +94,7 @@ struct snd_usb_endpoint {
        struct list_head ready_playback_urbs; /* playback URB FIFO for implicit fb */
 
        unsigned int nurbs;             /* # urbs */
+       unsigned int nominal_queue_size; /* total buffer sizes in URBs */
        unsigned long active_mask;      /* bitmask of active urbs */
        unsigned long unlink_mask;      /* bitmask of unlinked urbs */
        char *syncbuf;                  /* sync buffer for all sync URBs */
@@ -187,6 +188,7 @@ struct snd_usb_substream {
        } dsd_dop;
 
        bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */
+       bool early_playback_start;      /* early start needed for playback? */
        struct media_ctl *media_ctl;
 };
 
index 14456f6..81d5ce0 100644 (file)
@@ -324,11 +324,8 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
                                              sources[ret - 1],
                                              visited, validate);
                if (ret > 0) {
-                       /*
-                        * For Samsung USBC Headset (AKG), setting clock selector again
-                        * will result in incorrect default clock setting problems
-                        */
-                       if (chip->usb_id == USB_ID(0x04e8, 0xa051))
+                       /* Skip setting clock selector again for some devices */
+                       if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR)
                                return ret;
                        err = uac_clock_selector_set_val(chip, entity_id, cur);
                        if (err < 0)
@@ -426,7 +423,7 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip,
 
        /* Don't check the sample rate for devices which we know don't
         * support reading */
-       if (snd_usb_get_sample_rate_quirk(chip))
+       if (chip->quirk_flags & QUIRK_FLAG_GET_SAMPLE_RATE)
                return 0;
        /* the firmware is likely buggy, don't repeat to fail too many times */
        if (chip->sample_rate_read_error > 2)
@@ -541,10 +538,8 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip,
                 */
                clock = snd_usb_clock_find_source(chip, fmt, false);
 
-               /* Denon DN-X1600 hardcoded
-                * Sample rate seems to be set on the hardware itself
-                */
-               if (chip->usb_id == USB_ID(0x154e, 0x500e))
+               /* Hardcoded sample rates */
+               if (chip->quirk_flags & QUIRK_FLAG_IGNORE_CLOCK_SOURCE)
                        return 0;
 
                if (clock < 0)
index 4f85677..533919a 100644 (file)
@@ -240,6 +240,11 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep,
        call_retire_callback(ep, urb);
 }
 
+static inline bool has_tx_length_quirk(struct snd_usb_audio *chip)
+{
+       return chip->quirk_flags & QUIRK_FLAG_TX_LENGTH;
+}
+
 static void prepare_silent_urb(struct snd_usb_endpoint *ep,
                               struct snd_urb_ctx *ctx)
 {
@@ -250,7 +255,7 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep,
        int i;
 
        /* For tx_length_quirk, put packet length at start of packet */
-       if (ep->chip->tx_length_quirk)
+       if (has_tx_length_quirk(ep->chip))
                extra = sizeof(packet_length);
 
        for (i = 0; i < ctx->packets; ++i) {
@@ -803,7 +808,8 @@ static int endpoint_set_interface(struct snd_usb_audio *chip,
                return err;
        }
 
-       snd_usb_set_interface_quirk(chip);
+       if (chip->quirk_flags & QUIRK_FLAG_IFACE_DELAY)
+               msleep(50);
        return 0;
 }
 
@@ -952,7 +958,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
        unsigned int max_urbs, i;
        const struct audioformat *fmt = ep->cur_audiofmt;
        int frame_bits = ep->cur_frame_bytes * 8;
-       int tx_length_quirk = (chip->tx_length_quirk &&
+       int tx_length_quirk = (has_tx_length_quirk(chip) &&
                               usb_pipeout(ep->pipe));
 
        usb_audio_dbg(chip, "Setting params for data EP 0x%x, pipe 0x%x\n",
@@ -1126,6 +1132,10 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
                INIT_LIST_HEAD(&u->ready_list);
        }
 
+       /* total buffer bytes of all URBs plus the next queue;
+        * referred in pcm.c
+        */
+       ep->nominal_queue_size = maxsize * urb_packs * (ep->nurbs + 1);
        return 0;
 
 out_of_memory:
@@ -1287,6 +1297,9 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
         * to be set up before parameter setups
         */
        iface_first = ep->cur_audiofmt->protocol == UAC_VERSION_1;
+       /* Workaround for devices that require the interface setup at first like UAC1 */
+       if (chip->quirk_flags & QUIRK_FLAG_SET_IFACE_FIRST)
+               iface_first = true;
        if (iface_first) {
                err = endpoint_set_interface(chip, ep, true);
                if (err < 0)
@@ -1377,7 +1390,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
                goto __error;
 
        if (snd_usb_endpoint_implicit_feedback_sink(ep) &&
-           !ep->chip->playback_first) {
+           !(ep->chip->quirk_flags & QUIRK_FLAG_PLAYBACK_FIRST)) {
                for (i = 0; i < ep->nurbs; i++) {
                        struct snd_urb_ctx *ctx = ep->urb + i;
                        list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
index eb216fe..50efccb 100644 (file)
@@ -472,12 +472,8 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip,
         * behavior afterwards by some unknown reason.  Do this only for the
         * known devices.
         */
-       switch (USB_ID_VENDOR(chip->usb_id)) {
-       case 0x07fd: /* MOTU */
-               break;
-       default:
+       if (!(chip->quirk_flags & QUIRK_FLAG_VALIDATE_RATES))
                return 0; /* don't perform the validation as default */
-       }
 
        table = kcalloc(fp->nr_rates, sizeof(*table), GFP_KERNEL);
        if (!table)
index 590a0db..23767a1 100644 (file)
@@ -171,7 +171,7 @@ static int add_roland_implicit_fb(struct snd_usb_audio *chip,
        if (!usb_endpoint_is_isoc_in(epd) ||
            (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
                return 0;
-       chip->playback_first = 1;
+       chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST;
        return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0,
                                       alts->desc.bInterfaceNumber, alts);
 }
@@ -320,7 +320,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
                case IMPLICIT_FB_FIXED:
                        return 0; /* no quirk */
                case IMPLICIT_FB_BOTH:
-                       chip->playback_first = 1;
+                       chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST;
                        return add_generic_implicit_fb(chip, fmt, alts);
                }
        }
@@ -344,7 +344,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
 
        /* Pioneer devices with vendor spec class */
        if (is_pioneer_implicit_fb(chip, alts)) {
-               chip->playback_first = 1;
+               chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST;
                return add_implicit_fb_sync_ep(chip, fmt,
                                               get_endpoint(alts, 1)->bEndpointAddress,
                                               1, alts->desc.bInterfaceNumber,
index 9b713b4..43bc595 100644 (file)
@@ -1572,9 +1572,9 @@ static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str)
 static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
                                        struct snd_card *card)
 {
-       const char *names_to_check[] = {
+       static const char * const names_to_check[] = {
                "Headset", "headset", "Headphone", "headphone", NULL};
-       const char **s;
+       const char * const *s;
        bool found = false;
 
        if (strcmp("Speaker", kctl->id.name))
@@ -3183,7 +3183,6 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
                        state.map = map->map;
                        state.selector_map = map->selector_map;
                        mixer->connector_map = map->connector_map;
-                       mixer->ignore_ctl_error |= map->ignore_ctl_error;
                        break;
                }
        }
@@ -3508,8 +3507,7 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
        return 0;
 }
 
-int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
-                        int ignore_error)
+int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif)
 {
        static const struct snd_device_ops dev_ops = {
                .dev_free = snd_usb_mixer_dev_free
@@ -3523,7 +3521,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
        if (!mixer)
                return -ENOMEM;
        mixer->chip = chip;
-       mixer->ignore_ctl_error = ignore_error;
+       mixer->ignore_ctl_error = !!(chip->quirk_flags & QUIRK_FLAG_IGNORE_CTL_ERROR);
        mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems),
                                  GFP_KERNEL);
        if (!mixer->id_elems) {
index ea41e7a..876bbc9 100644 (file)
@@ -97,8 +97,7 @@ struct usb_mixer_elem_info {
        void *private_data;
 };
 
-int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
-                        int ignore_error);
+int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif);
 void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer);
 
 void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
index c5794e8..55eea90 100644 (file)
@@ -28,7 +28,6 @@ struct usbmix_ctl_map {
        const struct usbmix_name_map *map;
        const struct usbmix_selector_map *selector_map;
        const struct usbmix_connector_map *connector_map;
-       int ignore_ctl_error;
 };
 
 /*
@@ -432,7 +431,6 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
        {
                .id = USB_ID(0x041e, 0x3000),
                .map = extigy_map,
-               .ignore_ctl_error = 1,
        },
        {
                .id = USB_ID(0x041e, 0x3010),
@@ -452,28 +450,10 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
                .map = audigy2nx_map,
                .selector_map = audigy2nx_selectors,
        },
-       {       /* Logitech, Inc. QuickCam Pro for Notebooks */
-               .id = USB_ID(0x046d, 0x0991),
-               .ignore_ctl_error = 1,
-       },
-       {       /* Logitech, Inc. QuickCam E 3500 */
-               .id = USB_ID(0x046d, 0x09a4),
-               .ignore_ctl_error = 1,
-       },
        {       /* Plantronics GameCom 780 */
                .id = USB_ID(0x047f, 0xc010),
                .map = gamecom780_map,
        },
-       {
-               /* Hercules DJ Console (Windows Edition) */
-               .id = USB_ID(0x06f8, 0xb000),
-               .ignore_ctl_error = 1,
-       },
-       {
-               /* Hercules DJ Console (Macintosh Edition) */
-               .id = USB_ID(0x06f8, 0xd002),
-               .ignore_ctl_error = 1,
-       },
        {
                /* Hercules Gamesurround Muse Pocket LT
                 * (USB 5.1 Channel Audio Adapter)
@@ -492,7 +472,6 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
        {
                .id = USB_ID(0x08bb, 0x2702),
                .map = linex_map,
-               .ignore_ctl_error = 1,
        },
        {
                .id = USB_ID(0x0a92, 0x0091),
@@ -517,7 +496,6 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
        {
                .id = USB_ID(0x13e5, 0x0001),
                .map = scratch_live_map,
-               .ignore_ctl_error = 1,
        },
        {
                .id = USB_ID(0x200c, 0x1018),
index 0a3cb8f..a66ce03 100644 (file)
@@ -594,85 +594,208 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
                                          &snd_xonar_u1_output_switch, NULL);
 }
 
+/* Digidesign Mbox 1 helper functions */
+
+static int snd_mbox1_is_spdif_synced(struct snd_usb_audio *chip)
+{
+       unsigned char buff[3];
+       int err;
+       int is_spdif_synced;
+
+       /* Read clock source */
+       err = snd_usb_ctl_msg(chip->dev,
+                             usb_rcvctrlpipe(chip->dev, 0), 0x81,
+                             USB_DIR_IN |
+                             USB_TYPE_CLASS |
+                             USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+       if (err < 0)
+               return err;
+
+       /* spdif sync: buff is all zeroes */
+       is_spdif_synced = !(buff[0] | buff[1] | buff[2]);
+       return is_spdif_synced;
+}
+
+static int snd_mbox1_set_clk_source(struct snd_usb_audio *chip, int rate_or_zero)
+{
+       /* 2 possibilities:     Internal    -> expects sample rate
+        *                      S/PDIF sync -> expects rate = 0
+        */
+       unsigned char buff[3];
+
+       buff[0] = (rate_or_zero >>  0) & 0xff;
+       buff[1] = (rate_or_zero >>  8) & 0xff;
+       buff[2] = (rate_or_zero >> 16) & 0xff;
+
+       /* Set clock source */
+       return snd_usb_ctl_msg(chip->dev,
+                              usb_sndctrlpipe(chip->dev, 0), 0x1,
+                              USB_TYPE_CLASS |
+                              USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+}
+
+static int snd_mbox1_is_spdif_input(struct snd_usb_audio *chip)
+{
+       /* Hardware gives 2 possibilities:      ANALOG Source  -> 0x01
+        *                                      S/PDIF Source  -> 0x02
+        */
+       int err;
+       unsigned char source[1];
+
+       /* Read input source */
+       err = snd_usb_ctl_msg(chip->dev,
+                             usb_rcvctrlpipe(chip->dev, 0), 0x81,
+                             USB_DIR_IN |
+                             USB_TYPE_CLASS |
+                             USB_RECIP_INTERFACE, 0x00, 0x500, source, 1);
+       if (err < 0)
+               return err;
+
+       return (source[0] == 2);
+}
+
+static int snd_mbox1_set_input_source(struct snd_usb_audio *chip, int is_spdif)
+{
+       /* NB: Setting the input source to S/PDIF resets the clock source to S/PDIF
+        * Hardware expects 2 possibilities:    ANALOG Source  -> 0x01
+        *                                      S/PDIF Source  -> 0x02
+        */
+       unsigned char buff[1];
+
+       buff[0] = (is_spdif & 1) + 1;
+
+       /* Set input source */
+       return snd_usb_ctl_msg(chip->dev,
+                              usb_sndctrlpipe(chip->dev, 0), 0x1,
+                              USB_TYPE_CLASS |
+                              USB_RECIP_INTERFACE, 0x00, 0x500, buff, 1);
+}
+
 /* Digidesign Mbox 1 clock source switch (internal/spdif) */
 
-static int snd_mbox1_switch_get(struct snd_kcontrol *kctl,
-                               struct snd_ctl_elem_value *ucontrol)
+static int snd_mbox1_clk_switch_get(struct snd_kcontrol *kctl,
+                                   struct snd_ctl_elem_value *ucontrol)
 {
+       struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
+       struct snd_usb_audio *chip = list->mixer->chip;
+       int err;
+
+       err = snd_usb_lock_shutdown(chip);
+       if (err < 0)
+               goto err;
+
+       err = snd_mbox1_is_spdif_synced(chip);
+       if (err < 0)
+               goto err;
+
+       kctl->private_value = err;
+       err = 0;
        ucontrol->value.enumerated.item[0] = kctl->private_value;
-       return 0;
+err:
+       snd_usb_unlock_shutdown(chip);
+       return err;
 }
 
-static int snd_mbox1_switch_update(struct usb_mixer_interface *mixer, int val)
+static int snd_mbox1_clk_switch_update(struct usb_mixer_interface *mixer, int is_spdif_sync)
 {
        struct snd_usb_audio *chip = mixer->chip;
        int err;
-       unsigned char buff[3];
 
        err = snd_usb_lock_shutdown(chip);
        if (err < 0)
                return err;
 
-       /* Prepare for magic command to toggle clock source */
-       err = snd_usb_ctl_msg(chip->dev,
-                               usb_rcvctrlpipe(chip->dev, 0), 0x81,
-                               USB_DIR_IN |
-                               USB_TYPE_CLASS |
-                               USB_RECIP_INTERFACE, 0x00, 0x500, buff, 1);
+       err = snd_mbox1_is_spdif_input(chip);
        if (err < 0)
                goto err;
-       err = snd_usb_ctl_msg(chip->dev,
-                               usb_rcvctrlpipe(chip->dev, 0), 0x81,
-                               USB_DIR_IN |
-                               USB_TYPE_CLASS |
-                               USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+
+       err = snd_mbox1_is_spdif_synced(chip);
        if (err < 0)
                goto err;
 
-       /* 2 possibilities:     Internal    -> send sample rate
-        *                      S/PDIF sync -> send zeroes
-        * NB: Sample rate locked to 48kHz on purpose to
-        *     prevent user from resetting the sample rate
-        *     while S/PDIF sync is enabled and confusing
-        *     this configuration.
-        */
-       if (val == 0) {
-               buff[0] = 0x80;
-               buff[1] = 0xbb;
-               buff[2] = 0x00;
-       } else {
-               buff[0] = buff[1] = buff[2] = 0x00;
-       }
+       /* FIXME: hardcoded sample rate */
+       err = snd_mbox1_set_clk_source(chip, is_spdif_sync ? 0 : 48000);
+       if (err < 0)
+               goto err;
 
-       /* Send the magic command to toggle the clock source */
-       err = snd_usb_ctl_msg(chip->dev,
-                               usb_sndctrlpipe(chip->dev, 0), 0x1,
-                               USB_TYPE_CLASS |
-                               USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+       err = snd_mbox1_is_spdif_synced(chip);
+err:
+       snd_usb_unlock_shutdown(chip);
+       return err;
+}
+
+static int snd_mbox1_clk_switch_put(struct snd_kcontrol *kctl,
+                                   struct snd_ctl_elem_value *ucontrol)
+{
+       struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
+       struct usb_mixer_interface *mixer = list->mixer;
+       int err;
+       bool cur_val, new_val;
+
+       cur_val = kctl->private_value;
+       new_val = ucontrol->value.enumerated.item[0];
+       if (cur_val == new_val)
+               return 0;
+
+       kctl->private_value = new_val;
+       err = snd_mbox1_clk_switch_update(mixer, new_val);
+       return err < 0 ? err : 1;
+}
+
+static int snd_mbox1_clk_switch_info(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_info *uinfo)
+{
+       static const char *const texts[2] = {
+               "Internal",
+               "S/PDIF"
+       };
+
+       return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
+}
+
+static int snd_mbox1_clk_switch_resume(struct usb_mixer_elem_list *list)
+{
+       return snd_mbox1_clk_switch_update(list->mixer, list->kctl->private_value);
+}
+
+/* Digidesign Mbox 1 input source switch (analog/spdif) */
+
+static int snd_mbox1_src_switch_get(struct snd_kcontrol *kctl,
+                                   struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.enumerated.item[0] = kctl->private_value;
+       return 0;
+}
+
+static int snd_mbox1_src_switch_update(struct usb_mixer_interface *mixer, int is_spdif_input)
+{
+       struct snd_usb_audio *chip = mixer->chip;
+       int err;
+
+       err = snd_usb_lock_shutdown(chip);
+       if (err < 0)
+               return err;
+
+       err = snd_mbox1_is_spdif_input(chip);
        if (err < 0)
                goto err;
-       err = snd_usb_ctl_msg(chip->dev,
-                               usb_rcvctrlpipe(chip->dev, 0), 0x81,
-                               USB_DIR_IN |
-                               USB_TYPE_CLASS |
-                               USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+
+       err = snd_mbox1_set_input_source(chip, is_spdif_input);
        if (err < 0)
                goto err;
-       err = snd_usb_ctl_msg(chip->dev,
-                               usb_rcvctrlpipe(chip->dev, 0), 0x81,
-                               USB_DIR_IN |
-                               USB_TYPE_CLASS |
-                               USB_RECIP_ENDPOINT, 0x100, 0x2, buff, 3);
+
+       err = snd_mbox1_is_spdif_input(chip);
        if (err < 0)
                goto err;
 
+       err = snd_mbox1_is_spdif_synced(chip);
 err:
        snd_usb_unlock_shutdown(chip);
        return err;
 }
 
-static int snd_mbox1_switch_put(struct snd_kcontrol *kctl,
-                               struct snd_ctl_elem_value *ucontrol)
+static int snd_mbox1_src_switch_put(struct snd_kcontrol *kctl,
+                                   struct snd_ctl_elem_value *ucontrol)
 {
        struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
        struct usb_mixer_interface *mixer = list->mixer;
@@ -685,42 +808,60 @@ static int snd_mbox1_switch_put(struct snd_kcontrol *kctl,
                return 0;
 
        kctl->private_value = new_val;
-       err = snd_mbox1_switch_update(mixer, new_val);
+       err = snd_mbox1_src_switch_update(mixer, new_val);
        return err < 0 ? err : 1;
 }
 
-static int snd_mbox1_switch_info(struct snd_kcontrol *kcontrol,
-                                struct snd_ctl_elem_info *uinfo)
+static int snd_mbox1_src_switch_info(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_info *uinfo)
 {
        static const char *const texts[2] = {
-               "Internal",
+               "Analog",
                "S/PDIF"
        };
 
        return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
 }
 
-static int snd_mbox1_switch_resume(struct usb_mixer_elem_list *list)
+static int snd_mbox1_src_switch_resume(struct usb_mixer_elem_list *list)
 {
-       return snd_mbox1_switch_update(list->mixer, list->kctl->private_value);
+       return snd_mbox1_src_switch_update(list->mixer, list->kctl->private_value);
 }
 
-static const struct snd_kcontrol_new snd_mbox1_switch = {
+static const struct snd_kcontrol_new snd_mbox1_clk_switch = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Clock Source",
        .index = 0,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-       .info = snd_mbox1_switch_info,
-       .get = snd_mbox1_switch_get,
-       .put = snd_mbox1_switch_put,
+       .info = snd_mbox1_clk_switch_info,
+       .get = snd_mbox1_clk_switch_get,
+       .put = snd_mbox1_clk_switch_put,
+       .private_value = 0
+};
+
+static const struct snd_kcontrol_new snd_mbox1_src_switch = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Input Source",
+       .index = 1,
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = snd_mbox1_src_switch_info,
+       .get = snd_mbox1_src_switch_get,
+       .put = snd_mbox1_src_switch_put,
        .private_value = 0
 };
 
-static int snd_mbox1_create_sync_switch(struct usb_mixer_interface *mixer)
+static int snd_mbox1_controls_create(struct usb_mixer_interface *mixer)
 {
-       return add_single_ctl_with_resume(mixer, 0,
-                                         snd_mbox1_switch_resume,
-                                         &snd_mbox1_switch, NULL);
+       int err;
+       err = add_single_ctl_with_resume(mixer, 0,
+                                        snd_mbox1_clk_switch_resume,
+                                        &snd_mbox1_clk_switch, NULL);
+       if (err < 0)
+               return err;
+
+       return add_single_ctl_with_resume(mixer, 1,
+                                         snd_mbox1_src_switch_resume,
+                                         &snd_mbox1_src_switch, NULL);
 }
 
 /* Native Instruments device quirks */
@@ -3029,7 +3170,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
                break;
 
        case USB_ID(0x0dba, 0x1000): /* Digidesign Mbox 1 */
-               err = snd_mbox1_create_sync_switch(mixer);
+               err = snd_mbox1_controls_create(mixer);
                break;
 
        case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */
index 4e5031a..5dc9266 100644 (file)
@@ -614,6 +614,15 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
        subs->period_elapsed_pending = 0;
        runtime->delay = 0;
 
+       /* check whether early start is needed for playback stream */
+       subs->early_playback_start =
+               subs->direction == SNDRV_PCM_STREAM_PLAYBACK &&
+               (!chip->lowlatency ||
+                (subs->data_endpoint->nominal_queue_size >= subs->buffer_bytes));
+
+       if (subs->early_playback_start)
+               ret = start_endpoints(subs);
+
  unlock:
        snd_usb_unlock_shutdown(chip);
        return ret;
@@ -1394,7 +1403,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
                subs->trigger_tstamp_pending_update = false;
        }
 
-       if (period_elapsed && !subs->running) {
+       if (period_elapsed && !subs->running && !subs->early_playback_start) {
                subs->period_elapsed_pending = 1;
                period_elapsed = 0;
        }
@@ -1448,7 +1457,8 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
                                              prepare_playback_urb,
                                              retire_playback_urb,
                                              subs);
-               if (cmd == SNDRV_PCM_TRIGGER_START) {
+               if (!subs->early_playback_start &&
+                   cmd == SNDRV_PCM_TRIGGER_START) {
                        err = start_endpoints(subs);
                        if (err < 0) {
                                snd_usb_endpoint_set_callback(subs->data_endpoint,
index 19bb499..e03043f 100644 (file)
@@ -2730,23 +2730,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 
-/* Lenovo ThinkStation P620 Rear Line-in, Line-out and Microphone */
-{
-       USB_DEVICE(0x17aa, 0x1046),
-       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-               .ifnum = QUIRK_ANY_INTERFACE,
-               .type = QUIRK_SETUP_DISABLE_AUTOSUSPEND
-       }
-},
-/* Lenovo ThinkStation P620 Internal Speaker + Front Headset */
-{
-       USB_DEVICE(0x17aa, 0x104d),
-       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-               .ifnum = QUIRK_ANY_INTERFACE,
-               .type = QUIRK_SETUP_DISABLE_AUTOSUSPEND
-       }
-},
-
 /* Native Instruments MK2 series */
 {
        /* Komplete Audio 6 */
@@ -2802,53 +2785,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 
-/*
- * Auvitek au0828 devices with audio interface.
- * This should be kept in sync with drivers/media/usb/au0828/au0828-cards.c
- * Please notice that some drivers are DVB only, and don't need to be
- * here. That's the case, for example, of DVICO_FUSIONHDTV7.
- */
-
-#define AU0828_DEVICE(vid, pid, vname, pname) { \
-       USB_AUDIO_DEVICE(vid, pid), \
-       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { \
-               .vendor_name = vname, \
-               .product_name = pname, \
-               .ifnum = QUIRK_ANY_INTERFACE, \
-               .type = QUIRK_AUDIO_ALIGN_TRANSFER, \
-               .shares_media_device = 1, \
-       } \
-}
-
-AU0828_DEVICE(0x2040, 0x7200, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7240, "Hauppauge", "HVR-850"),
-AU0828_DEVICE(0x2040, 0x7210, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7217, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x721b, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x721e, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x721f, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7280, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x0fd9, 0x0008, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7201, "Hauppauge", "HVR-950Q-MXL"),
-AU0828_DEVICE(0x2040, 0x7211, "Hauppauge", "HVR-950Q-MXL"),
-AU0828_DEVICE(0x2040, 0x7281, "Hauppauge", "HVR-950Q-MXL"),
-AU0828_DEVICE(0x05e1, 0x0480, "Hauppauge", "Woodbury"),
-AU0828_DEVICE(0x2040, 0x8200, "Hauppauge", "Woodbury"),
-AU0828_DEVICE(0x2040, 0x7260, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7213, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
-
-/* Syntek STK1160 */
-{
-       USB_AUDIO_DEVICE(0x05e1, 0x0408),
-       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
-               .vendor_name = "Syntek",
-               .product_name = "STK1160",
-               .ifnum = QUIRK_ANY_INTERFACE,
-               .type = QUIRK_AUDIO_ALIGN_TRANSFER
-       }
-},
-
 /* Digidesign Mbox */
 {
        /* Thanks to Clemens Ladisch <clemens@ladisch.de> */
@@ -3811,7 +3747,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
  * MacroSilicon MS2109 based HDMI capture cards
  *
  * These claim 96kHz 1ch in the descriptors, but are actually 48kHz 2ch.
- * They also need QUIRK_AUDIO_ALIGN_TRANSFER, which makes one wonder if
+ * They also need QUIRK_FLAG_ALIGN_TRANSFER, which makes one wonder if
  * they pretend to be 96kHz mono as a workaround for stereo being broken
  * by that...
  *
@@ -3826,10 +3762,6 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                .ifnum = QUIRK_ANY_INTERFACE,
                .type = QUIRK_COMPOSITE,
                .data = &(const struct snd_usb_audio_quirk[]) {
-                       {
-                               .ifnum = 2,
-                               .type = QUIRK_AUDIO_ALIGN_TRANSFER,
-                       },
                        {
                                .ifnum = 2,
                                .type = QUIRK_AUDIO_STANDARD_MIXER,
index 326d1b0..4479a59 100644 (file)
@@ -75,19 +75,6 @@ static int ignore_interface_quirk(struct snd_usb_audio *chip,
 }
 
 
-/*
- * Allow alignment on audio sub-slot (channel samples) rather than
- * on audio slots (audio frames)
- */
-static int create_align_transfer_quirk(struct snd_usb_audio *chip,
-                                      struct usb_interface *iface,
-                                      struct usb_driver *driver,
-                                      const struct snd_usb_audio_quirk *quirk)
-{
-       chip->txfr_quirk = 1;
-       return 1;       /* Continue with creating streams and mixer */
-}
-
 static int create_any_midi_quirk(struct snd_usb_audio *chip,
                                 struct usb_interface *intf,
                                 struct usb_driver *driver,
@@ -108,9 +95,6 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
        struct usb_interface_descriptor *altsd;
        int err;
 
-       if (chip->usb_id == USB_ID(0x1686, 0x00dd)) /* Zoom R16/24 */
-               chip->tx_length_quirk = 1;
-
        alts = &iface->altsetting[0];
        altsd = get_iface_desc(alts);
        err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber);
@@ -547,16 +531,7 @@ static int create_standard_mixer_quirk(struct snd_usb_audio *chip,
        if (quirk->ifnum < 0)
                return 0;
 
-       return snd_usb_create_mixer(chip, quirk->ifnum, 0);
-}
-
-static int setup_disable_autosuspend(struct snd_usb_audio *chip,
-                                      struct usb_interface *iface,
-                                      struct usb_driver *driver,
-                                      const struct snd_usb_audio_quirk *quirk)
-{
-       usb_disable_autosuspend(interface_to_usbdev(iface));
-       return 1;       /* Continue with creating streams and mixer */
+       return snd_usb_create_mixer(chip, quirk->ifnum);
 }
 
 /*
@@ -595,9 +570,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
                [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
                [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
                [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
-               [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk,
                [QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk,
-               [QUIRK_SETUP_DISABLE_AUTOSUSPEND] = setup_disable_autosuspend,
        };
 
        if (quirk->type < QUIRK_TYPE_COUNT) {
@@ -1518,62 +1491,13 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
        }
 }
 
-bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
-{
-       /* devices which do not support reading the sample rate. */
-       switch (chip->usb_id) {
-       case USB_ID(0x041e, 0x4080): /* Creative Live Cam VF0610 */
-       case USB_ID(0x04d8, 0xfeea): /* Benchmark DAC1 Pre */
-       case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */
-       case USB_ID(0x05a3, 0x9420): /* ELP HD USB Camera */
-       case USB_ID(0x05a7, 0x1020): /* Bose Companion 5 */
-       case USB_ID(0x074d, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
-       case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */
-       case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */
-       case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */
-       case USB_ID(0x2912, 0x30c8): /* Audioengine D1 */
-       case USB_ID(0x413c, 0xa506): /* Dell AE515 sound bar */
-       case USB_ID(0x046d, 0x084c): /* Logitech ConferenceCam Connect */
-               return true;
-       }
-
-       /* devices of these vendors don't support reading rate, either */
-       switch (USB_ID_VENDOR(chip->usb_id)) {
-       case 0x045e: /* MS Lifecam */
-       case 0x047f: /* Plantronics */
-       case 0x1de7: /* Phoenix Audio */
-               return true;
-       }
-
-       return false;
-}
-
-/* ITF-USB DSD based DACs need a vendor cmd to switch
- * between PCM and native DSD mode
- */
-static bool is_itf_usb_dsd_dac(unsigned int id)
-{
-       switch (id) {
-       case USB_ID(0x154e, 0x1002): /* Denon DCD-1500RE */
-       case USB_ID(0x154e, 0x1003): /* Denon DA-300USB */
-       case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */
-       case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */
-       case USB_ID(0x1852, 0x5065): /* Luxman DA-06 */
-       case USB_ID(0x0644, 0x8043): /* TEAC UD-501/UD-501V2/UD-503/NT-503 */
-       case USB_ID(0x0644, 0x8044): /* Esoteric D-05X */
-       case USB_ID(0x0644, 0x804a): /* TEAC UD-301 */
-               return true;
-       }
-       return false;
-}
-
 int snd_usb_select_mode_quirk(struct snd_usb_audio *chip,
                              const struct audioformat *fmt)
 {
        struct usb_device *dev = chip->dev;
        int err;
 
-       if (is_itf_usb_dsd_dac(chip->usb_id)) {
+       if (chip->quirk_flags & QUIRK_FLAG_ITF_USB_DSD_DAC) {
                /* First switch to alt set 0, otherwise the mode switch cmd
                 * will not be accepted by the DAC
                 */
@@ -1636,22 +1560,6 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
                ep->tenor_fb_quirk = 1;
 }
 
-void snd_usb_set_interface_quirk(struct snd_usb_audio *chip)
-{
-       if (!chip)
-               return;
-       /*
-        * "Playback Design" products need a 50ms delay after setting the
-        * USB interface.
-        */
-       switch (USB_ID_VENDOR(chip->usb_id)) {
-       case 0x23ba: /* Playback Design */
-       case 0x0644: /* TEAC Corp. */
-               msleep(50);
-               break;
-       }
-}
-
 /* quirk applied after snd_usb_ctl_msg(); not applied during boot quirks */
 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
                           __u8 request, __u8 requesttype, __u16 value,
@@ -1659,57 +1567,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
 {
        struct snd_usb_audio *chip = dev_get_drvdata(&dev->dev);
 
-       if (!chip)
+       if (!chip || (requesttype & USB_TYPE_MASK) != USB_TYPE_CLASS)
                return;
-       /*
-        * "Playback Design" products need a 20ms delay after each
-        * class compliant request
-        */
-       if (USB_ID_VENDOR(chip->usb_id) == 0x23ba &&
-           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
-               msleep(20);
-
-       /*
-        * "TEAC Corp." products need a 20ms delay after each
-        * class compliant request
-        */
-       if (USB_ID_VENDOR(chip->usb_id) == 0x0644 &&
-           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
-               msleep(20);
-
-       /* ITF-USB DSD based DACs functionality need a delay
-        * after each class compliant request
-        */
-       if (is_itf_usb_dsd_dac(chip->usb_id)
-           && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
-               msleep(20);
 
-       /*
-        * Plantronics headsets (C320, C320-M, etc) need a delay to avoid
-        * random microhpone failures.
-        */
-       if (USB_ID_VENDOR(chip->usb_id) == 0x047f &&
-           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+       if (chip->quirk_flags & QUIRK_FLAG_CTL_MSG_DELAY)
                msleep(20);
-
-       /* Zoom R16/24, many Logitech(at least H650e/H570e/BCC950),
-        * Jabra 550a, Kingston HyperX needs a tiny delay here,
-        * otherwise requests like get/set frequency return
-        * as failed despite actually succeeding.
-        */
-       if ((chip->usb_id == USB_ID(0x1686, 0x00dd) ||
-            USB_ID_VENDOR(chip->usb_id) == 0x046d  || /* Logitech */
-            chip->usb_id == USB_ID(0x0b0e, 0x0349) ||
-            chip->usb_id == USB_ID(0x0951, 0x16ad)) &&
-           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+       else if (chip->quirk_flags & QUIRK_FLAG_CTL_MSG_DELAY_1M)
                usleep_range(1000, 2000);
-
-       /*
-        * Samsung USBC Headset (AKG) need a tiny delay after each
-        * class compliant request. (Model number: AAM625R or AAM627R)
-        */
-       if (chip->usb_id == USB_ID(0x04e8, 0xa051) &&
-           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+       else if (chip->quirk_flags & QUIRK_FLAG_CTL_MSG_DELAY_5M)
                usleep_range(5000, 6000);
 }
 
@@ -1796,7 +1661,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        }
 
        /* ITF-USB DSD based DACs */
-       if (is_itf_usb_dsd_dac(chip->usb_id)) {
+       if (chip->quirk_flags & QUIRK_FLAG_ITF_USB_DSD_DAC) {
                iface = usb_ifnum_to_if(chip->dev, fp->iface);
 
                /* Altsetting 2 support native DSD if the num of altsets is
@@ -1808,29 +1673,9 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
        }
 
-       /* Mostly generic method to detect many DSD-capable implementations -
-        * from XMOS/Thesycon
-        */
-       switch (USB_ID_VENDOR(chip->usb_id)) {
-       case 0x152a:  /* Thesycon devices */
-       case 0x20b1:  /* XMOS based devices */
-       case 0x22d9:  /* Oppo */
-       case 0x23ba:  /* Playback Designs */
-       case 0x25ce:  /* Mytek devices */
-       case 0x278b:  /* Rotel? */
-       case 0x292b:  /* Gustard/Ess based devices */
-       case 0x2972:  /* FiiO devices */
-       case 0x2ab6:  /* T+A devices */
-       case 0x3353:  /* Khadas devices */
-       case 0x3842:  /* EVGA */
-       case 0xc502:  /* HiBy devices */
-               if (fp->dsd_raw)
-                       return SNDRV_PCM_FMTBIT_DSD_U32_BE;
-               break;
-       default:
-               break;
-
-       }
+       /* Mostly generic method to detect many DSD-capable implementations */
+       if ((chip->quirk_flags & QUIRK_FLAG_DSD_RAW) && fp->dsd_raw)
+               return SNDRV_PCM_FMTBIT_DSD_U32_BE;
 
        return 0;
 }
@@ -1916,3 +1761,189 @@ bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface)
        /* Register as normal */
        return false;
 }
+
+/*
+ * driver behavior quirk flags
+ */
+struct usb_audio_quirk_flags_table {
+       u32 id;
+       u32 flags;
+};
+
+#define DEVICE_FLG(vid, pid, _flags) \
+       { .id = USB_ID(vid, pid), .flags = (_flags) }
+#define VENDOR_FLG(vid, _flags) DEVICE_FLG(vid, 0, _flags)
+
+static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+       /* Device matches */
+       DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x046d, 0x084c, /* Logitech ConferenceCam Connect */
+                  QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY_1M),
+       DEVICE_FLG(0x046d, 0x0991, /* Logitech QuickCam Pro */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x046d, 0x09a4, /* Logitech QuickCam E 3500 */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x04d8, 0xfeea, /* Benchmark DAC1 Pre */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x04e8, 0xa051, /* Samsung USBC Headset (AKG) */
+                  QUIRK_FLAG_SKIP_CLOCK_SELECTOR | QUIRK_FLAG_CTL_MSG_DELAY_5M),
+       DEVICE_FLG(0x054c, 0x0b8c, /* Sony WALKMAN NW-A45 DAC */
+                  QUIRK_FLAG_SET_IFACE_FIRST),
+       DEVICE_FLG(0x0556, 0x0014, /* Phoenix Audio TMX320VC */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x05a3, 0x9420, /* ELP HD USB Camera */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x05a7, 0x1020, /* Bose Companion 5 */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x05e1, 0x0408, /* Syntek STK1160 */
+                  QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x05e1, 0x0480, /* Hauppauge Woodbury */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x0644, 0x8043, /* TEAC UD-501/UD-501V2/UD-503/NT-503 */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+                  QUIRK_FLAG_IFACE_DELAY),
+       DEVICE_FLG(0x0644, 0x8044, /* Esoteric D-05X */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+                  QUIRK_FLAG_IFACE_DELAY),
+       DEVICE_FLG(0x0644, 0x804a, /* TEAC UD-301 */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+                  QUIRK_FLAG_IFACE_DELAY),
+       DEVICE_FLG(0x06f8, 0xb000, /* Hercules DJ Console (Windows Edition) */
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x06f8, 0xd002, /* Hercules DJ Console (Macintosh Edition) */
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x074d, 0x3553, /* Outlaw RR2150 (Micronas UAC3553B) */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x08bb, 0x2702, /* LineX FM Transmitter */
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x0951, 0x16ad, /* Kingston HyperX */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M),
+       DEVICE_FLG(0x0b0e, 0x0349, /* Jabra 550a */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M),
+       DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x13e5, 0x0001, /* Serato Phono */
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x154e, 0x1002, /* Denon DCD-1500RE */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x154e, 0x1003, /* Denon DA-300USB */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x154e, 0x3005, /* Marantz HD-DAC1 */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x154e, 0x3006, /* Marantz SA-14S1 */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x154e, 0x500e, /* Denon DN-X1600 */
+                  QUIRK_FLAG_IGNORE_CLOCK_SOURCE),
+       DEVICE_FLG(0x1686, 0x00dd, /* Zoom R16/24 */
+                  QUIRK_FLAG_TX_LENGTH | QUIRK_FLAG_CTL_MSG_DELAY_1M),
+       DEVICE_FLG(0x17aa, 0x1046, /* Lenovo ThinkStation P620 Rear Line-in, Line-out and Microphone */
+                  QUIRK_FLAG_DISABLE_AUTOSUSPEND),
+       DEVICE_FLG(0x17aa, 0x104d, /* Lenovo ThinkStation P620 Internal Speaker + Front Headset */
+                  QUIRK_FLAG_DISABLE_AUTOSUSPEND),
+       DEVICE_FLG(0x1852, 0x5065, /* Luxman DA-06 */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7210, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7211, /* Hauppauge HVR-950Q-MXL */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7213, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7217, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x721b, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x721e, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x721f, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7240, /* Hauppauge HVR-850 */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7260, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7270, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7280, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7281, /* Hauppauge HVR-950Q-MXL */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x8200, /* Hauppauge Woodbury */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */
+                  QUIRK_FLAG_ALIGN_TRANSFER),
+
+       /* Vendor matches */
+       VENDOR_FLG(0x045e, /* MS Lifecam */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       VENDOR_FLG(0x046d, /* Logitech */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M),
+       VENDOR_FLG(0x047f, /* Plantronics */
+                  QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY),
+       VENDOR_FLG(0x0644, /* TEAC Corp. */
+                  QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY),
+       VENDOR_FLG(0x07fd, /* MOTU */
+                  QUIRK_FLAG_VALIDATE_RATES),
+       VENDOR_FLG(0x152a, /* Thesycon devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x1de7, /* Phoenix Audio */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       VENDOR_FLG(0x20b1, /* XMOS based devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x22d9, /* Oppo */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x23ba, /* Playback Design */
+                  QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY |
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x25ce, /* Mytek devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x278b, /* Rotel? */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x292b, /* Gustard/Ess based devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x2972, /* FiiO devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x2ab6, /* T+A devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x3353, /* Khadas devices */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x3842, /* EVGA */
+                  QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0xc502, /* HiBy devices */
+                  QUIRK_FLAG_DSD_RAW),
+
+       {} /* terminator */
+};
+
+void snd_usb_init_quirk_flags(struct snd_usb_audio *chip)
+{
+       const struct usb_audio_quirk_flags_table *p;
+
+       for (p = quirk_flags_table; p->id; p++) {
+               if (chip->usb_id == p->id ||
+                   (!USB_ID_PRODUCT(p->id) &&
+                    USB_ID_VENDOR(chip->usb_id) == USB_ID_VENDOR(p->id))) {
+                       usb_audio_dbg(chip,
+                                     "Set quirk_flags 0x%x for device %04x:%04x\n",
+                                     p->flags, USB_ID_VENDOR(chip->usb_id),
+                                     USB_ID_PRODUCT(chip->usb_id));
+                       chip->quirk_flags |= p->flags;
+                       return;
+               }
+       }
+}
index 67a0230..31abb7c 100644 (file)
@@ -28,14 +28,11 @@ int snd_usb_apply_boot_quirk_once(struct usb_device *dev,
 void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
                              const struct audioformat *fmt);
 
-bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip);
-
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
                                 const struct audioformat *fp);
 
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);
 
-void snd_usb_set_interface_quirk(struct snd_usb_audio *chip);
 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
                           __u8 request, __u8 requesttype, __u16 value,
                           __u16 index, void *data, __u16 size);
@@ -53,4 +50,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip,
 
 bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface);
 
+void snd_usb_init_quirk_flags(struct snd_usb_audio *chip);
+
 #endif /* __USBAUDIO_QUIRKS_H */
index ee9aa1d..ceb93d7 100644 (file)
@@ -89,8 +89,8 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,
        subs->stream = as;
        subs->direction = stream;
        subs->dev = as->chip->dev;
-       subs->txfr_quirk = as->chip->txfr_quirk;
-       subs->tx_length_quirk = as->chip->tx_length_quirk;
+       subs->txfr_quirk = !!(as->chip->quirk_flags & QUIRK_FLAG_ALIGN_TRANSFER);
+       subs->tx_length_quirk = !!(as->chip->quirk_flags & QUIRK_FLAG_TX_LENGTH);
        subs->speed = snd_usb_get_speed(subs->dev);
        subs->pkt_offset_adj = 0;
        subs->stream_offset_adj = 0;
index 538831c..1678341 100644 (file)
@@ -34,10 +34,8 @@ struct snd_usb_audio {
        atomic_t shutdown;
        atomic_t usage_count;
        wait_queue_head_t shutdown_wait;
-       unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
-       unsigned int tx_length_quirk:1; /* Put length specifier in transfers */
+       unsigned int quirk_flags;
        unsigned int need_delayed_register:1; /* warn for delayed registration */
-       unsigned int playback_first:1;  /* for implicit fb: don't wait for the first capture URBs */
        int num_interfaces;
        int num_suspended_intf;
        int sample_rate_read_error;
@@ -57,6 +55,7 @@ struct snd_usb_audio {
        bool generic_implicit_fb;       /* from the 'implicit_fb' module param */
        bool autoclock;                 /* from the 'autoclock' module param */
 
+       bool lowlatency;                /* from the 'lowlatency' module param */
        struct usb_host_interface *ctrl_intf;   /* the audio control interface */
        struct media_device *media_dev;
        struct media_intf_devnode *ctl_intf_media_devnode;
@@ -102,10 +101,7 @@ enum quirk_type {
        QUIRK_AUDIO_STANDARD_INTERFACE,
        QUIRK_AUDIO_FIXED_ENDPOINT,
        QUIRK_AUDIO_EDIROL_UAXX,
-       QUIRK_AUDIO_ALIGN_TRANSFER,
        QUIRK_AUDIO_STANDARD_MIXER,
-       QUIRK_SETUP_FMT_AFTER_RESUME,
-       QUIRK_SETUP_DISABLE_AUTOSUSPEND,
 
        QUIRK_TYPE_COUNT
 };
@@ -115,7 +111,6 @@ struct snd_usb_audio_quirk {
        const char *product_name;
        int16_t ifnum;
        uint16_t type;
-       bool shares_media_device;
        const void *data;
 };
 
@@ -129,4 +124,64 @@ void snd_usb_unlock_shutdown(struct snd_usb_audio *chip);
 extern bool snd_usb_use_vmalloc;
 extern bool snd_usb_skip_validation;
 
+/*
+ * Driver behavior quirk flags, stored in chip->quirk_flags
+ *
+ * QUIRK_FLAG_GET_SAMPLE_RATE:
+ *  Skip reading sample rate for devices, as some devices behave inconsistently
+ *  or return error
+ * QUIRK_FLAG_SHARE_MEDIA_DEVICE:
+ *  Create Media Controller API entries
+ * QUIRK_FLAG_ALIGN_TRANSFER:
+ *  Allow alignment on audio sub-slot (channel samples) rather than on audio
+ *  slots (audio frames)
+ * QUIRK_TX_LENGTH:
+ *  Add length specifier to transfers
+ * QUIRK_FLAG_PLAYBACK_FIRST:
+ *  Start playback stream at first even in implement feedback mode
+ * QUIRK_FLAG_SKIP_CLOCK_SELECTOR:
+ *  Skip clock selector setup; the device may reset to invalid state
+ * QUIRK_FLAG_IGNORE_CLOCK_SOURCE:
+ *  Ignore errors from clock source search; i.e. hardcoded clock
+ * QUIRK_FLAG_ITF_USB_DSD_DAC:
+ *  Indicates the device is for ITF-USB DSD based DACs that need a vendor cmd
+ *  to switch between PCM and native DSD mode
+ * QUIRK_FLAG_CTL_MSG_DELAY:
+ *  Add a delay of 20ms at each control message handling
+ * QUIRK_FLAG_CTL_MSG_DELAY_1M:
+ *  Add a delay of 1-2ms at each control message handling
+ * QUIRK_FLAG_CTL_MSG_DELAY_5M:
+ *  Add a delay of 5-6ms at each control message handling
+ * QUIRK_FLAG_IFACE_DELAY:
+ *  Add a delay of 50ms at each interface setup
+ * QUIRK_FLAG_VALIDATE_RATES:
+ *  Perform sample rate validations at probe
+ * QUIRK_FLAG_DISABLE_AUTOSUSPEND:
+ *  Disable runtime PM autosuspend
+ * QUIRK_FLAG_IGNORE_CTL_ERROR:
+ *  Ignore errors for mixer access
+ * QUIRK_FLAG_DSD_RAW:
+ *  Support generic DSD raw U32_BE format
+ * QUIRK_FLAG_SET_IFACE_FIRST:
+ *  Set up the interface at first like UAC1
+ */
+
+#define QUIRK_FLAG_GET_SAMPLE_RATE     (1U << 0)
+#define QUIRK_FLAG_SHARE_MEDIA_DEVICE  (1U << 1)
+#define QUIRK_FLAG_ALIGN_TRANSFER      (1U << 2)
+#define QUIRK_FLAG_TX_LENGTH           (1U << 3)
+#define QUIRK_FLAG_PLAYBACK_FIRST      (1U << 4)
+#define QUIRK_FLAG_SKIP_CLOCK_SELECTOR (1U << 5)
+#define QUIRK_FLAG_IGNORE_CLOCK_SOURCE (1U << 6)
+#define QUIRK_FLAG_ITF_USB_DSD_DAC     (1U << 7)
+#define QUIRK_FLAG_CTL_MSG_DELAY       (1U << 8)
+#define QUIRK_FLAG_CTL_MSG_DELAY_1M    (1U << 9)
+#define QUIRK_FLAG_CTL_MSG_DELAY_5M    (1U << 10)
+#define QUIRK_FLAG_IFACE_DELAY         (1U << 11)
+#define QUIRK_FLAG_VALIDATE_RATES      (1U << 12)
+#define QUIRK_FLAG_DISABLE_AUTOSUSPEND (1U << 13)
+#define QUIRK_FLAG_IGNORE_CTL_ERROR    (1U << 14)
+#define QUIRK_FLAG_DSD_RAW             (1U << 15)
+#define QUIRK_FLAG_SET_IFACE_FIRST     (1U << 16)
+
 #endif /* __USBAUDIO_H */
index a34d7d9..3788263 100644 (file)
@@ -1024,19 +1024,21 @@ static void wait_clear_underrun_bit(struct snd_intelhad *intelhaddata)
        dev_err(intelhaddata->dev, "Unable to clear UNDERRUN bits\n");
 }
 
-/* Perform some reset procedure but only when need_reset is set;
+/* Perform some reset procedure after stopping the stream;
  * this is called from prepare or hw_free callbacks once after trigger STOP
  * or underrun has been processed in order to settle down the h/w state.
  */
-static void had_do_reset(struct snd_intelhad *intelhaddata)
+static int had_pcm_sync_stop(struct snd_pcm_substream *substream)
 {
-       if (!intelhaddata->need_reset || !intelhaddata->connected)
-               return;
+       struct snd_intelhad *intelhaddata = snd_pcm_substream_chip(substream);
+
+       if (!intelhaddata->connected)
+               return 0;
 
        /* Reset buffer pointers */
        had_reset_audio(intelhaddata);
        wait_clear_underrun_bit(intelhaddata);
-       intelhaddata->need_reset = false;
+       return 0;
 }
 
 /* called from irq handler */
@@ -1050,7 +1052,6 @@ static void had_process_buffer_underrun(struct snd_intelhad *intelhaddata)
                snd_pcm_stop_xrun(substream);
                had_substream_put(intelhaddata);
        }
-       intelhaddata->need_reset = true;
 }
 
 /*
@@ -1141,19 +1142,6 @@ static int had_pcm_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-/*
- * ALSA PCM hw_free callback
- */
-static int had_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       struct snd_intelhad *intelhaddata;
-
-       intelhaddata = snd_pcm_substream_chip(substream);
-       had_do_reset(intelhaddata);
-
-       return 0;
-}
-
 /*
  * ALSA PCM trigger callback
  */
@@ -1178,7 +1166,6 @@ static int had_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                /* Disable Audio */
                had_enable_audio(intelhaddata, false);
-               intelhaddata->need_reset = true;
                break;
 
        default:
@@ -1210,8 +1197,6 @@ static int had_pcm_prepare(struct snd_pcm_substream *substream)
        dev_dbg(intelhaddata->dev, "rate=%d\n", runtime->rate);
        dev_dbg(intelhaddata->dev, "channels=%d\n", runtime->channels);
 
-       had_do_reset(intelhaddata);
-
        /* Get N value in KHz */
        disp_samp_freq = intelhaddata->tmds_clock_speed;
 
@@ -1287,9 +1272,9 @@ static const struct snd_pcm_ops had_pcm_ops = {
        .open =         had_pcm_open,
        .close =        had_pcm_close,
        .hw_params =    had_pcm_hw_params,
-       .hw_free =      had_pcm_hw_free,
        .prepare =      had_pcm_prepare,
        .trigger =      had_pcm_trigger,
+       .sync_stop =    had_pcm_sync_stop,
        .pointer =      had_pcm_pointer,
        .mmap =         had_pcm_mmap,
 };
@@ -1672,11 +1657,6 @@ static void hdmi_lpe_audio_free(struct snd_card *card)
 
                cancel_work_sync(&ctx->hdmi_audio_wq);
        }
-
-       if (card_ctx->mmio_start)
-               iounmap(card_ctx->mmio_start);
-       if (card_ctx->irq >= 0)
-               free_irq(card_ctx->irq, card_ctx);
 }
 
 /*
@@ -1714,8 +1694,8 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
        }
 
        /* create a card instance with ALSA framework */
-       ret = snd_card_new(&pdev->dev, hdmi_card_index, hdmi_card_id,
-                          THIS_MODULE, sizeof(*card_ctx), &card);
+       ret = snd_devm_card_new(&pdev->dev, hdmi_card_index, hdmi_card_id,
+                               THIS_MODULE, sizeof(*card_ctx), &card);
        if (ret)
                return ret;
 
@@ -1751,20 +1731,20 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
                __func__, (unsigned int)res_mmio->start,
                (unsigned int)res_mmio->end);
 
-       card_ctx->mmio_start = ioremap(res_mmio->start,
-                                              (size_t)(resource_size(res_mmio)));
+       card_ctx->mmio_start =
+               devm_ioremap(&pdev->dev, res_mmio->start,
+                            (size_t)(resource_size(res_mmio)));
        if (!card_ctx->mmio_start) {
                dev_err(&pdev->dev, "Could not get ioremap\n");
-               ret = -EACCES;
-               goto err;
+               return -EACCES;
        }
 
        /* setup interrupt handler */
-       ret = request_irq(irq, display_pipe_interrupt_handler, 0,
-                         pdev->name, card_ctx);
+       ret = devm_request_irq(&pdev->dev, irq, display_pipe_interrupt_handler,
+                              0, pdev->name, card_ctx);
        if (ret < 0) {
                dev_err(&pdev->dev, "request_irq failed\n");
-               goto err;
+               return ret;
        }
 
        card_ctx->irq = irq;
@@ -1784,7 +1764,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
                ret = snd_pcm_new(card, INTEL_HAD, port, MAX_PB_STREAMS,
                                  MAX_CAP_STREAMS, &pcm);
                if (ret)
-                       goto err;
+                       return ret;
 
                /* setup private data which can be retrieved when required */
                pcm->private_data = ctx;
@@ -1796,7 +1776,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
                /* allocate dma pages;
                 * try to allocate 600k buffer as default which is large enough
                 */
-               snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_UC,
+               snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
                                               card->dev, HAD_DEFAULT_BUFFER,
                                               HAD_MAX_BUFFER);
 
@@ -1805,31 +1785,29 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
                        struct snd_kcontrol *kctl;
 
                        kctl = snd_ctl_new1(&had_controls[i], ctx);
-                       if (!kctl) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
+                       if (!kctl)
+                               return -ENOMEM;
 
                        kctl->id.device = pcm->device;
 
                        ret = snd_ctl_add(card, kctl);
                        if (ret < 0)
-                               goto err;
+                               return ret;
                }
 
                /* Register channel map controls */
                ret = had_register_chmap_ctls(ctx, pcm);
                if (ret < 0)
-                       goto err;
+                       return ret;
 
                ret = had_create_jack(ctx, pcm);
                if (ret < 0)
-                       goto err;
+                       return ret;
        }
 
        ret = snd_card_register(card);
        if (ret)
-               goto err;
+               return ret;
 
        spin_lock_irq(&pdata->lpe_audio_slock);
        pdata->notify_audio_lpe = notify_audio_lpe;
@@ -1846,23 +1824,6 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
        }
 
        return 0;
-
-err:
-       snd_card_free(card);
-       return ret;
-}
-
-/*
- * hdmi_lpe_audio_remove - stop bridge with i915
- *
- * This function is called when the platform device is destroyed.
- */
-static int hdmi_lpe_audio_remove(struct platform_device *pdev)
-{
-       struct snd_intelhad_card *card_ctx = platform_get_drvdata(pdev);
-
-       snd_card_free(card_ctx->card);
-       return 0;
 }
 
 static const struct dev_pm_ops hdmi_lpe_audio_pm = {
@@ -1875,7 +1836,6 @@ static struct platform_driver hdmi_lpe_audio_driver = {
                .pm = &hdmi_lpe_audio_pm,
        },
        .probe          = hdmi_lpe_audio_probe,
-       .remove         = hdmi_lpe_audio_remove,
 };
 
 module_platform_driver(hdmi_lpe_audio_driver);
index bb38531..7ce8c2a 100644 (file)
@@ -127,7 +127,6 @@ struct snd_intelhad {
        union aud_cfg aud_config;       /* AUD_CONFIG reg value cache */
        struct work_struct hdmi_audio_wq;
        struct mutex mutex; /* for protecting chmap and eld */
-       bool need_reset;
        struct snd_jack *jack;
 };