summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/ac97/bus.c6
-rw-r--r--sound/aoa/soundbus/core.c4
-rw-r--r--sound/arm/pxa2xx-ac97.c18
-rw-r--r--sound/arm/pxa2xx-pcm-lib.c90
-rw-r--r--sound/core/compress_offload.c69
-rw-r--r--sound/core/control_led.c2
-rw-r--r--sound/core/init.c105
-rw-r--r--sound/core/isadma.c38
-rw-r--r--sound/core/memalloc.c177
-rw-r--r--sound/core/memalloc_local.h2
-rw-r--r--sound/core/pcm_lib.c2
-rw-r--r--sound/core/pcm_memory.c67
-rw-r--r--sound/core/pcm_native.c18
-rw-r--r--sound/core/seq/seq_dummy.c8
-rw-r--r--sound/core/sgbuf.c30
-rw-r--r--sound/drivers/Kconfig2
-rw-r--r--sound/drivers/aloop.c26
-rw-r--r--sound/drivers/dummy.c24
-rw-r--r--sound/drivers/mpu401/mpu401.c34
-rw-r--r--sound/drivers/mtpav.c30
-rw-r--r--sound/drivers/pcsp/pcsp.c49
-rw-r--r--sound/drivers/pcsp/pcsp_input.c14
-rw-r--r--sound/drivers/pcsp/pcsp_input.h1
-rw-r--r--sound/drivers/serial-u16550.c57
-rw-r--r--sound/drivers/virmidi.c21
-rw-r--r--sound/drivers/vx/vx_core.c12
-rw-r--r--sound/firewire/motu/motu-protocol-v2.c22
-rw-r--r--sound/firewire/motu/motu.c1
-rw-r--r--sound/firewire/motu/motu.h1
-rw-r--r--sound/isa/ad1816a/ad1816a.c41
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c49
-rw-r--r--sound/isa/ad1848/ad1848.c19
-rw-r--r--sound/isa/adlib.c28
-rw-r--r--sound/isa/als100.c41
-rw-r--r--sound/isa/azt2320.c49
-rw-r--r--sound/isa/cmi8328.c31
-rw-r--r--sound/isa/cmi8330.c27
-rw-r--r--sound/isa/cs423x/cs4231.c21
-rw-r--r--sound/isa/cs423x/cs4236.c52
-rw-r--r--sound/isa/cs423x/cs4236_lib.c2
-rw-r--r--sound/isa/es1688/es1688.c33
-rw-r--r--sound/isa/es18xx.c112
-rw-r--r--sound/isa/galaxy/galaxy.c82
-rw-r--r--sound/isa/gus/gus_main.c44
-rw-r--r--sound/isa/gus/gusclassic.c28
-rw-r--r--sound/isa/gus/gusextreme.c39
-rw-r--r--sound/isa/gus/gusmax.c65
-rw-r--r--sound/isa/gus/interwave.c53
-rw-r--r--sound/isa/msnd/msnd.c8
-rw-r--r--sound/isa/msnd/msnd_pinnacle.c119
-rw-r--r--sound/isa/opl3sa2.c60
-rw-r--r--sound/isa/opti9xx/miro.c76
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c77
-rw-r--r--sound/isa/sb/emu8000.c48
-rw-r--r--sound/isa/sb/jazz16.c39
-rw-r--r--sound/isa/sb/sb16.c42
-rw-r--r--sound/isa/sb/sb8.c48
-rw-r--r--sound/isa/sb/sb_common.c64
-rw-r--r--sound/isa/sc6000.c84
-rw-r--r--sound/isa/sscape.c92
-rw-r--r--sound/isa/wavefront/wavefront.c46
-rw-r--r--sound/isa/wss/wss_lib.c67
-rw-r--r--sound/parisc/harmony.c14
-rw-r--r--sound/pci/ad1889.c144
-rw-r--r--sound/pci/ali5451/ali5451.c90
-rw-r--r--sound/pci/als300.c80
-rw-r--r--sound/pci/als4000.c59
-rw-r--r--sound/pci/atiixp.c92
-rw-r--r--sound/pci/atiixp_modem.c92
-rw-r--r--sound/pci/au88x0/au88x0.c134
-rw-r--r--sound/pci/aw2/aw2-alsa.c102
-rw-r--r--sound/pci/azt3328.c124
-rw-r--r--sound/pci/bt87x.c98
-rw-r--r--sound/pci/ca0106/ca0106.h3
-rw-r--r--sound/pci/ca0106/ca0106_main.c114
-rw-r--r--sound/pci/cmipci.c104
-rw-r--r--sound/pci/cs4281.c114
-rw-r--r--sound/pci/cs46xx/cs46xx.c51
-rw-r--r--sound/pci/cs46xx/cs46xx.h4
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c141
-rw-r--r--sound/pci/cs5530.c86
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c94
-rw-r--r--sound/pci/cs5535audio/cs5535audio_olpc.c7
-rw-r--r--sound/pci/echoaudio/echoaudio.c168
-rw-r--r--sound/pci/echoaudio/echoaudio.h2
-rw-r--r--sound/pci/emu10k1/emu10k1.c53
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c102
-rw-r--r--sound/pci/emu10k1/emu10k1x.c128
-rw-r--r--sound/pci/emu10k1/p16v.c22
-rw-r--r--sound/pci/ens1370.c115
-rw-r--r--sound/pci/es1938.c97
-rw-r--r--sound/pci/es1968.c112
-rw-r--r--sound/pci/fm801.c103
-rw-r--r--sound/pci/hda/Kconfig10
-rw-r--r--sound/pci/hda/Makefile2
-rw-r--r--sound/pci/hda/hda_auto_parser.c84
-rw-r--r--sound/pci/hda/hda_bind.c8
-rw-r--r--sound/pci/hda/hda_codec.c12
-rw-r--r--sound/pci/hda/hda_controller.c13
-rw-r--r--sound/pci/hda/hda_controller.h3
-rw-r--r--sound/pci/hda/hda_generic.c19
-rw-r--r--sound/pci/hda/hda_generic.h1
-rw-r--r--sound/pci/hda/hda_intel.c52
-rw-r--r--sound/pci/hda/hda_local.h2
-rw-r--r--sound/pci/hda/patch_analog.c11
-rw-r--r--sound/pci/hda/patch_ca0132.c8
-rw-r--r--sound/pci/hda/patch_cirrus.c1074
-rw-r--r--sound/pci/hda/patch_conexant.c15
-rw-r--r--sound/pci/hda/patch_cs8409-tables.c560
-rw-r--r--sound/pci/hda/patch_cs8409.c1299
-rw-r--r--sound/pci/hda/patch_cs8409.h371
-rw-r--r--sound/pci/hda/patch_hdmi.c7
-rw-r--r--sound/pci/hda/patch_realtek.c24
-rw-r--r--sound/pci/hda/patch_sigmatel.c23
-rw-r--r--sound/pci/ice1712/ice1712.c133
-rw-r--r--sound/pci/ice1712/ice1724.c167
-rw-r--r--sound/pci/intel8x0.c144
-rw-r--r--sound/pci/intel8x0m.c139
-rw-r--r--sound/pci/korg1212/korg1212.c211
-rw-r--r--sound/pci/lola/lola.c127
-rw-r--r--sound/pci/lola/lola.h5
-rw-r--r--sound/pci/lola/lola_pcm.c20
-rw-r--r--sound/pci/lx6464es/lx6464es.c112
-rw-r--r--sound/pci/maestro3.c106
-rw-r--r--sound/pci/nm256/nm256.c131
-rw-r--r--sound/pci/oxygen/oxygen.c1
-rw-r--r--sound/pci/oxygen/oxygen.h1
-rw-r--r--sound/pci/oxygen/oxygen_lib.c66
-rw-r--r--sound/pci/oxygen/se6x.c1
-rw-r--r--sound/pci/oxygen/virtuoso.c1
-rw-r--r--sound/pci/pcxhr/pcxhr.c47
-rw-r--r--sound/pci/riptide/riptide.c89
-rw-r--r--sound/pci/rme32.c49
-rw-r--r--sound/pci/rme96.c57
-rw-r--r--sound/pci/rme9652/hdsp.c95
-rw-r--r--sound/pci/rme9652/hdspm.c64
-rw-r--r--sound/pci/rme9652/rme9652.c91
-rw-r--r--sound/pci/sis7019.c87
-rw-r--r--sound/pci/sonicvibes.c117
-rw-r--r--sound/pci/trident/trident.c39
-rw-r--r--sound/pci/trident/trident.h7
-rw-r--r--sound/pci/trident/trident_main.c90
-rw-r--r--sound/pci/trident/trident_memory.c8
-rw-r--r--sound/pci/via82xx.c116
-rw-r--r--sound/pci/via82xx_modem.c88
-rw-r--r--sound/pci/vx222/vx222.c69
-rw-r--r--sound/pci/ymfpci/ymfpci.c66
-rw-r--r--sound/pci/ymfpci/ymfpci.h8
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c149
-rw-r--r--sound/pcmcia/vx/vxpocket.c22
-rw-r--r--sound/soc/amd/Kconfig9
-rw-r--r--sound/soc/amd/Makefile1
-rw-r--r--sound/soc/amd/acp-da7219-max98357a.c12
-rw-r--r--sound/soc/amd/acp-pcm-dma.c20
-rw-r--r--sound/soc/amd/acp3x-rt5682-max9836.c14
-rw-r--r--sound/soc/amd/raven/acp3x-pcm-dma.c10
-rw-r--r--sound/soc/amd/renoir/acp3x-pdm-dma.c8
-rw-r--r--sound/soc/amd/renoir/acp3x-rn.c7
-rw-r--r--sound/soc/amd/vangogh/Makefile9
-rw-r--r--sound/soc/amd/vangogh/acp5x-i2s.c427
-rw-r--r--sound/soc/amd/vangogh/acp5x-pcm-dma.c517
-rw-r--r--sound/soc/amd/vangogh/acp5x.h193
-rw-r--r--sound/soc/amd/vangogh/pci-acp5x.c326
-rw-r--r--sound/soc/amd/vangogh/vg_chip_offset_byte.h337
-rw-r--r--sound/soc/atmel/Kconfig1
-rw-r--r--sound/soc/atmel/mchp-spdifrx.c6
-rw-r--r--sound/soc/atmel/mchp-spdiftx.c2
-rw-r--r--sound/soc/atmel/tse850-pcm5142.c2
-rw-r--r--sound/soc/bcm/bcm63xx-pcm-whistler.c82
-rw-r--r--sound/soc/bcm/cygnus-pcm.c2
-rw-r--r--sound/soc/codecs/Kconfig21
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/ad193x.c30
-rw-r--r--sound/soc/codecs/ad193x.h4
-rw-r--r--sound/soc/codecs/cs42l42.c28
-rw-r--r--sound/soc/codecs/cx20442.c8
-rw-r--r--sound/soc/codecs/ics43432.c4
-rw-r--r--sound/soc/codecs/lpass-rx-macro.c65
-rw-r--r--sound/soc/codecs/max98090.c4
-rw-r--r--sound/soc/codecs/max98390.c26
-rw-r--r--sound/soc/codecs/max98390.h1
-rw-r--r--sound/soc/codecs/mt6359-accdet.c25
-rw-r--r--sound/soc/codecs/rt1015.c46
-rw-r--r--sound/soc/codecs/rt1015.h2
-rw-r--r--sound/soc/codecs/rt1015p.c2
-rw-r--r--sound/soc/codecs/rt5514.c2
-rw-r--r--sound/soc/codecs/rt5640.c133
-rw-r--r--sound/soc/codecs/rt5640.h6
-rw-r--r--sound/soc/codecs/rt5682-i2c.c15
-rw-r--r--sound/soc/codecs/rt5682.c57
-rw-r--r--sound/soc/codecs/sdw-mockup.c312
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c10
-rw-r--r--sound/soc/codecs/wcd9335.c23
-rw-r--r--sound/soc/codecs/wcd938x.c854
-rw-r--r--sound/soc/codecs/wcd938x.h1
-rw-r--r--sound/soc/codecs/wm_adsp.c9
-rw-r--r--sound/soc/dwc/dwc-i2s.c2
-rw-r--r--sound/soc/fsl/fsl_asrc_dma.c47
-rw-r--r--sound/soc/fsl/fsl_dma.c50
-rw-r--r--sound/soc/fsl/fsl_rpmsg.c20
-rw-r--r--sound/soc/fsl/fsl_xcvr.c4
-rw-r--r--sound/soc/fsl/imx-pcm-fiq.c75
-rw-r--r--sound/soc/fsl/imx-pcm-rpmsg.c89
-rw-r--r--sound/soc/fsl/imx-rpmsg.c2
-rw-r--r--sound/soc/fsl/mpc5200_dma.c63
-rw-r--r--sound/soc/generic/simple-card-utils.c4
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-pcm.c2
-rw-r--r--sound/soc/intel/atom/sst/sst_ipc.c2
-rw-r--r--sound/soc/intel/boards/Kconfig1
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c31
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c328
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c63
-rw-r--r--sound/soc/intel/boards/kbl_da7219_max98927.c55
-rw-r--r--sound/soc/intel/boards/sof_cs42l42.c361
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.c17
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.h4
-rw-r--r--sound/soc/intel/boards/sof_pcm512x.c13
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c66
-rw-r--r--sound/soc/intel/boards/sof_sdw.c105
-rw-r--r--sound/soc/intel/boards/sof_sdw_common.h64
-rw-r--r--sound/soc/intel/boards/sof_sdw_max98373.c7
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt1308.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt1316.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt5682.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt700.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt711.c51
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt711_sdca.c52
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt715.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt715_sdca.c3
-rw-r--r--sound/soc/intel/common/Makefile3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cml-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cnl-match.c15
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-jsl-match.c8
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-kbl-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c166
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h17
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-tgl-match.c38
-rw-r--r--sound/soc/intel/skylake/skl-messages.c155
-rw-r--r--sound/soc/intel/skylake/skl-pcm.c33
-rw-r--r--sound/soc/intel/skylake/skl-topology.c155
-rw-r--r--sound/soc/intel/skylake/skl-topology.h26
-rw-r--r--sound/soc/mediatek/Kconfig24
-rw-r--r--sound/soc/mediatek/Makefile1
-rw-r--r--sound/soc/mediatek/common/mtk-afe-fe-dai.c22
-rw-r--r--sound/soc/mediatek/common/mtk-base-afe.h10
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-afe-pcm.c43
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-afe-pcm.c27
-rw-r--r--sound/soc/mediatek/mt8195/Makefile15
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-clk.c441
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-clk.h109
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-common.h158
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-pcm.c3281
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-audsys-clk.c214
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-audsys-clk.h15
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-audsys-clkid.h93
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-dai-adda.c830
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-dai-etdm.c2639
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-dai-pcm.c389
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c1087
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-reg.h2796
-rw-r--r--sound/soc/pxa/pxa-ssp.c3
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c3
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c3
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c3
-rw-r--r--sound/soc/qcom/apq8016_sbc.c17
-rw-r--r--sound/soc/qcom/lpass-platform.c60
-rw-r--r--sound/soc/qcom/qdsp6/q6adm.c2
-rw-r--r--sound/soc/qcom/qdsp6/q6asm-dai.c63
-rw-r--r--sound/soc/qcom/qdsp6/q6asm.c2
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c212
-rw-r--r--sound/soc/rockchip/rockchip_i2s.h10
-rw-r--r--sound/soc/rockchip/rockchip_spdif.c38
-rw-r--r--sound/soc/samsung/aries_wm8994.c2
-rw-r--r--sound/soc/samsung/arndale.c4
-rw-r--r--sound/soc/samsung/h1940_uda1380.c2
-rw-r--r--sound/soc/samsung/littlemill.c2
-rw-r--r--sound/soc/samsung/midas_wm1811.c2
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c4
-rw-r--r--sound/soc/samsung/rx1950_uda1380.c2
-rw-r--r--sound/soc/samsung/smartq_wm8987.c2
-rw-r--r--sound/soc/samsung/smdk_wm8580.c2
-rw-r--r--sound/soc/samsung/smdk_wm8994.c2
-rw-r--r--sound/soc/samsung/smdk_wm8994pcm.c2
-rw-r--r--sound/soc/samsung/tm2_wm5110.c6
-rw-r--r--sound/soc/samsung/tobermory.c2
-rw-r--r--sound/soc/sh/Kconfig6
-rw-r--r--sound/soc/sh/Makefile4
-rw-r--r--sound/soc/sh/rcar/adg.c12
-rw-r--r--sound/soc/sh/rcar/core.c6
-rw-r--r--sound/soc/sh/rcar/dma.c2
-rw-r--r--sound/soc/sh/rcar/ssi.c6
-rw-r--r--sound/soc/sh/rz-ssi.c1074
-rw-r--r--sound/soc/soc-ac97.c14
-rw-r--r--sound/soc/soc-component.c4
-rw-r--r--sound/soc/soc-compress.c1
-rw-r--r--sound/soc/soc-core.c36
-rw-r--r--sound/soc/soc-dai.c18
-rw-r--r--sound/soc/soc-dapm.c65
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c9
-rw-r--r--sound/soc/soc-jack.c15
-rw-r--r--sound/soc/soc-ops.c21
-rw-r--r--sound/soc/soc-pcm.c22
-rw-r--r--sound/soc/soc-topology.c23
-rw-r--r--sound/soc/sof/intel/Kconfig10
-rw-r--r--sound/soc/sof/intel/cnl.c6
-rw-r--r--sound/soc/sof/intel/hda-pcm.c16
-rw-r--r--sound/soc/sof/intel/hda-stream.c11
-rw-r--r--sound/soc/sof/intel/hda.c39
-rw-r--r--sound/soc/sof/intel/hda.h8
-rw-r--r--sound/soc/sof/intel/icl.c3
-rw-r--r--sound/soc/sof/intel/pci-tng.c1
-rw-r--r--sound/soc/sof/intel/shim.h3
-rw-r--r--sound/soc/sof/intel/tgl.c12
-rw-r--r--sound/soc/sof/sof-audio.c42
-rw-r--r--sound/soc/sof/sof-pci-dev.c9
-rw-r--r--sound/soc/sprd/sprd-pcm-dma.c67
-rw-r--r--sound/soc/tegra/tegra210_admaif.c6
-rw-r--r--sound/soc/tegra/tegra30_ahub.c6
-rw-r--r--sound/soc/tegra/tegra30_i2s.c8
-rw-r--r--sound/soc/tegra/tegra_pcm.c93
-rw-r--r--sound/soc/tegra/tegra_pcm.h7
-rw-r--r--sound/soc/ti/Kconfig1
-rw-r--r--sound/soc/ti/davinci-mcasp.c176
-rw-r--r--sound/soc/ti/j721e-evm.c30
-rw-r--r--sound/soc/ti/omap-abe-twl6040.c5
-rw-r--r--sound/soc/uniphier/aio-cpu.c4
-rw-r--r--sound/usb/card.c46
-rw-r--r--sound/usb/card.h2
-rw-r--r--sound/usb/clock.c15
-rw-r--r--sound/usb/endpoint.c21
-rw-r--r--sound/usb/format.c6
-rw-r--r--sound/usb/implicit.c6
-rw-r--r--sound/usb/mixer.c10
-rw-r--r--sound/usb/mixer.h3
-rw-r--r--sound/usb/mixer_maps.c22
-rw-r--r--sound/usb/mixer_quirks.c265
-rw-r--r--sound/usb/pcm.c14
-rw-r--r--sound/usb/quirks-table.h70
-rw-r--r--sound/usb/quirks.c361
-rw-r--r--sound/usb/quirks.h5
-rw-r--r--sound/usb/stream.c4
-rw-r--r--sound/usb/usbaudio.h69
-rw-r--r--sound/x86/intel_hdmi_audio.c90
-rw-r--r--sound/x86/intel_hdmi_audio.h1
344 files changed, 23693 insertions, 9339 deletions
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c
index 6ddf646cda65..0d31a6d71468 100644
--- a/sound/ac97/bus.c
+++ b/sound/ac97/bus.c
@@ -514,7 +514,7 @@ static int ac97_bus_probe(struct device *dev)
return ret;
}
-static int ac97_bus_remove(struct device *dev)
+static void ac97_bus_remove(struct device *dev)
{
struct ac97_codec_device *adev = to_ac97_device(dev);
struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver);
@@ -522,7 +522,7 @@ static int ac97_bus_remove(struct device *dev)
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
- return ret;
+ return;
ret = adrv->remove(adev);
pm_runtime_put_noidle(dev);
@@ -530,8 +530,6 @@ static int ac97_bus_remove(struct device *dev)
ac97_put_disable_clk(adev);
pm_runtime_disable(dev);
-
- return ret;
}
static struct bus_type ac97_bus_type = {
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c
index 002fb5bf220b..c9579d97fbab 100644
--- a/sound/aoa/soundbus/core.c
+++ b/sound/aoa/soundbus/core.c
@@ -104,7 +104,7 @@ static int soundbus_uevent(struct device *dev, struct kobj_uevent_env *env)
return retval;
}
-static int soundbus_device_remove(struct device *dev)
+static void soundbus_device_remove(struct device *dev)
{
struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
@@ -112,8 +112,6 @@ static int soundbus_device_remove(struct device *dev)
if (dev->driver && drv->remove)
drv->remove(soundbus_dev);
soundbus_dev_put(soundbus_dev);
-
- return 0;
}
static void soundbus_device_shutdown(struct device *dev)
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index a67e6685b00c..c17a19fe59ed 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -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;
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c
index e81083e1bc68..0a48805e513a 100644
--- a/sound/arm/pxa2xx-pcm-lib.c
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -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");
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 21ce4c056a92..de514ec8c83d 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -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");
diff --git a/sound/core/control_led.c b/sound/core/control_led.c
index 764058cc345d..a95332b2b90b 100644
--- a/sound/core/control_led.c
+++ b/sound/core/control_led.c
@@ -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;
}
diff --git a/sound/core/init.c b/sound/core/init.c
index 1490568efdb0..ac335f5906c6 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -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);
diff --git a/sound/core/isadma.c b/sound/core/isadma.c
index c3d789ef6975..1f45ede023b4 100644
--- a/sound/core/isadma.c
+++ b/sound/core/isadma.c
@@ -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);
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 439a358ecfe9..c7c943c661e6 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -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
};
diff --git a/sound/core/memalloc_local.h b/sound/core/memalloc_local.h
index dbea7f2aed07..9f2e0a608b49 100644
--- a/sound/core/memalloc_local.h
+++ b/sound/core/memalloc_local.h
@@ -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);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 7d5883432085..a144a3f68e9e 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -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;
}
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index d7621ed105bd..7fbd1ccbb5b0 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -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;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 71323d807dbf..d233cb3b41d8 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -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.
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index ac760b1e3d12..8c18d8c4177e 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -20,15 +20,15 @@
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
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c
index 232cf3f1bcb3..8352a5cdb19f 100644
--- a/sound/core/sgbuf.c
+++ b/sound/core/sgbuf.c
@@ -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,
};
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 7141f73cddd3..ca4cdf666f82 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -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).
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 80b814b9922a..9b4a7cdb103a 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -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,
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 01a3eab50d7b..2a7fc49c1a7c 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -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,
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index d0b55dbb411a..3398aee33baa 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -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;
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index 0e95b08d34d6..11235baaf6fa 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -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,
},
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index 7689fa2f9531..c7be1c395bcb 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -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,
};
diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c
index e79603fe743d..5a799f7f00a2 100644
--- a/sound/drivers/pcsp/pcsp_input.c
+++ b/sound/drivers/pcsp/pcsp_input.c
@@ -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;
-}
diff --git a/sound/drivers/pcsp/pcsp_input.h b/sound/drivers/pcsp/pcsp_input.h
index e80079b38a56..42bfc9eab6eb 100644
--- a/sound/drivers/pcsp/pcsp_input.h
+++ b/sound/drivers/pcsp/pcsp_input.h
@@ -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
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index da9983cba01c..3cbc7a4adcb4 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -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,
},
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index 4206d93ab47e..7f7eed6faaae 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -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,
},
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index a10449af5a76..18901e5bcfcf 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -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;
diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c
index 93d5df1ae550..2bd4485e4bc7 100644
--- a/sound/firewire/motu/motu-protocol-v2.c
+++ b/sound/firewire/motu/motu-protocol-v2.c
@@ -12,11 +12,11 @@
#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,
diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c
index 543136578c70..f65426238d4c 100644
--- a/sound/firewire/motu/motu.c
+++ b/sound/firewire/motu/motu.c
@@ -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),
diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h
index 73f36d1be515..f1a830b358d4 100644
--- a/sound/firewire/motu/motu.h
+++ b/sound/firewire/motu/motu.h
@@ -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;
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index fa5bed0d5a6f..9ac873773129 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -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,
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index 6d4999b30461..132a095dca2c 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -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;
}
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index edafb49797e7..c471ac2aa450 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -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,
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
index e6cd7c4da38e..f079ba4ef1a0 100644
--- a/sound/isa/adlib.c
+++ b/sound/isa/adlib.c
@@ -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
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index d4597fdfe091..d582eff64082 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -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,
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
index dd5c059b3744..761cd198df2b 100644
--- a/sound/isa/azt2320.c
+++ b/sound/isa/azt2320.c
@@ -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,
diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c
index 3b9fbb02864b..8902cfb830f7 100644
--- a/sound/isa/cmi8328.c
+++ b/sound/isa/cmi8328.c
@@ -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
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index ef6d0a20efd8..f209b16c5229 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -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,
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index ec054b929214..1e8923385366 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -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,
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 0b7fd17f8ecc..b6bdebd9ef27 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -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,
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
index 63957aea456b..35f25911adcf 100644
--- a/sound/isa/cs423x/cs4236_lib.c
+++ b/sound/isa/cs423x/cs4236_lib.c
@@ -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);
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 750d4995634f..f935b56eeec7 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -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;
}
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 68b9c59e1127..3fcd168480b6 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -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,
diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c
index d33d69f29924..ea001c80149d 100644
--- a/sound/isa/galaxy/galaxy.c
+++ b/sound/isa/galaxy/galaxy.c
@@ -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
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index 3b46490271fe..ae1e2542ee4a 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -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;
}
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index bca1caa4968c..09cc53ceea2a 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -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
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index a409a4a29afc..63d9f2d75df0 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -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,
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index ad118d462142..6834c0560064 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -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
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 755de47d0bb6..20f490e9d563 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -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 */
};
diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c
index 4fbc22a5bc5a..c3fd1eb301bb 100644
--- a/sound/isa/msnd/msnd.c
+++ b/sound/isa/msnd/msnd.c
@@ -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,
};
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
index 69647b41300d..4433a92f08e7 100644
--- a/sound/isa/msnd/msnd_pinnacle.c
+++ b/sound/isa/msnd/msnd_pinnacle.c
@@ -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 */
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 6f42f869928c..bad1490a66a0 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -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,
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index e1fb7567fdcc..59242baed576 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -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;
}
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 4bd1dc6707fc..4beeb32fe2a7 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -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;
}
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 5e4187940265..e02029677743 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -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) {
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
index 7ba5dd1ec810..64936c917170 100644
--- a/sound/isa/sb/jazz16.c
+++ b/sound/isa/sb/jazz16.c
@@ -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,
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index d0f797c02841..e89b095aa282 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -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,
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index b08e6e7690c9..e5ef1777161f 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -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,
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index 57121218ed24..c0e319d14210 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -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;
}
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
index 3462663050bb..26ab7ff80768 100644
--- a/sound/isa/sc6000.c
+++ b/sound/isa/sc6000.c
@@ -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,
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index e70ef9aee545..0bc0025f7c19 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -328,17 +328,6 @@ static void activate_ad1845_unsafe(unsigned io_base)
}
/*
- * 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 */
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index dfdeaf7b6bf4..e6e46a0266b0 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -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 */
};
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 743e0f05e335..026061b55ee9 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -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;
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index 2e3e5aa47682..db9c296dd688 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -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,
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 5c78951dd596..bba4dae8dcc7 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -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);
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 0d66b92466d5..92eb59db106d 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -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,
},
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 668008fc21f7..b86565dcdbe4 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -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,
},
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 509f317ee682..535eccd124be 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -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,
},
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 5f8aa35c4bea..b8e035d5930d 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -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,
},
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 9739c3a82777..178dce8ef1e9 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -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,
},
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 1f7fee470266..342ef2a6655e 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -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);
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index 43396849a01c..d56f126d6fdd 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -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)
{
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 4ee7ab409807..089050470ff2 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -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,
},
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 39bcfb81e81c..d23f93163841 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -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)
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index 62a22ca3b9de..f246e6094289 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -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;
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 99778711006a..36fb150b72fb 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -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,
},
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index f44f118aacad..ea20236f35db 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -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,
},
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index e122a168c148..e7367402b84a 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -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,
},
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 358ca84cbdea..bd60308769ff 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -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,
diff --git a/sound/pci/cs46xx/cs46xx.h b/sound/pci/cs46xx/cs46xx.h
index b275df883d06..c4f0a0b94270 100644
--- a/sound/pci/cs46xx/cs46xx.h
+++ b/sound/pci/cs46xx/cs46xx.h
@@ -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);
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 1e1eb17f8e07..62f45847b351 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -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;
}
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c
index 20b4faea50a6..93ff029e6583 100644
--- a/sound/pci/cs5530.c
+++ b/sound/pci/cs5530.c
@@ -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);
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index e048b45d9e7e..499fa0148f9a 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -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,
diff --git a/sound/pci/cs5535audio/cs5535audio_olpc.c b/sound/pci/cs5535audio/cs5535audio_olpc.c
index 110d3209441b..122170a410d9 100644
--- a/sound/pci/cs5535audio/cs5535audio_olpc.c
+++ b/sound/pci/cs5535audio/cs5535audio_olpc.c
@@ -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);
}
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index a62e5581ad14..25b012ef5c3e 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -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,
},
diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h
index 0afe13f7b6e5..d51de3e4edfa 100644
--- a/sound/pci/echoaudio/echoaudio.h
+++ b/sound/pci/echoaudio/echoaudio.h
@@ -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;
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 887bfb3c1e17..672af4b9597b 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -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,
},
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 24a2fd706d69..86cc1ca025e4 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -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
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 89b0f3884067..c49c44dc1082 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -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);
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index ff2a3974c824..18a1b0740e6b 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -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;
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 728b69dad21b..2651f0c64c06 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -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,
},
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 33b1eb347a27..00b976f42a3d 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -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,
},
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index c038c1035c39..6a8a02a9ecf4 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -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,
},
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index ed9dae87145b..9c22ff19e56d 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -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,
},
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index c4360cdbc728..ab9d2746e804 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -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
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index b57432f00056..b8fa682ce66a 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -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
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 1a001ecf7f63..4a854475a0e6 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -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);
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c
index e8dee24c309d..2523b23389e9 100644
--- a/sound/pci/hda/hda_bind.c
+++ b/sound/pci/hda/hda_bind.c
@@ -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,
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 7a717e151156..a9ebefd60cf6 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -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
*/
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index ca2f2ecd1488..7cd452831fd3 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -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;
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h
index 68f9668788ea..3062f87380b1 100644
--- a/sound/pci/hda/hda_controller.h
+++ b/sound/pci/hda/hda_controller.h
@@ -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;
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 481d8f8d3396..3bf5e3410703 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -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
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index d4dd1b8a2e7e..c43bd0f0338e 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -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,
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 0062c18b646a..3aa432d814a2 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -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 */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 8d2503e8dad8..ea8ab8b43337 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -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
*/
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 2132b2acec4d..8afe6000f7da 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -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,
};
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index b66e7bdbf483..208933792787 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -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 = {
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 8629e84fef23..678fbcaf2a3b 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -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);
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index d111258c6f45..0515137a75b0 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -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
index 000000000000..0fb0a428428b
--- /dev/null
+++ b/sound/pci/hda/patch_cs8409-tables.c
@@ -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
index 000000000000..3c7ef55d016e
--- /dev/null
+++ b/sound/pci/hda/patch_cs8409.c
@@ -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
index 000000000000..ade2b838590c
--- /dev/null
+++ b/sound/pci/hda/patch_cs8409.h
@@ -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
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index e143e69d8184..65d2c5539919 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -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)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 7ad689f991e7..8b7a389b6aed 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -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,
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 3bd592e126a3..61df4d33c48f 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -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)
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index d54cd5143e9f..a5241a287851 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -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,
},
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index ef2367d86148..f6275868877a 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -2151,13 +2151,6 @@ static const struct snd_kcontrol_new snd_vt1724_mixer_pro_peak = {
};
/*
- *
- */
-
-static const struct snd_ice1712_card_info no_matched;
-
-
-/*
ooAoo cards with no controls
*/
static const unsigned char ooaoo_sq210_eeprom[] = {
@@ -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,
},
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index df3ba5c70de9..a51032b3ac4d 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -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,
},
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index b96fce6cbd83..7de3cb2f17b5 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -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,
},
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 030e01b062e4..5c9e240ff6a9 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -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);
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index 03b4be44bb26..5269a1d396a5 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -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);
diff --git a/sound/pci/lola/lola.h b/sound/pci/lola/lola.h
index 8a598aa40bf3..0ff772cf66e6 100644
--- a/sound/pci/lola/lola.h
+++ b/sound/pci/lola/lola.h
@@ -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);
diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c
index 684faaf40f31..738ec987000a 100644
--- a/sound/pci/lola/lola_pcm.c
+++ b/sound/pci/lola/lola_pcm.c
@@ -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);
-}
-
/*
*/
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
index 1be97c38bc71..168a1084f730 100644
--- a/sound/pci/lx6464es/lx6464es.c
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -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);
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 77a484bc8c0d..056838ead21d 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -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,
},
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 12d02d7d3b51..c9c178504959 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -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,
},
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index e335c4b5b381..c346f42befc2 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -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,
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index 06bf7e5744d0..0cae640708f3 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -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
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index afc6dd329c09..4fb3f2484fdb 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -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)
{
diff --git a/sound/pci/oxygen/se6x.c b/sound/pci/oxygen/se6x.c
index 434f885f6f91..17650a5b1bfa 100644
--- a/sound/pci/oxygen/se6x.c
+++ b/sound/pci/oxygen/se6x.c
@@ -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,
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index baa3244d4dab..2e405133371f 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -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,
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 96b9371c201a..242bd7e04b3e 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -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);
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 709a1a2cde20..5a987c683c41 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -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,
},
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index b5b357853c94..5b6bd9f0b2f7 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -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);
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index fc7ac077559c..8fc811504920 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -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,
},
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 8457a4bbc3df..75aa2ea733a5 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -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);
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 97a0bff96b28..ff06ee82607c 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -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);
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index f1aad38760d6..e76f737ac9e8 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -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);
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index 00ab51c889da..0b722b0e0604 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -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,
},
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 03a48da897e3..c8c49881008f 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -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);
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 60e4dca28c2b..9922ab40798c 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -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,
diff --git a/sound/pci/trident/trident.h b/sound/pci/trident/trident.h
index c579a44bb9ae..9768a7fc2349 100644
--- a/sound/pci/trident/trident.h
+++ b/sound/pci/trident/trident.h
@@ -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);
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index cfbca3bd60ed..e98eea1e6d81 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -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;
}
/*---------------------------------------------------------------------------
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
index 4ad3855101c9..05de2b9f4ed7 100644
--- a/sound/pci/trident/trident_memory.c
+++ b/sound/pci/trident/trident_memory.c
@@ -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 */
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 943813a06abc..65514f7e42d7 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -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,
},
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 07278a3dc8c1..234f7fbed236 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -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,
},
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index 04c7204cb7bc..f48cc20b9e8a 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -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,
},
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 7e32d57147ff..1e198e4d57b8 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -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,
diff --git a/sound/pci/ymfpci/ymfpci.h b/sound/pci/ymfpci/ymfpci.h
index c73d8a5f4d0b..66968776478a 100644
--- a/sound/pci/ymfpci/ymfpci.h
+++ b/sound/pci/ymfpci/ymfpci.h
@@ -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;
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 8fd060769882..c80114c0ad7b 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -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;
}
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 0dfb6a943b60..7a0f0e73ceb2 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -51,19 +51,6 @@ static void vxpocket_release(struct pcmcia_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);
diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index ba5a85bf7412..49ff5e73e9ba 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -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.
diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile
index e6df2f72a2a1..07150d26f315 100644
--- a/sound/soc/amd/Makefile
+++ b/sound/soc/amd/Makefile
@@ -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/
diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c
index 3c60c5f96dcb..b3df98a9f9f3 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -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");
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index cc1ce6f22caa..11b3c4f39eba 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -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,
};
diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c
index d9980aba2910..e561464f7d60 100644
--- a/sound/soc/amd/acp3x-rt5682-max9836.c
+++ b/sound/soc/amd/acp3x-rt5682-max9836.c
@@ -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[] = {
diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index 597d7c4b2a6b..75c06697fa09 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -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,
};
diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c
index 0391c28dd078..9dd22a2fa2e5 100644
--- a/sound/soc/amd/renoir/acp3x-pdm-dma.c
+++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c
@@ -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,
};
diff --git a/sound/soc/amd/renoir/acp3x-rn.c b/sound/soc/amd/renoir/acp3x-rn.c
index 306134b89a82..5d979a7b77fb 100644
--- a/sound/soc/amd/renoir/acp3x-rn.c
+++ b/sound/soc/amd/renoir/acp3x-rn.c
@@ -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
index 000000000000..3353f93dc610
--- /dev/null
+++ b/sound/soc/amd/vangogh/Makefile
@@ -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
index 000000000000..2705e57eb713
--- /dev/null
+++ b/sound/soc/amd/vangogh/acp5x-i2s.c
@@ -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
index 000000000000..f10de38976cb
--- /dev/null
+++ b/sound/soc/amd/vangogh/acp5x-pcm-dma.c
@@ -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
index 000000000000..a808635f9740
--- /dev/null
+++ b/sound/soc/amd/vangogh/acp5x.h
@@ -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
index 000000000000..a57b762d9f2e
--- /dev/null
+++ b/sound/soc/amd/vangogh/pci-acp5x.c
@@ -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
index 000000000000..b1165ae142b7
--- /dev/null
+++ b/sound/soc/amd/vangogh/vg_chip_offset_byte.h
@@ -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
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index ec04e3386bc0..8617793ed955 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -11,7 +11,6 @@ if SND_ATMEL_SOC
config SND_ATMEL_SOC_PDC
bool
- depends on HAS_DMA
config SND_ATMEL_SOC_DMA
bool
diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c
index e6ded6f8453f..bcd4f3e4fb0f 100644
--- a/sound/soc/atmel/mchp-spdifrx.c
+++ b/sound/soc/atmel/mchp-spdifrx.c
@@ -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);
diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c
index 3bd350afb743..d24380046435 100644
--- a/sound/soc/atmel/mchp-spdiftx.c
+++ b/sound/soc/atmel/mchp-spdiftx.c
@@ -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)
diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c
index 59e2edb22b3a..50c3dc6936f9 100644
--- a/sound/soc/atmel/tse850-pcm5142.c
+++ b/sound/soc/atmel/tse850-pcm5142.c
@@ -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'.
diff --git a/sound/soc/bcm/bcm63xx-pcm-whistler.c b/sound/soc/bcm/bcm63xx-pcm-whistler.c
index 7ec8559d53a2..b5096f64c576 100644
--- a/sound/soc/bcm/bcm63xx-pcm-whistler.c
+++ b/sound/soc/bcm/bcm63xx-pcm-whistler.c
@@ -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,
diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c
index 56b71b965624..3abeaf0f1b1c 100644
--- a/sound/soc/bcm/cygnus-pcm.c
+++ b/sound/soc/bcm/cygnus-pcm.c
@@ -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__);
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index db16071205ba..82ee233a269d 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -187,6 +187,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_RT715_SDCA_SDW
imply SND_SOC_RT1308_SDW
imply SND_SOC_RT1316_SDW
+ imply SND_SOC_SDW_MOCKUP
imply SND_SOC_SGTL5000
imply SND_SOC_SI476X
imply SND_SOC_SIMPLE_AMPLIFIER
@@ -847,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"
@@ -1287,6 +1288,23 @@ config SND_SOC_RT715_SDCA_SDW
select REGMAP_SOUNDWIRE
select REGMAP_SOUNDWIRE_MBQ
+config SND_SOC_SDW_MOCKUP
+ tristate "SoundWire mockup codec"
+ depends on EXPERT
+ depends on SOUNDWIRE
+ help
+ This option enables a SoundWire mockup codec that does not drive the
+ bus, take part in the command/command protocol or generate data on a
+ Source port.
+ This option is only intended to be used for tests on a device
+ with a connector, in combination with a bus analyzer, or to test new
+ topologies that differ from the actual hardware layout.
+ This mockup device could be totally virtual but could also be a
+ real physical one with one key restriction: it is not allowed by the
+ SoundWire specification to be configured via a sideband mechanism and
+ generate audio data for capture. However, nothing prevents such a
+ peripheral device from snooping the bus.
+
#Freescale sgtl5000 codec
config SND_SOC_SGTL5000
tristate "Freescale SGTL5000 CODEC"
@@ -1564,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
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 7bb38c370842..8dcea2c4604a 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -203,6 +203,7 @@ snd-soc-rt711-objs := rt711.o rt711-sdw.o
snd-soc-rt711-sdca-objs := rt711-sdca.o rt711-sdca-sdw.o
snd-soc-rt715-objs := rt715.o rt715-sdw.o
snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o
+snd-soc-sdw-mockup-objs := sdw-mockup.o
snd-soc-sgtl5000-objs := sgtl5000.o
snd-soc-alc5623-objs := alc5623.o
snd-soc-alc5632-objs := alc5632.o
@@ -530,6 +531,7 @@ obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o
obj-$(CONFIG_SND_SOC_RT711_SDCA_SDW) += snd-soc-rt711-sdca.o
obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o
obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o
+obj-$(CONFIG_SND_SOC_SDW_MOCKUP) += snd-soc-sdw-mockup.o
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index f37ab7eda615..278a55af158b 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -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,
},
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h
index 377854712c20..61f4648861d5 100644
--- a/sound/soc/codecs/ad193x.h
+++ b/sound/soc/codecs/ad193x.h
@@ -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)
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 99c022be94a6..fb1e4c33e27d 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -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");
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index ec8d6e74b467..13258f3ca9aa 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -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);
diff --git a/sound/soc/codecs/ics43432.c b/sound/soc/codecs/ics43432.c
index 47e749f03940..de4c8460ab3d 100644
--- a/sound/soc/codecs/ics43432.c
+++ b/sound/soc/codecs/ics43432.c
@@ -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);
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c
index 3622961f7c2c..196b06898eeb 100644
--- a/sound/soc/codecs/lpass-rx-macro.c
+++ b/sound/soc/codecs/lpass-rx-macro.c
@@ -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;
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index bc30a1dc7530..b45ec35cd63c 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -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);
diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c
index 94773ccee9d5..b392567c2b3e 100644
--- a/sound/soc/codecs/max98390.c
+++ b/sound/soc/codecs/max98390.c
@@ -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);
diff --git a/sound/soc/codecs/max98390.h b/sound/soc/codecs/max98390.h
index e31516717d3b..c250740f73a2 100644
--- a/sound/soc/codecs/max98390.h
+++ b/sound/soc/codecs/max98390.h
@@ -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
diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 78314187d37e..6d3d170144a0 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -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");
diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c
index 9238f12999aa..c0c5952cdff7 100644
--- a/sound/soc/codecs/rt1015.c
+++ b/sound/soc/codecs/rt1015.c
@@ -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,
diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h
index 14344532048e..c9f636af7fd1 100644
--- a/sound/soc/codecs/rt1015.h
+++ b/sound/soc/codecs/rt1015.h
@@ -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__ */
diff --git a/sound/soc/codecs/rt1015p.c b/sound/soc/codecs/rt1015p.c
index 40f2063aefbe..415cfb3b2f0d 100644
--- a/sound/soc/codecs/rt1015p.c
+++ b/sound/soc/codecs/rt1015p.c
@@ -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);
diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c
index 7081142a355e..4b1ad5054e8d 100644
--- a/sound/soc/codecs/rt5514.c
+++ b/sound/soc/codecs/rt5514.c
@@ -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]) {
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 9523f4b5c800..cd1db5caabad 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -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));
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index 4fd47f2b936b..2c28f83e338a 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -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
diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c
index 4a56a52adab5..b9d5d7a0975b 100644
--- a/sound/soc/codecs/rt5682-i2c.c
+++ b/sound/soc/codecs/rt5682-i2c.c
@@ -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;
}
diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c
index 51ecaa2abcd1..e822fa1b9d4b 100644
--- a/sound/soc/codecs/rt5682.c
+++ b/sound/soc/codecs/rt5682.c
@@ -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));
diff --git a/sound/soc/codecs/sdw-mockup.c b/sound/soc/codecs/sdw-mockup.c
new file mode 100644
index 000000000000..8ea13cfa9f8e
--- /dev/null
+++ b/sound/soc/codecs/sdw-mockup.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// sdw-mockup.c -- a mockup SoundWire codec for tests where only the host
+// drives the bus.
+//
+// Copyright(c) 2021 Intel Corporation
+//
+//
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_type.h>
+#include <linux/soundwire/sdw_registers.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+struct sdw_mockup_priv {
+ struct sdw_slave *slave;
+};
+
+struct sdw_stream_data {
+ struct sdw_stream_runtime *sdw_stream;
+};
+
+static int sdw_mockup_component_probe(struct snd_soc_component *component)
+{
+ return 0;
+}
+
+static void sdw_mockup_component_remove(struct snd_soc_component *component)
+{
+}
+
+static const struct snd_soc_component_driver snd_soc_sdw_mockup_component = {
+ .probe = sdw_mockup_component_probe,
+ .remove = sdw_mockup_component_remove,
+};
+
+static int sdw_mockup_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
+ int direction)
+{
+ struct sdw_stream_data *stream;
+
+ if (!sdw_stream)
+ return 0;
+
+ stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+ if (!stream)
+ return -ENOMEM;
+
+ stream->sdw_stream = sdw_stream;
+
+ /* Use tx_mask or rx_mask to configure stream tag and set dma_data */
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+ dai->playback_dma_data = stream;
+ else
+ dai->capture_dma_data = stream;
+
+ return 0;
+}
+
+static void sdw_mockup_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct sdw_stream_data *stream;
+
+ stream = snd_soc_dai_get_dma_data(dai, substream);
+ snd_soc_dai_set_dma_data(dai, substream, NULL);
+ kfree(stream);
+}
+
+static int sdw_mockup_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component);
+ struct sdw_stream_config stream_config;
+ struct sdw_port_config port_config;
+ enum sdw_data_direction direction;
+ struct sdw_stream_data *stream;
+ int num_channels;
+ int port;
+ int ret;
+
+ stream = snd_soc_dai_get_dma_data(dai, substream);
+ if (!stream)
+ return -EINVAL;
+
+ if (!sdw_mockup->slave)
+ return -EINVAL;
+
+ /* SoundWire specific configuration */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ direction = SDW_DATA_DIR_RX;
+ port = 1;
+ } else {
+ direction = SDW_DATA_DIR_TX;
+ port = 8;
+ }
+
+ stream_config.frame_rate = params_rate(params);
+ stream_config.ch_count = params_channels(params);
+ stream_config.bps = snd_pcm_format_width(params_format(params));
+ stream_config.direction = direction;
+
+ num_channels = params_channels(params);
+ port_config.ch_mask = (1 << num_channels) - 1;
+ port_config.num = port;
+
+ ret = sdw_stream_add_slave(sdw_mockup->slave, &stream_config,
+ &port_config, 1, stream->sdw_stream);
+ if (ret)
+ dev_err(dai->dev, "Unable to configure port\n");
+
+ return ret;
+}
+
+static int sdw_mockup_pcm_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component);
+ struct sdw_stream_data *stream =
+ snd_soc_dai_get_dma_data(dai, substream);
+
+ if (!sdw_mockup->slave)
+ return -EINVAL;
+
+ sdw_stream_remove_slave(sdw_mockup->slave, stream->sdw_stream);
+ return 0;
+}
+
+static const struct snd_soc_dai_ops sdw_mockup_ops = {
+ .hw_params = sdw_mockup_pcm_hw_params,
+ .hw_free = sdw_mockup_pcm_hw_free,
+ .set_sdw_stream = sdw_mockup_set_sdw_stream,
+ .shutdown = sdw_mockup_shutdown,
+};
+
+static struct snd_soc_dai_driver sdw_mockup_dai[] = {
+ {
+ .name = "sdw-mockup-aif1",
+ .id = 1,
+ .playback = {
+ .stream_name = "DP1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .capture = {
+ .stream_name = "DP8 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &sdw_mockup_ops,
+ },
+};
+
+static int sdw_mockup_update_status(struct sdw_slave *slave,
+ enum sdw_slave_status status)
+{
+ return 0;
+}
+
+static int sdw_mockup_read_prop(struct sdw_slave *slave)
+{
+ struct sdw_slave_prop *prop = &slave->prop;
+ int nval;
+ int i, j;
+ u32 bit;
+ unsigned long addr;
+ struct sdw_dpn_prop *dpn;
+
+ prop->paging_support = false;
+
+ /*
+ * first we need to allocate memory for set bits in port lists
+ * the port allocation is completely arbitrary:
+ * DP0 is not supported
+ * DP1 is sink
+ * DP8 is source
+ */
+ prop->source_ports = BIT(8);
+ prop->sink_ports = BIT(1);
+
+ nval = hweight32(prop->source_ports);
+ prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval,
+ sizeof(*prop->src_dpn_prop),
+ GFP_KERNEL);
+ if (!prop->src_dpn_prop)
+ return -ENOMEM;
+
+ i = 0;
+ dpn = prop->src_dpn_prop;
+ addr = prop->source_ports;
+ for_each_set_bit(bit, &addr, 32) {
+ dpn[i].num = bit;
+ dpn[i].type = SDW_DPN_FULL;
+ dpn[i].simple_ch_prep_sm = true;
+ i++;
+ }
+
+ /* do this again for sink now */
+ nval = hweight32(prop->sink_ports);
+ prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval,
+ sizeof(*prop->sink_dpn_prop),
+ GFP_KERNEL);
+ if (!prop->sink_dpn_prop)
+ return -ENOMEM;
+
+ j = 0;
+ dpn = prop->sink_dpn_prop;
+ addr = prop->sink_ports;
+ for_each_set_bit(bit, &addr, 32) {
+ dpn[j].num = bit;
+ dpn[j].type = SDW_DPN_FULL;
+ dpn[j].simple_ch_prep_sm = true;
+ j++;
+ }
+
+ prop->simple_clk_stop_capable = true;
+
+ /* wake-up event */
+ prop->wake_capable = 0;
+
+ return 0;
+}
+
+static int sdw_mockup_bus_config(struct sdw_slave *slave,
+ struct sdw_bus_params *params)
+{
+ return 0;
+}
+
+static int sdw_mockup_interrupt_callback(struct sdw_slave *slave,
+ struct sdw_slave_intr_status *status)
+{
+ return 0;
+}
+
+static const struct sdw_slave_ops sdw_mockup_slave_ops = {
+ .read_prop = sdw_mockup_read_prop,
+ .interrupt_callback = sdw_mockup_interrupt_callback,
+ .update_status = sdw_mockup_update_status,
+ .bus_config = sdw_mockup_bus_config,
+};
+
+static int sdw_mockup_sdw_probe(struct sdw_slave *slave,
+ const struct sdw_device_id *id)
+{
+ struct device *dev = &slave->dev;
+ struct sdw_mockup_priv *sdw_mockup;
+ int ret;
+
+ sdw_mockup = devm_kzalloc(dev, sizeof(*sdw_mockup), GFP_KERNEL);
+ if (!sdw_mockup)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, sdw_mockup);
+ sdw_mockup->slave = slave;
+
+ slave->is_mockup_device = true;
+
+ ret = devm_snd_soc_register_component(dev,
+ &snd_soc_sdw_mockup_component,
+ sdw_mockup_dai,
+ ARRAY_SIZE(sdw_mockup_dai));
+
+ return ret;
+}
+
+static int sdw_mockup_sdw_remove(struct sdw_slave *slave)
+{
+ return 0;
+}
+
+/*
+ * Intel reserved parts ID with the following mapping expected:
+ * 0xAAAA: generic full-duplex codec
+ * 0xAA55: headset codec (mock-up of RT711/RT5682) - full-duplex
+ * 0x55AA: amplifier (mock-up of RT1308/Maxim 98373) - playback only with
+ * IV feedback
+ * 0x5555: mic codec (mock-up of RT715) - capture-only
+ */
+static const struct sdw_device_id sdw_mockup_id[] = {
+ SDW_SLAVE_ENTRY_EXT(0x0105, 0xAAAA, 0x0, 0, 0),
+ SDW_SLAVE_ENTRY_EXT(0x0105, 0xAA55, 0x0, 0, 0),
+ SDW_SLAVE_ENTRY_EXT(0x0105, 0x55AA, 0x0, 0, 0),
+ SDW_SLAVE_ENTRY_EXT(0x0105, 0x5555, 0x0, 0, 0),
+ {},
+};
+MODULE_DEVICE_TABLE(sdw, sdw_mockup_id);
+
+static struct sdw_driver sdw_mockup_sdw_driver = {
+ .driver = {
+ .name = "sdw-mockup",
+ .owner = THIS_MODULE,
+ },
+ .probe = sdw_mockup_sdw_probe,
+ .remove = sdw_mockup_sdw_remove,
+ .ops = &sdw_mockup_slave_ops,
+ .id_table = sdw_mockup_id,
+};
+module_sdw_driver(sdw_mockup_sdw_driver);
+
+MODULE_DESCRIPTION("ASoC SDW mockup codec driver");
+MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 2e9175b37dc9..d39c7d52ecfd 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -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" },
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 86c92e03ea5d..d885ced34f60 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -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,
diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c
index 2fcc97370be2..f0daf8defcf1 100644
--- a/sound/soc/codecs/wcd938x.c
+++ b/sound/soc/codecs/wcd938x.c
@@ -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)
diff --git a/sound/soc/codecs/wcd938x.h b/sound/soc/codecs/wcd938x.h
index 07b08de4cebf..ea82039e7843 100644
--- a/sound/soc/codecs/wcd938x.h
+++ b/sound/soc/codecs/wcd938x.h
@@ -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;
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index fe15cbc7bcaf..f7c800927cb2 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -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;
}
diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c
index 8ebf76e04702..33ce257ae198 100644
--- a/sound/soc/dwc/dwc-i2s.c
+++ b/sound/soc/dwc/dwc-i2s.c
@@ -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);
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
index c313a26c8f95..cd9b36ec0ecb 100644
--- a/sound/soc/fsl/fsl_asrc_dma.c
+++ b/sound/soc/fsl/fsl_asrc_dma.c
@@ -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);
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 84bd8a5356eb..808fb61a7a0f 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -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;
diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c
index ea5c973e2e84..d60f4dac6c1b 100644
--- a/sound/soc/fsl/fsl_rpmsg.c
+++ b/sound/soc/fsl/fsl_rpmsg.c
@@ -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);
diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
index fb7c29fc39d7..31c5ee641fe7 100644
--- a/sound/soc/fsl/fsl_xcvr.c
+++ b/sound/soc/fsl/fsl_xcvr.c
@@ -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) {
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
index f20d5b1c3848..0d124002678e 100644
--- a/sound/soc/fsl/imx-pcm-fiq.c
+++ b/sound/soc/fsl/imx-pcm-fiq.c
@@ -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,
};
diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
index 6d6c44cf3451..35049043e532 100644
--- a/sound/soc/fsl/imx-pcm-rpmsg.c
+++ b/sound/soc/fsl/imx-pcm-rpmsg.c
@@ -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,
};
diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c
index f0cae8c59d54..f96fe4ff8425 100644
--- a/sound/soc/fsl/imx-rpmsg.c
+++ b/sound/soc/fsl/imx-rpmsg.c
@@ -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;
}
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index 6c65cd858b0b..901497810020 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -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)
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 677f7da93b4b..10c63b73900c 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -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;
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index 905c7965f653..5db2f4865bbb 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
@@ -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;
diff --git a/sound/soc/intel/atom/sst/sst_ipc.c b/sound/soc/intel/atom/sst/sst_ipc.c
index a8a9aa0057d3..4e8382097e61 100644
--- a/sound/soc/intel/atom/sst/sst_ipc.c
+++ b/sound/soc/intel/atom/sst/sst_ipc.c
@@ -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;
}
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index 7e29b0d911e2..046955bf717c 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -602,6 +602,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
select SND_SOC_DMIC
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_INTEL_SOF_MAXIM_COMMON
+ select SND_SOC_SDW_MOCKUP
help
Add support for Intel SoundWire-based platforms connected to
MAX98373, RT700, RT711, RT1308 and RT715
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
index a0af91580184..055248f104b2 100644
--- a/sound/soc/intel/boards/bytcht_es8316.c
+++ b/sound/soc/intel/boards/bytcht_es8316.c
@@ -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;
}
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 91a6d712eb58..a6e837290c7d 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -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);
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index e13c0c63a949..e94c9124d4f4 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -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);
diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c
index a31a7a7bbf66..2b43459adc33 100644
--- a/sound/soc/intel/boards/kbl_da7219_max98927.c
+++ b/sound/soc/intel/boards/kbl_da7219_max98927.c
@@ -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);
}
diff --git a/sound/soc/intel/boards/sof_cs42l42.c b/sound/soc/intel/boards/sof_cs42l42.c
index 42aadf801f72..ce78c1879887 100644
--- a/sound/soc/intel/boards/sof_cs42l42.c
+++ b/sound/soc/intel/boards/sof_cs42l42.c
@@ -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"
@@ -36,7 +37,20 @@
#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),
},
{ }
};
diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c
index e9c52f8b6428..e66dfe666915 100644
--- a/sound/soc/intel/boards/sof_maxim_common.c
+++ b/sound/soc/intel/boards/sof_maxim_common.c
@@ -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");
diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h
index 2674f1e373ef..3ff5e8fec4de 100644
--- a/sound/soc/intel/boards/sof_maxim_common.h
+++ b/sound/soc/intel/boards/sof_maxim_common.h
@@ -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 */
diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c
index 2ec9c62366e2..6815204e58d5 100644
--- a/sound/soc/intel/boards/sof_pcm512x.c
+++ b/sound/soc/intel/boards/sof_pcm512x.c
@@ -26,11 +26,16 @@
#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;
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c
index 39217223d50c..f096bd6d69be 100644
--- a/sound/soc/intel/boards/sof_rt5682.c
+++ b/sound/soc/intel/boards/sof_rt5682.c
@@ -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]);
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index 1a867c73a48e..6602eda89e8e 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -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,17 +126,29 @@ 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 = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
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,6 +352,20 @@ static const struct snd_soc_ops sdw_ops = {
.shutdown = sdw_shutdown,
};
+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)
+{
+ /*
+ * force DAI link to use same ID as RT715 and DMIC
+ * to reuse topologies
+ */
+ dai_links->id = SDW_DMIC_DAI_ID;
+ return 0;
+}
+
static struct sof_sdw_codec_info codec_info_list[] = {
{
.part_id = 0x700,
@@ -410,6 +448,34 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt5682-sdw",
.init = sof_sdw_rt5682_init,
},
+ {
+ .part_id = 0xaaaa, /* generic codec mockup */
+ .version_id = 0,
+ .direction = {true, true},
+ .dai_name = "sdw-mockup-aif1",
+ .init = NULL,
+ },
+ {
+ .part_id = 0xaa55, /* headset codec mockup */
+ .version_id = 0,
+ .direction = {true, true},
+ .dai_name = "sdw-mockup-aif1",
+ .init = NULL,
+ },
+ {
+ .part_id = 0x55aa, /* amplifier mockup */
+ .version_id = 0,
+ .direction = {true, false},
+ .dai_name = "sdw-mockup-aif1",
+ .init = NULL,
+ },
+ {
+ .part_id = 0x5555,
+ .version_id = 0,
+ .direction = {false, true},
+ .dai_name = "sdw-mockup-aif1",
+ .init = sof_sdw_mic_codec_mockup_init,
+ },
};
static inline int find_codec_info_part(u64 adr)
@@ -632,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)
{
@@ -655,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);
@@ -740,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,
@@ -861,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);
@@ -1042,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,
@@ -1105,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;
@@ -1328,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",
diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h
index ec5740486b75..b35f5a9b96f5 100644
--- a/sound/soc/intel/boards/sof_sdw_common.h
+++ b/sound/soc/intel/boards/sof_sdw_common.h
@@ -23,11 +23,6 @@
#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);
diff --git a/sound/soc/intel/boards/sof_sdw_max98373.c b/sound/soc/intel/boards/sof_sdw_max98373.c
index 25daef910aee..77a3f32db11e 100644
--- a/sound/soc/intel/boards/sof_sdw_max98373.c
+++ b/sound/soc/intel/boards/sof_sdw_max98373.c
@@ -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)
diff --git a/sound/soc/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt1308.c
index 0d476f6f6313..f078fb1aad02 100644
--- a/sound/soc/intel/boards/sof_sdw_rt1308.c
+++ b/sound/soc/intel/boards/sof_sdw_rt1308.c
@@ -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)
diff --git a/sound/soc/intel/boards/sof_sdw_rt1316.c b/sound/soc/intel/boards/sof_sdw_rt1316.c
index d6e1ebf18d57..58194b380232 100644
--- a/sound/soc/intel/boards/sof_sdw_rt1316.c
+++ b/sound/soc/intel/boards/sof_sdw_rt1316.c
@@ -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)
diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c
index 5fa1a59615b6..ea55479609a8 100644
--- a/sound/soc/intel/boards/sof_sdw_rt5682.c
+++ b/sound/soc/intel/boards/sof_sdw_rt5682.c
@@ -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)
diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c
index 21e7e4a81779..bb9584c8f866 100644
--- a/sound/soc/intel/boards/sof_sdw_rt700.c
+++ b/sound/soc/intel/boards/sof_sdw_rt700.c
@@ -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)
diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c
index 04074c09dded..c38b70c9fac3 100644
--- a/sound/soc/intel/boards/sof_sdw_rt711.c
+++ b/sound/soc/intel/boards/sof_sdw_rt711.c
@@ -21,23 +21,23 @@
* 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;
diff --git a/sound/soc/intel/boards/sof_sdw_rt711_sdca.c b/sound/soc/intel/boards/sof_sdw_rt711_sdca.c
index 19496f0f9110..4215ddc36419 100644
--- a/sound/soc/intel/boards/sof_sdw_rt711_sdca.c
+++ b/sound/soc/intel/boards/sof_sdw_rt711_sdca.c
@@ -21,23 +21,24 @@
* 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;
diff --git a/sound/soc/intel/boards/sof_sdw_rt715.c b/sound/soc/intel/boards/sof_sdw_rt715.c
index 9b298f79e784..c8af3780cbc3 100644
--- a/sound/soc/intel/boards/sof_sdw_rt715.c
+++ b/sound/soc/intel/boards/sof_sdw_rt715.c
@@ -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)
diff --git a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c
index c056e56a139b..85d3d8c355cc 100644
--- a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c
+++ b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c
@@ -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)
diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile
index 12a205ccdeeb..fef0b2d1de68 100644
--- a/sound/soc/intel/common/Makefile
+++ b/sound/soc/intel/common/Makefile
@@ -9,7 +9,8 @@ snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-m
soc-acpi-intel-cml-match.o soc-acpi-intel-icl-match.o \
soc-acpi-intel-tgl-match.o soc-acpi-intel-ehl-match.o \
soc-acpi-intel-jsl-match.o soc-acpi-intel-adl-match.o \
- soc-acpi-intel-hda-match.o
+ soc-acpi-intel-hda-match.o \
+ soc-acpi-intel-sdw-mockup-match.o
obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o
obj-$(CONFIG_SND_SOC_ACPI_INTEL_MATCH) += snd-soc-acpi-intel-match.o
diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
index 42ef51c3fb4f..b591c6fd13fd 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
@@ -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",
diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
index 39dad32564e6..94b650767e11 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
@@ -9,6 +9,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
#include "../skylake/skl.h"
+#include "soc-acpi-intel-sdw-mockup-match.h"
static struct skl_machine_pdata cnl_pdata = {
.use_tplg_pcm = true,
@@ -60,6 +61,20 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[] = {
.sof_fw_filename = "sof-cnl.ri",
.sof_tplg_filename = "sof-cnl-rt5682-sdw2.tplg"
},
+ {
+ .link_mask = GENMASK(3, 0),
+ .links = sdw_mockup_headset_2amps_mic,
+ .drv_name = "sof_sdw",
+ .sof_fw_filename = "sof-cnl.ri",
+ .sof_tplg_filename = "sof-cml-rt711-rt1308-rt715.tplg",
+ },
+ {
+ .link_mask = BIT(0) | BIT(1) | BIT(3),
+ .links = sdw_mockup_headset_1amp_mic,
+ .drv_name = "sof_sdw",
+ .sof_fw_filename = "sof-cnl.ri",
+ .sof_tplg_filename = "sof-cml-rt711-rt1308-mono-rt715.tplg",
+ },
{}
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cnl_sdw_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
index 3586ce72c42c..69ff7286d357 100644
--- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
@@ -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);
diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
index ba5ff468c265..741bf2f9e081 100644
--- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
@@ -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,
diff --git a/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c
new file mode 100644
index 000000000000..a3d33997736a
--- /dev/null
+++ b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// soc-acpi-intel-sdw-mockup-match.c - tables and support for SoundWire
+// mockup device ACPI enumeration.
+//
+// Copyright (c) 2021, Intel Corporation.
+//
+
+#include <sound/soc-acpi.h>
+#include <sound/soc-acpi-intel-match.h>
+#include "soc-acpi-intel-sdw-mockup-match.h"
+
+static const struct snd_soc_acpi_endpoint sdw_mockup_single_endpoint = {
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+};
+
+static const struct snd_soc_acpi_endpoint sdw_mockup_l_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 0,
+ .group_id = 1,
+};
+
+static const struct snd_soc_acpi_endpoint sdw_mockup_r_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 1,
+ .group_id = 1,
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_headset_0_adr[] = {
+ {
+ .adr = 0x0000000105AA5500ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_single_endpoint,
+ .name_prefix = "sdw_mockup_headset0"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_headset_1_adr[] = {
+ {
+ .adr = 0x0001000105AA5500ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_single_endpoint,
+ .name_prefix = "sdw_mockup_headset1"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_amp_1_adr[] = {
+ {
+ .adr = 0x000100010555AA00ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_single_endpoint,
+ .name_prefix = "sdw_mockup_amp1"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_amp_2_adr[] = {
+ {
+ .adr = 0x000200010555AA00ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_single_endpoint,
+ .name_prefix = "sdw_mockup_amp2"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_mic_0_adr[] = {
+ {
+ .adr = 0x0000000105555500ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_single_endpoint,
+ .name_prefix = "sdw_mockup_mic0"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_mic_3_adr[] = {
+ {
+ .adr = 0x0003000105555500ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_single_endpoint,
+ .name_prefix = "sdw_mockup_mic3"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_amp_1_group1_adr[] = {
+ {
+ .adr = 0x000100010555AA00ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_l_endpoint,
+ .name_prefix = "sdw_mockup_amp1_l"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_amp_2_group1_adr[] = {
+ {
+ .adr = 0x000200010555AA00ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_r_endpoint,
+ .name_prefix = "sdw_mockup_amp2_r"
+ }
+};
+
+const struct snd_soc_acpi_link_adr sdw_mockup_headset_1amp_mic[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(sdw_mockup_headset_0_adr),
+ .adr_d = sdw_mockup_headset_0_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(sdw_mockup_amp_1_adr),
+ .adr_d = sdw_mockup_amp_1_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(sdw_mockup_mic_3_adr),
+ .adr_d = sdw_mockup_mic_3_adr,
+ },
+ {}
+};
+
+const struct snd_soc_acpi_link_adr sdw_mockup_headset_2amps_mic[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(sdw_mockup_headset_0_adr),
+ .adr_d = sdw_mockup_headset_0_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(sdw_mockup_amp_1_group1_adr),
+ .adr_d = sdw_mockup_amp_1_group1_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(sdw_mockup_amp_2_group1_adr),
+ .adr_d = sdw_mockup_amp_2_group1_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(sdw_mockup_mic_3_adr),
+ .adr_d = sdw_mockup_mic_3_adr,
+ },
+ {}
+};
+
+const struct snd_soc_acpi_link_adr sdw_mockup_mic_headset_1amp[] = {
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(sdw_mockup_headset_1_adr),
+ .adr_d = sdw_mockup_headset_1_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(sdw_mockup_amp_2_adr),
+ .adr_d = sdw_mockup_amp_2_adr,
+ },
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(sdw_mockup_mic_0_adr),
+ .adr_d = sdw_mockup_mic_0_adr,
+ },
+ {}
+};
diff --git a/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h
new file mode 100644
index 000000000000..c99eecd19e03
--- /dev/null
+++ b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * soc-acpi-intel-sdw-mockup-match.h - tables and support for SoundWire
+ * mockup device ACPI enumeration.
+ *
+ * Copyright (c) 2021, Intel Corporation.
+ *
+ */
+
+#ifndef _SND_SOC_ACPI_INTEL_SDW_MOCKUP_MATCH
+#define _SND_SOC_ACPI_INTEL_SDW_MOCKUP_MATCH
+
+extern const struct snd_soc_acpi_link_adr sdw_mockup_headset_1amp_mic[];
+extern const struct snd_soc_acpi_link_adr sdw_mockup_headset_2amps_mic[];
+extern const struct snd_soc_acpi_link_adr sdw_mockup_mic_headset_1amp[];
+
+#endif
diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
index 66595e3ab13f..785d5f5f8a9c 100644
--- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
@@ -8,6 +8,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
+#include "soc-acpi-intel-sdw-mockup-match.h"
static const struct snd_soc_acpi_codecs tgl_codecs = {
.num_codecs = 1,
@@ -196,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),
@@ -351,6 +361,28 @@ EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_machines);
/* this table is used when there is no I2S codec present */
struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
+ /* mockup tests need to be first */
+ {
+ .link_mask = GENMASK(3, 0),
+ .links = sdw_mockup_headset_2amps_mic,
+ .drv_name = "sof_sdw",
+ .sof_fw_filename = "sof-tgl.ri",
+ .sof_tplg_filename = "sof-tgl-rt711-rt1308-rt715.tplg",
+ },
+ {
+ .link_mask = BIT(0) | BIT(1) | BIT(3),
+ .links = sdw_mockup_headset_1amp_mic,
+ .drv_name = "sof_sdw",
+ .sof_fw_filename = "sof-tgl.ri",
+ .sof_tplg_filename = "sof-tgl-rt711-rt1308-mono-rt715.tplg",
+ },
+ {
+ .link_mask = BIT(0) | BIT(1) | BIT(2),
+ .links = sdw_mockup_mic_headset_1amp,
+ .drv_name = "sof_sdw",
+ .sof_fw_filename = "sof-tgl.ri",
+ .sof_tplg_filename = "sof-tgl-rt715-rt711-rt1308-mono.tplg",
+ },
{
.link_mask = 0x7,
.links = tgl_sdw_rt711_link1_rt1308_link2_rt715_link0,
@@ -398,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);
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c
index 476ef1897961..eaad180af42e 100644
--- a/sound/soc/intel/skylake/skl-messages.c
+++ b/sound/soc/intel/skylake/skl-messages.c
@@ -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
@@ -738,28 +807,6 @@ static void skl_set_copier_format(struct skl_dev *skl,
}
/*
- * 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
/*
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c
index b1ca64d2f7ea..9ecaf6a1e847 100644
--- a/sound/soc/intel/skylake/skl-pcm.c
+++ b/sound/soc/intel/skylake/skl-pcm.c
@@ -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 */
};
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c
index c0fdab39e7c2..b036852d6889 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -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)
diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h
index fb011862fb24..f0695b2ac5dd 100644
--- a/sound/soc/intel/skylake/skl-topology.h
+++ b/sound/soc/intel/skylake/skl-topology.h
@@ -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];
};
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 74dae4332d17..cf567a89f421 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -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".
diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile
index f6cb6b8508e3..34778ca12106 100644
--- a/sound/soc/mediatek/Makefile
+++ b/sound/soc/mediatek/Makefile
@@ -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/
diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
index 3cb2adf420bb..baaa5881b1d4 100644
--- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c
+++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
@@ -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);
}
diff --git a/sound/soc/mediatek/common/mtk-base-afe.h b/sound/soc/mediatek/common/mtk-base-afe.h
index a6f68c68581c..ef83e78c22a8 100644
--- a/sound/soc/mediatek/common/mtk-base-afe.h
+++ b/sound/soc/mediatek/common/mtk-base-afe.h
@@ -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;
diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
index c4a598cbbdaa..14e77df06b01 100644
--- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
+++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
@@ -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)
diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
index 7a1724f5ff4c..31c280339c50 100644
--- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
+++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
@@ -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
index 000000000000..44775f400b40
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/Makefile
@@ -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
index 000000000000..8420b2c71332
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
@@ -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
index 000000000000..f8e6eeb29a89
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.h
@@ -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
index 000000000000..f93f439e2bd9
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-afe-common.h
@@ -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
index 000000000000..6635c3f72ecc
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
@@ -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
index 000000000000..740aa6ddda0e
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.c
@@ -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
index 000000000000..239d31016ba7
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.h
@@ -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
index 000000000000..4dd0a5c8b8fa
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-audsys-clkid.h
@@ -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
index 000000000000..878dec0b69ed
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c
@@ -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
index 000000000000..7378e42f2766
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c
@@ -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
index 000000000000..5d10d2c4c991
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c
@@ -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
index 000000000000..5dc217f59bd6
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c
@@ -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
index 000000000000..d06f9cf85a4e
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-reg.h
@@ -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
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 939e7e28486a..7f13a35e9cc1 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -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,
};
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 4240fde6aae8..58f8541ba55c 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -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
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index bcde4a96c168..5bfc1a966532 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -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,
};
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 2b7839715dd5..9d6c41f775e5 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -19,15 +19,12 @@
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)
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c
index 08a05f0ecad7..ba2a98268ee4 100644
--- a/sound/soc/qcom/apq8016_sbc.c
+++ b/sound/soc/qcom/apq8016_sbc.c
@@ -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,
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
index f9df76d37858..a59e9d20cb46 100644
--- a/sound/soc/qcom/lpass-platform.c
+++ b/sound/soc/qcom/lpass-platform.c
@@ -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,
diff --git a/sound/soc/qcom/qdsp6/q6adm.c b/sound/soc/qcom/qdsp6/q6adm.c
index 1855b805eba2..3d831b635524 100644
--- a/sound/soc/qcom/qdsp6/q6adm.c
+++ b/sound/soc/qcom/qdsp6/q6adm.c
@@ -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 */
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c
index 5ff56a735419..46f365528d50 100644
--- a/sound/soc/qcom/qdsp6/q6asm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
@@ -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),
diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c
index 36bf8bd4edd7..9251d8548965 100644
--- a/sound/soc/qcom/qdsp6/q6asm.c
+++ b/sound/soc/qcom/qdsp6/q6asm.c
@@ -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);
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index c7dc3509bceb..53e0b4a1c7d2 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -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");
diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h
index fcaae24e40af..251851bf4f2c 100644
--- a/sound/soc/rockchip/rockchip_i2s.h
+++ b/sound/soc/rockchip/rockchip_i2s.h
@@ -88,15 +88,17 @@
#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)
diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c
index 73226a46d489..d027ca4b1796 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -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);
}
diff --git a/sound/soc/samsung/aries_wm8994.c b/sound/soc/samsung/aries_wm8994.c
index 0ac5956ba270..313ab650f8d9 100644
--- a/sound/soc/samsung/aries_wm8994.c
+++ b/sound/soc/samsung/aries_wm8994.c
@@ -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,
};
diff --git a/sound/soc/samsung/arndale.c b/sound/soc/samsung/arndale.c
index 28587375813a..606ac5e33a8e 100644
--- a/sound/soc/samsung/arndale.c
+++ b/sound/soc/samsung/arndale.c
@@ -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,
};
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c
index 8aa78ff640f5..c994e67d1eaf 100644
--- a/sound/soc/samsung/h1940_uda1380.c
+++ b/sound/soc/samsung/h1940_uda1380.c
@@ -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,
};
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
index a1ff1400857e..390f2dd735ad 100644
--- a/sound/soc/samsung/littlemill.c
+++ b/sound/soc/samsung/littlemill.c
@@ -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,
};
diff --git a/sound/soc/samsung/midas_wm1811.c b/sound/soc/samsung/midas_wm1811.c
index 1f9a553edf19..a2019535a0b1 100644
--- a/sound/soc/samsung/midas_wm1811.c
+++ b/sound/soc/samsung/midas_wm1811.c
@@ -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,
};
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index 9266070e0181..c98b68567a89 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -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,
};
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c
index 400a7f77c711..6ea1c8cc9167 100644
--- a/sound/soc/samsung/rx1950_uda1380.c
+++ b/sound/soc/samsung/rx1950_uda1380.c
@@ -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,
};
diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c
index c95629becbc3..cee39ad16667 100644
--- a/sound/soc/samsung/smartq_wm8987.c
+++ b/sound/soc/samsung/smartq_wm8987.c
@@ -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,
};
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index ed753a2f202e..78703d095a6f 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -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,
};
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
index 39a7a449f554..7661b637946d 100644
--- a/sound/soc/samsung/smdk_wm8994.c
+++ b/sound/soc/samsung/smdk_wm8994.c
@@ -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,
};
diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c
index a01640576f71..029448f5bedb 100644
--- a/sound/soc/samsung/smdk_wm8994pcm.c
+++ b/sound/soc/samsung/smdk_wm8994pcm.c
@@ -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,
};
diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c
index 84c2c63d5a87..a2c77e6defec 100644
--- a/sound/soc/samsung/tm2_wm5110.c
+++ b/sound/soc/samsung/tm2_wm5110.c
@@ -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,
};
diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c
index c962d2c2a7f7..15223d860cb7 100644
--- a/sound/soc/samsung/tobermory.c
+++ b/sound/soc/samsung/tobermory.c
@@ -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,
};
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 346c806ba390..ae46f187cc2a 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -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
##
diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
index 51bd7c81671c..f6fd79948f6a 100644
--- a/sound/soc/sh/Makefile
+++ b/sound/soc/sh/Makefile
@@ -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
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index 0ebee1ed06a9..5f1e72edfee0 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -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;
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 5e382b5c9d45..978bd0406729 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -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;
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index 82d16e037d9a..16c6e0265749 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -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;
}
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 27f34ca6059d..87e606f688d3 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -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
index 000000000000..fa0cc08f70ec
--- /dev/null
+++ b/sound/soc/sh/rz-ssi.c
@@ -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>");
diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c
index 65db083e242b..5f49e3dec3fc 100644
--- a/sound/soc/soc-ac97.c
+++ b/sound/soc/soc-ac97.c
@@ -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);
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index c8dfd0de30e4..8e8d917d22f8 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -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);
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index b4f59350a5a8..36060800e9bd 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -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) {
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 583f2381cfc8..c830e96afba2 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -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;
diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c
index a56dcc8d6fb7..3db0fcf24385 100644
--- a/sound/soc/soc-dai.c
+++ b/sound/soc/soc-dai.c
@@ -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);
}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 91bf939d5233..7b67f1e19ae9 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -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) {
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index 9ef80a48707e..4aa48c74f21a 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -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;
}
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 0f1820f36b4d..d798765d168c 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -17,12 +17,6 @@
#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)
{
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index 58527247df83..08eaa9ddf191 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -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;
}
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index d1c570ca21ea..48f71bb81a2f 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -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;
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 0a24d0d409d2..f6e5ac3e0314 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -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;
diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig
index 4447f515e8b1..88b6176af021 100644
--- a/sound/soc/sof/intel/Kconfig
+++ b/sound/soc/sof/intel/Kconfig
@@ -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
diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c
index 821f25fbcf08..e115e12a856f 100644
--- a/sound/soc/sof/intel/cnl.c
+++ b/sound/soc/sof/intel/cnl.c
@@ -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);
diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c
index df00db8369c7..cc8ddef37f37 100644
--- a/sound/soc/sof/intel/hda-pcm.c
+++ b/sound/soc/sof/intel/hda-pcm.c
@@ -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"
@@ -27,6 +28,10 @@
#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;
diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
index 40a3993ae2cb..63c367478f1c 100644
--- a/sound/soc/sof/intel/hda-stream.c
+++ b/sound/soc/sof/intel/hda-stream.c
@@ -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);
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 891e6e1b9121..f60e2c57d3d0 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -41,6 +41,17 @@
#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;
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index 4d44f8910393..4fdfb108645c 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -233,7 +233,6 @@
#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 */
diff --git a/sound/soc/sof/intel/icl.c b/sound/soc/sof/intel/icl.c
index 88a74be8a0c1..ee095b8f2d01 100644
--- a/sound/soc/sof/intel/icl.c
+++ b/sound/soc/sof/intel/icl.c
@@ -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);
diff --git a/sound/soc/sof/intel/pci-tng.c b/sound/soc/sof/intel/pci-tng.c
index 4ee1da397d4e..4bded668b672 100644
--- a/sound/soc/sof/intel/pci-tng.c
+++ b/sound/soc/sof/intel/pci-tng.c
@@ -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"
diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h
index 529f68d0ca47..e9f7d4d7fcce 100644
--- a/sound/soc/sof/intel/shim.h
+++ b/sound/soc/sof/intel/shim.h
@@ -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;
diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c
index 2ed788304414..199d41a7dc9b 100644
--- a/sound/soc/sof/intel/tgl.c
+++ b/sound/soc/sof/intel/tgl.c
@@ -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);
diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index 510883cd9107..989912f2b739 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -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,17 +449,46 @@ 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.
*/
int sof_machine_check(struct snd_sof_dev *sdev)
diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c
index 03119462f9e2..bc9e70765678 100644
--- a/sound/soc/sof/sof-pci-dev.c
+++ b/sound/soc/sof/sof-pci-dev.c
@@ -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",
+ },
{}
};
diff --git a/sound/soc/sprd/sprd-pcm-dma.c b/sound/soc/sprd/sprd-pcm-dma.c
index 5e3a96d4793c..48d90616b23f 100644
--- a/sound/soc/sprd/sprd-pcm-dma.c
+++ b/sound/soc/sprd/sprd-pcm-dma.c
@@ -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,
};
diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c
index 0f9beef429a2..bcccdf3ddc52 100644
--- a/sound/soc/tegra/tegra210_admaif.c
+++ b/sound/soc/tegra/tegra210_admaif.c
@@ -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,
};
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index b3e1df693381..ef011a488ceb 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -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);
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index 36344f0a64c1..084a533bf4f2 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -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);
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index d3276b4595af..ef1e74d95236 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -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");
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h
index 4838cdcee20e..d602126c65b7 100644
--- a/sound/soc/tegra/tegra_pcm.h
+++ b/sound/soc/tegra/tegra_pcm.h
@@ -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);
diff --git a/sound/soc/ti/Kconfig b/sound/soc/ti/Kconfig
index 698d7bc84dcf..1d9fe3fca193 100644
--- a/sound/soc/ti/Kconfig
+++ b/sound/soc/ti/Kconfig
@@ -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)
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
index 017a5a5e56cd..56a19eeec5c7 100644
--- a/sound/soc/ti/davinci-mcasp.c
+++ b/sound/soc/ti/davinci-mcasp.c
@@ -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);
diff --git a/sound/soc/ti/j721e-evm.c b/sound/soc/ti/j721e-evm.c
index 265bbc5a2f96..9347f982c3e1 100644
--- a/sound/soc/ti/j721e-evm.c
+++ b/sound/soc/ti/j721e-evm.c
@@ -23,8 +23,11 @@
*/
#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;
diff --git a/sound/soc/ti/omap-abe-twl6040.c b/sound/soc/ti/omap-abe-twl6040.c
index 91cc9a4f44d7..2e3d1eea77c1 100644
--- a/sound/soc/ti/omap-abe-twl6040.c
+++ b/sound/soc/ti/omap-abe-twl6040.c
@@ -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;
diff --git a/sound/soc/uniphier/aio-cpu.c b/sound/soc/uniphier/aio-cpu.c
index cf9814130067..4e8d5f7532ba 100644
--- a/sound/soc/uniphier/aio-cpu.c
+++ b/sound/soc/uniphier/aio-cpu.c
@@ -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))
diff --git a/sound/usb/card.c b/sound/usb/card.c
index a1f8c3a026f5..fd570a42f043 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -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--;
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 6c0a052a28f9..5b19901f305a 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -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;
};
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index 14456f61539e..81d5ce07d548 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -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)
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 4f856771216b..533919a28856 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -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);
diff --git a/sound/usb/format.c b/sound/usb/format.c
index eb216fef4ba7..50efccbffb8a 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -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)
diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c
index 590a0dbba7a2..23767a14d126 100644
--- a/sound/usb/implicit.c
+++ b/sound/usb/implicit.c
@@ -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,
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 9b713b4a5ec4..43bc59575a6e 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -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) {
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index ea41e7a1f7bf..876bbc9a71ad 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -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);
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index c5794e83fd80..55eea90ee993 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -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,29 +450,11 @@ 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),
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 0a3cb8fd7d00..a66ce0375fd9 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -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 */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 4e5031a68064..5dc9266180e3 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -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,
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 19bb499c17da..e03043f7dad3 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -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...
*
@@ -3828,10 +3764,6 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
.data = &(const struct snd_usb_audio_quirk[]) {
{
.ifnum = 2,
- .type = QUIRK_AUDIO_ALIGN_TRANSFER,
- },
- {
- .ifnum = 2,
.type = QUIRK_AUDIO_STANDARD_MIXER,
},
{
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 326d1b0ea5e6..4479a590194f 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -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;
+ }
+ }
+}
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 67a02303c820..31abb7cb01a5 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -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 */
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index ee9aa1dcf0d8..ceb93d798182 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -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;
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 538831cbd925..167834133b9b 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -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 */
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c
index a34d7d9c2a57..378826312abe 100644
--- a/sound/x86/intel_hdmi_audio.c
+++ b/sound/x86/intel_hdmi_audio.c
@@ -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;
}
/*
@@ -1142,19 +1143,6 @@ static int had_pcm_hw_params(struct snd_pcm_substream *substream,
}
/*
- * 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
*/
static int had_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
@@ -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);
diff --git a/sound/x86/intel_hdmi_audio.h b/sound/x86/intel_hdmi_audio.h
index bb3853195922..7ce8c2a7d714 100644
--- a/sound/x86/intel_hdmi_audio.h
+++ b/sound/x86/intel_hdmi_audio.h
@@ -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;
};