summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/Kconfig2
-rw-r--r--sound/aoa/codecs/onyx.c2
-rw-r--r--sound/aoa/codecs/tas.c2
-rw-r--r--sound/arm/pxa2xx-ac97.c2
-rw-r--r--sound/atmel/ac97c.c2
-rw-r--r--sound/core/Kconfig3
-rw-r--r--sound/core/compress_offload.c360
-rw-r--r--sound/core/control.c2
-rw-r--r--sound/core/init.c14
-rw-r--r--sound/core/oss/mixer_oss.c4
-rw-r--r--sound/core/oss/rate.c2
-rw-r--r--sound/core/pcm_native.c24
-rw-r--r--sound/core/sound.c2
-rw-r--r--sound/core/ump.c6
-rw-r--r--sound/drivers/mts64.c2
-rw-r--r--sound/drivers/pcmtest.c2
-rw-r--r--sound/drivers/portman2x4.c2
-rw-r--r--sound/firewire/amdtp-stream.c3
-rw-r--r--sound/firewire/cmp.c47
-rw-r--r--sound/firewire/cmp.h1
-rw-r--r--sound/firewire/tascam/amdtp-tascam.c2
-rw-r--r--sound/hda/hdac_stream.c7
-rw-r--r--sound/hda/intel-dsp-config.c4
-rw-r--r--sound/hda/intel-sdw-acpi.c33
-rw-r--r--sound/i2c/cs8427.c2
-rw-r--r--sound/isa/gus/gus_pcm.c4
-rw-r--r--sound/mips/hal2.c2
-rw-r--r--sound/mips/sgio2audio.c4
-rw-r--r--sound/oss/dmasound/dmasound_paula.c2
-rw-r--r--sound/pci/hda/Kconfig2
-rw-r--r--sound/pci/hda/cs35l41_hda_i2c.c2
-rw-r--r--sound/pci/hda/hda_auto_parser.c61
-rw-r--r--sound/pci/hda/hda_codec.c2
-rw-r--r--sound/pci/hda/hda_controller.c3
-rw-r--r--sound/pci/hda/hda_controller.h2
-rw-r--r--sound/pci/hda/hda_eld.c2
-rw-r--r--sound/pci/hda/hda_generic.c4
-rw-r--r--sound/pci/hda/hda_generic.h1
-rw-r--r--sound/pci/hda/hda_intel.c48
-rw-r--r--sound/pci/hda/hda_local.h28
-rw-r--r--sound/pci/hda/hda_tegra.c2
-rw-r--r--sound/pci/hda/patch_analog.c6
-rw-r--r--sound/pci/hda/patch_cirrus.c8
-rw-r--r--sound/pci/hda/patch_conexant.c49
-rw-r--r--sound/pci/hda/patch_cs8409-tables.c2
-rw-r--r--sound/pci/hda/patch_cs8409.c5
-rw-r--r--sound/pci/hda/patch_cs8409.h2
-rw-r--r--sound/pci/hda/patch_realtek.c302
-rw-r--r--sound/pci/hda/patch_sigmatel.c22
-rw-r--r--sound/pci/hda/patch_via.c2
-rw-r--r--sound/pci/hda/tas2781_hda_i2c.c4
-rw-r--r--sound/pci/ice1712/prodigy192.c9
-rw-r--r--sound/pci/korg1212/korg1212.c6
-rw-r--r--sound/ppc/powermac.c2
-rw-r--r--sound/sh/aica.c4
-rw-r--r--sound/sh/sh_dac_audio.c2
-rw-r--r--sound/soc/Kconfig3
-rw-r--r--sound/soc/Makefile3
-rw-r--r--sound/soc/amd/acp-da7219-max98357a.c20
-rw-r--r--sound/soc/amd/acp-es8336.c2
-rw-r--r--sound/soc/amd/acp/Kconfig29
-rw-r--r--sound/soc/amd/acp/Makefile4
-rw-r--r--sound/soc/amd/acp/acp-i2s.c38
-rw-r--r--sound/soc/amd/acp/acp-legacy-common.c24
-rw-r--r--sound/soc/amd/acp/acp-legacy-mach.c8
-rw-r--r--sound/soc/amd/acp/acp-mach-common.c63
-rw-r--r--sound/soc/amd/acp/acp-mach.h12
-rw-r--r--sound/soc/amd/acp/acp-pci.c7
-rw-r--r--sound/soc/amd/acp/acp-pdm.c2
-rw-r--r--sound/soc/amd/acp/acp-platform.c18
-rw-r--r--sound/soc/amd/acp/acp-rembrandt.c4
-rw-r--r--sound/soc/amd/acp/acp-renoir.c4
-rw-r--r--sound/soc/amd/acp/acp-sdw-legacy-mach.c486
-rw-r--r--sound/soc/amd/acp/acp-sdw-mach-common.c64
-rw-r--r--sound/soc/amd/acp/acp-sdw-sof-mach.c109
-rw-r--r--sound/soc/amd/acp/acp-sof-mach.c6
-rw-r--r--sound/soc/amd/acp/acp63.c4
-rw-r--r--sound/soc/amd/acp/acp70.c14
-rw-r--r--sound/soc/amd/acp/acp_common.h19
-rw-r--r--sound/soc/amd/acp/amd-acp63-acpi-match.c54
-rw-r--r--sound/soc/amd/acp/amd.h9
-rw-r--r--sound/soc/amd/acp/soc_amd_sdw_common.h4
-rw-r--r--sound/soc/amd/acp3x-rt5682-max9836.c6
-rw-r--r--sound/soc/amd/mach-config.h1
-rw-r--r--sound/soc/amd/ps/pci-ps.c4
-rw-r--r--sound/soc/amd/ps/ps-sdw-dma.c2
-rw-r--r--sound/soc/amd/vangogh/acp5x-mach.c6
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c35
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c5
-rw-r--r--sound/soc/atmel/mchp-pdmc.c3
-rw-r--r--sound/soc/atmel/mchp-spdifrx.c2
-rw-r--r--sound/soc/atmel/mchp-spdiftx.c2
-rw-r--r--sound/soc/au1x/dbdma2.c2
-rw-r--r--sound/soc/au1x/dma.c2
-rw-r--r--sound/soc/bcm/bcm2835-i2s.c2
-rw-r--r--sound/soc/bcm/bcm63xx-pcm-whistler.c6
-rw-r--r--sound/soc/bcm/cygnus-pcm.c2
-rw-r--r--sound/soc/codecs/Kconfig69
-rw-r--r--sound/soc/codecs/Makefile20
-rw-r--r--sound/soc/codecs/adau1372-i2c.c1
-rw-r--r--sound/soc/codecs/adau1372-spi.c1
-rw-r--r--sound/soc/codecs/adau1372.c8
-rw-r--r--sound/soc/codecs/adau1372.h1
-rw-r--r--sound/soc/codecs/adau1373.c200
-rw-r--r--sound/soc/codecs/adau1701.c2
-rw-r--r--sound/soc/codecs/adau17x1.c2
-rw-r--r--sound/soc/codecs/aw88081.c1087
-rw-r--r--sound/soc/codecs/aw88081.h286
-rw-r--r--sound/soc/codecs/aw88395/aw88395_device.c2
-rw-r--r--sound/soc/codecs/aw88395/aw88395_lib.c2
-rw-r--r--sound/soc/codecs/aw88399.c4
-rw-r--r--sound/soc/codecs/cpcap.c2
-rw-r--r--sound/soc/codecs/cs35l45-tables.c2
-rw-r--r--sound/soc/codecs/cs35l45.h2
-rw-r--r--sound/soc/codecs/cs42l43.c42
-rw-r--r--sound/soc/codecs/cs42l51.c7
-rw-r--r--sound/soc/codecs/cs42l84.c1111
-rw-r--r--sound/soc/codecs/cs42l84.h210
-rw-r--r--sound/soc/codecs/da7213.c27
-rw-r--r--sound/soc/codecs/da7213.h1
-rw-r--r--sound/soc/codecs/da7219.c9
-rw-r--r--sound/soc/codecs/es8323.c792
-rw-r--r--sound/soc/codecs/es8323.h78
-rw-r--r--sound/soc/codecs/es8326.c20
-rw-r--r--sound/soc/codecs/hdmi-codec.c140
-rw-r--r--sound/soc/codecs/lpass-rx-macro.c17
-rw-r--r--sound/soc/codecs/max9768.c11
-rw-r--r--sound/soc/codecs/max98088.c86
-rw-r--r--sound/soc/codecs/max98388.c1
-rw-r--r--sound/soc/codecs/nau8821.c9
-rw-r--r--sound/soc/codecs/ntp8835.c480
-rw-r--r--sound/soc/codecs/ntp8918.c397
-rw-r--r--sound/soc/codecs/ntpfw.c137
-rw-r--r--sound/soc/codecs/ntpfw.h23
-rw-r--r--sound/soc/codecs/pcm186x.c4
-rw-r--r--sound/soc/codecs/pcm3060-i2c.c4
-rw-r--r--sound/soc/codecs/pcm3060-spi.c4
-rw-r--r--sound/soc/codecs/pcm3060.c4
-rw-r--r--sound/soc/codecs/pcm3060.h2
-rw-r--r--sound/soc/codecs/pcm5102a.c2
-rw-r--r--sound/soc/codecs/pcm6240.c2
-rw-r--r--sound/soc/codecs/peb2466.c2
-rw-r--r--sound/soc/codecs/rt-sdw-common.c238
-rw-r--r--sound/soc/codecs/rt-sdw-common.h66
-rw-r--r--sound/soc/codecs/rt1320-sdw.c3668
-rw-r--r--sound/soc/codecs/rt1320-sdw.h6
-rw-r--r--sound/soc/codecs/rt5640.c27
-rw-r--r--sound/soc/codecs/rt712-sdca-sdw.c1
-rw-r--r--sound/soc/codecs/rt712-sdca.c38
-rw-r--r--sound/soc/codecs/rt712-sdca.h1
-rw-r--r--sound/soc/codecs/rt721-sdca-sdw.c546
-rw-r--r--sound/soc/codecs/rt721-sdca-sdw.h150
-rw-r--r--sound/soc/codecs/rt721-sdca.c1545
-rw-r--r--sound/soc/codecs/rt721-sdca.h269
-rw-r--r--sound/soc/codecs/rt722-sdca-sdw.c14
-rw-r--r--sound/soc/codecs/rt722-sdca.c15
-rw-r--r--sound/soc/codecs/sigmadsp-i2c.c2
-rw-r--r--sound/soc/codecs/simple-mux.c39
-rw-r--r--sound/soc/codecs/sma1307.c2049
-rw-r--r--sound/soc/codecs/sma1307.h444
-rw-r--r--sound/soc/codecs/spdif_receiver.c2
-rw-r--r--sound/soc/codecs/spdif_transmitter.c2
-rw-r--r--sound/soc/codecs/tas2781-fmwlib.c3
-rw-r--r--sound/soc/codecs/tas2781-i2c.c37
-rw-r--r--sound/soc/codecs/tas571x.c2
-rw-r--r--sound/soc/codecs/tas5805m.c2
-rw-r--r--sound/soc/codecs/tas6424.c2
-rw-r--r--sound/soc/codecs/tlv320adc3xxx.c2
-rw-r--r--sound/soc/codecs/tlv320aic31xx.c2
-rw-r--r--sound/soc/codecs/twl4030.c12
-rw-r--r--sound/soc/codecs/uda1342.c347
-rw-r--r--sound/soc/codecs/uda1342.h78
-rw-r--r--sound/soc/codecs/wcd9335.c1
-rw-r--r--sound/soc/codecs/wcd937x.c13
-rw-r--r--sound/soc/codecs/wcd937x.h4
-rw-r--r--sound/soc/codecs/wm5102.c2
-rw-r--r--sound/soc/codecs/wm8958-dsp2.c2
-rw-r--r--sound/soc/fsl/Kconfig1
-rw-r--r--sound/soc/fsl/fsl-asoc-card.c32
-rw-r--r--sound/soc/fsl/fsl_aud2htx.c2
-rw-r--r--sound/soc/fsl/fsl_easrc.c2
-rw-r--r--sound/soc/fsl/fsl_esai.c4
-rw-r--r--sound/soc/fsl/fsl_micfil.c132
-rw-r--r--sound/soc/fsl/fsl_mqs.c41
-rw-r--r--sound/soc/fsl/fsl_qmc_audio.c2
-rw-r--r--sound/soc/fsl/fsl_sai.c5
-rw-r--r--sound/soc/fsl/fsl_sai.h1
-rw-r--r--sound/soc/fsl/fsl_xcvr.c94
-rw-r--r--sound/soc/fsl/fsl_xcvr.h5
-rw-r--r--sound/soc/fsl/imx-audmix.c18
-rw-r--r--sound/soc/fsl/imx-card.c70
-rw-r--r--sound/soc/generic/audio-graph-card.c2
-rw-r--r--sound/soc/generic/audio-graph-card2.c109
-rw-r--r--sound/soc/generic/simple-card-utils.c16
-rw-r--r--sound/soc/generic/test-component.c5
-rw-r--r--sound/soc/intel/Kconfig8
-rw-r--r--sound/soc/intel/atom/sst/sst_acpi.c64
-rw-r--r--sound/soc/intel/avs/boards/da7219.c2
-rw-r--r--sound/soc/intel/avs/boards/dmic.c4
-rw-r--r--sound/soc/intel/avs/boards/es8336.c2
-rw-r--r--sound/soc/intel/avs/boards/hdaudio.c4
-rw-r--r--sound/soc/intel/avs/boards/i2s_test.c2
-rw-r--r--sound/soc/intel/avs/boards/max98357a.c2
-rw-r--r--sound/soc/intel/avs/boards/max98373.c2
-rw-r--r--sound/soc/intel/avs/boards/max98927.c2
-rw-r--r--sound/soc/intel/avs/boards/nau8825.c2
-rw-r--r--sound/soc/intel/avs/boards/rt274.c2
-rw-r--r--sound/soc/intel/avs/boards/rt286.c2
-rw-r--r--sound/soc/intel/avs/boards/rt298.c2
-rw-r--r--sound/soc/intel/avs/boards/rt5514.c2
-rw-r--r--sound/soc/intel/avs/boards/rt5663.c2
-rw-r--r--sound/soc/intel/avs/boards/rt5682.c2
-rw-r--r--sound/soc/intel/avs/boards/ssm4567.c2
-rw-r--r--sound/soc/intel/avs/core.c3
-rw-r--r--sound/soc/intel/avs/pcm.c21
-rw-r--r--sound/soc/intel/avs/pcm.h16
-rw-r--r--sound/soc/intel/boards/Kconfig1
-rw-r--r--sound/soc/intel/boards/bdw-rt5650.c4
-rw-r--r--sound/soc/intel/boards/bdw-rt5677.c4
-rw-r--r--sound/soc/intel/boards/bdw_rt286.c10
-rw-r--r--sound/soc/intel/boards/bytcht_cx2072x.c6
-rw-r--r--sound/soc/intel/boards/bytcht_da7213.c6
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c6
-rw-r--r--sound/soc/intel/boards/bytcht_nocodec.c6
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c54
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c6
-rw-r--r--sound/soc/intel/boards/bytcr_wm5102.c6
-rw-r--r--sound/soc/intel/boards/cht_bsw_max98090_ti.c6
-rw-r--r--sound/soc/intel/boards/cht_bsw_nau8824.c6
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5645.c6
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5672.c6
-rw-r--r--sound/soc/intel/boards/ehl_rt5660.c14
-rw-r--r--sound/soc/intel/boards/hsw_rt5640.c10
-rw-r--r--sound/soc/intel/boards/sof_board_helpers.c15
-rw-r--r--sound/soc/intel/boards/sof_es8336.c8
-rw-r--r--sound/soc/intel/boards/sof_pcm512x.c9
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c15
-rw-r--r--sound/soc/intel/boards/sof_sdw.c137
-rw-r--r--sound/soc/intel/boards/sof_wm8804.c2
-rw-r--r--sound/soc/intel/common/Makefile6
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-arl-match.c65
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-lnl-match.c103
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c58
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-ptl-match.c75
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-rpl-match.c1
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c42
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h14
-rw-r--r--sound/soc/intel/common/sst-dsp-priv.h101
-rw-r--r--sound/soc/intel/common/sst-dsp.c250
-rw-r--r--sound/soc/intel/common/sst-dsp.h61
-rw-r--r--sound/soc/intel/common/sst-ipc.c294
-rw-r--r--sound/soc/intel/common/sst-ipc.h86
-rw-r--r--sound/soc/loongson/Kconfig32
-rw-r--r--sound/soc/loongson/Makefile9
-rw-r--r--sound/soc/loongson/loongson_card.c1
-rw-r--r--sound/soc/loongson/loongson_i2s.c5
-rw-r--r--sound/soc/loongson/loongson_i2s_plat.c185
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-cs42448.c20
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-wm8960.c6
-rw-r--r--sound/soc/mediatek/mt6797/mt6797-mt6351.c24
-rw-r--r--sound/soc/mediatek/mt7986/mt7986-wm8960.c6
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-max98090.c6
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c6
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c10
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-rt5650.c10
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c34
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-dai-i2s.c7
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c34
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366.c86
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-dai-adda.c1
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-dai-etdm.c5
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-dai-pcm.c2
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-mt6359.c58
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c78
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-dai-pcm.c2
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-mt6359.c60
-rw-r--r--sound/soc/mediatek/mt8365/mt8365-dai-dmic.c6
-rw-r--r--sound/soc/mediatek/mt8365/mt8365-dai-pcm.c2
-rw-r--r--sound/soc/mediatek/mt8365/mt8365-mt6357.c14
-rw-r--r--sound/soc/meson/axg-card.c6
-rw-r--r--sound/soc/meson/axg-tdm-interface.c12
-rw-r--r--sound/soc/meson/axg-tdm.h2
-rw-r--r--sound/soc/meson/gx-card.c2
-rw-r--r--sound/soc/qcom/Kconfig2
-rw-r--r--sound/soc/qcom/lpass-cpu.c2
-rw-r--r--sound/soc/qcom/sc7280.c10
-rw-r--r--sound/soc/qcom/sc8280xp.c1
-rw-r--r--sound/soc/qcom/sdm845.c7
-rw-r--r--sound/soc/qcom/sm8250.c13
-rw-r--r--sound/soc/qcom/x1e80100.c40
-rw-r--r--sound/soc/renesas/Kconfig (renamed from sound/soc/sh/Kconfig)0
-rw-r--r--sound/soc/renesas/Makefile (renamed from sound/soc/sh/Makefile)0
-rw-r--r--sound/soc/renesas/dma-sh7760.c (renamed from sound/soc/sh/dma-sh7760.c)0
-rw-r--r--sound/soc/renesas/fsi.c (renamed from sound/soc/sh/fsi.c)0
-rw-r--r--sound/soc/renesas/hac.c (renamed from sound/soc/sh/hac.c)0
-rw-r--r--sound/soc/renesas/migor.c (renamed from sound/soc/sh/migor.c)0
-rw-r--r--sound/soc/renesas/rcar/Makefile (renamed from sound/soc/sh/rcar/Makefile)0
-rw-r--r--sound/soc/renesas/rcar/adg.c (renamed from sound/soc/sh/rcar/adg.c)0
-rw-r--r--sound/soc/renesas/rcar/cmd.c (renamed from sound/soc/sh/rcar/cmd.c)0
-rw-r--r--sound/soc/renesas/rcar/core.c (renamed from sound/soc/sh/rcar/core.c)29
-rw-r--r--sound/soc/renesas/rcar/ctu.c (renamed from sound/soc/sh/rcar/ctu.c)0
-rw-r--r--sound/soc/renesas/rcar/debugfs.c (renamed from sound/soc/sh/rcar/debugfs.c)0
-rw-r--r--sound/soc/renesas/rcar/dma.c (renamed from sound/soc/sh/rcar/dma.c)0
-rw-r--r--sound/soc/renesas/rcar/dvc.c (renamed from sound/soc/sh/rcar/dvc.c)0
-rw-r--r--sound/soc/renesas/rcar/gen.c (renamed from sound/soc/sh/rcar/gen.c)0
-rw-r--r--sound/soc/renesas/rcar/mix.c (renamed from sound/soc/sh/rcar/mix.c)0
-rw-r--r--sound/soc/renesas/rcar/rsnd.h (renamed from sound/soc/sh/rcar/rsnd.h)0
-rw-r--r--sound/soc/renesas/rcar/src.c (renamed from sound/soc/sh/rcar/src.c)0
-rw-r--r--sound/soc/renesas/rcar/ssi.c (renamed from sound/soc/sh/rcar/ssi.c)0
-rw-r--r--sound/soc/renesas/rcar/ssiu.c (renamed from sound/soc/sh/rcar/ssiu.c)0
-rw-r--r--sound/soc/renesas/rz-ssi.c (renamed from sound/soc/sh/rz-ssi.c)6
-rw-r--r--sound/soc/renesas/sh7760-ac97.c (renamed from sound/soc/sh/sh7760-ac97.c)0
-rw-r--r--sound/soc/renesas/siu.h (renamed from sound/soc/sh/siu.h)0
-rw-r--r--sound/soc/renesas/siu_dai.c (renamed from sound/soc/sh/siu_dai.c)0
-rw-r--r--sound/soc/renesas/siu_pcm.c (renamed from sound/soc/sh/siu_pcm.c)0
-rw-r--r--sound/soc/renesas/ssi.c (renamed from sound/soc/sh/ssi.c)0
-rw-r--r--sound/soc/samsung/odroid.c11
-rw-r--r--sound/soc/sdca/Kconfig11
-rw-r--r--sound/soc/sdca/Makefile5
-rw-r--r--sound/soc/sdca/sdca_device.c67
-rw-r--r--sound/soc/sdca/sdca_functions.c177
-rw-r--r--sound/soc/sdw_utils/Makefile3
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt712_sdca.c48
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt722_sdca.c41
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c90
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c8
-rw-r--r--sound/soc/sdw_utils/soc_sdw_utils.c80
-rw-r--r--sound/soc/soc-acpi.c30
-rw-r--r--sound/soc/soc-component.c14
-rw-r--r--sound/soc/soc-compress.c28
-rw-r--r--sound/soc/soc-core.c70
-rw-r--r--sound/soc/soc-dai.c14
-rw-r--r--sound/soc/soc-dapm.c6
-rw-r--r--sound/soc/soc-devres.c37
-rw-r--r--sound/soc/soc-link.c10
-rw-r--r--sound/soc/soc-pcm.c152
-rw-r--r--sound/soc/soc-topology-test.c2
-rw-r--r--sound/soc/soc-topology.c8
-rw-r--r--sound/soc/soc-utils.c4
-rw-r--r--sound/soc/sof/amd/acp-common.c3
-rw-r--r--sound/soc/sof/amd/acp-loader.c5
-rw-r--r--sound/soc/sof/amd/acp.c14
-rw-r--r--sound/soc/sof/core.c64
-rw-r--r--sound/soc/sof/intel/hda-dai-ops.c23
-rw-r--r--sound/soc/sof/intel/hda-dai.c41
-rw-r--r--sound/soc/sof/intel/hda-dsp.c5
-rw-r--r--sound/soc/sof/intel/hda-loader.c117
-rw-r--r--sound/soc/sof/intel/hda-mlink.c18
-rw-r--r--sound/soc/sof/intel/hda-stream.c32
-rw-r--r--sound/soc/sof/intel/hda.c27
-rw-r--r--sound/soc/sof/intel/hda.h14
-rw-r--r--sound/soc/sof/intel/lnl.c10
-rw-r--r--sound/soc/sof/iomem-utils.c2
-rw-r--r--sound/soc/sof/ipc3-loader.c3
-rw-r--r--sound/soc/sof/ipc3.c2
-rw-r--r--sound/soc/sof/ipc4-pcm.c3
-rw-r--r--sound/soc/sof/ipc4-topology.c391
-rw-r--r--sound/soc/sof/nocodec.c7
-rw-r--r--sound/soc/sof/ops.h8
-rw-r--r--sound/soc/sof/sof-acpi-dev.c4
-rw-r--r--sound/soc/sof/sof-client-probes-ipc4.c1
-rw-r--r--sound/soc/sof/sof-of-dev.c14
-rw-r--r--sound/soc/sof/sof-pci-dev.c12
-rw-r--r--sound/soc/sof/sof-utils.c2
-rw-r--r--sound/soc/stm/stm32_adfsdm.c4
-rw-r--r--sound/soc/stm/stm32_i2s.c211
-rw-r--r--sound/soc/stm/stm32_sai.c58
-rw-r--r--sound/soc/stm/stm32_sai.h6
-rw-r--r--sound/soc/stm/stm32_sai_sub.c152
-rw-r--r--sound/soc/stm/stm32_spdifrx.c2
-rw-r--r--sound/soc/sunxi/sun4i-codec.c298
-rw-r--r--sound/soc/tegra/tegra186_dspk.c3
-rw-r--r--sound/soc/tegra/tegra210_admaif.c11
-rw-r--r--sound/soc/tegra/tegra210_adx.c9
-rw-r--r--sound/soc/tegra/tegra210_amx.c9
-rw-r--r--sound/soc/tegra/tegra210_dmic.c7
-rw-r--r--sound/soc/tegra/tegra210_i2s.c14
-rw-r--r--sound/soc/tegra/tegra210_i2s.h9
-rw-r--r--sound/soc/tegra/tegra210_mixer.c9
-rw-r--r--sound/soc/tegra/tegra210_mvc.c9
-rw-r--r--sound/soc/tegra/tegra210_ope.c9
-rw-r--r--sound/soc/tegra/tegra210_sfc.c9
-rw-r--r--sound/soc/ti/rx51.c12
-rw-r--r--sound/soc/uniphier/aio-core.c25
-rw-r--r--sound/soc/uniphier/evea.c2
-rw-r--r--sound/soc/ux500/ux500_msp_dai.c6
-rw-r--r--sound/sparc/cs4231.c2
-rw-r--r--sound/sparc/dbri.c4
-rw-r--r--sound/usb/6fire/chip.c10
-rw-r--r--sound/usb/caiaq/audio.c10
-rw-r--r--sound/usb/caiaq/audio.h1
-rw-r--r--sound/usb/caiaq/device.c19
-rw-r--r--sound/usb/caiaq/input.c12
-rw-r--r--sound/usb/caiaq/input.h1
-rw-r--r--sound/usb/line6/capture.c2
-rw-r--r--sound/usb/line6/capture.h2
-rw-r--r--sound/usb/line6/driver.c4
-rw-r--r--sound/usb/line6/driver.h2
-rw-r--r--sound/usb/line6/midi.c2
-rw-r--r--sound/usb/line6/midi.h2
-rw-r--r--sound/usb/line6/midibuf.c2
-rw-r--r--sound/usb/line6/midibuf.h2
-rw-r--r--sound/usb/line6/pcm.c2
-rw-r--r--sound/usb/line6/pcm.h2
-rw-r--r--sound/usb/line6/playback.c2
-rw-r--r--sound/usb/line6/playback.h2
-rw-r--r--sound/usb/line6/pod.c2
-rw-r--r--sound/usb/line6/podhd.c2
-rw-r--r--sound/usb/line6/toneport.c2
-rw-r--r--sound/usb/line6/variax.c2
-rw-r--r--sound/usb/mixer.c60
-rw-r--r--sound/usb/mixer_quirks.c71
-rw-r--r--sound/usb/mixer_scarlett2.c222
-rw-r--r--sound/usb/quirks-table.h71
-rw-r--r--sound/usb/quirks.c35
-rw-r--r--sound/usb/stream.c1
-rw-r--r--sound/usb/usbaudio.h4
-rw-r--r--sound/usb/usx2y/us122l.c21
-rw-r--r--sound/usb/usx2y/us122l.h2
-rw-r--r--sound/usb/usx2y/usbusx2y.c2
420 files changed, 16908 insertions, 6475 deletions
diff --git a/sound/Kconfig b/sound/Kconfig
index 4c036a9a420a..8b40205394fe 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
menuconfig SOUND
tristate "Sound card support"
- depends on HAS_IOMEM || UML
+ depends on HAS_IOMEM || INDIRECT_IOMEM
help
If you have a sound card in your computer, i.e. if it can say more
than an occasional beep, say Y.
diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c
index e90e03bb0dc0..ac347a14f282 100644
--- a/sound/aoa/codecs/onyx.c
+++ b/sound/aoa/codecs/onyx.c
@@ -1040,7 +1040,7 @@ static void onyx_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id onyx_i2c_id[] = {
- { "MAC,pcm3052", 0 },
+ { "MAC,pcm3052" },
{ }
};
MODULE_DEVICE_TABLE(i2c,onyx_i2c_id);
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
index be9822ebf9f8..804b2ebbe28f 100644
--- a/sound/aoa/codecs/tas.c
+++ b/sound/aoa/codecs/tas.c
@@ -927,7 +927,7 @@ static void tas_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id tas_i2c_id[] = {
- { "MAC,tas3004", 0 },
+ { "MAC,tas3004" },
{ }
};
MODULE_DEVICE_TABLE(i2c,tas_i2c_id);
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 4c367e73b2c9..77b11616a7ee 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -271,7 +271,7 @@ static void pxa2xx_ac97_remove(struct platform_device *dev)
static struct platform_driver pxa2xx_ac97_driver = {
.probe = pxa2xx_ac97_probe,
- .remove_new = pxa2xx_ac97_remove,
+ .remove = pxa2xx_ac97_remove,
.driver = {
.name = "pxa2xx-ac97",
.pm = &pxa2xx_ac97_pm_ops,
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index 402b5f66dcc3..d8f8e08f1bb7 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -861,7 +861,7 @@ static void atmel_ac97c_remove(struct platform_device *pdev)
static struct platform_driver atmel_ac97c_driver = {
.probe = atmel_ac97c_probe,
- .remove_new = atmel_ac97c_remove,
+ .remove = atmel_ac97c_remove,
.driver = {
.name = "atmel_ac97c",
.pm = ATMEL_AC97C_PM_OPS,
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 2c5b9f964703..48db44fa56fe 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -59,6 +59,9 @@ config SND_CORE_TEST
config SND_COMPRESS_OFFLOAD
tristate
+config SND_COMPRESS_ACCEL
+ bool
+
config SND_JACK
bool
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index b8c0d6edbdd1..86ed2fbee0c8 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -24,6 +24,7 @@
#include <linux/types.h>
#include <linux/uio.h>
#include <linux/uaccess.h>
+#include <linux/dma-buf.h>
#include <linux/module.h>
#include <linux/compat.h>
#include <sound/core.h>
@@ -54,6 +55,12 @@ struct snd_compr_file {
static void error_delayed_work(struct work_struct *work);
+#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL)
+static void snd_compr_task_free_all(struct snd_compr_stream *stream);
+#else
+static inline void snd_compr_task_free_all(struct snd_compr_stream *stream) { }
+#endif
+
/*
* a note on stream states used:
* we use following states in the compressed core
@@ -85,6 +92,8 @@ static int snd_compr_open(struct inode *inode, struct file *f)
dirn = SND_COMPRESS_PLAYBACK;
else if ((f->f_flags & O_ACCMODE) == O_RDONLY)
dirn = SND_COMPRESS_CAPTURE;
+ else if ((f->f_flags & O_ACCMODE) == O_RDWR)
+ dirn = SND_COMPRESS_ACCEL;
else
return -EINVAL;
@@ -125,6 +134,9 @@ static int snd_compr_open(struct inode *inode, struct file *f)
}
runtime->state = SNDRV_PCM_STATE_OPEN;
init_waitqueue_head(&runtime->sleep);
+#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL)
+ INIT_LIST_HEAD(&runtime->tasks);
+#endif
data->stream.runtime = runtime;
f->private_data = (void *)data;
scoped_guard(mutex, &compr->lock)
@@ -154,6 +166,8 @@ static int snd_compr_free(struct inode *inode, struct file *f)
break;
}
+ snd_compr_task_free_all(&data->stream);
+
data->stream.ops->free(&data->stream);
if (!data->stream.runtime->dma_buffer_p)
kfree(data->stream.runtime->buffer);
@@ -226,6 +240,9 @@ snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
struct snd_compr_avail ioctl_avail;
size_t avail;
+ if (stream->direction == SND_COMPRESS_ACCEL)
+ return -EBADFD;
+
avail = snd_compr_calc_avail(stream, &ioctl_avail);
ioctl_avail.avail = avail;
@@ -287,8 +304,10 @@ static ssize_t snd_compr_write(struct file *f, const char __user *buf,
return -EFAULT;
stream = &data->stream;
+ if (stream->direction == SND_COMPRESS_ACCEL)
+ return -EBADFD;
guard(mutex)(&stream->device->lock);
- /* write is allowed when stream is running or has been steup */
+ /* write is allowed when stream is running or has been setup */
switch (stream->runtime->state) {
case SNDRV_PCM_STATE_SETUP:
case SNDRV_PCM_STATE_PREPARED:
@@ -336,6 +355,8 @@ static ssize_t snd_compr_read(struct file *f, char __user *buf,
return -EFAULT;
stream = &data->stream;
+ if (stream->direction == SND_COMPRESS_ACCEL)
+ return -EBADFD;
guard(mutex)(&stream->device->lock);
/* read is allowed when stream is running, paused, draining and setup
@@ -385,6 +406,7 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait)
{
struct snd_compr_file *data = f->private_data;
struct snd_compr_stream *stream;
+ struct snd_compr_runtime *runtime;
size_t avail;
__poll_t retval = 0;
@@ -392,10 +414,11 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait)
return EPOLLERR;
stream = &data->stream;
+ runtime = stream->runtime;
guard(mutex)(&stream->device->lock);
- switch (stream->runtime->state) {
+ switch (runtime->state) {
case SNDRV_PCM_STATE_OPEN:
case SNDRV_PCM_STATE_XRUN:
return snd_compr_get_poll(stream) | EPOLLERR;
@@ -403,23 +426,37 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait)
break;
}
- poll_wait(f, &stream->runtime->sleep, wait);
+ poll_wait(f, &runtime->sleep, wait);
+
+#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL)
+ if (stream->direction == SND_COMPRESS_ACCEL) {
+ struct snd_compr_task_runtime *task;
+ if (runtime->fragments > runtime->active_tasks)
+ retval |= EPOLLOUT | EPOLLWRNORM;
+ task = list_first_entry_or_null(&runtime->tasks,
+ struct snd_compr_task_runtime,
+ list);
+ if (task && task->state == SND_COMPRESS_TASK_STATE_FINISHED)
+ retval |= EPOLLIN | EPOLLRDNORM;
+ return retval;
+ }
+#endif
avail = snd_compr_get_avail(stream);
pr_debug("avail is %ld\n", (unsigned long)avail);
/* check if we have at least one fragment to fill */
- switch (stream->runtime->state) {
+ switch (runtime->state) {
case SNDRV_PCM_STATE_DRAINING:
/* stream has been woken up after drain is complete
* draining done so set stream state to stopped
*/
retval = snd_compr_get_poll(stream);
- stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+ runtime->state = SNDRV_PCM_STATE_SETUP;
break;
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
- if (avail >= stream->runtime->fragment_size)
+ if (avail >= runtime->fragment_size)
retval = snd_compr_get_poll(stream);
break;
default:
@@ -521,6 +558,9 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
unsigned int buffer_size;
void *buffer = NULL;
+ if (stream->direction == SND_COMPRESS_ACCEL)
+ goto params;
+
buffer_size = params->buffer.fragment_size * params->buffer.fragments;
if (stream->ops->copy) {
buffer = NULL;
@@ -543,18 +583,30 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
if (!buffer)
return -ENOMEM;
}
- stream->runtime->fragment_size = params->buffer.fragment_size;
- stream->runtime->fragments = params->buffer.fragments;
+
stream->runtime->buffer = buffer;
stream->runtime->buffer_size = buffer_size;
+params:
+ stream->runtime->fragment_size = params->buffer.fragment_size;
+ stream->runtime->fragments = params->buffer.fragments;
return 0;
}
-static int snd_compress_check_input(struct snd_compr_params *params)
+static int
+snd_compress_check_input(struct snd_compr_stream *stream, struct snd_compr_params *params)
{
+ u32 max_fragments;
+
/* first let's check the buffer parameter's */
- if (params->buffer.fragment_size == 0 ||
- params->buffer.fragments > U32_MAX / params->buffer.fragment_size ||
+ if (params->buffer.fragment_size == 0)
+ return -EINVAL;
+
+ if (stream->direction == SND_COMPRESS_ACCEL)
+ max_fragments = 64; /* safe value */
+ else
+ max_fragments = U32_MAX / params->buffer.fragment_size;
+
+ if (params->buffer.fragments > max_fragments ||
params->buffer.fragments == 0)
return -EINVAL;
@@ -583,7 +635,7 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
if (IS_ERR(params))
return PTR_ERR(params);
- retval = snd_compress_check_input(params);
+ retval = snd_compress_check_input(stream, params);
if (retval)
return retval;
@@ -939,6 +991,264 @@ static int snd_compr_partial_drain(struct snd_compr_stream *stream)
return snd_compress_wait_for_drain(stream);
}
+#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL)
+
+static struct snd_compr_task_runtime *
+snd_compr_find_task(struct snd_compr_stream *stream, __u64 seqno)
+{
+ struct snd_compr_task_runtime *task;
+
+ list_for_each_entry(task, &stream->runtime->tasks, list) {
+ if (task->seqno == seqno)
+ return task;
+ }
+ return NULL;
+}
+
+static void snd_compr_task_free(struct snd_compr_task_runtime *task)
+{
+ if (task->output)
+ dma_buf_put(task->output);
+ if (task->input)
+ dma_buf_put(task->input);
+ kfree(task);
+}
+
+static u64 snd_compr_seqno_next(struct snd_compr_stream *stream)
+{
+ u64 seqno = ++stream->runtime->task_seqno;
+ if (seqno == 0)
+ seqno = ++stream->runtime->task_seqno;
+ return seqno;
+}
+
+static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_task *utask)
+{
+ struct snd_compr_task_runtime *task;
+ int retval;
+
+ if (stream->runtime->total_tasks >= stream->runtime->fragments)
+ return -EBUSY;
+ if (utask->origin_seqno != 0 || utask->input_size != 0)
+ return -EINVAL;
+ task = kzalloc(sizeof(*task), GFP_KERNEL);
+ if (task == NULL)
+ return -ENOMEM;
+ task->seqno = utask->seqno = snd_compr_seqno_next(stream);
+ task->input_size = utask->input_size;
+ retval = stream->ops->task_create(stream, task);
+ if (retval < 0)
+ goto cleanup;
+ utask->input_fd = dma_buf_fd(task->input, O_WRONLY|O_CLOEXEC);
+ if (utask->input_fd < 0) {
+ retval = utask->input_fd;
+ goto cleanup;
+ }
+ utask->output_fd = dma_buf_fd(task->output, O_RDONLY|O_CLOEXEC);
+ if (utask->output_fd < 0) {
+ retval = utask->output_fd;
+ goto cleanup;
+ }
+ /* keep dmabuf reference until freed with task free ioctl */
+ dma_buf_get(utask->input_fd);
+ dma_buf_get(utask->output_fd);
+ list_add_tail(&task->list, &stream->runtime->tasks);
+ stream->runtime->total_tasks++;
+ return 0;
+cleanup:
+ snd_compr_task_free(task);
+ return retval;
+}
+
+static int snd_compr_task_create(struct snd_compr_stream *stream, unsigned long arg)
+{
+ struct snd_compr_task *task __free(kfree) = NULL;
+ int retval;
+
+ if (stream->runtime->state != SNDRV_PCM_STATE_SETUP)
+ return -EPERM;
+ task = memdup_user((void __user *)arg, sizeof(*task));
+ if (IS_ERR(task))
+ return PTR_ERR(no_free_ptr(task));
+ retval = snd_compr_task_new(stream, task);
+ if (retval >= 0)
+ if (copy_to_user((void __user *)arg, task, sizeof(*task)))
+ retval = -EFAULT;
+ return retval;
+}
+
+static int snd_compr_task_start_prepare(struct snd_compr_task_runtime *task,
+ struct snd_compr_task *utask)
+{
+ if (task == NULL)
+ return -EINVAL;
+ if (task->state >= SND_COMPRESS_TASK_STATE_FINISHED)
+ return -EBUSY;
+ if (utask->input_size > task->input->size)
+ return -EINVAL;
+ task->flags = utask->flags;
+ task->input_size = utask->input_size;
+ task->state = SND_COMPRESS_TASK_STATE_IDLE;
+ return 0;
+}
+
+static int snd_compr_task_start(struct snd_compr_stream *stream, struct snd_compr_task *utask)
+{
+ struct snd_compr_task_runtime *task;
+ int retval;
+
+ if (utask->origin_seqno > 0) {
+ task = snd_compr_find_task(stream, utask->origin_seqno);
+ retval = snd_compr_task_start_prepare(task, utask);
+ if (retval < 0)
+ return retval;
+ task->seqno = utask->seqno = snd_compr_seqno_next(stream);
+ utask->origin_seqno = 0;
+ list_move_tail(&task->list, &stream->runtime->tasks);
+ } else {
+ task = snd_compr_find_task(stream, utask->seqno);
+ if (task && task->state != SND_COMPRESS_TASK_STATE_IDLE)
+ return -EBUSY;
+ retval = snd_compr_task_start_prepare(task, utask);
+ if (retval < 0)
+ return retval;
+ }
+ retval = stream->ops->task_start(stream, task);
+ if (retval >= 0) {
+ task->state = SND_COMPRESS_TASK_STATE_ACTIVE;
+ stream->runtime->active_tasks++;
+ }
+ return retval;
+}
+
+static int snd_compr_task_start_ioctl(struct snd_compr_stream *stream, unsigned long arg)
+{
+ struct snd_compr_task *task __free(kfree) = NULL;
+ int retval;
+
+ if (stream->runtime->state != SNDRV_PCM_STATE_SETUP)
+ return -EPERM;
+ task = memdup_user((void __user *)arg, sizeof(*task));
+ if (IS_ERR(task))
+ return PTR_ERR(no_free_ptr(task));
+ retval = snd_compr_task_start(stream, task);
+ if (retval >= 0)
+ if (copy_to_user((void __user *)arg, task, sizeof(*task)))
+ retval = -EFAULT;
+ return retval;
+}
+
+static void snd_compr_task_stop_one(struct snd_compr_stream *stream,
+ struct snd_compr_task_runtime *task)
+{
+ if (task->state != SND_COMPRESS_TASK_STATE_ACTIVE)
+ return;
+ stream->ops->task_stop(stream, task);
+ if (!snd_BUG_ON(stream->runtime->active_tasks == 0))
+ stream->runtime->active_tasks--;
+ list_move_tail(&task->list, &stream->runtime->tasks);
+ task->state = SND_COMPRESS_TASK_STATE_IDLE;
+}
+
+static void snd_compr_task_free_one(struct snd_compr_stream *stream,
+ struct snd_compr_task_runtime *task)
+{
+ snd_compr_task_stop_one(stream, task);
+ stream->ops->task_free(stream, task);
+ list_del(&task->list);
+ snd_compr_task_free(task);
+ stream->runtime->total_tasks--;
+}
+
+static void snd_compr_task_free_all(struct snd_compr_stream *stream)
+{
+ struct snd_compr_task_runtime *task, *temp;
+
+ list_for_each_entry_safe_reverse(task, temp, &stream->runtime->tasks, list)
+ snd_compr_task_free_one(stream, task);
+}
+
+typedef void (*snd_compr_seq_func_t)(struct snd_compr_stream *stream,
+ struct snd_compr_task_runtime *task);
+
+static int snd_compr_task_seq(struct snd_compr_stream *stream, unsigned long arg,
+ snd_compr_seq_func_t fcn)
+{
+ struct snd_compr_task_runtime *task;
+ __u64 seqno;
+ int retval;
+
+ if (stream->runtime->state != SNDRV_PCM_STATE_SETUP)
+ return -EPERM;
+ retval = get_user(seqno, (__u64 __user *)arg);
+ if (retval < 0)
+ return retval;
+ retval = 0;
+ if (seqno == 0) {
+ list_for_each_entry_reverse(task, &stream->runtime->tasks, list)
+ fcn(stream, task);
+ } else {
+ task = snd_compr_find_task(stream, seqno);
+ if (task == NULL) {
+ retval = -EINVAL;
+ } else {
+ fcn(stream, task);
+ }
+ }
+ return retval;
+}
+
+static int snd_compr_task_status(struct snd_compr_stream *stream,
+ struct snd_compr_task_status *status)
+{
+ struct snd_compr_task_runtime *task;
+
+ task = snd_compr_find_task(stream, status->seqno);
+ if (task == NULL)
+ return -EINVAL;
+ status->input_size = task->input_size;
+ status->output_size = task->output_size;
+ status->state = task->state;
+ return 0;
+}
+
+static int snd_compr_task_status_ioctl(struct snd_compr_stream *stream, unsigned long arg)
+{
+ struct snd_compr_task_status *status __free(kfree) = NULL;
+ int retval;
+
+ if (stream->runtime->state != SNDRV_PCM_STATE_SETUP)
+ return -EPERM;
+ status = memdup_user((void __user *)arg, sizeof(*status));
+ if (IS_ERR(status))
+ return PTR_ERR(no_free_ptr(status));
+ retval = snd_compr_task_status(stream, status);
+ if (retval >= 0)
+ if (copy_to_user((void __user *)arg, status, sizeof(*status)))
+ retval = -EFAULT;
+ return retval;
+}
+
+/**
+ * snd_compr_task_finished: Notify that the task was finished
+ * @stream: pointer to stream
+ * @task: runtime task structure
+ *
+ * Set the finished task state and notify waiters.
+ */
+void snd_compr_task_finished(struct snd_compr_stream *stream,
+ struct snd_compr_task_runtime *task)
+{
+ guard(mutex)(&stream->device->lock);
+ if (!snd_BUG_ON(stream->runtime->active_tasks == 0))
+ stream->runtime->active_tasks--;
+ task->state = SND_COMPRESS_TASK_STATE_FINISHED;
+ wake_up(&stream->runtime->sleep);
+}
+EXPORT_SYMBOL_GPL(snd_compr_task_finished);
+
+#endif /* CONFIG_SND_COMPRESS_ACCEL */
+
static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
struct snd_compr_file *data = f->private_data;
@@ -968,6 +1278,27 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
return snd_compr_set_metadata(stream, arg);
case _IOC_NR(SNDRV_COMPRESS_GET_METADATA):
return snd_compr_get_metadata(stream, arg);
+ }
+
+ if (stream->direction == SND_COMPRESS_ACCEL) {
+#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL)
+ switch (_IOC_NR(cmd)) {
+ case _IOC_NR(SNDRV_COMPRESS_TASK_CREATE):
+ return snd_compr_task_create(stream, arg);
+ case _IOC_NR(SNDRV_COMPRESS_TASK_FREE):
+ return snd_compr_task_seq(stream, arg, snd_compr_task_free_one);
+ case _IOC_NR(SNDRV_COMPRESS_TASK_START):
+ return snd_compr_task_start_ioctl(stream, arg);
+ case _IOC_NR(SNDRV_COMPRESS_TASK_STOP):
+ return snd_compr_task_seq(stream, arg, snd_compr_task_stop_one);
+ case _IOC_NR(SNDRV_COMPRESS_TASK_STATUS):
+ return snd_compr_task_status_ioctl(stream, arg);
+ }
+#endif
+ return -ENOTTY;
+ }
+
+ switch (_IOC_NR(cmd)) {
case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
return snd_compr_tstamp(stream, arg);
case _IOC_NR(SNDRV_COMPRESS_AVAIL):
@@ -1140,6 +1471,11 @@ int snd_compress_new(struct snd_card *card, int device,
};
int ret;
+#if !IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL)
+ if (snd_BUG_ON(dirn == SND_COMPRESS_ACCEL))
+ return -EINVAL;
+#endif
+
compr->card = card;
compr->device = device;
compr->direction = dirn;
diff --git a/sound/core/control.c b/sound/core/control.c
index 2f790a7b1e90..0ddade871b52 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1641,6 +1641,8 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
count = info->owner;
if (count == 0)
count = 1;
+ if (count > MAX_CONTROL_COUNT)
+ return -EINVAL;
/* Arrange access permissions if needed. */
access = info->access;
diff --git a/sound/core/init.c b/sound/core/init.c
index b92aa7103589..114fb87de990 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -654,13 +654,19 @@ void snd_card_free(struct snd_card *card)
}
EXPORT_SYMBOL(snd_card_free);
+/* check, if the character is in the valid ASCII range */
+static inline bool safe_ascii_char(char c)
+{
+ return isascii(c) && isalnum(c);
+}
+
/* retrieve the last word of shortname or longname */
static const char *retrieve_id_from_card_name(const char *name)
{
const char *spos = name;
while (*name) {
- if (isspace(*name) && isalnum(name[1]))
+ if (isspace(*name) && safe_ascii_char(name[1]))
spos = name + 1;
name++;
}
@@ -687,12 +693,12 @@ static void copy_valid_id_string(struct snd_card *card, const char *src,
{
char *id = card->id;
- while (*nid && !isalnum(*nid))
+ while (*nid && !safe_ascii_char(*nid))
nid++;
if (isdigit(*nid))
*id++ = isalpha(*src) ? *src : 'D';
while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) {
- if (isalnum(*nid))
+ if (safe_ascii_char(*nid))
*id++ = *nid;
nid++;
}
@@ -787,7 +793,7 @@ static ssize_t id_store(struct device *dev, struct device_attribute *attr,
for (idx = 0; idx < copy; idx++) {
c = buf[idx];
- if (!isalnum(c) && c != '_' && c != '-')
+ if (!safe_ascii_char(c) && c != '_' && c != '-')
return -EINVAL;
}
memcpy(buf1, buf, copy);
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 668604d0ec9d..05fc8911479c 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -900,8 +900,8 @@ static void snd_mixer_oss_slot_free(struct snd_mixer_oss_slot *chn)
struct slot *p = chn->private_data;
if (p) {
if (p->allocated && p->assigned) {
- kfree_const(p->assigned->name);
- kfree_const(p->assigned);
+ kfree(p->assigned->name);
+ kfree(p->assigned);
}
kfree(p);
}
diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c
index 98269119347f..b56eeda5e30e 100644
--- a/sound/core/oss/rate.c
+++ b/sound/core/oss/rate.c
@@ -294,7 +294,7 @@ static int rate_action(struct snd_pcm_plugin *plugin,
default:
break;
}
- return 0; /* silenty ignore other actions */
+ return 0; /* silently ignore other actions */
}
int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 5b9076829ade..b44d205cc838 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2250,7 +2250,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
bool nonatomic = substream->pcm->nonatomic;
CLASS(fd, f)(fd);
- if (!fd_file(f))
+ if (fd_empty(f))
return -EBADFD;
if (!is_pcm_file(fd_file(f)))
return -EBADFD;
@@ -3115,7 +3115,7 @@ struct snd_pcm_sync_ptr32 {
} c;
} __packed;
-/* recalcuate the boundary within 32bit */
+/* recalculate the boundary within 32bit */
static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime)
{
snd_pcm_uframes_t boundary;
@@ -3774,6 +3774,26 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
#endif /* coherent mmap */
/*
+ * snd_pcm_mmap_data_open - increase the mmap counter
+ */
+static void snd_pcm_mmap_data_open(struct vm_area_struct *area)
+{
+ struct snd_pcm_substream *substream = area->vm_private_data;
+
+ atomic_inc(&substream->mmap_count);
+}
+
+/*
+ * snd_pcm_mmap_data_close - decrease the mmap counter
+ */
+static void snd_pcm_mmap_data_close(struct vm_area_struct *area)
+{
+ struct snd_pcm_substream *substream = area->vm_private_data;
+
+ atomic_dec(&substream->mmap_count);
+}
+
+/*
* fault callback for mmapping a RAM page
*/
static vm_fault_t snd_pcm_mmap_data_fault(struct vm_fault *vmf)
diff --git a/sound/core/sound.c b/sound/core/sound.c
index b9db9aa0bfcb..6531a67f13b3 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -133,7 +133,7 @@ static struct snd_minor *autoload_device(unsigned int minor)
/* /dev/aloadSEQ */
snd_request_other(minor);
}
- mutex_lock(&sound_mutex); /* reacuire lock */
+ mutex_lock(&sound_mutex); /* reacquire lock */
return snd_minors[minor];
}
#else /* !CONFIG_MODULES */
diff --git a/sound/core/ump.c b/sound/core/ump.c
index cf22a17e38dd..5d4dd207e5ab 100644
--- a/sound/core/ump.c
+++ b/sound/core/ump.c
@@ -366,7 +366,7 @@ int snd_ump_block_new(struct snd_ump_endpoint *ump, unsigned int blk,
{
struct snd_ump_block *fb, *p;
- if (blk < 0 || blk >= SNDRV_UMP_MAX_BLOCKS)
+ if (blk >= SNDRV_UMP_MAX_BLOCKS)
return -EINVAL;
if (snd_ump_get_block(ump, blk))
@@ -387,7 +387,7 @@ int snd_ump_block_new(struct snd_ump_endpoint *ump, unsigned int blk,
fb->info.first_group = first_group;
fb->info.num_groups = num_groups;
/* fill the default name, may be overwritten to a better name */
- snprintf(fb->info.name, sizeof(fb->info.name), "Group %d-%d",
+ snprintf(fb->info.name, sizeof(fb->info.name), "Group %u-%u",
first_group + 1, first_group + num_groups);
/* put the entry in the ordered list */
@@ -1233,7 +1233,7 @@ static int fill_legacy_mapping(struct snd_ump_endpoint *ump)
num = 0;
for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++)
- if (group_maps & (1U << i))
+ if ((group_maps & (1U << i)) && ump->groups[i].valid)
ump->legacy_mapping[num++] = i;
return num;
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
index 6fc255a6754d..17f215bad0ec 100644
--- a/sound/drivers/mts64.c
+++ b/sound/drivers/mts64.c
@@ -1008,7 +1008,7 @@ static void snd_mts64_remove(struct platform_device *pdev)
static struct platform_driver snd_mts64_driver = {
.probe = snd_mts64_probe,
- .remove_new = snd_mts64_remove,
+ .remove = snd_mts64_remove,
.driver = {
.name = PLATFORM_DRIVER,
}
diff --git a/sound/drivers/pcmtest.c b/sound/drivers/pcmtest.c
index 21cefaf5419a..72378f354fd0 100644
--- a/sound/drivers/pcmtest.c
+++ b/sound/drivers/pcmtest.c
@@ -640,7 +640,7 @@ static struct platform_device pcmtst_pdev = {
static struct platform_driver pcmtst_pdrv = {
.probe = pcmtst_probe,
- .remove_new = pdev_remove,
+ .remove = pdev_remove,
.driver = {
.name = "pcmtest",
},
diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c
index 54d818d2f53d..5e4ef25a83a4 100644
--- a/sound/drivers/portman2x4.c
+++ b/sound/drivers/portman2x4.c
@@ -794,7 +794,7 @@ static void snd_portman_remove(struct platform_device *pdev)
static struct platform_driver snd_portman_driver = {
.probe = snd_portman_probe,
- .remove_new = snd_portman_remove,
+ .remove = snd_portman_remove,
.driver = {
.name = PLATFORM_DRIVER,
}
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index c72b2a754775..7fc51f829ecc 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -172,6 +172,9 @@ static int apply_constraint_to_size(struct snd_pcm_hw_params *params,
step = max(step, amdtp_syt_intervals[i]);
}
+ if (step == 0)
+ return -EINVAL;
+
t.min = roundup(s->min, step);
t.max = rounddown(s->max, step);
t.integer = 1;
diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c
index b596bec19774..f5028a061a91 100644
--- a/sound/firewire/cmp.c
+++ b/sound/firewire/cmp.c
@@ -333,53 +333,6 @@ retry_after_bus_reset:
}
EXPORT_SYMBOL(cmp_connection_establish);
-/**
- * cmp_connection_update - update the connection after a bus reset
- * @c: the connection manager
- *
- * This function must be called from the driver's .update handler to
- * reestablish any connection that might have been active.
- *
- * Returns zero on success, or a negative error code. On an error, the
- * connection is broken and the caller must stop transmitting iso packets.
- */
-int cmp_connection_update(struct cmp_connection *c)
-{
- int err;
-
- mutex_lock(&c->mutex);
-
- if (!c->connected) {
- mutex_unlock(&c->mutex);
- return 0;
- }
-
- err = fw_iso_resources_update(&c->resources);
- if (err < 0)
- goto err_unconnect;
-
- if (c->direction == CMP_OUTPUT)
- err = pcr_modify(c, opcr_set_modify, pcr_set_check,
- SUCCEED_ON_BUS_RESET);
- else
- err = pcr_modify(c, ipcr_set_modify, pcr_set_check,
- SUCCEED_ON_BUS_RESET);
-
- if (err < 0)
- goto err_unconnect;
-
- mutex_unlock(&c->mutex);
-
- return 0;
-
-err_unconnect:
- c->connected = false;
- mutex_unlock(&c->mutex);
-
- return err;
-}
-EXPORT_SYMBOL(cmp_connection_update);
-
static __be32 pcr_break_modify(struct cmp_connection *c, __be32 pcr)
{
return pcr & ~cpu_to_be32(PCR_BCAST_CONN | PCR_P2P_CONN_MASK);
diff --git a/sound/firewire/cmp.h b/sound/firewire/cmp.h
index 26ab88000e34..66fc08b742d2 100644
--- a/sound/firewire/cmp.h
+++ b/sound/firewire/cmp.h
@@ -47,7 +47,6 @@ int cmp_connection_reserve(struct cmp_connection *connection,
void cmp_connection_release(struct cmp_connection *connection);
int cmp_connection_establish(struct cmp_connection *connection);
-int cmp_connection_update(struct cmp_connection *connection);
void cmp_connection_break(struct cmp_connection *connection);
#endif
diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c
index 0b42d6559008..079afa4bd381 100644
--- a/sound/firewire/tascam/amdtp-tascam.c
+++ b/sound/firewire/tascam/amdtp-tascam.c
@@ -238,7 +238,7 @@ int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit,
err = amdtp_stream_init(s, unit, dir, flags, fmt,
process_ctx_payloads, sizeof(struct amdtp_tscm));
if (err < 0)
- return 0;
+ return err;
if (dir == AMDTP_OUT_STREAM) {
// Use fixed value for FDF field.
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c
index b53de020309f..2670792f43b4 100644
--- a/sound/hda/hdac_stream.c
+++ b/sound/hda/hdac_stream.c
@@ -657,6 +657,7 @@ static void azx_timecounter_init(struct hdac_stream *azx_dev,
* snd_hdac_stream_timecounter_init - initialize time counter
* @azx_dev: HD-audio core stream (master stream)
* @streams: bit flags of streams to set up
+ * @start: true for PCM trigger start, false for other cases
*
* Initializes the time counter of streams marked by the bit flags (each
* bit corresponds to the stream index).
@@ -664,7 +665,7 @@ static void azx_timecounter_init(struct hdac_stream *azx_dev,
* updated accordingly, too.
*/
void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev,
- unsigned int streams)
+ unsigned int streams, bool start)
{
struct hdac_bus *bus = azx_dev->bus;
struct snd_pcm_runtime *runtime = azx_dev->substream->runtime;
@@ -672,6 +673,9 @@ void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev,
bool inited = false;
u64 cycle_last = 0;
+ if (!start)
+ goto skip;
+
list_for_each_entry(s, &bus->stream_list, list) {
if ((streams & (1 << s->index))) {
azx_timecounter_init(s, inited, cycle_last);
@@ -682,6 +686,7 @@ void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev,
}
}
+skip:
snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
runtime->trigger_tstamp_latched = true;
}
diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
index f018bd779862..9f849e05ce79 100644
--- a/sound/hda/intel-dsp-config.c
+++ b/sound/hda/intel-dsp-config.c
@@ -723,6 +723,10 @@ static const struct config_entry acpi_config_table[] = {
/* BayTrail */
{
.flags = FLAG_SST_OR_SOF_BYT,
+ .acpi_hid = "LPE0F28",
+ },
+ {
+ .flags = FLAG_SST_OR_SOF_BYT,
.acpi_hid = "80860F28",
},
/* CherryTrail */
diff --git a/sound/hda/intel-sdw-acpi.c b/sound/hda/intel-sdw-acpi.c
index 04d6b6beabca..ed530e0dd4dd 100644
--- a/sound/hda/intel-sdw-acpi.c
+++ b/sound/hda/intel-sdw-acpi.c
@@ -56,18 +56,21 @@ static int
sdw_intel_scan_controller(struct sdw_intel_acpi_info *info)
{
struct acpi_device *adev = acpi_fetch_acpi_dev(info->handle);
- u8 count, i;
+ struct fwnode_handle *fwnode;
+ unsigned long list;
+ unsigned int i;
+ u32 count;
+ u32 tmp;
int ret;
if (!adev)
return -EINVAL;
- /* Found controller, find links supported */
- count = 0;
- ret = fwnode_property_read_u8_array(acpi_fwnode_handle(adev),
- "mipi-sdw-master-count", &count, 1);
+ fwnode = acpi_fwnode_handle(adev);
/*
+ * Found controller, find links supported
+ *
* In theory we could check the number of links supported in
* hardware, but in that step we cannot assume SoundWire IP is
* powered.
@@ -78,11 +81,19 @@ sdw_intel_scan_controller(struct sdw_intel_acpi_info *info)
*
* We will check the hardware capabilities in the startup() step
*/
-
+ ret = fwnode_property_read_u32(fwnode, "mipi-sdw-manager-list", &tmp);
if (ret) {
- dev_err(&adev->dev,
- "Failed to read mipi-sdw-master-count: %d\n", ret);
- return -EINVAL;
+ ret = fwnode_property_read_u32(fwnode, "mipi-sdw-master-count", &count);
+ if (ret) {
+ dev_err(&adev->dev,
+ "Failed to read mipi-sdw-master-count: %d\n",
+ ret);
+ return ret;
+ }
+ list = GENMASK(count - 1, 0);
+ } else {
+ list = tmp;
+ count = hweight32(list);
}
/* Check count is within bounds */
@@ -101,14 +112,14 @@ sdw_intel_scan_controller(struct sdw_intel_acpi_info *info)
info->count = count;
info->link_mask = 0;
- for (i = 0; i < count; i++) {
+ for_each_set_bit(i, &list, SDW_INTEL_MAX_LINKS) {
if (ctrl_link_mask && !(ctrl_link_mask & BIT(i))) {
dev_dbg(&adev->dev,
"Link %d masked, will not be enabled\n", i);
continue;
}
- if (!is_link_enabled(acpi_fwnode_handle(adev), i)) {
+ if (!is_link_enabled(fwnode, i)) {
dev_dbg(&adev->dev,
"Link %d not selected in firmware\n", i);
continue;
diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c
index 29a1a7a0d050..46f081268348 100644
--- a/sound/i2c/cs8427.c
+++ b/sound/i2c/cs8427.c
@@ -10,7 +10,7 @@
#include <linux/init.h>
#include <linux/bitrev.h>
#include <linux/module.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index bcbcaa924c12..16f9bbb43a54 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -364,7 +364,7 @@ static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream,
bpos = get_bpos(pcmp, voice, pos, len);
if (bpos < 0)
- return pos;
+ return bpos;
if (copy_from_iter(runtime->dma_area + bpos, len, src) != len)
return -EFAULT;
return playback_copy_ack(substream, bpos, len);
@@ -381,7 +381,7 @@ static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream,
bpos = get_bpos(pcmp, voice, pos, len);
if (bpos < 0)
- return pos;
+ return bpos;
snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos,
bytes_to_samples(runtime, count));
return playback_copy_ack(substream, bpos, len);
diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c
index 3c26334227bb..991793e6bda9 100644
--- a/sound/mips/hal2.c
+++ b/sound/mips/hal2.c
@@ -886,7 +886,7 @@ static void hal2_remove(struct platform_device *pdev)
static struct platform_driver hal2_driver = {
.probe = hal2_probe,
- .remove_new = hal2_remove,
+ .remove = hal2_remove,
.driver = {
.name = "sgihal2",
}
diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c
index a8551ccdd1bf..4e2ff954ff59 100644
--- a/sound/mips/sgio2audio.c
+++ b/sound/mips/sgio2audio.c
@@ -917,8 +917,8 @@ static void snd_sgio2audio_remove(struct platform_device *pdev)
static struct platform_driver sgio2audio_driver = {
.probe = snd_sgio2audio_probe,
- .remove_new = snd_sgio2audio_remove,
- .driver = {
+ .remove = snd_sgio2audio_remove,
+ .driver = {
.name = "sgio2audio",
}
};
diff --git a/sound/oss/dmasound/dmasound_paula.c b/sound/oss/dmasound/dmasound_paula.c
index b8fad12f9e5f..8d443a3663d3 100644
--- a/sound/oss/dmasound/dmasound_paula.c
+++ b/sound/oss/dmasound/dmasound_paula.c
@@ -732,7 +732,7 @@ static void __exit amiga_audio_remove(struct platform_device *pdev)
* triggering a section mismatch warning.
*/
static struct platform_driver amiga_audio_driver __refdata = {
- .remove_new = __exit_p(amiga_audio_remove),
+ .remove = __exit_p(amiga_audio_remove),
.driver = {
.name = "amiga-audio",
},
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index bb15a0248250..68f1eee9e5c9 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -198,7 +198,7 @@ config SND_HDA_SCODEC_TAS2781_I2C
depends on SND_SOC
select SND_SOC_TAS2781_COMLIB
select SND_SOC_TAS2781_FMWLIB
- select CRC32_SARWATE
+ select CRC32
help
Say Y or M here to include TAS2781 I2C HD-audio side codec support
in snd-hda-intel driver, such as ALC287.
diff --git a/sound/pci/hda/cs35l41_hda_i2c.c b/sound/pci/hda/cs35l41_hda_i2c.c
index 603e9bff3a71..bb84740c8520 100644
--- a/sound/pci/hda/cs35l41_hda_i2c.c
+++ b/sound/pci/hda/cs35l41_hda_i2c.c
@@ -39,7 +39,7 @@ static void cs35l41_hda_i2c_remove(struct i2c_client *clt)
}
static const struct i2c_device_id cs35l41_hda_i2c_id[] = {
- { "cs35l41-hda", 0 },
+ { "cs35l41-hda" },
{}
};
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 7c6b1fe8dfcc..8e74be038b0f 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -956,6 +956,28 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec,
}
EXPORT_SYMBOL_GPL(snd_hda_pick_pin_fixup);
+/* check whether the given quirk entry matches with vendor/device pair */
+static bool hda_quirk_match(u16 vendor, u16 device, const struct hda_quirk *q)
+{
+ if (q->subvendor != vendor)
+ return false;
+ return !q->subdevice ||
+ (device & q->subdevice_mask) == q->subdevice;
+}
+
+/* look through the quirk list and return the matching entry */
+static const struct hda_quirk *
+hda_quirk_lookup_id(u16 vendor, u16 device, const struct hda_quirk *list)
+{
+ const struct hda_quirk *q;
+
+ for (q = list; q->subvendor || q->subdevice; q++) {
+ if (hda_quirk_match(vendor, device, q))
+ return q;
+ }
+ return NULL;
+}
+
/**
* snd_hda_pick_fixup - Pick up a fixup matching with PCI/codec SSID or model string
* @codec: the HDA codec
@@ -975,14 +997,16 @@ EXPORT_SYMBOL_GPL(snd_hda_pick_pin_fixup);
*/
void snd_hda_pick_fixup(struct hda_codec *codec,
const struct hda_model_fixup *models,
- const struct snd_pci_quirk *quirk,
+ const struct hda_quirk *quirk,
const struct hda_fixup *fixlist)
{
- const struct snd_pci_quirk *q;
+ const struct hda_quirk *q;
int id = HDA_FIXUP_ID_NOT_SET;
const char *name = NULL;
const char *type = NULL;
unsigned int vendor, device;
+ u16 pci_vendor, pci_device;
+ u16 codec_vendor, codec_device;
if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
return;
@@ -1013,27 +1037,42 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
if (!quirk)
return;
+ if (codec->bus->pci) {
+ pci_vendor = codec->bus->pci->subsystem_vendor;
+ pci_device = codec->bus->pci->subsystem_device;
+ }
+
+ codec_vendor = codec->core.subsystem_id >> 16;
+ codec_device = codec->core.subsystem_id & 0xffff;
+
/* 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);
+ q = hda_quirk_lookup_id(vendor, device, quirk);
if (q) {
type = "alias SSID";
goto found_device;
}
}
- /* match with the PCI SSID */
- q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
- if (q) {
- type = "PCI SSID";
- goto found_device;
+ /* match primarily with the PCI SSID */
+ for (q = quirk; q->subvendor || q->subdevice; q++) {
+ /* if the entry is specific to codec SSID, check with it */
+ if (!codec->bus->pci || q->match_codec_ssid) {
+ if (hda_quirk_match(codec_vendor, codec_device, q)) {
+ type = "codec SSID";
+ goto found_device;
+ }
+ } else {
+ if (hda_quirk_match(pci_vendor, pci_device, q)) {
+ type = "PCI SSID";
+ goto found_device;
+ }
+ }
}
/* match with the codec SSID */
- q = snd_pci_quirk_lookup_id(codec->core.subsystem_id >> 16,
- codec->core.subsystem_id & 0xffff,
- quirk);
+ q = hda_quirk_lookup_id(codec_vendor, codec_device, quirk);
if (q) {
type = "codec SSID";
goto found_device;
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 3dd1bda0c5c6..14763c0f31ad 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1734,9 +1734,9 @@ EXPORT_SYMBOL_GPL(snd_hda_ctl_add);
/**
* snd_hda_add_nid - Assign a NID to a control element
* @codec: HD-audio codec
- * @nid: corresponding NID (optional)
* @kctl: the control element to assign
* @index: index to kctl
+ * @nid: corresponding NID (optional)
*
* Add the given control element to an array inside the codec instance.
* This function is used when #snd_hda_ctl_add cannot be used for 1:1
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 5d86e5a9c814..f3330b7e0fcf 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -275,8 +275,7 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
spin_lock(&bus->reg_lock);
/* reset SYNC bits */
snd_hdac_stream_sync_trigger(hstr, false, sbits, sync_reg);
- if (start)
- snd_hdac_stream_timecounter_init(hstr, sbits);
+ snd_hdac_stream_timecounter_init(hstr, sbits, start);
spin_unlock(&bus->reg_lock);
return 0;
}
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h
index 68c883f202ca..c2d0109866e6 100644
--- a/sound/pci/hda/hda_controller.h
+++ b/sound/pci/hda/hda_controller.h
@@ -28,7 +28,7 @@
#else
#define AZX_DCAPS_I915_COMPONENT 0 /* NOP */
#endif
-#define AZX_DCAPS_AMD_ALLOC_FIX (1 << 14) /* AMD allocation workaround */
+/* 14 unused */
#define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */
#define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */
#define AZX_DCAPS_AMD_WORKAROUND (1 << 17) /* AMD-specific workaround */
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 1d108ed5c6f2..301730432375 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -12,7 +12,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <sound/core.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <sound/hda_chmap.h>
#include <sound/hda_codec.h>
#include "hda_local.h"
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 9cff87dfbecb..b34d84fedcc8 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -1383,7 +1383,7 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs,
struct nid_path *path;
hda_nid_t pin = pins[i];
- if (!spec->obey_preferred_dacs) {
+ if (!spec->preferred_dacs) {
path = snd_hda_get_path_from_idx(codec, path_idx[i]);
if (path) {
badness += assign_out_path_ctls(codec, path);
@@ -1395,7 +1395,7 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs,
if (dacs[i]) {
if (is_dac_already_used(codec, dacs[i]))
badness += bad->shared_primary;
- } else if (spec->obey_preferred_dacs) {
+ } else if (spec->preferred_dacs) {
badness += BAD_NO_PRIMARY_DAC;
}
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 08544601b4ce..9612afaa61c2 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -232,7 +232,6 @@ struct hda_gen_spec {
unsigned int power_down_unused:1; /* power down unused widgets */
unsigned int dac_min_mute:1; /* minimal = mute for DACs */
unsigned int suppress_vmaster:1; /* don't create vmaster kctls */
- unsigned int obey_preferred_dacs:1; /* obey preferred_dacs assignment */
/* other internal flags */
unsigned int no_analog:1; /* digital I/O only */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 045cd555c291..4a62440adfaf 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -40,7 +40,6 @@
#ifdef CONFIG_X86
/* for snoop control */
-#include <linux/dma-map-ops.h>
#include <asm/set_memory.h>
#include <asm/cpufeature.h>
#endif
@@ -307,7 +306,7 @@ enum {
/* quirks for ATI HDMI with snoop off */
#define AZX_DCAPS_PRESET_ATI_HDMI_NS \
- (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_AMD_ALLOC_FIX)
+ (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_SNOOP_OFF)
/* quirks for AMD SB */
#define AZX_DCAPS_PRESET_AMD_SB \
@@ -774,6 +773,14 @@ static void azx_clear_irq_pending(struct azx *chip)
static int azx_acquire_irq(struct azx *chip, int do_disconnect)
{
struct hdac_bus *bus = azx_bus(chip);
+ int ret;
+
+ if (!chip->msi || pci_alloc_irq_vectors(chip->pci, 1, 1, PCI_IRQ_MSI) < 0) {
+ ret = pci_alloc_irq_vectors(chip->pci, 1, 1, PCI_IRQ_INTX);
+ if (ret < 0)
+ return ret;
+ chip->msi = 0;
+ }
if (request_irq(chip->pci->irq, azx_interrupt,
chip->msi ? 0 : IRQF_SHARED,
@@ -787,7 +794,6 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect)
}
bus->irq = chip->pci->irq;
chip->card->sync_irq = bus->irq;
- pci_intx(chip->pci, !chip->msi);
return 0;
}
@@ -1033,22 +1039,12 @@ static int azx_suspend(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
struct azx *chip;
- struct hdac_bus *bus;
if (!azx_is_pm_ready(card))
return 0;
chip = card->private_data;
- bus = azx_bus(chip);
azx_shutdown_chip(chip);
- if (bus->irq >= 0) {
- free_irq(bus->irq, chip);
- bus->irq = -1;
- chip->card->sync_irq = -1;
- }
-
- if (chip->msi)
- pci_disable_msi(chip->pci);
trace_azx_suspend(chip);
return 0;
@@ -1063,11 +1059,6 @@ static int __maybe_unused azx_resume(struct device *dev)
return 0;
chip = card->private_data;
- if (chip->msi)
- if (pci_enable_msi(chip->pci) < 0)
- chip->msi = 0;
- if (azx_acquire_irq(chip, 1) < 0)
- return -EIO;
__azx_runtime_resume(chip);
@@ -1707,13 +1698,6 @@ static void azx_check_snoop_available(struct azx *chip)
if (chip->driver_caps & AZX_DCAPS_SNOOP_OFF)
snoop = false;
-#ifdef CONFIG_X86
- /* check the presence of DMA ops (i.e. IOMMU), disable snoop conditionally */
- if ((chip->driver_caps & AZX_DCAPS_AMD_ALLOC_FIX) &&
- !get_dma_ops(chip->card->dev))
- snoop = false;
-#endif
-
chip->snoop = snoop;
if (!snoop) {
dev_info(chip->card->dev, "Force to non-snoop mode\n");
@@ -1875,6 +1859,8 @@ static int azx_first_init(struct azx *chip)
bus->polling_mode = 1;
bus->not_use_interrupts = 1;
bus->access_sdnctl_in_dword = 1;
+ if (!chip->jackpoll_interval)
+ chip->jackpoll_interval = msecs_to_jiffies(1500);
}
err = pcim_iomap_regions(pci, 1 << 0, "ICH HD audio");
@@ -1900,13 +1886,9 @@ static int azx_first_init(struct azx *chip)
chip->gts_present = true;
#endif
- if (chip->msi) {
- if (chip->driver_caps & AZX_DCAPS_NO_MSI64) {
- dev_dbg(card->dev, "Disabling 64bit MSI\n");
- pci->no_64bit_msi = true;
- }
- if (pci_enable_msi(pci) < 0)
- chip->msi = 0;
+ if (chip->msi && chip->driver_caps & AZX_DCAPS_NO_MSI64) {
+ dev_dbg(card->dev, "Disabling 64bit MSI\n");
+ pci->no_64bit_msi = true;
}
pci_set_master(pci);
@@ -2058,7 +2040,7 @@ static int disable_msi_reset_irq(struct azx *chip)
free_irq(bus->irq, chip);
bus->irq = -1;
chip->card->sync_irq = -1;
- pci_disable_msi(chip->pci);
+ pci_free_irq_vectors(chip->pci);
chip->msi = 0;
err = azx_acquire_irq(chip, 1);
if (err < 0)
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 53a5a62b78fa..763f79f6f32e 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -292,6 +292,32 @@ struct hda_fixup {
} v;
};
+/*
+ * extended form of snd_pci_quirk:
+ * for PCI SSID matching, use SND_PCI_QUIRK() like before;
+ * for codec SSID matching, use the new HDA_CODEC_QUIRK() instead
+ */
+struct hda_quirk {
+ unsigned short subvendor; /* PCI subvendor ID */
+ unsigned short subdevice; /* PCI subdevice ID */
+ unsigned short subdevice_mask; /* bitmask to match */
+ bool match_codec_ssid; /* match only with codec SSID */
+ int value; /* value */
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ const char *name; /* name of the device (optional) */
+#endif
+};
+
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+#define HDA_CODEC_QUIRK(vend, dev, xname, val) \
+ { _SND_PCI_QUIRK_ID(vend, dev), .value = (val), .name = (xname),\
+ .match_codec_ssid = true }
+#else
+#define HDA_CODEC_QUIRK(vend, dev, xname, val) \
+ { _SND_PCI_QUIRK_ID(vend, dev), .value = (val), \
+ .match_codec_ssid = true }
+#endif
+
struct snd_hda_pin_quirk {
unsigned int codec; /* Codec vendor/device ID */
unsigned short subvendor; /* PCI subvendor ID */
@@ -351,7 +377,7 @@ void snd_hda_apply_fixup(struct hda_codec *codec, int action);
void __snd_hda_apply_fixup(struct hda_codec *codec, int id, int action, int depth);
void snd_hda_pick_fixup(struct hda_codec *codec,
const struct hda_model_fixup *models,
- const struct snd_pci_quirk *quirk,
+ const struct hda_quirk *quirk,
const struct hda_fixup *fixlist);
void snd_hda_pick_pin_fixup(struct hda_codec *codec,
const struct snd_hda_pin_quirk *pin_quirk,
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
index d967e70a7058..b1e30a83dfb0 100644
--- a/sound/pci/hda/hda_tegra.c
+++ b/sound/pci/hda/hda_tegra.c
@@ -606,7 +606,7 @@ static struct platform_driver tegra_platform_hda = {
.of_match_table = hda_tegra_match,
},
.probe = hda_tegra_probe,
- .remove_new = hda_tegra_remove,
+ .remove = hda_tegra_remove,
.shutdown = hda_tegra_shutdown,
};
module_platform_driver(tegra_platform_hda);
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 1e9dadcdc51b..56354fe060a1 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -345,7 +345,7 @@ static const struct hda_fixup ad1986a_fixups[] = {
},
};
-static const struct snd_pci_quirk ad1986a_fixup_tbl[] = {
+static const struct hda_quirk ad1986a_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_FIXUP_LAPTOP_IMIC),
SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9V", AD1986A_FIXUP_LAPTOP_IMIC),
SND_PCI_QUIRK(0x1043, 0x1443, "ASUS Z99He", AD1986A_FIXUP_EAPD),
@@ -588,7 +588,7 @@ static const struct hda_fixup ad1981_fixups[] = {
},
};
-static const struct snd_pci_quirk ad1981_fixup_tbl[] = {
+static const struct hda_quirk ad1981_fixup_tbl[] = {
SND_PCI_QUIRK_VENDOR(0x1014, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1981_FIXUP_HP_EAPD),
SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
@@ -1061,7 +1061,7 @@ static const struct hda_fixup ad1884_fixups[] = {
},
};
-static const struct snd_pci_quirk ad1884_fixup_tbl[] = {
+static const struct hda_quirk ad1884_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x2a82, "HP Touchsmart", AD1884_FIXUP_HP_TOUCHSMART),
SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1884_FIXUP_HP_EAPD),
SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1884_FIXUP_THINKPAD),
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 654724559355..06e046214a41 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -385,7 +385,7 @@ static const struct hda_model_fixup cs420x_models[] = {
{}
};
-static const struct snd_pci_quirk cs420x_fixup_tbl[] = {
+static const struct hda_quirk cs420x_fixup_tbl[] = {
SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53),
SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55),
SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
@@ -634,13 +634,13 @@ static const struct hda_model_fixup cs4208_models[] = {
{}
};
-static const struct snd_pci_quirk cs4208_fixup_tbl[] = {
+static const struct hda_quirk cs4208_fixup_tbl[] = {
SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS4208_MAC_AUTO),
{} /* terminator */
};
/* codec SSID matching */
-static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = {
+static const struct hda_quirk cs4208_mac_fixup_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x5e00, "MacBookPro 11,2", CS4208_MBP11),
SND_PCI_QUIRK(0x106b, 0x6c00, "MacMini 7,1", CS4208_MACMINI),
SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6),
@@ -818,7 +818,7 @@ static const struct hda_model_fixup cs421x_models[] = {
{}
};
-static const struct snd_pci_quirk cs421x_fixup_tbl[] = {
+static const struct hda_quirk cs421x_fixup_tbl[] = {
/* Test Intel board + CDB2410 */
SND_PCI_QUIRK(0x8086, 0x5001, "DP45SG/CDB4210", CS421X_CDB4210),
{} /* terminator */
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index e851785ff058..2e9f817b948e 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -166,18 +166,18 @@ static void cxt_init_gpio_led(struct hda_codec *codec)
static void cx_fixup_headset_recog(struct hda_codec *codec)
{
- unsigned int mic_persent;
+ unsigned int mic_present;
/* fix some headset type recognize fail issue, such as EDIFIER headset */
- /* set micbiasd output current comparator threshold from 66% to 55%. */
+ /* set micbias output current comparator threshold from 66% to 55%. */
snd_hda_codec_write(codec, 0x1c, 0, 0x320, 0x010);
- /* set OFF voltage for DFET from -1.2V to -0.8V, set headset micbias registor
+ /* set OFF voltage for DFET from -1.2V to -0.8V, set headset micbias register
* value adjustment trim from 2.2K ohms to 2.0K ohms.
*/
snd_hda_codec_write(codec, 0x1c, 0, 0x3b0, 0xe10);
/* fix reboot headset type recognize fail issue */
- mic_persent = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0x0);
- if (mic_persent & AC_PINSENSE_PRESENCE)
+ mic_present = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0x0);
+ if (mic_present & AC_PINSENSE_PRESENCE)
/* enable headset mic VREF */
snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24);
else
@@ -205,8 +205,6 @@ static void cx_auto_shutdown(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
- snd_hda_gen_shutup_speakers(codec);
-
/* 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);
@@ -249,9 +247,9 @@ static void cx_update_headset_mic_vref(struct hda_codec *codec, struct hda_jack_
{
unsigned int mic_present;
- /* In cx8070 and sn6140, the node 16 can only be config to headphone or disabled,
- * the node 19 can only be config to microphone or disabled.
- * Check hp&mic tag to process headset pulgin&plugout.
+ /* In cx8070 and sn6140, the node 16 can only be configured to headphone or disabled,
+ * the node 19 can only be configured to microphone or disabled.
+ * Check hp&mic tag to process headset plugin & plugout.
*/
mic_present = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0x0);
if (!(mic_present & AC_PINSENSE_PRESENCE)) /* mic plugout */
@@ -303,6 +301,7 @@ enum {
CXT_FIXUP_HP_SPECTRE,
CXT_FIXUP_HP_GATE_MIC,
CXT_FIXUP_MUTE_LED_GPIO,
+ CXT_FIXUP_HP_ELITEONE_OUT_DIS,
CXT_FIXUP_HP_ZBOOK_MUTE_LED,
CXT_FIXUP_HEADSET_MIC,
CXT_FIXUP_HP_MIC_NO_PRESENCE,
@@ -320,6 +319,19 @@ static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
spec->gen.inv_dmic_split = 1;
}
+/* fix widget control pin settings */
+static void cxt_fixup_update_pinctl(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ if (action == HDA_FIXUP_ACT_PROBE) {
+ /* Unset OUT_EN for this Node pin, leaving only HP_EN.
+ * This is the value stored in the codec register after
+ * the correct initialization of the previous windows boot.
+ */
+ snd_hda_set_pin_ctl_cache(codec, 0x1d, AC_PINCTL_HP_EN);
+ }
+}
+
static void cxt5066_increase_mic_boost(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@@ -954,6 +966,10 @@ static const struct hda_fixup cxt_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = cxt_fixup_mute_led_gpio,
},
+ [CXT_FIXUP_HP_ELITEONE_OUT_DIS] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = cxt_fixup_update_pinctl,
+ },
[CXT_FIXUP_HP_ZBOOK_MUTE_LED] = {
.type = HDA_FIXUP_FUNC,
.v.func = cxt_fixup_hp_zbook_mute_led,
@@ -984,7 +1000,7 @@ static const struct hda_fixup cxt_fixups[] = {
},
};
-static const struct snd_pci_quirk cxt5045_fixups[] = {
+static const struct hda_quirk cxt5045_fixups[] = {
SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT_FIXUP_HP_530),
SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT_FIXUP_TOSHIBA_P105),
/* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have
@@ -1004,7 +1020,7 @@ static const struct hda_model_fixup cxt5045_fixup_models[] = {
{}
};
-static const struct snd_pci_quirk cxt5047_fixups[] = {
+static const struct hda_quirk cxt5047_fixups[] = {
/* HP laptops have really bad sound over 0 dB on NID 0x10.
*/
SND_PCI_QUIRK_VENDOR(0x103c, "HP", CXT_FIXUP_CAP_MIX_AMP_5047),
@@ -1016,7 +1032,7 @@ static const struct hda_model_fixup cxt5047_fixup_models[] = {
{}
};
-static const struct snd_pci_quirk cxt5051_fixups[] = {
+static const struct hda_quirk cxt5051_fixups[] = {
SND_PCI_QUIRK(0x103c, 0x360b, "Compaq CQ60", CXT_PINCFG_COMPAQ_CQ60),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200),
{}
@@ -1027,7 +1043,7 @@ static const struct hda_model_fixup cxt5051_fixup_models[] = {
{}
};
-static const struct snd_pci_quirk cxt5066_fixups[] = {
+static const struct hda_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC),
SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC),
@@ -1047,6 +1063,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x103c, 0x83b2, "HP EliteBook 840 G5", CXT_FIXUP_HP_DOCK),
SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK),
SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK),
+ SND_PCI_QUIRK(0x103c, 0x83e5, "HP EliteOne 1000 G2", CXT_FIXUP_HP_ELITEONE_OUT_DIS),
SND_PCI_QUIRK(0x103c, 0x8402, "HP ProBook 645 G4", CXT_FIXUP_MUTE_LED_GPIO),
SND_PCI_QUIRK(0x103c, 0x8427, "HP ZBook Studio G5", CXT_FIXUP_HP_ZBOOK_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x844f, "HP ZBook Studio G5", CXT_FIXUP_HP_ZBOOK_MUTE_LED),
@@ -1078,8 +1095,8 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", CXT_FIXUP_THINKPAD_ACPI),
SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),
SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205),
- SND_PCI_QUIRK(0x2782, 0x12c3, "Sirius Gen1", CXT_PINCFG_TOP_SPEAKER),
- SND_PCI_QUIRK(0x2782, 0x12c5, "Sirius Gen2", CXT_PINCFG_TOP_SPEAKER),
+ HDA_CODEC_QUIRK(0x2782, 0x12c3, "Sirius Gen1", CXT_PINCFG_TOP_SPEAKER),
+ HDA_CODEC_QUIRK(0x2782, 0x12c5, "Sirius Gen2", CXT_PINCFG_TOP_SPEAKER),
{}
};
diff --git a/sound/pci/hda/patch_cs8409-tables.c b/sound/pci/hda/patch_cs8409-tables.c
index 36b411d1a960..759f48038273 100644
--- a/sound/pci/hda/patch_cs8409-tables.c
+++ b/sound/pci/hda/patch_cs8409-tables.c
@@ -473,7 +473,7 @@ struct sub_codec dolphin_cs42l42_1 = {
* Arrays Used for all projects using CS8409
******************************************************************************/
-const struct snd_pci_quirk cs8409_fixup_tbl[] = {
+const struct hda_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),
diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c
index 26f3c31600d7..614327218634 100644
--- a/sound/pci/hda/patch_cs8409.c
+++ b/sound/pci/hda/patch_cs8409.c
@@ -1403,8 +1403,9 @@ void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int ac
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;
+ if (kctrl)
+ 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;
diff --git a/sound/pci/hda/patch_cs8409.h b/sound/pci/hda/patch_cs8409.h
index 937e9387abdc..5e48115caf09 100644
--- a/sound/pci/hda/patch_cs8409.h
+++ b/sound/pci/hda/patch_cs8409.h
@@ -355,7 +355,7 @@ int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uc
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_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[];
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 4ca66234e561..56a3622ca2c1 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -587,6 +587,7 @@ static void alc_shutup_pins(struct hda_codec *codec)
switch (codec->core.vendor_id) {
case 0x10ec0236:
case 0x10ec0256:
+ case 0x10ec0257:
case 0x19e58326:
case 0x10ec0283:
case 0x10ec0285:
@@ -1564,7 +1565,7 @@ static const struct hda_fixup alc880_fixups[] = {
},
};
-static const struct snd_pci_quirk alc880_fixup_tbl[] = {
+static const struct hda_quirk alc880_fixup_tbl[] = {
SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810),
SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS W5A", ALC880_FIXUP_ASUS_W5A),
SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V),
@@ -1873,7 +1874,7 @@ static const struct hda_fixup alc260_fixups[] = {
},
};
-static const struct snd_pci_quirk alc260_fixup_tbl[] = {
+static const struct hda_quirk alc260_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1),
SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF),
SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1),
@@ -2565,7 +2566,7 @@ static const struct hda_fixup alc882_fixups[] = {
},
};
-static const struct snd_pci_quirk alc882_fixup_tbl[] = {
+static const struct hda_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD),
SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
SND_PCI_QUIRK(0x1025, 0x0107, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
@@ -2909,7 +2910,7 @@ static const struct hda_fixup alc262_fixups[] = {
},
};
-static const struct snd_pci_quirk alc262_fixup_tbl[] = {
+static const struct hda_quirk alc262_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", ALC262_FIXUP_HP_Z200),
SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu Lifebook S7110", ALC262_FIXUP_FSC_S7110),
SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
@@ -3070,7 +3071,7 @@ static const struct hda_model_fixup alc268_fixup_models[] = {
{}
};
-static const struct snd_pci_quirk alc268_fixup_tbl[] = {
+static const struct hda_quirk alc268_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0139, "Acer TravelMate 6293", ALC268_FIXUP_SPDIF),
SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC),
/* below is codec SSID since multiple Toshiba laptops have the
@@ -3867,20 +3868,18 @@ static void alc_default_init(struct hda_codec *codec)
hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
- if (hp_pin_sense)
+ if (hp_pin_sense) {
msleep(2);
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- if (hp_pin_sense)
- msleep(85);
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+ msleep(75);
- if (hp_pin_sense)
- msleep(100);
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+ msleep(75);
+ }
}
static void alc_default_shutup(struct hda_codec *codec)
@@ -3896,22 +3895,20 @@ static void alc_default_shutup(struct hda_codec *codec)
hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
- if (hp_pin_sense)
+ if (hp_pin_sense) {
msleep(2);
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- if (hp_pin_sense)
- msleep(85);
-
- if (!spec->no_shutup_pins)
snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
- if (hp_pin_sense)
- msleep(100);
+ msleep(75);
+
+ if (!spec->no_shutup_pins)
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+ msleep(75);
+ }
alc_auto_setup_eapd(codec, false);
alc_shutup_pins(codec);
}
@@ -6644,10 +6641,8 @@ static void alc289_fixup_asus_ga401(struct hda_codec *codec,
};
struct alc_spec *spec = codec->spec;
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+ if (action == HDA_FIXUP_ACT_PRE_PROBE)
spec->gen.preferred_dacs = preferred_pairs;
- spec->gen.obey_preferred_dacs = 1;
- }
}
/* The DAC of NID 0x3 will introduce click/pop noise on headphones, so invalidate it */
@@ -7404,6 +7399,49 @@ static void alc245_fixup_hp_spectre_x360_eu0xxx(struct hda_codec *codec,
alc245_fixup_hp_gpio_led(codec, fix, action);
}
+/* some changes for Spectre x360 16, 2024 model */
+static void alc245_fixup_hp_spectre_x360_16_aa0xxx(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ /*
+ * The Pin Complex 0x14 for the treble speakers is wrongly reported as
+ * unconnected.
+ * The Pin Complex 0x17 for the bass speakers has the lowest association
+ * and sequence values so shift it up a bit to squeeze 0x14 in.
+ */
+ struct alc_spec *spec = codec->spec;
+ static const struct hda_pintbl pincfgs[] = {
+ { 0x14, 0x90170110 }, // top/treble
+ { 0x17, 0x90170111 }, // bottom/bass
+ { }
+ };
+
+ /*
+ * Force DAC 0x02 for the bass speakers 0x17.
+ */
+ static const hda_nid_t conn[] = { 0x02 };
+
+ switch (action) {
+ case HDA_FIXUP_ACT_PRE_PROBE:
+ /* needed for amp of back speakers */
+ spec->gpio_mask |= 0x01;
+ spec->gpio_dir |= 0x01;
+ snd_hda_apply_pincfgs(codec, pincfgs);
+ snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
+ break;
+ case HDA_FIXUP_ACT_INIT:
+ /* need to toggle GPIO to enable the amp of back speakers */
+ alc_update_gpio_data(codec, 0x01, true);
+ msleep(100);
+ alc_update_gpio_data(codec, 0x01, false);
+ break;
+ }
+
+ cs35l41_fixup_i2c_two(codec, fix, action);
+ alc245_fixup_hp_mute_led_coefbit(codec, fix, action);
+ alc245_fixup_hp_gpio_led(codec, fix, action);
+}
+
/*
* ALC287 PCM hooks
*/
@@ -7412,7 +7450,6 @@ static void alc287_alc1318_playback_pcm_hook(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream,
int action)
{
- alc_write_coef_idx(codec, 0x10, 0x8806); /* Change MLK to GPIO3 */
switch (action) {
case HDA_GEN_PCM_ACT_OPEN:
alc_write_coefex_idx(codec, 0x5a, 0x00, 0x954f); /* write gpio3 to high */
@@ -7426,7 +7463,6 @@ static void alc287_alc1318_playback_pcm_hook(struct hda_pcm_stream *hinfo,
static void alc287_s4_power_gpio3_default(struct hda_codec *codec)
{
if (is_s4_suspend(codec)) {
- alc_write_coef_idx(codec, 0x10, 0x8806); /* Change MLK to GPIO3 */
alc_write_coefex_idx(codec, 0x5a, 0x00, 0x554f); /* write gpio3 as default value */
}
}
@@ -7435,9 +7471,17 @@ static void alc287_fixup_lenovo_thinkpad_with_alc1318(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
+ static const struct coef_fw coefs[] = {
+ WRITE_COEF(0x24, 0x0013), WRITE_COEF(0x25, 0x0000), WRITE_COEF(0x26, 0xC300),
+ WRITE_COEF(0x28, 0x0001), WRITE_COEF(0x29, 0xb023),
+ WRITE_COEF(0x24, 0x0013), WRITE_COEF(0x25, 0x0000), WRITE_COEF(0x26, 0xC301),
+ WRITE_COEF(0x28, 0x0001), WRITE_COEF(0x29, 0xb023),
+ };
if (action != HDA_FIXUP_ACT_PRE_PROBE)
return;
+ alc_update_coef_idx(codec, 0x10, 1<<11, 1<<11);
+ alc_process_coef_fw(codec, coefs);
spec->power_hook = alc287_s4_power_gpio3_default;
spec->gen.pcm_playback_hook = alc287_alc1318_playback_pcm_hook;
}
@@ -7483,6 +7527,7 @@ enum {
ALC286_FIXUP_SONY_MIC_NO_PRESENCE,
ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT,
ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+ ALC269_FIXUP_DELL1_LIMIT_INT_MIC_BOOST,
ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
@@ -7513,10 +7558,12 @@ enum {
ALC290_FIXUP_SUBWOOFER_HSJACK,
ALC269_FIXUP_THINKPAD_ACPI,
ALC269_FIXUP_DMIC_THINKPAD_ACPI,
+ ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13,
ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO,
ALC255_FIXUP_ACER_MIC_NO_PRESENCE,
ALC255_FIXUP_ASUS_MIC_NO_PRESENCE,
ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ ALC255_FIXUP_DELL1_LIMIT_INT_MIC_BOOST,
ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
ALC255_FIXUP_HEADSET_MODE,
ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
@@ -7607,6 +7654,7 @@ enum {
ALC286_FIXUP_ACER_AIO_HEADSET_MIC,
ALC256_FIXUP_ASUS_HEADSET_MIC,
ALC256_FIXUP_ASUS_MIC_NO_PRESENCE,
+ ALC255_FIXUP_PREDATOR_SUBWOOFER,
ALC299_FIXUP_PREDATOR_SPK,
ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE,
ALC289_FIXUP_DELL_SPK1,
@@ -7688,8 +7736,6 @@ enum {
ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE,
ALC287_FIXUP_YOGA7_14ITL_SPEAKERS,
ALC298_FIXUP_LENOVO_C940_DUET7,
- ALC287_FIXUP_LENOVO_14IRP8_DUETITL,
- ALC287_FIXUP_LENOVO_LEGION_7,
ALC287_FIXUP_13S_GEN2_SPEAKERS,
ALC256_FIXUP_SET_COEF_DEFAULTS,
ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
@@ -7726,6 +7772,7 @@ enum {
ALC256_FIXUP_ACER_SFG16_MICMUTE_LED,
ALC256_FIXUP_HEADPHONE_AMP_VOL,
ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX,
+ ALC245_FIXUP_HP_SPECTRE_X360_16_AA0XXX,
ALC285_FIXUP_ASUS_GA403U,
ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC,
ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1,
@@ -7733,8 +7780,6 @@ enum {
ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1,
ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318,
ALC256_FIXUP_CHROME_BOOK,
- ALC287_FIXUP_LENOVO_14ARP8_LEGION_IAH7,
- ALC287_FIXUP_LENOVO_SSID_17AA3820,
ALC245_FIXUP_CLEVO_NOISY_MIC,
ALC269_FIXUP_VAIO_VJFH52_MIC_NO_PRESENCE,
};
@@ -7756,72 +7801,6 @@ static void alc298_fixup_lenovo_c940_duet7(struct hda_codec *codec,
__snd_hda_apply_fixup(codec, id, action, 0);
}
-/* A special fixup for Lenovo Slim/Yoga Pro 9 14IRP8 and Yoga DuetITL 2021;
- * 14IRP8 PCI SSID will mistakenly be matched with the DuetITL codec SSID,
- * so we need to apply a different fixup in this case. The only DuetITL codec
- * SSID reported so far is the 17aa:3802 while the 14IRP8 has the 17aa:38be
- * and 17aa:38bf. If it weren't for the PCI SSID, the 14IRP8 models would
- * have matched correctly by their codecs.
- */
-static void alc287_fixup_lenovo_14irp8_duetitl(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- int id;
-
- if (codec->core.subsystem_id == 0x17aa3802)
- id = ALC287_FIXUP_YOGA7_14ITL_SPEAKERS; /* DuetITL */
- else
- id = ALC287_FIXUP_TAS2781_I2C; /* 14IRP8 */
- __snd_hda_apply_fixup(codec, id, action, 0);
-}
-
-/* Similar to above the Lenovo Yoga Pro 7 14ARP8 PCI SSID matches the codec SSID of the
- Legion Y9000X 2022 IAH7.*/
-static void alc287_fixup_lenovo_14arp8_legion_iah7(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- int id;
-
- if (codec->core.subsystem_id == 0x17aa386e)
- id = ALC287_FIXUP_CS35L41_I2C_2; /* Legion Y9000X 2022 IAH7 */
- else
- id = ALC285_FIXUP_SPEAKER2_TO_DAC1; /* Yoga Pro 7 14ARP8 */
- __snd_hda_apply_fixup(codec, id, action, 0);
-}
-
-/* Another hilarious PCI SSID conflict with Lenovo Legion Pro 7 16ARX8H (with
- * TAS2781 codec) and Legion 7i 16IAX7 (with CS35L41 codec);
- * we apply a corresponding fixup depending on the codec SSID instead
- */
-static void alc287_fixup_lenovo_legion_7(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- int id;
-
- if (codec->core.subsystem_id == 0x17aa38a8)
- id = ALC287_FIXUP_TAS2781_I2C; /* Legion Pro 7 16ARX8H */
- else
- id = ALC287_FIXUP_CS35L41_I2C_2; /* Legion 7i 16IAX7 */
- __snd_hda_apply_fixup(codec, id, action, 0);
-}
-
-/* Yet more conflicting PCI SSID (17aa:3820) on two Lenovo models */
-static void alc287_fixup_lenovo_ssid_17aa3820(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- int id;
-
- if (codec->core.subsystem_id == 0x17aa3820)
- id = ALC269_FIXUP_ASPIRE_HEADSET_MIC; /* IdeaPad 330-17IKB 81DM */
- else /* 0x17aa3802 */
- id = ALC287_FIXUP_YOGA7_14ITL_SPEAKERS; /* "Yoga Duet 7 13ITL6 */
- __snd_hda_apply_fixup(codec, id, action, 0);
-}
-
static const struct hda_fixup alc269_fixups[] = {
[ALC269_FIXUP_GPIO2] = {
.type = HDA_FIXUP_FUNC,
@@ -7956,6 +7935,16 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc269_fixup_pincfg_U7x7_headset_mic,
},
+ [ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x14, 0x90170151 }, /* use as internal speaker (LFE) */
+ { 0x1b, 0x90170152 }, /* use as internal speaker (back) */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
+ },
[ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
@@ -8074,6 +8063,12 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MODE
},
+ [ALC269_FIXUP_DELL1_LIMIT_INT_MIC_BOOST] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc269_fixup_limit_int_mic_boost,
+ .chained = true,
+ .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
+ },
[ALC269_FIXUP_DELL2_MIC_NO_PRESENCE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
@@ -8354,6 +8349,12 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC255_FIXUP_HEADSET_MODE
},
+ [ALC255_FIXUP_DELL1_LIMIT_INT_MIC_BOOST] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc269_fixup_limit_int_mic_boost,
+ .chained = true,
+ .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
+ },
[ALC255_FIXUP_DELL2_MIC_NO_PRESENCE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
@@ -9020,6 +9021,13 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE
},
+ [ALC255_FIXUP_PREDATOR_SUBWOOFER] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x17, 0x90170151 }, /* use as internal speaker (LFE) */
+ { 0x1b, 0x90170152 } /* use as internal speaker (back) */
+ }
+ },
[ALC299_FIXUP_PREDATOR_SPK] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
@@ -9732,14 +9740,6 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc298_fixup_lenovo_c940_duet7,
},
- [ALC287_FIXUP_LENOVO_14IRP8_DUETITL] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_lenovo_14irp8_duetitl,
- },
- [ALC287_FIXUP_LENOVO_LEGION_7] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_lenovo_legion_7,
- },
[ALC287_FIXUP_13S_GEN2_SPEAKERS] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
@@ -9924,10 +9924,6 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK,
},
- [ALC287_FIXUP_LENOVO_14ARP8_LEGION_IAH7] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_lenovo_14arp8_legion_iah7,
- },
[ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc287_fixup_yoga9_14iap7_bass_spk_pin,
@@ -10012,6 +10008,10 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc245_fixup_hp_spectre_x360_eu0xxx,
},
+ [ALC245_FIXUP_HP_SPECTRE_X360_16_AA0XXX] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc245_fixup_hp_spectre_x360_16_aa0xxx,
+ },
[ALC285_FIXUP_ASUS_GA403U] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc285_fixup_asus_ga403u,
@@ -10058,10 +10058,6 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC225_FIXUP_HEADSET_JACK
},
- [ALC287_FIXUP_LENOVO_SSID_17AA3820] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_lenovo_ssid_17aa3820,
- },
[ALC245_FIXUP_CLEVO_NOISY_MIC] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc269_fixup_limit_int_mic_boost,
@@ -10080,7 +10076,7 @@ static const struct hda_fixup alc269_fixups[] = {
},
};
-static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0283, "Acer TravelMate 8371", ALC269_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
@@ -10103,6 +10099,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x110e, "Acer Aspire ES1-432", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1166, "Acer Veriton N4640G", ALC269_FIXUP_LIFEBOOK),
SND_PCI_QUIRK(0x1025, 0x1167, "Acer Veriton N6640G", ALC269_FIXUP_LIFEBOOK),
+ SND_PCI_QUIRK(0x1025, 0x1177, "Acer Predator G9-593", ALC255_FIXUP_PREDATOR_SUBWOOFER),
+ SND_PCI_QUIRK(0x1025, 0x1178, "Acer Predator G9-593", ALC255_FIXUP_PREDATOR_SUBWOOFER),
SND_PCI_QUIRK(0x1025, 0x1246, "Acer Predator Helios 500", ALC299_FIXUP_PREDATOR_SPK),
SND_PCI_QUIRK(0x1025, 0x1247, "Acer vCopperbox", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS),
SND_PCI_QUIRK(0x1025, 0x1248, "Acer Veriton N4660G", ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE),
@@ -10199,6 +10197,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0c1e, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS),
SND_PCI_QUIRK(0x1028, 0x0c28, "Dell Inspiron 16 Plus 7630", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
SND_PCI_QUIRK(0x1028, 0x0c4d, "Dell", ALC287_FIXUP_CS35L41_I2C_4),
+ SND_PCI_QUIRK(0x1028, 0x0c94, "Dell Polaris 3 metal", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x1028, 0x0c96, "Dell Polaris 2in1", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1028, 0x0cbd, "Dell Oasis 13 CS MTL-U", ALC289_FIXUP_DELL_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1028, 0x0cbe, "Dell Oasis 13 2-IN-1 MTL-U", ALC289_FIXUP_DELL_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1028, 0x0cbf, "Dell Oasis 13 Low Weight MTU-L", ALC289_FIXUP_DELL_CS35L41_SPI_2),
@@ -10349,6 +10349,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x8898, "HP EliteBook 845 G8 Notebook PC", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x103c, 0x88d0, "HP Pavilion 15-eh1xxx (mainboard 88D0)", ALC287_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x88dd, "HP Pavilion 15z-ec200", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x8902, "HP OMEN 16", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x890e, "HP 255 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x8919, "HP Pavilion Aero Laptop 13-be0xxx", ALC287_FIXUP_HP_GPIO_LED),
@@ -10415,6 +10416,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8b59, "HP Elite mt645 G7 Mobile Thin Client U89", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+ SND_PCI_QUIRK(0x103c, 0x8b5f, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8b63, "HP Elite Dragonfly 13.5 inch G4", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b65, "HP ProBook 455 15.6 inch G10 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8b66, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
@@ -10448,7 +10450,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8be9, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8c15, "HP Spectre x360 2-in-1 Laptop 14-eu0xxx", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
- SND_PCI_QUIRK(0x103c, 0x8c16, "HP Spectre 16", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x103c, 0x8c16, "HP Spectre x360 2-in-1 Laptop 16-aa0xxx", ALC245_FIXUP_HP_SPECTRE_X360_16_AA0XXX),
SND_PCI_QUIRK(0x103c, 0x8c17, "HP Spectre 16", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8c21, "HP Pavilion Plus Laptop 14-ey0XXX", ALC245_FIXUP_HP_X360_MUTE_LEDS),
SND_PCI_QUIRK(0x103c, 0x8c30, "HP Victus 15-fb1xxx", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
@@ -10490,6 +10492,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8ca2, "HP ZBook Power", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8ca4, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8ca7, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8caf, "HP Elite mt645 G8 Mobile Thin Client", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8cbd, "HP Pavilion Aero Laptop 13-bg0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
SND_PCI_QUIRK(0x103c, 0x8cdd, "HP Spectre", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8cde, "HP Spectre", ALC287_FIXUP_CS35L41_I2C_2),
@@ -10500,11 +10503,15 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x1043, 0x10a1, "ASUS UX391UA", ALC294_FIXUP_ASUS_SPK),
+ SND_PCI_QUIRK(0x1043, 0x10a4, "ASUS TP3407SA", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x10c0, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x10d3, "ASUS K6500ZC", ALC294_FIXUP_ASUS_SPK),
+ SND_PCI_QUIRK(0x1043, 0x1154, "ASUS TP3607SH", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1043, 0x1204, "ASUS Strix G615JHR_JMR_JPR", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x1214, "ASUS Strix G615LH_LM_LP", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x125e, "ASUS Q524UQK", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1271, "ASUS X430UN", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
@@ -10582,6 +10589,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS),
SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401),
+ SND_PCI_QUIRK(0x1043, 0x1eb3, "ASUS Ally RCLA72", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x1ed3, "ASUS HN7306W", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401),
@@ -10596,6 +10604,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x3a40, "ASUS G814JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
SND_PCI_QUIRK(0x1043, 0x3a50, "ASUS G834JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
SND_PCI_QUIRK(0x1043, 0x3a60, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
+ SND_PCI_QUIRK(0x1043, 0x3e30, "ASUS TP3607SA", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x3ee0, "ASUS Strix G815_JHR_JMR_JPR", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x3ef0, "ASUS Strix G635LR_LW_LX", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x3f00, "ASUS Strix G815LH_LM_LP", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x3f10, "ASUS Strix G835LR_LW_LX", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x3f20, "ASUS Strix G615LR_LW", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x3f30, "ASUS Strix G815LR_LW", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
@@ -10656,6 +10671,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1558, 0x1404, "Clevo N150CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x14a1, "Clevo L141MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x2624, "Clevo L240TU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x28c1, "Clevo V370VND", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1558, 0x4018, "Clevo NV40M[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x4019, "Clevo NV40MZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x4020, "Clevo NV40MB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -10793,11 +10809,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x31af, "ThinkCentre Station", ALC623_FIXUP_LENOVO_THINKSTATION_P340),
SND_PCI_QUIRK(0x17aa, 0x334b, "Lenovo ThinkCentre M70 Gen5", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x3801, "Lenovo Yoga9 14IAP7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
- SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo Yoga Pro 9 14IRP8 / DuetITL 2021", ALC287_FIXUP_LENOVO_14IRP8_DUETITL),
+ HDA_CODEC_QUIRK(0x17aa, 0x3802, "DuetITL 2021", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
+ SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo Yoga Pro 9 14IRP8", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940 / Yoga Duet 7", ALC298_FIXUP_LENOVO_C940_DUET7),
SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS),
- SND_PCI_QUIRK(0x17aa, 0x3820, "IdeaPad 330 / Yoga Duet 7", ALC287_FIXUP_LENOVO_SSID_17AA3820),
+ HDA_CODEC_QUIRK(0x17aa, 0x3820, "IdeaPad 330-17IKB 81DM", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
+ SND_PCI_QUIRK(0x17aa, 0x3820, "Yoga Duet 7 13ITL6", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3824, "Legion Y9000X 2020", ALC285_FIXUP_LEGION_Y9000X_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF),
SND_PCI_QUIRK(0x17aa, 0x3834, "Lenovo IdeaPad Slim 9i 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
@@ -10811,18 +10829,23 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3865, "Lenovo 13X", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3866, "Lenovo 13X", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
- SND_PCI_QUIRK(0x17aa, 0x386e, "Legion Y9000X 2022 IAH7 / Yoga Pro 7 14ARP8", ALC287_FIXUP_LENOVO_14ARP8_LEGION_IAH7),
- SND_PCI_QUIRK(0x17aa, 0x386f, "Legion Pro 7/7i", ALC287_FIXUP_LENOVO_LEGION_7),
+ HDA_CODEC_QUIRK(0x17aa, 0x386e, "Legion Y9000X 2022 IAH7", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x17aa, 0x386e, "Yoga Pro 7 14ARP8", ALC285_FIXUP_SPEAKER2_TO_DAC1),
+ HDA_CODEC_QUIRK(0x17aa, 0x386f, "Legion Pro 7 16ARX8H", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x386f, "Legion Pro 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C),
SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3878, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x387d, "Yoga S780-16 pro Quad AAC", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x387e, "Yoga S780-16 pro Quad YC", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x387f, "Yoga S780-16 pro dual LX", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x3880, "Yoga S780-16 pro dual YC", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3881, "YB9 dual power mode2 YC", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3882, "Lenovo Yoga Pro 7 14APH8", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
SND_PCI_QUIRK(0x17aa, 0x3884, "Y780 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3886, "Y780 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3891, "Lenovo Yoga Pro 7 14AHP9", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x38a5, "Y580P AMD dual", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38a7, "Y780P AMD YG dual", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38a8, "Y780P AMD VECO dual", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38a9, "Thinkbook 16P", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
@@ -10831,6 +10854,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x38b5, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x38b6, "Legion Slim 7 16APH8", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x38b7, "Legion Slim 7 16APH8", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x17aa, 0x38b8, "Yoga S780-14.5 proX AMD YC Dual", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x38b9, "Yoga S780-14.5 proX AMD LX Dual", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38ba, "Yoga S780-14.5 Air AMD quad YC", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38bb, "Yoga S780-14.5 Air AMD quad AAC", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38be, "Yoga S980-14.5 proX YC Dual", ALC287_FIXUP_TAS2781_I2C),
@@ -10841,11 +10866,22 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x38cb, "Y790 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38cd, "Y790 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38d2, "Lenovo Yoga 9 14IMH9", ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x38d3, "Yoga S990-16 Pro IMH YC Dual", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x38d4, "Yoga S990-16 Pro IMH VECO Dual", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x38d5, "Yoga S990-16 Pro IMH YC Quad", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x38d6, "Yoga S990-16 Pro IMH VECO Quad", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38d7, "Lenovo Yoga 9 14IMH9", ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x38df, "Yoga Y990 Intel YC Dual", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x38e0, "Yoga Y990 Intel VECO Dual", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x38f8, "Yoga Book 9i", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x38df, "Y990 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38f9, "Thinkbook 16P Gen5", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x38fa, "Thinkbook 16P Gen5", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x17aa, 0x38fd, "ThinkBook plus Gen5 Hybrid", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
SND_PCI_QUIRK(0x17aa, 0x3913, "Lenovo 145", ALC236_FIXUP_LENOVO_INV_DMIC),
+ SND_PCI_QUIRK(0x17aa, 0x391f, "Yoga S990-16 pro Quad YC Quad", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x3920, "Yoga S990-16 pro Quad VECO Quad", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
@@ -10878,6 +10914,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1854, 0x048a, "LG gram 17 (17ZD90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x19e5, 0x3212, "Huawei KLV-WX9 ", ALC256_FIXUP_ACER_HEADSET_MIC),
SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20),
SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI),
SND_PCI_QUIRK(0x1b35, 0x1237, "CZC L101", ALC269_FIXUP_CZC_L101),
@@ -10896,6 +10933,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1d05, 0x115c, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
SND_PCI_QUIRK(0x1d05, 0x121b, "TongFang GMxAGxx", ALC269_FIXUP_NO_SHUTUP),
SND_PCI_QUIRK(0x1d05, 0x1387, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1d05, 0x1409, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1d17, 0x3288, "Haier Boyue G42", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS),
SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -10903,6 +10941,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+ SND_PCI_QUIRK(0x2782, 0x0228, "Infinix ZERO BOOK 13", ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13),
SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO),
SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME),
SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
@@ -10964,7 +11003,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
{}
};
-static const struct snd_pci_quirk alc269_fixup_vendor_tbl[] = {
+static const struct hda_quirk alc269_fixup_vendor_tbl[] = {
SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
@@ -10990,6 +11029,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"},
{.id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, .name = "dell-headset3"},
{.id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, .name = "dell-headset4"},
+ {.id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE_QUIET, .name = "dell-headset4-quiet"},
{.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"},
{.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
{.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"},
@@ -11544,20 +11584,22 @@ static const struct snd_hda_pin_quirk alc269_fallback_pin_fixup_tbl[] = {
SND_HDA_PIN_QUIRK(0x10ec0289, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
{0x19, 0x40000000},
{0x1b, 0x40000000}),
- SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
+ SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE_QUIET,
{0x19, 0x40000000},
{0x1b, 0x40000000}),
SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
{0x19, 0x40000000},
{0x1a, 0x40000000}),
- SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_LIMIT_INT_MIC_BOOST,
{0x19, 0x40000000},
{0x1a, 0x40000000}),
- SND_HDA_PIN_QUIRK(0x10ec0274, 0x1028, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB,
+ SND_HDA_PIN_QUIRK(0x10ec0274, 0x1028, "Dell", ALC269_FIXUP_DELL1_LIMIT_INT_MIC_BOOST,
{0x19, 0x40000000},
{0x1a, 0x40000000}),
SND_HDA_PIN_QUIRK(0x10ec0256, 0x1043, "ASUS", ALC2XX_FIXUP_HEADSET_MIC,
{0x19, 0x40000000}),
+ SND_HDA_PIN_QUIRK(0x10ec0255, 0x1558, "Clevo", ALC2XX_FIXUP_HEADSET_MIC,
+ {0x19, 0x40000000}),
{}
};
@@ -11897,7 +11939,7 @@ static const struct hda_fixup alc861_fixups[] = {
}
};
-static const struct snd_pci_quirk alc861_fixup_tbl[] = {
+static const struct hda_quirk alc861_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1253, "ASUS W7J", ALC660_FIXUP_ASUS_W7J),
SND_PCI_QUIRK(0x1043, 0x1263, "ASUS Z35HL", ALC660_FIXUP_ASUS_W7J),
SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
@@ -12001,7 +12043,7 @@ static const struct hda_fixup alc861vd_fixups[] = {
},
};
-static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
+static const struct hda_quirk alc861vd_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_FIX_DALLAS),
SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_FIX_DALLAS),
@@ -12802,7 +12844,7 @@ static const struct hda_fixup alc662_fixups[] = {
},
};
-static const struct snd_pci_quirk alc662_fixup_tbl[] = {
+static const struct hda_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
SND_PCI_QUIRK(0x1019, 0x9859, "JP-IK LEAP W502", ALC897_FIXUP_HEADSET_MIC_PIN3),
SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index ae1a34c68c61..bde6b7373858 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1462,7 +1462,7 @@ static const struct hda_model_fixup stac9200_models[] = {
{}
};
-static const struct snd_pci_quirk stac9200_fixup_tbl[] = {
+static const struct hda_quirk stac9200_fixup_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_REF),
@@ -1683,7 +1683,7 @@ static const struct hda_model_fixup stac925x_models[] = {
{}
};
-static const struct snd_pci_quirk stac925x_fixup_tbl[] = {
+static const struct hda_quirk stac925x_fixup_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_REF),
@@ -1957,7 +1957,7 @@ static const struct hda_model_fixup stac92hd73xx_models[] = {
{}
};
-static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = {
+static const struct hda_quirk stac92hd73xx_fixup_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_92HD73XX_REF),
@@ -2753,7 +2753,7 @@ static const struct hda_model_fixup stac92hd83xxx_models[] = {
{}
};
-static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = {
+static const struct hda_quirk stac92hd83xxx_fixup_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_92HD83XXX_REF),
@@ -3236,7 +3236,7 @@ static const struct hda_model_fixup stac92hd71bxx_models[] = {
{}
};
-static const struct snd_pci_quirk stac92hd71bxx_fixup_tbl[] = {
+static const struct hda_quirk stac92hd71bxx_fixup_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_92HD71BXX_REF),
@@ -3496,7 +3496,7 @@ static const struct hda_pintbl ecs202_pin_configs[] = {
};
/* codec SSIDs for Intel Mac sharing the same PCI SSID 8384:7680 */
-static const struct snd_pci_quirk stac922x_intel_mac_fixup_tbl[] = {
+static const struct hda_quirk stac922x_intel_mac_fixup_tbl[] = {
SND_PCI_QUIRK(0x0000, 0x0100, "Mac Mini", STAC_INTEL_MAC_V3),
SND_PCI_QUIRK(0x106b, 0x0800, "Mac", STAC_INTEL_MAC_V1),
SND_PCI_QUIRK(0x106b, 0x0600, "Mac", STAC_INTEL_MAC_V2),
@@ -3640,7 +3640,7 @@ static const struct hda_model_fixup stac922x_models[] = {
{}
};
-static const struct snd_pci_quirk stac922x_fixup_tbl[] = {
+static const struct hda_quirk stac922x_fixup_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_D945_REF),
@@ -3968,7 +3968,7 @@ static const struct hda_model_fixup stac927x_models[] = {
{}
};
-static const struct snd_pci_quirk stac927x_fixup_tbl[] = {
+static const struct hda_quirk stac927x_fixup_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_D965_REF),
@@ -4178,7 +4178,7 @@ static const struct hda_model_fixup stac9205_models[] = {
{}
};
-static const struct snd_pci_quirk stac9205_fixup_tbl[] = {
+static const struct hda_quirk stac9205_fixup_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_9205_REF),
@@ -4255,7 +4255,7 @@ static const struct hda_fixup stac92hd95_fixups[] = {
},
};
-static const struct snd_pci_quirk stac92hd95_fixup_tbl[] = {
+static const struct hda_quirk stac92hd95_fixup_tbl[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1911, "HP Spectre 13", STAC_92HD95_HP_BASS),
{} /* terminator */
};
@@ -5002,7 +5002,7 @@ static const struct hda_fixup stac9872_fixups[] = {
},
};
-static const struct snd_pci_quirk stac9872_fixup_tbl[] = {
+static const struct hda_quirk stac9872_fixup_tbl[] = {
SND_PCI_QUIRK_MASK(0x104d, 0xfff0, 0x81e0,
"Sony VAIO F/S", STAC_9872_VAIO),
{} /* terminator */
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index a8ef4bb70dd0..d0893059b1b9 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -1035,7 +1035,7 @@ static const struct hda_fixup via_fixups[] = {
},
};
-static const struct snd_pci_quirk vt2002p_fixups[] = {
+static const struct hda_quirk vt2002p_fixups[] = {
SND_PCI_QUIRK(0x1043, 0x13f7, "Asus B23E", VIA_FIXUP_POWER_SAVE),
SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c
index f58f434e7110..370d847517f9 100644
--- a/sound/pci/hda/tas2781_hda_i2c.c
+++ b/sound/pci/hda/tas2781_hda_i2c.c
@@ -7,7 +7,7 @@
// Author: Shenghao Ding <shenghao-ding@ti.com>
// Current maintainer: Baojun Xu <baojun.xu@ti.com>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <linux/acpi.h>
#include <linux/crc8.h>
#include <linux/crc32.h>
@@ -951,7 +951,7 @@ static const struct dev_pm_ops tas2781_hda_pm_ops = {
};
static const struct i2c_device_id tas2781_hda_i2c_id[] = {
- { "tas2781-hda", 0 },
+ { "tas2781-hda" },
{}
};
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index 096ec76f5304..a12dafbf53ab 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -170,14 +170,9 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
tmp = stac9460_get(ice, idx);
ovol = 0x7f - (tmp & 0x7f);
change = (ovol != nvol);
- if (change) {
- ovol = (0x7f - nvol) | (tmp & 0x80);
- /*
- dev_dbg(ice->card->dev, "DAC Volume: reg 0x%02x: 0x%02x\n",
- idx, ovol);
- */
+ if (change)
stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
- }
+
return change;
}
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index e62fb1ad6d77..49b71082c485 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2108,7 +2108,7 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci)
for (i=0; i<kAudioChannels; i++)
korg1212->volumePhase[i] = 0;
- err = pcim_iomap_regions_request_all(pci, 1 << 0, "korg1212");
+ err = pcim_request_all_regions(pci, "korg1212");
if (err < 0)
return err;
@@ -2130,7 +2130,9 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci)
korg1212->iomem2, iomem2_size,
stateName[korg1212->cardState]);
- korg1212->iobase = pcim_iomap_table(pci)[0];
+ korg1212->iobase = pcim_iomap(pci, 0, 0);
+ if (!korg1212->iobase)
+ return -ENOMEM;
err = devm_request_irq(&pci->dev, pci->irq, snd_korg1212_interrupt,
IRQF_SHARED,
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index 8e29c92830ad..f1b0cf9ea555 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -160,7 +160,7 @@ static SIMPLE_DEV_PM_OPS(snd_pmac_pm, snd_pmac_driver_suspend, snd_pmac_driver_r
static struct platform_driver snd_pmac_driver = {
.probe = snd_pmac_probe,
- .remove_new = snd_pmac_remove,
+ .remove = snd_pmac_remove,
.driver = {
.name = SND_PMAC_DRIVER,
.pm = SND_PMAC_PM_OPS,
diff --git a/sound/sh/aica.c b/sound/sh/aica.c
index 936cd6e91529..39bf51ff43a1 100644
--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -315,8 +315,6 @@ static void aica_period_elapsed(struct timer_list *t)
static void spu_begin_dma(struct snd_pcm_substream *substream)
{
struct snd_card_aica *dreamcastcard;
- struct snd_pcm_runtime *runtime;
- runtime = substream->runtime;
dreamcastcard = substream->pcm->private_data;
/*get the queue to do the work */
schedule_work(&(dreamcastcard->spu_dma_work));
@@ -601,7 +599,7 @@ static int snd_aica_probe(struct platform_device *devptr)
static struct platform_driver snd_aica_driver = {
.probe = snd_aica_probe,
- .remove_new = snd_aica_remove,
+ .remove = snd_aica_remove,
.driver = {
.name = SND_AICA_DRIVER,
},
diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c
index e7b6ce7bd086..e7b80328f0ef 100644
--- a/sound/sh/sh_dac_audio.c
+++ b/sound/sh/sh_dac_audio.c
@@ -383,7 +383,7 @@ probe_error:
*/
static struct platform_driver sh_dac_driver = {
.probe = snd_sh_dac_probe,
- .remove_new = snd_sh_dac_remove,
+ .remove = snd_sh_dac_remove,
.driver = {
.name = "dac_audio",
},
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index e87bd15a8b43..5efba76abb31 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -106,9 +106,10 @@ source "sound/soc/meson/Kconfig"
source "sound/soc/mxs/Kconfig"
source "sound/soc/pxa/Kconfig"
source "sound/soc/qcom/Kconfig"
+source "sound/soc/renesas/Kconfig"
source "sound/soc/rockchip/Kconfig"
source "sound/soc/samsung/Kconfig"
-source "sound/soc/sh/Kconfig"
+source "sound/soc/sdca/Kconfig"
source "sound/soc/sof/Kconfig"
source "sound/soc/spear/Kconfig"
source "sound/soc/sprd/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 775bb38c2ed4..08baaa11d813 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -59,9 +59,10 @@ obj-$(CONFIG_SND_SOC) += mxs/
obj-$(CONFIG_SND_SOC) += kirkwood/
obj-$(CONFIG_SND_SOC) += pxa/
obj-$(CONFIG_SND_SOC) += qcom/
+obj-$(CONFIG_SND_SOC) += renesas/
obj-$(CONFIG_SND_SOC) += rockchip/
obj-$(CONFIG_SND_SOC) += samsung/
-obj-$(CONFIG_SND_SOC) += sh/
+obj-$(CONFIG_SND_SOC) += sdca/
obj-$(CONFIG_SND_SOC) += sof/
obj-$(CONFIG_SND_SOC) += spear/
obj-$(CONFIG_SND_SOC) += sprd/
diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c
index 77cf72082e73..02b04f355ca6 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -542,7 +542,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
.init = cz_da7219_init,
- .dpcm_playback = 1,
+ .playback_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_da7219_play_ops,
SND_SOC_DAILINK_REG(designware1, dlgs, platform),
@@ -552,7 +552,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
.stream_name = "Capture",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_da7219_cap_ops,
SND_SOC_DAILINK_REG(designware2, dlgs, platform),
@@ -562,7 +562,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
.stream_name = "HiFi Playback",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_playback = 1,
+ .playback_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_max_play_ops,
SND_SOC_DAILINK_REG(designware3, mx, platform),
@@ -573,7 +573,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
.stream_name = "DMIC0 Capture",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_dmic0_cap_ops,
SND_SOC_DAILINK_REG(designware3, adau, platform),
@@ -584,7 +584,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
.stream_name = "DMIC1 Capture",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_dmic1_cap_ops,
SND_SOC_DAILINK_REG(designware2, adau, platform),
@@ -598,7 +598,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
.init = cz_rt5682_init,
- .dpcm_playback = 1,
+ .playback_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_rt5682_play_ops,
SND_SOC_DAILINK_REG(designware1, rt5682, platform),
@@ -608,7 +608,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.stream_name = "Capture",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_rt5682_cap_ops,
SND_SOC_DAILINK_REG(designware2, rt5682, platform),
@@ -618,7 +618,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.stream_name = "HiFi Playback",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_playback = 1,
+ .playback_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_rt5682_max_play_ops,
SND_SOC_DAILINK_REG(designware3, mx, platform),
@@ -629,7 +629,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.stream_name = "DMIC0 Capture",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_rt5682_dmic0_cap_ops,
SND_SOC_DAILINK_REG(designware3, adau, platform),
@@ -640,7 +640,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.stream_name = "DMIC1 Capture",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
.ops = &cz_rt5682_dmic1_cap_ops,
SND_SOC_DAILINK_REG(designware2, adau, platform),
diff --git a/sound/soc/amd/acp-es8336.c b/sound/soc/amd/acp-es8336.c
index 3756b8bef17b..0193b3eae7a6 100644
--- a/sound/soc/amd/acp-es8336.c
+++ b/sound/soc/amd/acp-es8336.c
@@ -150,8 +150,6 @@ static struct snd_soc_dai_link st_dai_es8336[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
.trigger_stop = SND_SOC_TRIGGER_ORDER_LDC,
- .dpcm_capture = 1,
- .dpcm_playback = 1,
.init = st_es8336_init,
.ops = &st_es8336_ops,
SND_SOC_DAILINK_REG(designware1, codec, platform),
diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 88391e4c17e3..03f3fcbba5af 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -119,10 +119,17 @@ config SND_SOC_AMD_SOF_MACH
help
This option enables SOF sound card support for ACP audio.
+config SND_SOC_AMD_SDW_MACH_COMMON
+ tristate
+ help
+ This option enables common SoundWire Machine driver module for
+ AMD platforms.
+
config SND_SOC_AMD_SOF_SDW_MACH
tristate "AMD SOF Soundwire Machine Driver Support"
depends on X86 && PCI && ACPI
depends on SOUNDWIRE
+ select SND_SOC_AMD_SDW_MACH_COMMON
select SND_SOC_SDW_UTILS
select SND_SOC_DMIC
select SND_SOC_RT711_SDW
@@ -137,6 +144,28 @@ config SND_SOC_AMD_SOF_SDW_MACH
on AMD platform.
If unsure select "N".
+config SND_SOC_AMD_LEGACY_SDW_MACH
+ tristate "AMD Legacy(No DSP) Soundwire Machine Driver Support"
+ depends on X86 && PCI && ACPI
+ depends on SOUNDWIRE
+ select SND_SOC_AMD_SDW_MACH_COMMON
+ select SND_SOC_SDW_UTILS
+ select SND_SOC_DMIC
+ select SND_SOC_RT711_SDW
+ select SND_SOC_RT711_SDCA_SDW
+ select SND_SOC_RT712_SDCA_SDW
+ select SND_SOC_RT712_SDCA_DMIC_SDW
+ select SND_SOC_RT1316_SDW
+ select SND_SOC_RT715_SDW
+ select SND_SOC_RT715_SDCA_SDW
+ select SND_SOC_RT722_SDCA_SDW
+ help
+ This option enables Legacy(No DSP) sound card support for SoundWire
+ enabled AMD platforms along with ACP PDM controller.
+ Say Y if you want to enable SoundWire based machine driver support
+ on AMD platform.
+ If unsure select "N".
+
endif # SND_SOC_AMD_ACP_COMMON
config SND_AMD_SOUNDWIRE_ACPI
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index 82cf5d180b3a..bb2702036338 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -23,7 +23,9 @@ snd-acp-mach-y := acp-mach-common.o
snd-acp-legacy-mach-y := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o
snd-acp-sof-mach-y := acp-sof-mach.o
snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o
+snd-acp-sdw-mach-y := acp-sdw-mach-common.o
snd-acp-sdw-sof-mach-y += acp-sdw-sof-mach.o
+snd-acp-sdw-legacy-mach-y += acp-sdw-legacy-mach.o
obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o
obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o
@@ -41,4 +43,6 @@ obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o
obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o
obj-$(CONFIG_SND_SOC_AMD_SOF_MACH) += snd-acp-sof-mach.o
obj-$(CONFIG_SND_SOC_ACPI_AMD_MATCH) += snd-soc-acpi-amd-match.o
+obj-$(CONFIG_SND_SOC_AMD_SDW_MACH_COMMON) += snd-acp-sdw-mach.o
obj-$(CONFIG_SND_SOC_AMD_SOF_SDW_MACH) += snd-acp-sdw-sof-mach.o
+obj-$(CONFIG_SND_SOC_AMD_LEGACY_SDW_MACH) += snd-acp-sdw-legacy-mach.o
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c
index 56ce9e4b6acc..515bf862deb5 100644
--- a/sound/soc/amd/acp/acp-i2s.c
+++ b/sound/soc/amd/acp/acp-i2s.c
@@ -59,9 +59,9 @@ static inline void acp_set_i2s_clk(struct acp_dev_data *adata, int dai_id)
val |= BIT(1);
switch (chip->acp_rev) {
- case ACP63_DEV:
- case ACP70_DEV:
- case ACP71_DEV:
+ case ACP63_PCI_ID:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
val |= FIELD_PREP(ACP63_LRCLK_DIV_FIELD, adata->lrclk_div);
val |= FIELD_PREP(ACP63_BCLK_DIV_FIELD, adata->bclk_div);
break;
@@ -121,8 +121,8 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas
}
switch (chip->acp_rev) {
- case ACP3X_DEV:
- case ACP6X_DEV:
+ case ACP_RN_PCI_ID:
+ case ACP_RMB_PCI_ID:
switch (slots) {
case 1 ... 7:
no_of_slots = slots;
@@ -135,9 +135,9 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas
return -EINVAL;
}
break;
- case ACP63_DEV:
- case ACP70_DEV:
- case ACP71_DEV:
+ case ACP63_PCI_ID:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
switch (slots) {
case 1 ... 31:
no_of_slots = slots;
@@ -160,8 +160,8 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas
spin_lock_irq(&adata->acp_lock);
list_for_each_entry(stream, &adata->stream_list, list) {
switch (chip->acp_rev) {
- case ACP3X_DEV:
- case ACP6X_DEV:
+ case ACP_RN_PCI_ID:
+ case ACP_RMB_PCI_ID:
if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
adata->tdm_tx_fmt[stream->dai_id - 1] =
FRM_LEN | (slots << 15) | (slot_len << 18);
@@ -169,9 +169,9 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas
adata->tdm_rx_fmt[stream->dai_id - 1] =
FRM_LEN | (slots << 15) | (slot_len << 18);
break;
- case ACP63_DEV:
- case ACP70_DEV:
- case ACP71_DEV:
+ case ACP63_PCI_ID:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
adata->tdm_tx_fmt[stream->dai_id - 1] =
FRM_LEN | (slots << 13) | (slot_len << 18);
@@ -534,7 +534,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata);
reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata);
- if (chip->acp_rev >= ACP70_DEV)
+ if (chip->acp_rev >= ACP70_PCI_ID)
phy_addr = ACP7x_I2S_SP_TX_MEM_WINDOW_START;
else
phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
@@ -546,7 +546,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata);
reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata);
- if (chip->acp_rev >= ACP70_DEV)
+ if (chip->acp_rev >= ACP70_PCI_ID)
phy_addr = ACP7x_I2S_SP_RX_MEM_WINDOW_START;
else
phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
@@ -561,7 +561,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata);
reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata);
- if (chip->acp_rev >= ACP70_DEV)
+ if (chip->acp_rev >= ACP70_PCI_ID)
phy_addr = ACP7x_I2S_BT_TX_MEM_WINDOW_START;
else
phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
@@ -573,7 +573,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata);
reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata);
- if (chip->acp_rev >= ACP70_DEV)
+ if (chip->acp_rev >= ACP70_PCI_ID)
phy_addr = ACP7x_I2S_BT_RX_MEM_WINDOW_START;
else
phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
@@ -588,7 +588,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
reg_fifo_addr = ACP_HS_TX_FIFOADDR;
reg_fifo_size = ACP_HS_TX_FIFOSIZE;
- if (chip->acp_rev >= ACP70_DEV)
+ if (chip->acp_rev >= ACP70_PCI_ID)
phy_addr = ACP7x_I2S_HS_TX_MEM_WINDOW_START;
else
phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
@@ -600,7 +600,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
reg_fifo_addr = ACP_HS_RX_FIFOADDR;
reg_fifo_size = ACP_HS_RX_FIFOSIZE;
- if (chip->acp_rev >= ACP70_DEV)
+ if (chip->acp_rev >= ACP70_PCI_ID)
phy_addr = ACP7x_I2S_HS_RX_MEM_WINDOW_START;
else
phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c
index be01b178172e..3f76d1f0a9e7 100644
--- a/sound/soc/amd/acp/acp-legacy-common.c
+++ b/sound/soc/amd/acp/acp-legacy-common.c
@@ -257,20 +257,20 @@ static int acp_power_on(struct acp_chip_info *chip)
base = chip->base;
switch (chip->acp_rev) {
- case ACP3X_DEV:
+ case ACP_RN_PCI_ID:
acp_pgfsm_stat_reg = ACP_PGFSM_STATUS;
acp_pgfsm_ctrl_reg = ACP_PGFSM_CONTROL;
break;
- case ACP6X_DEV:
+ case ACP_RMB_PCI_ID:
acp_pgfsm_stat_reg = ACP6X_PGFSM_STATUS;
acp_pgfsm_ctrl_reg = ACP6X_PGFSM_CONTROL;
break;
- case ACP63_DEV:
+ case ACP63_PCI_ID:
acp_pgfsm_stat_reg = ACP63_PGFSM_STATUS;
acp_pgfsm_ctrl_reg = ACP63_PGFSM_CONTROL;
break;
- case ACP70_DEV:
- case ACP71_DEV:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
acp_pgfsm_stat_reg = ACP70_PGFSM_STATUS;
acp_pgfsm_ctrl_reg = ACP70_PGFSM_CONTROL;
break;
@@ -322,7 +322,7 @@ int acp_init(struct acp_chip_info *chip)
pr_err("ACP reset failed\n");
return ret;
}
- if (chip->acp_rev >= ACP70_DEV)
+ if (chip->acp_rev >= ACP70_PCI_ID)
writel(0, chip->base + ACP_ZSC_DSP_CTRL);
return 0;
}
@@ -337,7 +337,7 @@ int acp_deinit(struct acp_chip_info *chip)
if (ret)
return ret;
- if (chip->acp_rev < ACP70_DEV)
+ if (chip->acp_rev < ACP70_PCI_ID)
writel(0, chip->base + ACP_CONTROL);
else
writel(0x01, chip->base + ACP_ZSC_DSP_CTRL);
@@ -448,20 +448,20 @@ void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip)
u32 pdm_addr;
switch (chip->acp_rev) {
- case ACP3X_DEV:
+ case ACP_RN_PCI_ID:
pdm_addr = ACP_RENOIR_PDM_ADDR;
check_acp3x_config(chip);
break;
- case ACP6X_DEV:
+ case ACP_RMB_PCI_ID:
pdm_addr = ACP_REMBRANDT_PDM_ADDR;
check_acp6x_config(chip);
break;
- case ACP63_DEV:
+ case ACP63_PCI_ID:
pdm_addr = ACP63_PDM_ADDR;
check_acp6x_config(chip);
break;
- case ACP70_DEV:
- case ACP71_DEV:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
pdm_addr = ACP70_PDM_ADDR;
check_acp70_config(chip);
break;
diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c
index d104f7e8fdcd..45613a865d2b 100644
--- a/sound/soc/amd/acp/acp-legacy-mach.c
+++ b/sound/soc/amd/acp/acp-legacy-mach.c
@@ -57,7 +57,6 @@ static struct acp_card_drvdata es83xx_rn_data = {
.dmic_cpu_id = DMIC,
.hs_codec_id = ES83XX,
.dmic_codec_id = DMIC,
- .platform = RENOIR,
};
static struct acp_card_drvdata max_nau8825_data = {
@@ -68,7 +67,6 @@ static struct acp_card_drvdata max_nau8825_data = {
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
.soc_mclk = true,
- .platform = REMBRANDT,
.tdm_mode = false,
};
@@ -80,7 +78,6 @@ static struct acp_card_drvdata rt5682s_rt1019_rmb_data = {
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
.soc_mclk = true,
- .platform = REMBRANDT,
.tdm_mode = false,
};
@@ -126,6 +123,7 @@ static int acp_asoc_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = NULL;
struct device *dev = &pdev->dev;
+ struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
const struct dmi_system_id *dmi_id;
struct acp_card_drvdata *acp_card_drvdata;
int ret;
@@ -171,7 +169,9 @@ static int acp_asoc_probe(struct platform_device *pdev)
goto out;
}
if (!strcmp(pdev->name, "acp-pdm-mach"))
- acp_card_drvdata->platform = *((int *)dev->platform_data);
+ acp_card_drvdata->acp_rev = *((int *)dev->platform_data);
+ else
+ acp_card_drvdata->acp_rev = mach->mach_params.subsystem_rev;
dmi_id = dmi_first_match(acp_quirk_table);
if (dmi_id && dmi_id->driver_data)
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
index e9ff4815c12c..d314253207d5 100644
--- a/sound/soc/amd/acp/acp-mach-common.c
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -1407,8 +1407,6 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(sof_sp);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
- links[i].dpcm_playback = 1;
- links[i].dpcm_capture = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
if (!drv_data->hs_codec_id) {
@@ -1444,8 +1442,6 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(sof_hs);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
- links[i].dpcm_playback = 1;
- links[i].dpcm_capture = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
if (!drv_data->hs_codec_id) {
@@ -1471,7 +1467,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
if (drv_data->amp_cpu_id == I2S_SP) {
links[i].name = "acp-amp-codec";
links[i].id = AMP_BE_ID;
- if (drv_data->platform == RENOIR) {
+ if (drv_data->acp_rev == ACP_RN_PCI_ID) {
links[i].cpus = sof_sp;
links[i].num_cpus = ARRAY_SIZE(sof_sp);
} else {
@@ -1480,7 +1476,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
}
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
- links[i].dpcm_playback = 1;
+ links[i].playback_only = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
if (!drv_data->amp_codec_id) {
@@ -1512,7 +1508,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(sof_hs_virtual);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
- links[i].dpcm_playback = 1;
+ links[i].playback_only = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
if (!drv_data->amp_codec_id) {
@@ -1527,7 +1523,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].init = acp_card_maxim_init;
}
if (drv_data->amp_codec_id == MAX98388) {
- links[i].dpcm_capture = 1;
+ links[i].playback_only = 0;
links[i].codecs = max98388;
links[i].num_codecs = ARRAY_SIZE(max98388);
links[i].ops = &acp_max98388_ops;
@@ -1553,8 +1549,6 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(sof_bt);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
- links[i].dpcm_playback = 1;
- links[i].dpcm_capture = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
if (!drv_data->bt_codec_id) {
@@ -1574,7 +1568,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(sof_dmic);
links[i].platforms = sof_component;
links[i].num_platforms = ARRAY_SIZE(sof_component);
- links[i].dpcm_capture = 1;
+ links[i].capture_only = 1;
links[i].nonatomic = true;
links[i].no_pcm = 1;
}
@@ -1613,8 +1607,6 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(i2s_sp);
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
- links[i].dpcm_playback = 1;
- links[i].dpcm_capture = 1;
if (!drv_data->hs_codec_id) {
/* Use dummy codec if codec id not specified */
links[i].codecs = &snd_soc_dummy_dlc;
@@ -1647,18 +1639,21 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].id = HEADSET_BE_ID;
links[i].cpus = i2s_hs;
links[i].num_cpus = ARRAY_SIZE(i2s_hs);
- if (drv_data->platform == REMBRANDT) {
+ switch (drv_data->acp_rev) {
+ case ACP_RMB_PCI_ID:
links[i].platforms = platform_rmb_component;
links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
- } else if (drv_data->platform == ACP63) {
+ break;
+ case ACP63_PCI_ID:
links[i].platforms = platform_acp63_component;
links[i].num_platforms = ARRAY_SIZE(platform_acp63_component);
- } else {
+ break;
+ default:
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
+ break;
}
- links[i].dpcm_playback = 1;
- links[i].dpcm_capture = 1;
+
if (!drv_data->hs_codec_id) {
/* Use dummy codec if codec id not specified */
links[i].codecs = &snd_soc_dummy_dlc;
@@ -1686,7 +1681,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].num_cpus = ARRAY_SIZE(i2s_sp);
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
- links[i].dpcm_playback = 1;
+ links[i].playback_only = 1;
if (!drv_data->amp_codec_id) {
/* Use dummy codec if codec id not specified */
links[i].codecs = &snd_soc_dummy_dlc;
@@ -1714,17 +1709,22 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
links[i].id = AMP_BE_ID;
links[i].cpus = i2s_hs;
links[i].num_cpus = ARRAY_SIZE(i2s_hs);
- if (drv_data->platform == REMBRANDT) {
+ switch (drv_data->acp_rev) {
+ case ACP_RMB_PCI_ID:
links[i].platforms = platform_rmb_component;
links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
- } else if (drv_data->platform == ACP63) {
+ break;
+ case ACP63_PCI_ID:
links[i].platforms = platform_acp63_component;
links[i].num_platforms = ARRAY_SIZE(platform_acp63_component);
- } else {
+ break;
+ default:
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
+ break;
}
- links[i].dpcm_playback = 1;
+
+ links[i].playback_only = 1;
if (!drv_data->amp_codec_id) {
/* Use dummy codec if codec id not specified */
links[i].codecs = &snd_soc_dummy_dlc;
@@ -1749,6 +1749,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
if (drv_data->dmic_cpu_id == DMIC) {
links[i].name = "acp-dmic-codec";
+ links[i].stream_name = "DMIC capture";
links[i].id = DMIC_BE_ID;
if (drv_data->dmic_codec_id == DMIC) {
links[i].codecs = dmic_codec;
@@ -1760,21 +1761,27 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
}
links[i].cpus = pdm_dmic;
links[i].num_cpus = ARRAY_SIZE(pdm_dmic);
- if (drv_data->platform == REMBRANDT) {
+ switch (drv_data->acp_rev) {
+ case ACP_RMB_PCI_ID:
links[i].platforms = platform_rmb_component;
links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
- } else if (drv_data->platform == ACP63) {
+ break;
+ case ACP63_PCI_ID:
links[i].platforms = platform_acp63_component;
links[i].num_platforms = ARRAY_SIZE(platform_acp63_component);
- } else if ((drv_data->platform == ACP70) || (drv_data->platform == ACP71)) {
+ break;
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
links[i].platforms = platform_acp70_component;
links[i].num_platforms = ARRAY_SIZE(platform_acp70_component);
- } else {
+ break;
+ default:
links[i].platforms = platform_component;
links[i].num_platforms = ARRAY_SIZE(platform_component);
+ break;
}
links[i].ops = &acp_card_dmic_ops;
- links[i].dpcm_capture = 1;
+ links[i].capture_only = 1;
}
card->dai_link = links;
diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h
index 93d9e3886b7e..f94c30c20f20 100644
--- a/sound/soc/amd/acp/acp-mach.h
+++ b/sound/soc/amd/acp/acp-mach.h
@@ -18,6 +18,8 @@
#include <linux/module.h>
#include <sound/soc.h>
+#include "acp_common.h"
+
#define TDM_CHANNELS 8
#define ACP_OPS(priv, cb) ((priv)->ops.cb)
@@ -51,14 +53,6 @@ enum codec_endpoints {
ES83XX,
};
-enum platform_end_point {
- RENOIR = 0,
- REMBRANDT,
- ACP63,
- ACP70,
- ACP71,
-};
-
struct acp_mach_ops {
int (*probe)(struct snd_soc_card *card);
int (*configure_link)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
@@ -77,7 +71,7 @@ struct acp_card_drvdata {
unsigned int bt_codec_id;
unsigned int dmic_codec_id;
unsigned int dai_fmt;
- unsigned int platform;
+ unsigned int acp_rev;
struct clk *wclk;
struct clk *bclk;
struct acp_mach_ops ops;
diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
index f7450a5bd103..4b6ad7abc3ba 100644
--- a/sound/soc/amd/acp/acp-pci.c
+++ b/sound/soc/amd/acp/acp-pci.c
@@ -77,27 +77,22 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
res_acp = acp_res;
num_res = ARRAY_SIZE(acp_res);
-
+ chip->acp_rev = pci->revision;
switch (pci->revision) {
case 0x01:
chip->name = "acp_asoc_renoir";
- chip->acp_rev = ACP3X_DEV;
break;
case 0x6f:
chip->name = "acp_asoc_rembrandt";
- chip->acp_rev = ACP6X_DEV;
break;
case 0x63:
chip->name = "acp_asoc_acp63";
- chip->acp_rev = ACP63_DEV;
break;
case 0x70:
chip->name = "acp_asoc_acp70";
- chip->acp_rev = ACP70_DEV;
break;
case 0x71:
chip->name = "acp_asoc_acp70";
- chip->acp_rev = ACP71_DEV;
break;
default:
dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision);
diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c
index 22dd8988d005..48faafe724ed 100644
--- a/sound/soc/amd/acp/acp-pdm.c
+++ b/sound/soc/amd/acp/acp-pdm.c
@@ -47,7 +47,7 @@ static int acp_dmic_prepare(struct snd_pcm_substream *substream,
size_dmic = frames_to_bytes(substream->runtime,
substream->runtime->buffer_size);
- if (chip->acp_rev >= ACP70_DEV)
+ if (chip->acp_rev >= ACP70_PCI_ID)
physical_addr = ACP7x_DMIC_MEM_WINDOW_START;
else
physical_addr = stream->reg_offset + MEM_WINDOW_START;
diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c
index 3a7a467b7063..1f352b2b3002 100644
--- a/sound/soc/amd/acp/acp-platform.c
+++ b/sound/soc/amd/acp/acp-platform.c
@@ -114,7 +114,7 @@ int acp_machine_select(struct acp_dev_data *adata)
int size, platform;
if (adata->flag == FLAG_AMD_LEGACY_ONLY_DMIC) {
- platform = adata->platform;
+ platform = adata->acp_rev;
adata->mach_dev = platform_device_register_data(adata->dev, "acp-pdm-mach",
PLATFORM_DEVID_NONE, &platform,
sizeof(platform));
@@ -125,6 +125,7 @@ int acp_machine_select(struct acp_dev_data *adata)
dev_err(adata->dev, "warning: No matching ASoC machine driver found\n");
return -EINVAL;
}
+ mach->mach_params.subsystem_rev = adata->acp_rev;
adata->mach_dev = platform_device_register_data(adata->dev, mach->drv_name,
PLATFORM_DEVID_NONE, mach, size);
}
@@ -142,9 +143,6 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
u16 i2s_flag = 0;
u32 ext_intr_stat, ext_intr_stat1;
- if (!adata)
- return IRQ_NONE;
-
if (adata->rsrc->no_of_ctrls == 2)
ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(adata, (rsrc->irqp_used - 1)));
@@ -204,9 +202,9 @@ void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int s
u32 low, high, val;
u16 page_idx;
- switch (adata->platform) {
- case ACP70:
- case ACP71:
+ switch (adata->acp_rev) {
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
switch (stream->dai_id) {
case I2S_SP_INSTANCE:
if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
@@ -270,9 +268,9 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs
stream->substream = substream;
chip = dev_get_platdata(dev);
switch (chip->acp_rev) {
- case ACP63_DEV:
- case ACP70_DEV:
- case ACP71_DEV:
+ case ACP63_PCI_ID:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
runtime->hw = acp6x_pcm_hardware_playback;
else
diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c
index 396434a45eea..008d97598b62 100644
--- a/sound/soc/amd/acp/acp-rembrandt.c
+++ b/sound/soc/amd/acp/acp-rembrandt.c
@@ -197,7 +197,7 @@ static int rembrandt_audio_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (chip->acp_rev != ACP6X_DEV) {
+ if (chip->acp_rev != ACP_RMB_PCI_ID) {
dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
return -ENODEV;
}
@@ -227,7 +227,7 @@ static int rembrandt_audio_probe(struct platform_device *pdev)
adata->dai_driver = acp_rmb_dai;
adata->num_dai = ARRAY_SIZE(acp_rmb_dai);
adata->rsrc = &rsrc;
- adata->platform = REMBRANDT;
+ adata->acp_rev = chip->acp_rev;
adata->flag = chip->flag;
adata->is_i2s_config = chip->is_i2s_config;
adata->machines = snd_soc_acpi_amd_rmb_acp_machines;
diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
index 5e3f730aa6bf..166f1efacf1d 100644
--- a/sound/soc/amd/acp/acp-renoir.c
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -157,7 +157,7 @@ static int renoir_audio_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (chip->acp_rev != ACP3X_DEV) {
+ if (chip->acp_rev != ACP_RN_PCI_ID) {
dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
return -ENODEV;
}
@@ -185,7 +185,7 @@ static int renoir_audio_probe(struct platform_device *pdev)
adata->dai_driver = acp_renoir_dai;
adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
adata->rsrc = &rsrc;
- adata->platform = RENOIR;
+ adata->acp_rev = chip->acp_rev;
adata->flag = chip->flag;
adata->machines = snd_soc_acpi_amd_acp_machines;
diff --git a/sound/soc/amd/acp/acp-sdw-legacy-mach.c b/sound/soc/amd/acp/acp-sdw-legacy-mach.c
new file mode 100644
index 000000000000..48952a238946
--- /dev/null
+++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c
@@ -0,0 +1,486 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright(c) 2024 Advanced Micro Devices, Inc.
+
+/*
+ * acp-sdw-legacy-mach - ASoC legacy Machine driver for AMD SoundWire platforms
+ */
+
+#include <linux/bitmap.h>
+#include <linux/device.h>
+#include <linux/dmi.h>
+#include <linux/module.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_type.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+#include "soc_amd_sdw_common.h"
+#include "../../codecs/rt711.h"
+
+static unsigned long soc_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");
+
+static void log_quirks(struct device *dev)
+{
+ if (SOC_JACK_JDSRC(soc_sdw_quirk))
+ dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
+ SOC_JACK_JDSRC(soc_sdw_quirk));
+ if (soc_sdw_quirk & ASOC_SDW_ACP_DMIC)
+ dev_dbg(dev, "quirk SOC_SDW_ACP_DMIC enabled\n");
+}
+
+static int soc_sdw_quirk_cb(const struct dmi_system_id *id)
+{
+ soc_sdw_quirk = (unsigned long)id->driver_data;
+ return 1;
+}
+
+static const struct dmi_system_id soc_sdw_quirk_table[] = {
+ {
+ .callback = soc_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "AMD"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Birman-PHX"),
+ },
+ .driver_data = (void *)RT711_JD2,
+ },
+ {}
+};
+
+static const struct snd_soc_ops sdw_ops = {
+ .startup = asoc_sdw_startup,
+ .prepare = asoc_sdw_prepare,
+ .trigger = asoc_sdw_trigger,
+ .hw_params = asoc_sdw_hw_params,
+ .hw_free = asoc_sdw_hw_free,
+ .shutdown = asoc_sdw_shutdown,
+};
+
+static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};
+
+static int create_sdw_dailink(struct snd_soc_card *card,
+ struct asoc_sdw_dailink *soc_dai,
+ struct snd_soc_dai_link **dai_links,
+ int *be_id, struct snd_soc_codec_conf **codec_conf,
+ struct snd_soc_dai_link_component *sdw_platform_component)
+{
+ struct device *dev = card->dev;
+ struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
+ struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private;
+ struct asoc_sdw_endpoint *soc_end;
+ int cpu_pin_id;
+ int stream;
+ int ret;
+
+ list_for_each_entry(soc_end, &soc_dai->endpoints, list) {
+ if (soc_end->name_prefix) {
+ (*codec_conf)->dlc.name = soc_end->codec_name;
+ (*codec_conf)->name_prefix = soc_end->name_prefix;
+ (*codec_conf)++;
+ }
+
+ if (soc_end->include_sidecar) {
+ ret = soc_end->codec_info->add_sidecar(card, dai_links, codec_conf);
+ if (ret)
+ return ret;
+ }
+ }
+
+ for_each_pcm_streams(stream) {
+ static const char * const sdw_stream_name[] = {
+ "SDW%d-PIN%d-PLAYBACK",
+ "SDW%d-PIN%d-CAPTURE",
+ "SDW%d-PIN%d-PLAYBACK-%s",
+ "SDW%d-PIN%d-CAPTURE-%s",
+ };
+ struct snd_soc_dai_link_ch_map *codec_maps;
+ struct snd_soc_dai_link_component *codecs;
+ struct snd_soc_dai_link_component *cpus;
+ int num_cpus = hweight32(soc_dai->link_mask[stream]);
+ int num_codecs = soc_dai->num_devs[stream];
+ int playback, capture;
+ int j = 0;
+ char *name;
+
+ if (!soc_dai->num_devs[stream])
+ continue;
+
+ soc_end = list_first_entry(&soc_dai->endpoints,
+ struct asoc_sdw_endpoint, list);
+
+ *be_id = soc_end->dai_info->dailink[stream];
+ if (*be_id < 0) {
+ dev_err(dev, "Invalid dailink id %d\n", *be_id);
+ return -EINVAL;
+ }
+
+ switch (amd_ctx->acp_rev) {
+ case ACP63_PCI_REV:
+ ret = get_acp63_cpu_pin_id(ffs(soc_end->link_mask - 1),
+ *be_id, &cpu_pin_id, dev);
+ if (ret)
+ return ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* create stream name according to first link id */
+ if (ctx->append_dai_type) {
+ name = devm_kasprintf(dev, GFP_KERNEL,
+ sdw_stream_name[stream + 2],
+ ffs(soc_end->link_mask) - 1,
+ cpu_pin_id,
+ type_strings[soc_end->dai_info->dai_type]);
+ } else {
+ name = devm_kasprintf(dev, GFP_KERNEL,
+ sdw_stream_name[stream],
+ ffs(soc_end->link_mask) - 1,
+ cpu_pin_id);
+ }
+ if (!name)
+ return -ENOMEM;
+
+ cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL);
+ if (!cpus)
+ return -ENOMEM;
+
+ codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL);
+ if (!codecs)
+ return -ENOMEM;
+
+ codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL);
+ if (!codec_maps)
+ return -ENOMEM;
+
+ list_for_each_entry(soc_end, &soc_dai->endpoints, list) {
+ if (!soc_end->dai_info->direction[stream])
+ continue;
+
+ int link_num = ffs(soc_end->link_mask) - 1;
+
+ cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
+ "SDW%d Pin%d",
+ link_num, cpu_pin_id);
+ dev_dbg(dev, "cpu->dai_name:%s\n", cpus->dai_name);
+ if (!cpus->dai_name)
+ return -ENOMEM;
+
+ codec_maps[j].cpu = 0;
+ codec_maps[j].codec = j;
+
+ codecs[j].name = soc_end->codec_name;
+ codecs[j].dai_name = soc_end->dai_info->dai_name;
+ j++;
+ }
+
+ WARN_ON(j != num_codecs);
+
+ playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
+ capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
+
+ asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture,
+ cpus, num_cpus, sdw_platform_component,
+ 1, codecs, num_codecs,
+ 0, asoc_sdw_rtd_init, &sdw_ops);
+ /*
+ * SoundWire DAILINKs use 'stream' functions and Bank Switch operations
+ * based on wait_for_completion(), tag them as 'nonatomic'.
+ */
+ (*dai_links)->nonatomic = true;
+ (*dai_links)->ch_maps = codec_maps;
+
+ list_for_each_entry(soc_end, &soc_dai->endpoints, list) {
+ if (soc_end->dai_info->init)
+ soc_end->dai_info->init(card, *dai_links,
+ soc_end->codec_info,
+ playback);
+ }
+
+ (*dai_links)++;
+ }
+
+ return 0;
+}
+
+static int create_sdw_dailinks(struct snd_soc_card *card,
+ struct snd_soc_dai_link **dai_links, int *be_id,
+ struct asoc_sdw_dailink *soc_dais,
+ struct snd_soc_codec_conf **codec_conf)
+{
+ struct device *dev = card->dev;
+ struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
+ struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private;
+ struct snd_soc_dai_link_component *sdw_platform_component;
+ int ret;
+
+ sdw_platform_component = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
+ GFP_KERNEL);
+ if (!sdw_platform_component)
+ return -ENOMEM;
+
+ switch (amd_ctx->acp_rev) {
+ case ACP63_PCI_REV:
+ sdw_platform_component->name = "amd_ps_sdw_dma.0";
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* generate DAI links by each sdw link */
+ while (soc_dais->initialised) {
+ int current_be_id;
+
+ ret = create_sdw_dailink(card, soc_dais, dai_links,
+ &current_be_id, codec_conf, sdw_platform_component);
+ if (ret)
+ return ret;
+
+ /* Update the be_id to match the highest ID used for SDW link */
+ if (*be_id < current_be_id)
+ *be_id = current_be_id;
+
+ soc_dais++;
+ }
+
+ return 0;
+}
+
+static int create_dmic_dailinks(struct snd_soc_card *card,
+ struct snd_soc_dai_link **dai_links, int *be_id, int no_pcm)
+{
+ struct device *dev = card->dev;
+ struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
+ struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private;
+ struct snd_soc_dai_link_component *pdm_cpu;
+ struct snd_soc_dai_link_component *pdm_platform;
+ int ret;
+
+ pdm_cpu = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), GFP_KERNEL);
+ if (!pdm_cpu)
+ return -ENOMEM;
+
+ pdm_platform = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), GFP_KERNEL);
+ if (!pdm_platform)
+ return -ENOMEM;
+
+ switch (amd_ctx->acp_rev) {
+ case ACP63_PCI_REV:
+ pdm_cpu->name = "acp_ps_pdm_dma.0";
+ pdm_platform->name = "acp_ps_pdm_dma.0";
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *be_id = ACP_DMIC_BE_ID;
+ ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "acp-dmic-codec",
+ 0, 1, // DMIC only supports capture
+ pdm_cpu->name, pdm_platform->name, 1,
+ "dmic-codec.0", "dmic-hifi", no_pcm,
+ asoc_sdw_dmic_init, NULL);
+ if (ret)
+ return ret;
+
+ (*dai_links)++;
+
+ return 0;
+}
+
+static int soc_card_dai_links_create(struct snd_soc_card *card)
+{
+ struct device *dev = card->dev;
+ struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
+ int sdw_be_num = 0, dmic_num = 0;
+ struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
+ struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
+ struct asoc_sdw_endpoint *soc_ends __free(kfree) = NULL;
+ struct asoc_sdw_dailink *soc_dais __free(kfree) = NULL;
+ struct snd_soc_codec_conf *codec_conf;
+ struct snd_soc_dai_link *dai_links;
+ int num_devs = 0;
+ int num_ends = 0;
+ int num_links;
+ int be_id = 0;
+ int ret;
+
+ ret = asoc_sdw_count_sdw_endpoints(card, &num_devs, &num_ends);
+ if (ret < 0) {
+ dev_err(dev, "failed to count devices/endpoints: %d\n", ret);
+ return ret;
+ }
+
+ /* One per DAI link, worst case is a DAI link for every endpoint */
+ soc_dais = kcalloc(num_ends, sizeof(*soc_dais), GFP_KERNEL);
+ if (!soc_dais)
+ return -ENOMEM;
+
+ /* One per endpoint, ie. each DAI on each codec/amp */
+ soc_ends = kcalloc(num_ends, sizeof(*soc_ends), GFP_KERNEL);
+ if (!soc_ends)
+ return -ENOMEM;
+
+ ret = asoc_sdw_parse_sdw_endpoints(card, soc_dais, soc_ends, &num_devs);
+ if (ret < 0)
+ return ret;
+
+ sdw_be_num = ret;
+
+ /* enable dmic */
+ if (soc_sdw_quirk & ASOC_SDW_ACP_DMIC || mach_params->dmic_num)
+ dmic_num = 1;
+
+ dev_dbg(dev, "sdw %d, dmic %d", sdw_be_num, dmic_num);
+
+ codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL);
+ if (!codec_conf)
+ return -ENOMEM;
+
+ /* allocate BE dailinks */
+ num_links = sdw_be_num + dmic_num;
+ dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL);
+ if (!dai_links)
+ return -ENOMEM;
+
+ card->codec_conf = codec_conf;
+ card->num_configs = num_devs;
+ card->dai_link = dai_links;
+ card->num_links = num_links;
+
+ /* SDW */
+ if (sdw_be_num) {
+ ret = create_sdw_dailinks(card, &dai_links, &be_id,
+ soc_dais, &codec_conf);
+ if (ret)
+ return ret;
+ }
+
+ /* dmic */
+ if (dmic_num > 0) {
+ if (ctx->ignore_internal_dmic) {
+ dev_warn(dev, "Ignoring ACP DMIC\n");
+ } else {
+ ret = create_dmic_dailinks(card, &dai_links, &be_id, 0);
+ if (ret)
+ return ret;
+ }
+ }
+
+ WARN_ON(codec_conf != card->codec_conf + card->num_configs);
+ WARN_ON(dai_links != card->dai_link + card->num_links);
+
+ return ret;
+}
+
+static int mc_probe(struct platform_device *pdev)
+{
+ struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
+ struct snd_soc_card *card;
+ struct amd_mc_ctx *amd_ctx;
+ struct asoc_sdw_mc_private *ctx;
+ int amp_num = 0, i;
+ int ret;
+
+ amd_ctx = devm_kzalloc(&pdev->dev, sizeof(*amd_ctx), GFP_KERNEL);
+ if (!amd_ctx)
+ return -ENOMEM;
+
+ amd_ctx->acp_rev = mach->mach_params.subsystem_rev;
+ amd_ctx->max_sdw_links = ACP63_SDW_MAX_LINKS;
+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count();
+ ctx->private = amd_ctx;
+ card = &ctx->card;
+ card->dev = &pdev->dev;
+ card->name = "amd-soundwire";
+ card->owner = THIS_MODULE;
+ card->late_probe = asoc_sdw_card_late_probe;
+
+ snd_soc_card_set_drvdata(card, ctx);
+
+ dmi_check_system(soc_sdw_quirk_table);
+
+ if (quirk_override != -1) {
+ dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n",
+ soc_sdw_quirk, quirk_override);
+ soc_sdw_quirk = quirk_override;
+ }
+
+ log_quirks(card->dev);
+
+ ctx->mc_quirk = soc_sdw_quirk;
+ dev_dbg(card->dev, "legacy quirk 0x%lx\n", ctx->mc_quirk);
+ /* reset amp_num to ensure amp_num++ starts from 0 in each probe */
+ for (i = 0; i < ctx->codec_info_list_count; i++)
+ codec_info_list[i].amp_num = 0;
+
+ ret = soc_card_dai_links_create(card);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * the default amp_num is zero for each codec and
+ * amp_num will only be increased for active amp
+ * codecs on used platform
+ */
+ for (i = 0; i < ctx->codec_info_list_count; i++)
+ amp_num += codec_info_list[i].amp_num;
+
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+ " cfg-amp:%d", amp_num);
+ if (!card->components)
+ return -ENOMEM;
+ if (mach->mach_params.dmic_num) {
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+ "%s mic:dmic cfg-mics:%d",
+ card->components,
+ mach->mach_params.dmic_num);
+ if (!card->components)
+ return -ENOMEM;
+ }
+
+ /* Register the card */
+ ret = devm_snd_soc_register_card(card->dev, card);
+ if (ret) {
+ dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret);
+ asoc_sdw_mc_dailink_exit_loop(card);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, card);
+
+ return ret;
+}
+
+static void mc_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ asoc_sdw_mc_dailink_exit_loop(card);
+}
+
+static const struct platform_device_id mc_id_table[] = {
+ { "amd_sdw", },
+ {}
+};
+MODULE_DEVICE_TABLE(platform, mc_id_table);
+
+static struct platform_driver soc_sdw_driver = {
+ .driver = {
+ .name = "amd_sdw",
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = mc_probe,
+ .remove = mc_remove,
+ .id_table = mc_id_table,
+};
+
+module_platform_driver(soc_sdw_driver);
+
+MODULE_DESCRIPTION("ASoC AMD SoundWire Legacy Generic Machine driver");
+MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SND_SOC_SDW_UTILS);
+MODULE_IMPORT_NS(SND_SOC_AMD_SDW_MACH);
diff --git a/sound/soc/amd/acp/acp-sdw-mach-common.c b/sound/soc/amd/acp/acp-sdw-mach-common.c
new file mode 100644
index 000000000000..d9393cc4a302
--- /dev/null
+++ b/sound/soc/amd/acp/acp-sdw-mach-common.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright(c) 2024 Advanced Micro Devices, Inc.
+
+/*
+ * acp-sdw-mach-common - Common machine driver helper functions for
+ * legacy(No DSP) stack and SOF stack.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include "soc_amd_sdw_common.h"
+
+int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev)
+{
+ switch (sdw_link_id) {
+ case AMD_SDW0:
+ switch (be_id) {
+ case SOC_SDW_JACK_OUT_DAI_ID:
+ *cpu_pin_id = ACP63_SW0_AUDIO0_TX;
+ break;
+ case SOC_SDW_JACK_IN_DAI_ID:
+ *cpu_pin_id = ACP63_SW0_AUDIO0_RX;
+ break;
+ case SOC_SDW_AMP_OUT_DAI_ID:
+ *cpu_pin_id = ACP63_SW0_AUDIO1_TX;
+ break;
+ case SOC_SDW_AMP_IN_DAI_ID:
+ *cpu_pin_id = ACP63_SW0_AUDIO1_RX;
+ break;
+ case SOC_SDW_DMIC_DAI_ID:
+ *cpu_pin_id = ACP63_SW0_AUDIO2_RX;
+ break;
+ default:
+ dev_err(dev, "Invalid be id:%d\n", be_id);
+ return -EINVAL;
+ }
+ break;
+ case AMD_SDW1:
+ switch (be_id) {
+ case SOC_SDW_JACK_OUT_DAI_ID:
+ case SOC_SDW_AMP_OUT_DAI_ID:
+ *cpu_pin_id = ACP63_SW1_AUDIO0_TX;
+ break;
+ case SOC_SDW_JACK_IN_DAI_ID:
+ case SOC_SDW_AMP_IN_DAI_ID:
+ case SOC_SDW_DMIC_DAI_ID:
+ *cpu_pin_id = ACP63_SW1_AUDIO0_RX;
+ break;
+ default:
+ dev_err(dev, "invalid be_id:%d\n", be_id);
+ return -EINVAL;
+ }
+ break;
+ default:
+ dev_err(dev, "Invalid link id:%d\n", sdw_link_id);
+ return -EINVAL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(get_acp63_cpu_pin_id, SND_SOC_AMD_SDW_MACH);
+
+MODULE_DESCRIPTION("AMD SoundWire Common Machine driver");
+MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c
index 6c50c8276538..0d256c0749c9 100644
--- a/sound/soc/amd/acp/acp-sdw-sof-mach.c
+++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c
@@ -64,54 +64,6 @@ static const struct snd_soc_ops sdw_ops = {
.shutdown = asoc_sdw_shutdown,
};
-static int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev)
-{
- switch (sdw_link_id) {
- case AMD_SDW0:
- switch (be_id) {
- case SOC_SDW_JACK_OUT_DAI_ID:
- *cpu_pin_id = ACP63_SW0_AUDIO0_TX;
- break;
- case SOC_SDW_JACK_IN_DAI_ID:
- *cpu_pin_id = ACP63_SW0_AUDIO0_RX;
- break;
- case SOC_SDW_AMP_OUT_DAI_ID:
- *cpu_pin_id = ACP63_SW0_AUDIO1_TX;
- break;
- case SOC_SDW_AMP_IN_DAI_ID:
- *cpu_pin_id = ACP63_SW0_AUDIO1_RX;
- break;
- case SOC_SDW_DMIC_DAI_ID:
- *cpu_pin_id = ACP63_SW0_AUDIO2_RX;
- break;
- default:
- dev_err(dev, "Invalid be id:%d\n", be_id);
- return -EINVAL;
- }
- break;
- case AMD_SDW1:
- switch (be_id) {
- case SOC_SDW_JACK_OUT_DAI_ID:
- case SOC_SDW_AMP_OUT_DAI_ID:
- *cpu_pin_id = ACP63_SW1_AUDIO0_TX;
- break;
- case SOC_SDW_JACK_IN_DAI_ID:
- case SOC_SDW_AMP_IN_DAI_ID:
- case SOC_SDW_DMIC_DAI_ID:
- *cpu_pin_id = ACP63_SW1_AUDIO0_RX;
- break;
- default:
- dev_err(dev, "invalid be_id:%d\n", be_id);
- return -EINVAL;
- }
- break;
- default:
- dev_err(dev, "Invalid link id:%d\n", sdw_link_id);
- return -EINVAL;
- }
- return 0;
-}
-
static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};
static int create_sdw_dailink(struct snd_soc_card *card,
@@ -154,7 +106,7 @@ static int create_sdw_dailink(struct snd_soc_card *card,
int num_cpus = hweight32(sof_dai->link_mask[stream]);
int num_codecs = sof_dai->num_devs[stream];
int playback, capture;
- int i = 0, j = 0;
+ int j = 0;
char *name;
if (!sof_dai->num_devs[stream])
@@ -213,14 +165,14 @@ static int create_sdw_dailink(struct snd_soc_card *card,
int link_num = ffs(sof_end->link_mask) - 1;
- cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL,
- "SDW%d Pin%d",
- link_num, cpu_pin_id);
- dev_dbg(dev, "cpu[%d].dai_name:%s\n", i, cpus[i].dai_name);
- if (!cpus[i].dai_name)
+ cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
+ "SDW%d Pin%d",
+ link_num, cpu_pin_id);
+ dev_dbg(dev, "cpu->dai_name:%s\n", cpus->dai_name);
+ if (!cpus->dai_name)
return -ENOMEM;
- codec_maps[j].cpu = i;
+ codec_maps[j].cpu = 0;
codec_maps[j].codec = j;
codecs[j].name = sof_end->codec_name;
@@ -236,7 +188,7 @@ static int create_sdw_dailink(struct snd_soc_card *card,
asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture,
cpus, num_cpus, platform_component,
ARRAY_SIZE(platform_component), codecs, num_codecs,
- asoc_sdw_rtd_init, &sdw_ops);
+ 1, asoc_sdw_rtd_init, &sdw_ops);
/*
* SoundWire DAILINKs use 'stream' functions and Bank Switch operations
@@ -285,7 +237,7 @@ static int create_sdw_dailinks(struct snd_soc_card *card,
}
static int create_dmic_dailinks(struct snd_soc_card *card,
- struct snd_soc_dai_link **dai_links, int *be_id)
+ struct snd_soc_dai_link **dai_links, int *be_id, int no_pcm)
{
struct device *dev = card->dev;
int ret;
@@ -294,7 +246,7 @@ static int create_dmic_dailinks(struct snd_soc_card *card,
0, 1, // DMIC only supports capture
"acp-sof-dmic", platform_component->name,
ARRAY_SIZE(platform_component),
- "dmic-codec", "dmic-hifi",
+ "dmic-codec", "dmic-hifi", no_pcm,
asoc_sdw_dmic_init, NULL);
if (ret)
return ret;
@@ -311,9 +263,9 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
int sdw_be_num = 0, dmic_num = 0;
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
+ struct asoc_sdw_endpoint *sof_ends __free(kfree) = NULL;
+ struct asoc_sdw_dailink *sof_dais __free(kfree) = NULL;
struct snd_soc_codec_conf *codec_conf;
- struct asoc_sdw_endpoint *sof_ends;
- struct asoc_sdw_dailink *sof_dais;
struct snd_soc_dai_link *dai_links;
int num_devs = 0;
int num_ends = 0;
@@ -334,14 +286,12 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
/* One per endpoint, ie. each DAI on each codec/amp */
sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL);
- if (!sof_ends) {
- ret = -ENOMEM;
- goto err_dai;
- }
+ if (!sof_ends)
+ return -ENOMEM;
ret = asoc_sdw_parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs);
if (ret < 0)
- goto err_end;
+ return ret;
sdw_be_num = ret;
@@ -352,18 +302,14 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
dev_dbg(dev, "sdw %d, dmic %d", sdw_be_num, dmic_num);
codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL);
- if (!codec_conf) {
- ret = -ENOMEM;
- goto err_end;
- }
+ if (!codec_conf)
+ return -ENOMEM;
/* allocate BE dailinks */
num_links = sdw_be_num + dmic_num;
dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL);
- if (!dai_links) {
- ret = -ENOMEM;
- goto err_end;
- }
+ if (!dai_links)
+ return -ENOMEM;
card->codec_conf = codec_conf;
card->num_configs = num_devs;
@@ -375,7 +321,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
ret = create_sdw_dailinks(card, &dai_links, &be_id,
sof_dais, &codec_conf);
if (ret)
- goto err_end;
+ return ret;
}
/* dmic */
@@ -383,26 +329,18 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
if (ctx->ignore_internal_dmic) {
dev_warn(dev, "Ignoring ACP DMIC\n");
} else {
- ret = create_dmic_dailinks(card, &dai_links, &be_id);
+ ret = create_dmic_dailinks(card, &dai_links, &be_id, 1);
if (ret)
- goto err_end;
+ return ret;
}
}
WARN_ON(codec_conf != card->codec_conf + card->num_configs);
WARN_ON(dai_links != card->dai_link + card->num_links);
-err_end:
- kfree(sof_ends);
-err_dai:
- kfree(sof_dais);
-
return ret;
}
-/* SoC card */
-static const char sdw_card_long_name[] = "AMD Soundwire SOF";
-
static int mc_probe(struct platform_device *pdev)
{
struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
@@ -463,8 +401,6 @@ static int mc_probe(struct platform_device *pdev)
if (!card->components)
return -ENOMEM;
- card->long_name = sdw_card_long_name;
-
/* Register the card */
ret = devm_snd_soc_register_card(card->dev, card);
if (ret) {
@@ -507,3 +443,4 @@ MODULE_DESCRIPTION("ASoC AMD SoundWire Generic Machine driver");
MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(SND_SOC_SDW_UTILS);
+MODULE_IMPORT_NS(SND_SOC_AMD_SDW_MACH);
diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c
index f36750167fa2..63a9621ede6d 100644
--- a/sound/soc/amd/acp/acp-sof-mach.c
+++ b/sound/soc/amd/acp/acp-sof-mach.c
@@ -46,7 +46,6 @@ static struct acp_card_drvdata sof_rt5682s_rt1019_data = {
.hs_codec_id = RT5682S,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
- .platform = RENOIR,
};
static struct acp_card_drvdata sof_rt5682s_max_data = {
@@ -56,7 +55,6 @@ static struct acp_card_drvdata sof_rt5682s_max_data = {
.hs_codec_id = RT5682S,
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
- .platform = RENOIR,
};
static struct acp_card_drvdata sof_nau8825_data = {
@@ -66,7 +64,6 @@ static struct acp_card_drvdata sof_nau8825_data = {
.hs_codec_id = NAU8825,
.amp_codec_id = MAX98360A,
.dmic_codec_id = DMIC,
- .platform = REMBRANDT,
.soc_mclk = true,
};
@@ -77,7 +74,6 @@ static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = {
.hs_codec_id = RT5682S,
.amp_codec_id = RT1019,
.dmic_codec_id = DMIC,
- .platform = REMBRANDT,
.soc_mclk = true,
};
@@ -94,6 +90,7 @@ static int acp_sof_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = NULL;
struct device *dev = &pdev->dev;
+ struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
const struct dmi_system_id *dmi_id;
struct acp_card_drvdata *acp_card_drvdata;
int ret;
@@ -116,6 +113,7 @@ static int acp_sof_probe(struct platform_device *pdev)
if (dmi_id && dmi_id->driver_data)
acp_card_drvdata->tdm_mode = dmi_id->driver_data;
+ acp_card_drvdata->acp_rev = mach->mach_params.subsystem_rev;
ret = acp_sofdsp_dai_links_create(card);
if (ret)
return dev_err_probe(&pdev->dev, ret, "Failed to create DAI links\n");
diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c
index f325c374f228..e0b86132eb95 100644
--- a/sound/soc/amd/acp/acp63.c
+++ b/sound/soc/amd/acp/acp63.c
@@ -207,7 +207,7 @@ static int acp63_audio_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (chip->acp_rev != ACP63_DEV) {
+ if (chip->acp_rev != ACP63_PCI_ID) {
dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
return -ENODEV;
}
@@ -237,7 +237,7 @@ static int acp63_audio_probe(struct platform_device *pdev)
adata->dai_driver = acp63_dai;
adata->num_dai = ARRAY_SIZE(acp63_dai);
adata->rsrc = &rsrc;
- adata->platform = ACP63;
+ adata->acp_rev = chip->acp_rev;
adata->flag = chip->flag;
adata->is_i2s_config = chip->is_i2s_config;
adata->machines = snd_soc_acpi_amd_acp63_acp_machines;
diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c
index 68d2590e1a4e..3e4fd113a8a4 100644
--- a/sound/soc/amd/acp/acp70.c
+++ b/sound/soc/amd/acp/acp70.c
@@ -142,9 +142,9 @@ static int acp70_i2s_master_clock_generate(struct acp_dev_data *adata)
struct pci_dev *smn_dev;
u32 device_id;
- if (adata->platform == ACP70)
+ if (adata->acp_rev == ACP70_PCI_ID)
device_id = 0x1507;
- else if (adata->platform == ACP71)
+ else if (adata->acp_rev == ACP71_PCI_ID)
device_id = 0x1122;
else
return -ENODEV;
@@ -175,8 +175,8 @@ static int acp_acp70_audio_probe(struct platform_device *pdev)
}
switch (chip->acp_rev) {
- case ACP70_DEV:
- case ACP71_DEV:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
break;
default:
dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
@@ -209,11 +209,7 @@ static int acp_acp70_audio_probe(struct platform_device *pdev)
adata->num_dai = ARRAY_SIZE(acp70_dai);
adata->rsrc = &rsrc;
adata->machines = snd_soc_acpi_amd_acp70_acp_machines;
- if (chip->acp_rev == ACP70_DEV)
- adata->platform = ACP70;
- else
- adata->platform = ACP71;
-
+ adata->acp_rev = chip->acp_rev;
adata->flag = chip->flag;
acp_machine_select(adata);
diff --git a/sound/soc/amd/acp/acp_common.h b/sound/soc/amd/acp/acp_common.h
new file mode 100644
index 000000000000..f1ae88013f62
--- /dev/null
+++ b/sound/soc/amd/acp/acp_common.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ * Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved
+ */
+
+/*
+ * acp_common.h - acp common header file
+ */
+
+#ifndef __ACP_COMMON_H
+#define __ACP_COMMON_H
+
+#define ACP_RN_PCI_ID 0x01
+#define ACP_VANGOGH_PCI_ID 0x50
+#define ACP_RMB_PCI_ID 0x6F
+#define ACP63_PCI_ID 0x63
+#define ACP70_PCI_ID 0x70
+#define ACP71_PCI_ID 0x71
+
+#endif
diff --git a/sound/soc/amd/acp/amd-acp63-acpi-match.c b/sound/soc/amd/acp/amd-acp63-acpi-match.c
index be9367913073..9b6a49c051cd 100644
--- a/sound/soc/amd/acp/amd-acp63-acpi-match.c
+++ b/sound/soc/amd/acp/amd-acp63-acpi-match.c
@@ -73,6 +73,45 @@ static const struct snd_soc_acpi_link_adr acp63_4_in_1_sdca[] = {
{}
};
+static const struct snd_soc_acpi_endpoint rt722_endpoints[] = {
+ {
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ {
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ {
+ .num = 2,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
+static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = {
+ {
+ .adr = 0x000030025d072201ull,
+ .num_endpoints = ARRAY_SIZE(rt722_endpoints),
+ .endpoints = rt722_endpoints,
+ .name_prefix = "rt722"
+ }
+};
+
+static const struct snd_soc_acpi_link_adr acp63_rt722_only[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt722_0_single_adr),
+ .adr_d = rt722_0_single_adr,
+ },
+ {}
+};
+
struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[] = {
{
.link_mask = BIT(0) | BIT(1),
@@ -85,6 +124,21 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[] = {
};
EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sof_sdw_machines);
+struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sdw_machines[] = {
+ {
+ .link_mask = BIT(0),
+ .links = acp63_rt722_only,
+ .drv_name = "amd_sdw",
+ },
+ {
+ .link_mask = BIT(0) | BIT(1),
+ .links = acp63_4_in_1_sdca,
+ .drv_name = "amd_sdw",
+ },
+ {},
+};
+EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sdw_machines);
+
MODULE_DESCRIPTION("AMD ACP6.3 tables and support for ACPI enumeration");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index 854269fea875..ee69dfb10cb8 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -16,14 +16,9 @@
#include <sound/soc-acpi.h>
#include <sound/soc-dai.h>
+#include "acp_common.h"
#include "chip_offset_byte.h"
-#define ACP3X_DEV 3
-#define ACP6X_DEV 6
-#define ACP63_DEV 0x63
-#define ACP70_DEV 0x70
-#define ACP71_DEV 0x71
-
#define DMIC_INSTANCE 0x00
#define I2S_SP_INSTANCE 0x01
#define I2S_BT_INSTANCE 0x02
@@ -182,6 +177,7 @@ struct acp_dev_data {
struct device *dev;
void __iomem *acp_base;
unsigned int i2s_irq;
+ unsigned int acp_rev; /* ACP Revision id */
bool tdm_mode;
bool is_i2s_config;
@@ -205,7 +201,6 @@ struct acp_dev_data {
u32 xfer_tx_resolution[3];
u32 xfer_rx_resolution[3];
unsigned int flag;
- unsigned int platform;
};
enum acp_config {
diff --git a/sound/soc/amd/acp/soc_amd_sdw_common.h b/sound/soc/amd/acp/soc_amd_sdw_common.h
index f1bd5a7afc8e..b7bae107c13e 100644
--- a/sound/soc/amd/acp/soc_amd_sdw_common.h
+++ b/sound/soc/amd/acp/soc_amd_sdw_common.h
@@ -36,9 +36,13 @@
#define ACP63_SW1_AUDIO0_TX 0
#define ACP63_SW1_AUDIO0_RX 1
+#define ACP_DMIC_BE_ID 4
+
struct amd_mc_ctx {
unsigned int acp_rev;
unsigned int max_sdw_links;
};
+int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev);
+
#endif
diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c
index 357dfd016baf..4ca1978020a9 100644
--- a/sound/soc/amd/acp3x-rt5682-max9836.c
+++ b/sound/soc/amd/acp3x-rt5682-max9836.c
@@ -317,8 +317,6 @@ static struct snd_soc_dai_link acp3x_dai[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBP_CFP,
.init = acp3x_5682_init,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &acp3x_5682_ops,
SND_SOC_DAILINK_REG(acp3x_i2s, rt5682, platform),
},
@@ -327,7 +325,7 @@ static struct snd_soc_dai_link acp3x_dai[] = {
.stream_name = "HiFi Playback",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &acp3x_max_play_ops,
.cpus = acp3x_bt,
.num_cpus = ARRAY_SIZE(acp3x_bt),
@@ -339,7 +337,7 @@ static struct snd_soc_dai_link acp3x_dai[] = {
.stream_name = "Capture DMIC0",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &acp3x_ec_cap0_ops,
SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
},
diff --git a/sound/soc/amd/mach-config.h b/sound/soc/amd/mach-config.h
index 1a967da35a0f..a86c76f781f9 100644
--- a/sound/soc/amd/mach-config.h
+++ b/sound/soc/amd/mach-config.h
@@ -23,6 +23,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_amd_vangogh_sof_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_machines[];
+extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sof_machines[];
diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c
index 0c3bb1da5097..aef73ec6f7ef 100644
--- a/sound/soc/amd/ps/pci-ps.c
+++ b/sound/soc/amd/ps/pci-ps.c
@@ -303,8 +303,7 @@ static struct snd_soc_acpi_mach *acp63_sdw_machine_select(struct device *dev)
link = mach->links;
for (i = 0; i < acp_data->info.count && link->num_adr; link++, i++) {
if (!snd_soc_acpi_sdw_link_slaves_found(dev, link,
- acp_data->sdw->ids,
- acp_data->sdw->num_slaves))
+ acp_data->sdw->peripherals))
break;
}
if (i == acp_data->info.count || !link->num_adr)
@@ -601,6 +600,7 @@ static int snd_acp63_probe(struct pci_dev *pci,
dev_err(&pci->dev, "ACP platform devices creation failed\n");
goto de_init;
}
+ adata->machines = snd_soc_acpi_amd_acp63_sdw_machines;
ret = acp63_machine_register(&pci->dev);
if (ret) {
dev_err(&pci->dev, "ACP machine register failed\n");
diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c
index 3b4b9c6b3171..b602cca92b8b 100644
--- a/sound/soc/amd/ps/ps-sdw-dma.c
+++ b/sound/soc/amd/ps/ps-sdw-dma.c
@@ -445,6 +445,8 @@ static const struct snd_soc_component_driver acp63_sdw_component = {
.trigger = acp63_sdw_dma_trigger,
.pointer = acp63_sdw_dma_pointer,
.pcm_construct = acp63_sdw_dma_new,
+ .use_dai_pcm_id = true,
+
};
static int acp63_sdw_platform_probe(struct platform_device *pdev)
diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c
index 7878e061ecb9..2ca904db82ab 100644
--- a/sound/soc/amd/vangogh/acp5x-mach.c
+++ b/sound/soc/amd/vangogh/acp5x-mach.c
@@ -276,8 +276,6 @@ static struct snd_soc_dai_link acp5x_8821_35l41_dai[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &acp5x_8821_ops,
.init = acp5x_8821_init,
SND_SOC_DAILINK_REG(acp5x_i2s, nau8821, platform),
@@ -288,7 +286,6 @@ static struct snd_soc_dai_link acp5x_8821_35l41_dai[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
.playback_only = 1,
.ops = &acp5x_cs35l41_play_ops,
SND_SOC_DAILINK_REG(acp5x_bt, cs35l41, platform),
@@ -375,8 +372,6 @@ static struct snd_soc_dai_link acp5x_8821_98388_dai[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &acp5x_8821_ops,
.init = acp5x_8821_init,
SND_SOC_DAILINK_REG(acp5x_i2s, nau8821, platform),
@@ -387,7 +382,6 @@ static struct snd_soc_dai_link acp5x_8821_98388_dai[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
.playback_only = 1,
.ops = &acp5x_max98388_play_ops,
SND_SOC_DAILINK_REG(acp5x_bt, max98388, platform),
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index 06349bf0b658..2436e8deb2be 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -231,6 +231,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21M4"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21M5"),
}
},
@@ -329,6 +336,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "E1404FA"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "E1504FA"),
}
},
@@ -342,6 +356,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
{
.driver_data = &acp6x_card,
.matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "M3502RA"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."),
DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 B7ED"),
}
@@ -384,6 +405,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
{
.driver_data = &acp6x_card,
.matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "TIMI"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Xiaomi Book Pro 14 2022"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Razer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Blade 14 (2022) - RZ09-0427"),
}
@@ -448,6 +476,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
+ DMI_MATCH(DMI_BOARD_NAME, "8A7F"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
DMI_MATCH(DMI_BOARD_NAME, "8B27"),
}
},
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index 3763454436c1..89098f41679c 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -821,8 +821,9 @@ static int atmel_ssc_resume(struct snd_soc_component *component)
return 0;
}
+/* S24_LE is not supported if more than 2 channels (of TDM slots) are used. */
#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
- SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+ SNDRV_PCM_FMTBIT_S32_LE)
static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
.startup = atmel_ssc_startup,
@@ -836,6 +837,7 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
static struct snd_soc_dai_driver atmel_ssc_dai = {
.playback = {
+ .stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
@@ -843,6 +845,7 @@ static struct snd_soc_dai_driver atmel_ssc_dai = {
.rate_max = 384000,
.formats = ATMEL_SSC_FORMATS,},
.capture = {
+ .stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c
index 939cd44ebc8a..06dc3c48e7e8 100644
--- a/sound/soc/atmel/mchp-pdmc.c
+++ b/sound/soc/atmel/mchp-pdmc.c
@@ -302,6 +302,9 @@ static int mchp_pdmc_chmap_ctl_put(struct snd_kcontrol *kcontrol,
if (!substream)
return -ENODEV;
+ if (!substream->runtime)
+ return 0; /* just for avoiding error from alsactl restore */
+
map = mchp_pdmc_chmap_get(substream, info);
if (!map)
return -EINVAL;
diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c
index b2507a1491b7..fb820609c043 100644
--- a/sound/soc/atmel/mchp-spdifrx.c
+++ b/sound/soc/atmel/mchp-spdifrx.c
@@ -1014,7 +1014,7 @@ static const struct snd_soc_dai_ops mchp_spdifrx_dai_ops = {
static struct snd_soc_dai_driver mchp_spdifrx_dai = {
.name = "mchp-spdifrx",
.capture = {
- .stream_name = "S/PDIF Capture",
+ .stream_name = "Capture",
.channels_min = SPDIFRX_CHANNELS,
.channels_max = SPDIFRX_CHANNELS,
.rates = MCHP_SPDIF_RATES,
diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c
index 4c60ea652896..245c0352c141 100644
--- a/sound/soc/atmel/mchp-spdiftx.c
+++ b/sound/soc/atmel/mchp-spdiftx.c
@@ -707,7 +707,7 @@ static const struct snd_soc_dai_ops mchp_spdiftx_dai_ops = {
static struct snd_soc_dai_driver mchp_spdiftx_dai = {
.name = "mchp-spdiftx",
.playback = {
- .stream_name = "S/PDIF Playback",
+ .stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
.rates = MCHP_SPDIFTX_RATES,
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index ea01d6490cec..3392693faeb9 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -311,7 +311,7 @@ static int au1xpsc_pcm_new(struct snd_soc_component *component,
}
/* au1xpsc audio platform */
-static struct snd_soc_component_driver au1xpsc_soc_component = {
+static const struct snd_soc_component_driver au1xpsc_soc_component = {
.name = DRV_NAME,
.open = au1xpsc_pcm_open,
.close = au1xpsc_pcm_close,
diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c
index d2fdebd8881b..c9c2b1e71d55 100644
--- a/sound/soc/au1x/dma.c
+++ b/sound/soc/au1x/dma.c
@@ -289,7 +289,7 @@ static int alchemy_pcm_new(struct snd_soc_component *component,
return 0;
}
-static struct snd_soc_component_driver alchemy_pcm_soc_component = {
+static const struct snd_soc_component_driver alchemy_pcm_soc_component = {
.name = DRV_NAME,
.open = alchemy_pcm_open,
.close = alchemy_pcm_close,
diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c
index 9bda6499e66e..87d2f06c2f53 100644
--- a/sound/soc/bcm/bcm2835-i2s.c
+++ b/sound/soc/bcm/bcm2835-i2s.c
@@ -817,7 +817,7 @@ static const struct regmap_config bcm2835_regmap_config = {
.max_register = BCM2835_I2S_GRAY_REG,
.precious_reg = bcm2835_i2s_precious_reg,
.volatile_reg = bcm2835_i2s_volatile_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static const struct snd_soc_component_driver bcm2835_i2s_component = {
diff --git a/sound/soc/bcm/bcm63xx-pcm-whistler.c b/sound/soc/bcm/bcm63xx-pcm-whistler.c
index 018f2372e892..e3a4fcc63a56 100644
--- a/sound/soc/bcm/bcm63xx-pcm-whistler.c
+++ b/sound/soc/bcm/bcm63xx-pcm-whistler.c
@@ -256,12 +256,16 @@ static irqreturn_t i2s_dma_isr(int irq, void *bcm_i2s_priv)
offlevel = (int_status & I2S_RX_DESC_OFF_LEVEL_MASK) >>
I2S_RX_DESC_OFF_LEVEL_SHIFT;
+ bool val_read = false;
while (offlevel) {
regmap_read(regmap_i2s, I2S_RX_DESC_OFF_ADDR, &val_1);
regmap_read(regmap_i2s, I2S_RX_DESC_OFF_LEN, &val_2);
+ val_read = true;
offlevel--;
}
- prtd->dma_addr_next = val_1 + val_2;
+ if (val_read)
+ prtd->dma_addr_next = val_1 + val_2;
+
ifflevel = (int_status & I2S_RX_DESC_IFF_LEVEL_MASK) >>
I2S_RX_DESC_IFF_LEVEL_SHIFT;
diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c
index 2d1e241d8367..4cb2fe10bcdc 100644
--- a/sound/soc/bcm/cygnus-pcm.c
+++ b/sound/soc/bcm/cygnus-pcm.c
@@ -707,7 +707,7 @@ static int cygnus_dma_new(struct snd_soc_component *component,
return 0;
}
-static struct snd_soc_component_driver cygnus_soc_platform = {
+static const struct snd_soc_component_driver cygnus_soc_platform = {
.open = cygnus_pcm_open,
.close = cygnus_pcm_close,
.prepare = cygnus_pcm_prepare,
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 7092842480ef..0f2df7c91e18 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -57,6 +57,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_AW8738
imply SND_SOC_AW87390
imply SND_SOC_AW88395
+ imply SND_SOC_AW88081
imply SND_SOC_AW88261
imply SND_SOC_AW88399
imply SND_SOC_BT_SCO
@@ -85,6 +86,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_CS42L52
imply SND_SOC_CS42L56
imply SND_SOC_CS42L73
+ imply SND_SOC_CS42L84
imply SND_SOC_CS4234
imply SND_SOC_CS4265
imply SND_SOC_CS4270
@@ -112,6 +114,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_DA9055
imply SND_SOC_DMIC
imply SND_SOC_ES8316
+ imply SND_SOC_ES8323
imply SND_SOC_ES8326
imply SND_SOC_ES8328_SPI
imply SND_SOC_ES8328_I2C
@@ -222,6 +225,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_RT712_SDCA_DMIC_SDW
imply SND_SOC_RT715_SDW
imply SND_SOC_RT715_SDCA_SDW
+ imply SND_SOC_RT721_SDCA_SDW
imply SND_SOC_RT722_SDCA_SDW
imply SND_SOC_RT1308_SDW
imply SND_SOC_RT1316_SDW
@@ -236,6 +240,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_SIMPLE_AMPLIFIER
imply SND_SOC_SIMPLE_MUX
imply SND_SOC_SMA1303
+ imply SND_SOC_SMA1307
imply SND_SOC_SPDIF
imply SND_SOC_SRC4XXX_I2C
imply SND_SOC_SSM2305
@@ -281,6 +286,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_TWL4030
imply SND_SOC_TWL6040
imply SND_SOC_UDA1334
+ imply SND_SOC_UDA1342
imply SND_SOC_UDA1380
imply SND_SOC_WCD9335
imply SND_SOC_WCD934X
@@ -461,7 +467,7 @@ config SND_SOC_ADAU1372_SPI
select REGMAP_SPI
config SND_SOC_ADAU1373
- tristate
+ tristate "Analog Devices ADAU1373 CODEC"
depends on I2C
select SND_SOC_ADAU_UTILS
@@ -685,6 +691,17 @@ config SND_SOC_AW88261
boost converter can be adjusted smartly according to
the input amplitude.
+config SND_SOC_AW88081
+ tristate "Soc Audio for awinic aw88081"
+ depends on I2C
+ select REGMAP_I2C
+ select SND_SOC_AW88395_LIB
+ help
+ This option enables support for aw88081 Smart PA.
+ The awinic AW88081 is an I2S/TDM input, high efficiency
+ digital Smart K audio amplifier. Due to its 9uV noise
+ floor and ultra-low distortion, clean listening is guaranteed.
+
config SND_SOC_AW87390
tristate "Soc Audio for awinic aw87390"
depends on I2C
@@ -926,6 +943,12 @@ config SND_SOC_CS42L83
select REGMAP_I2C
select SND_SOC_CS42L42_CORE
+config SND_SOC_CS42L84
+ tristate "Cirrus Logic CS42L84 CODEC"
+ depends on I2C
+ select REGMAP
+ select REGMAP_I2C
+
config SND_SOC_CS4234
tristate "Cirrus Logic CS4234 CODEC"
depends on I2C
@@ -1143,6 +1166,10 @@ config SND_SOC_ES8316
tristate "Everest Semi ES8316 CODEC"
depends on I2C
+config SND_SOC_ES8323
+ tristate "Everest Semi ES8323 CODEC"
+ depends on I2C
+
config SND_SOC_ES8326
tristate "Everest Semi ES8326 CODEC"
depends on I2C
@@ -1545,6 +1572,11 @@ config SND_SOC_RL6231
default m if SND_SOC_RT1305=m
default m if SND_SOC_RT1308=m
+config SND_SOC_RT_SDW_COMMON
+ tristate
+ default y if SND_SOC_RT721_SDCA_SDW=y
+ default m if SND_SOC_RT721_SDCA_SDW=m
+
config SND_SOC_RL6347A
tristate
default y if SND_SOC_RT274=y
@@ -1743,6 +1775,12 @@ config SND_SOC_RT712_SDCA_DMIC_SDW
select REGMAP_SOUNDWIRE
select REGMAP_SOUNDWIRE_MBQ
+config SND_SOC_RT721_SDCA_SDW
+ tristate "Realtek RT721 SDCA Codec - SDW"
+ depends on SOUNDWIRE
+ select REGMAP_SOUNDWIRE
+ select REGMAP_SOUNDWIRE_MBQ
+
config SND_SOC_RT722_SDCA_SDW
tristate "Realtek RT722 SDCA Codec - SDW"
depends on SOUNDWIRE
@@ -1836,6 +1874,15 @@ config SND_SOC_SMA1303
help
Enable support for Iron Device SMA1303 Boosted Class-D amplifier
+config SND_SOC_SMA1307
+ tristate "Iron Device SMA1307 Audio Amplifier"
+ depends on I2C
+ help
+ Enable support for Iron Device SMA1307 boosted digital speaker
+ amplifier with feedback-loop.
+ If you are using a system with an SMA1307 amplifier connected
+ via I2C, enable this option.
+
config SND_SOC_SPDIF
tristate "S/PDIF CODEC"
@@ -2114,6 +2161,13 @@ config SND_SOC_UDA1334
and has basic features such as de-emphasis (at 44.1 kHz sampling
rate) and mute.
+config SND_SOC_UDA1342
+ tristate "NXP UDA1342 CODEC"
+ depends on I2C
+ help
+ The UDA1342 is an NXP audio codec, support 2x Stereo audio ADC (4x PGA
+ mic inputs), stereo audio DAC, with basic audio processing.
+
config SND_SOC_UDA1380
tristate
depends on I2C
@@ -2565,6 +2619,19 @@ config SND_SOC_NAU8825
tristate
depends on I2C
+config SND_SOC_NTPFW
+ tristate
+
+config SND_SOC_NTP8918
+ select SND_SOC_NTPFW
+ tristate "NeoFidelity NTP8918 amplifier"
+ depends on I2C
+
+config SND_SOC_NTP8835
+ select SND_SOC_NTPFW
+ tristate "NeoFidelity NTP8835 and NTP8835C amplifiers"
+ depends on I2C
+
config SND_SOC_TPA6130A2
tristate "Texas Instruments TPA6130A2 headphone amplifier"
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 54cbc3feae32..f37e82ddb7a1 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -49,6 +49,7 @@ snd-soc-arizona-y := arizona.o arizona-jack.o
snd-soc-audio-iio-aux-y := audio-iio-aux.o
snd-soc-aw8738-y := aw8738.o
snd-soc-aw87390-y := aw87390.o
+snd-soc-aw88081-y := aw88081.o
snd-soc-aw88395-lib-y := aw88395/aw88395_lib.o
snd-soc-aw88395-y := aw88395/aw88395.o \
aw88395/aw88395_device.o
@@ -91,6 +92,7 @@ snd-soc-cs42l52-y := cs42l52.o
snd-soc-cs42l56-y := cs42l56.o
snd-soc-cs42l73-y := cs42l73.o
snd-soc-cs42l83-i2c-y := cs42l83-i2c.o
+snd-soc-cs42l84-objs := cs42l84.o
snd-soc-cs4234-y := cs4234.o
snd-soc-cs4265-y := cs4265.o
snd-soc-cs4270-y := cs4270.o
@@ -125,6 +127,7 @@ snd-soc-es7241-y := es7241.o
snd-soc-es83xx-dsm-common-y := es83xx-dsm-common.o
snd-soc-es8311-y := es8311.o
snd-soc-es8316-y := es8316.o
+snd-soc-es8323-y := es8323.o
snd-soc-es8326-y := es8326.o
snd-soc-es8328-y := es8328.o
snd-soc-es8328-i2c-y := es8328-i2c.o
@@ -189,6 +192,9 @@ snd-soc-nau8821-y := nau8821.o
snd-soc-nau8822-y := nau8822.o
snd-soc-nau8824-y := nau8824.o
snd-soc-nau8825-y := nau8825.o
+snd-soc-ntp8835-y := ntp8835.o
+snd-soc-ntp8918-y := ntp8918.o
+snd-soc-ntpfw-y := ntpfw.o
snd-soc-hdmi-codec-y := hdmi-codec.o
snd-soc-pcm1681-y := pcm1681.o
snd-soc-pcm1789-codec-y := pcm1789.o
@@ -216,6 +222,7 @@ snd-soc-rk3308-y := rk3308_codec.o
snd-soc-rk3328-y := rk3328_codec.o
snd-soc-rk817-y := rk817_codec.o
snd-soc-rl6231-y := rl6231.o
+snd-soc-rt-sdw-common-y := rt-sdw-common.o
snd-soc-rl6347a-y := rl6347a.o
snd-soc-rt1011-y := rt1011.o
snd-soc-rt1015-y := rt1015.o
@@ -259,6 +266,7 @@ snd-soc-rt712-sdca-y := rt712-sdca.o rt712-sdca-sdw.o
snd-soc-rt712-sdca-dmic-y := rt712-sdca-dmic.o
snd-soc-rt715-y := rt715.o rt715-sdw.o
snd-soc-rt715-sdca-y := rt715-sdca.o rt715-sdca-sdw.o
+snd-soc-rt721-sdca-y := rt721-sdca.o rt721-sdca-sdw.o
snd-soc-rt722-sdca-y := rt722-sdca.o rt722-sdca-sdw.o
snd-soc-rt9120-y := rt9120.o
snd-soc-rtq9128-y := rtq9128.o
@@ -271,6 +279,7 @@ snd-soc-sigmadsp-i2c-y := sigmadsp-i2c.o
snd-soc-sigmadsp-regmap-y := sigmadsp-regmap.o
snd-soc-si476x-y := si476x.o
snd-soc-sma1303-y := sma1303.o
+snd-soc-sma1307-y := sma1307.o
snd-soc-spdif-tx-y := spdif_transmitter.o
snd-soc-spdif-rx-y := spdif_receiver.o
snd-soc-src4xxx-y := src4xxx.o
@@ -319,6 +328,7 @@ snd-soc-ts3a227e-y := ts3a227e.o
snd-soc-twl4030-y := twl4030.o
snd-soc-twl6040-y := twl6040.o
snd-soc-uda1334-y := uda1334.o
+snd-soc-uda1342-y := uda1342.o
snd-soc-uda1380-y := uda1380.o
snd-soc-wcd-classh-y := wcd-clsh-v2.o
snd-soc-wcd-mbhc-y := wcd-mbhc-v2.o
@@ -457,6 +467,7 @@ obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o
obj-$(CONFIG_SND_SOC_AUDIO_IIO_AUX) += snd-soc-audio-iio-aux.o
obj-$(CONFIG_SND_SOC_AW8738) += snd-soc-aw8738.o
obj-$(CONFIG_SND_SOC_AW87390) += snd-soc-aw87390.o
+obj-$(CONFIG_SND_SOC_AW88081) += snd-soc-aw88081.o
obj-$(CONFIG_SND_SOC_AW88395_LIB) += snd-soc-aw88395-lib.o
obj-$(CONFIG_SND_SOC_AW88395) +=snd-soc-aw88395.o
obj-$(CONFIG_SND_SOC_AW88261) +=snd-soc-aw88261.o
@@ -498,6 +509,7 @@ obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
obj-$(CONFIG_SND_SOC_CS42L56) += snd-soc-cs42l56.o
obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o
obj-$(CONFIG_SND_SOC_CS42L83) += snd-soc-cs42l83-i2c.o
+obj-$(CONFIG_SND_SOC_CS42L84) += snd-soc-cs42l84.o
obj-$(CONFIG_SND_SOC_CS4234) += snd-soc-cs4234.o
obj-$(CONFIG_SND_SOC_CS4265) += snd-soc-cs4265.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
@@ -532,6 +544,7 @@ obj-$(CONFIG_SND_SOC_ES7241) += snd-soc-es7241.o
obj-$(CONFIG_SND_SOC_ES83XX_DSM_COMMON) += snd-soc-es83xx-dsm-common.o
obj-$(CONFIG_SND_SOC_ES8311) += snd-soc-es8311.o
obj-$(CONFIG_SND_SOC_ES8316) += snd-soc-es8316.o
+obj-$(CONFIG_SND_SOC_ES8323) += snd-soc-es8323.o
obj-$(CONFIG_SND_SOC_ES8326) += snd-soc-es8326.o
obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
@@ -591,6 +604,9 @@ obj-$(CONFIG_SND_SOC_NAU8821) += snd-soc-nau8821.o
obj-$(CONFIG_SND_SOC_NAU8822) += snd-soc-nau8822.o
obj-$(CONFIG_SND_SOC_NAU8824) += snd-soc-nau8824.o
obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o
+obj-$(CONFIG_SND_SOC_NTP8835) += snd-soc-ntp8835.o
+obj-$(CONFIG_SND_SOC_NTP8918) += snd-soc-ntp8918.o
+obj-$(CONFIG_SND_SOC_NTPFW) += snd-soc-ntpfw.o
obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o
obj-$(CONFIG_SND_SOC_PCM179X) += snd-soc-pcm179x-codec.o
@@ -618,6 +634,7 @@ obj-$(CONFIG_SND_SOC_RK3308) += snd-soc-rk3308.o
obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o
obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
+obj-$(CONFIG_SND_SOC_RT_SDW_COMMON) += snd-soc-rt-sdw-common.o
obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o
obj-$(CONFIG_SND_SOC_RT1011) += snd-soc-rt1011.o
obj-$(CONFIG_SND_SOC_RT1015) += snd-soc-rt1015.o
@@ -662,6 +679,7 @@ obj-$(CONFIG_SND_SOC_RT712_SDCA_SDW) += snd-soc-rt712-sdca.o
obj-$(CONFIG_SND_SOC_RT712_SDCA_DMIC_SDW) += snd-soc-rt712-sdca-dmic.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_RT721_SDCA_SDW) += snd-soc-rt721-sdca.o
obj-$(CONFIG_SND_SOC_RT722_SDCA_SDW) += snd-soc-rt722-sdca.o
obj-$(CONFIG_SND_SOC_RT9120) += snd-soc-rt9120.o
obj-$(CONFIG_SND_SOC_RTQ9128) += snd-soc-rtq9128.o
@@ -672,6 +690,7 @@ obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o
obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP) += snd-soc-sigmadsp-regmap.o
obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o
obj-$(CONFIG_SND_SOC_SMA1303) += snd-soc-sma1303.o
+obj-$(CONFIG_SND_SOC_SMA1307) += snd-soc-sma1307.o
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
obj-$(CONFIG_SND_SOC_SRC4XXX) += snd-soc-src4xxx.o
obj-$(CONFIG_SND_SOC_SRC4XXX_I2C) += snd-soc-src4xxx-i2c.o
@@ -723,6 +742,7 @@ obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o
obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
obj-$(CONFIG_SND_SOC_UDA1334) += snd-soc-uda1334.o
+obj-$(CONFIG_SND_SOC_UDA1342) += snd-soc-uda1342.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
obj-$(CONFIG_SND_SOC_WCD_CLASSH) += snd-soc-wcd-classh.o
obj-$(CONFIG_SND_SOC_WCD_MBHC) += snd-soc-wcd-mbhc.o
diff --git a/sound/soc/codecs/adau1372-i2c.c b/sound/soc/codecs/adau1372-i2c.c
index 2869325f9ace..73f83be38f74 100644
--- a/sound/soc/codecs/adau1372-i2c.c
+++ b/sound/soc/codecs/adau1372-i2c.c
@@ -29,6 +29,7 @@ MODULE_DEVICE_TABLE(i2c, adau1372_i2c_ids);
static struct i2c_driver adau1372_i2c_driver = {
.driver = {
.name = "adau1372",
+ .of_match_table = adau1372_of_match,
},
.probe = adau1372_i2c_probe,
.id_table = adau1372_i2c_ids,
diff --git a/sound/soc/codecs/adau1372-spi.c b/sound/soc/codecs/adau1372-spi.c
index 51298e00fbd6..656bd1fabeb3 100644
--- a/sound/soc/codecs/adau1372-spi.c
+++ b/sound/soc/codecs/adau1372-spi.c
@@ -47,6 +47,7 @@ MODULE_DEVICE_TABLE(spi, adau1372_spi_id);
static struct spi_driver adau1372_spi_driver = {
.driver = {
.name = "adau1372",
+ .of_match_table = adau1372_of_match,
},
.probe = adau1372_spi_probe,
.id_table = adau1372_spi_id,
diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
index 98380a7ce64d..fdee689cae53 100644
--- a/sound/soc/codecs/adau1372.c
+++ b/sound/soc/codecs/adau1372.c
@@ -11,6 +11,7 @@
#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <linux/pm.h>
#include <linux/slab.h>
@@ -1060,6 +1061,13 @@ const struct regmap_config adau1372_regmap_config = {
};
EXPORT_SYMBOL_GPL(adau1372_regmap_config);
+const struct of_device_id adau1372_of_match[] = {
+ { .compatible = "adi,adau1372" },
+ { }
+};
+EXPORT_SYMBOL_GPL(adau1372_of_match);
+MODULE_DEVICE_TABLE(of, adau1372_of_match);
+
MODULE_DESCRIPTION("ASoC ADAU1372 CODEC driver");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/adau1372.h b/sound/soc/codecs/adau1372.h
index a9d2c59b73a9..c55b1c24fe39 100644
--- a/sound/soc/codecs/adau1372.h
+++ b/sound/soc/codecs/adau1372.h
@@ -13,6 +13,7 @@
struct device;
+extern const struct of_device_id adau1372_of_match[];
int adau1372_probe(struct device *dev, struct regmap *regmap,
void (*switch_mode)(struct device *dev));
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index a910e252aa12..16b9b2658341 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -8,8 +8,10 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <linux/pm.h>
+#include <linux/property.h>
#include <linux/i2c.h>
#include <linux/slab.h>
@@ -18,7 +20,6 @@
#include <sound/pcm_params.h>
#include <sound/tlv.h>
#include <sound/soc.h>
-#include <sound/adau1373.h>
#include "adau1373.h"
#include "adau-utils.h"
@@ -30,9 +31,28 @@ struct adau1373_dai {
bool clock_provider;
};
+enum adau1373_micbias_voltage {
+ ADAU1373_MICBIAS_2_9V,
+ ADAU1373_MICBIAS_2_2V,
+ ADAU1373_MICBIAS_2_6V,
+ ADAU1373_MICBIAS_1_8V,
+};
+
+#define ADAU1373_DRC_SIZE 13
+
struct adau1373 {
struct regmap *regmap;
struct adau1373_dai dais[3];
+
+ bool input_differential[4];
+ bool lineout_differential;
+ bool lineout_ground_sense;
+
+ unsigned int num_drc;
+ u8 drc_setting[3][ADAU1373_DRC_SIZE];
+
+ enum adau1373_micbias_voltage micbias1;
+ enum adau1373_micbias_voltage micbias2;
};
#define ADAU1373_INPUT_MODE 0x00
@@ -1332,66 +1352,61 @@ static void adau1373_load_drc_settings(struct adau1373 *adau1373,
regmap_write(adau1373->regmap, ADAU1373_DRC(nr) + i, drc[i]);
}
-static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias)
+static int adau1373_get_micbias(unsigned int val,
+ enum adau1373_micbias_voltage *micbias)
{
- switch (micbias) {
- case ADAU1373_MICBIAS_2_9V:
- case ADAU1373_MICBIAS_2_2V:
- case ADAU1373_MICBIAS_2_6V:
- case ADAU1373_MICBIAS_1_8V:
- return true;
+ switch (val) {
+ case 2900000:
+ *micbias = ADAU1373_MICBIAS_2_9V;
+ return 0;
+ case 2200000:
+ *micbias = ADAU1373_MICBIAS_2_2V;
+ return 0;
+ case 2600000:
+ *micbias = ADAU1373_MICBIAS_2_6V;
+ return 0;
+ case 1800000:
+ *micbias = ADAU1373_MICBIAS_1_8V;
+ return 0;
default:
- break;
+ return -EINVAL;
}
- return false;
}
static int adau1373_probe(struct snd_soc_component *component)
{
struct adau1373 *adau1373 = snd_soc_component_get_drvdata(component);
- struct adau1373_platform_data *pdata = component->dev->platform_data;
- bool lineout_differential = false;
unsigned int val;
int i;
- if (pdata) {
- if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting))
- return -EINVAL;
-
- if (!adau1373_valid_micbias(pdata->micbias1) ||
- !adau1373_valid_micbias(pdata->micbias2))
- return -EINVAL;
-
- for (i = 0; i < pdata->num_drc; ++i) {
- adau1373_load_drc_settings(adau1373, i,
- pdata->drc_setting[i]);
- }
+ for (i = 0; i < adau1373->num_drc; ++i) {
+ adau1373_load_drc_settings(adau1373, i,
+ adau1373->drc_setting[i]);
+ }
- snd_soc_add_component_controls(component, adau1373_drc_controls,
- pdata->num_drc);
+ snd_soc_add_component_controls(component, adau1373_drc_controls,
+ adau1373->num_drc);
- val = 0;
- for (i = 0; i < 4; ++i) {
- if (pdata->input_differential[i])
- val |= BIT(i);
- }
- regmap_write(adau1373->regmap, ADAU1373_INPUT_MODE, val);
+ val = 0;
+ for (i = 0; i < ARRAY_SIZE(adau1373->input_differential); ++i) {
+ if (adau1373->input_differential[i])
+ val |= BIT(i);
+ }
+ regmap_write(adau1373->regmap, ADAU1373_INPUT_MODE, val);
- val = 0;
- if (pdata->lineout_differential)
- val |= ADAU1373_OUTPUT_CTRL_LDIFF;
- if (pdata->lineout_ground_sense)
- val |= ADAU1373_OUTPUT_CTRL_LNFBEN;
- regmap_write(adau1373->regmap, ADAU1373_OUTPUT_CTRL, val);
+ val = 0;
+ if (adau1373->lineout_differential)
+ val |= ADAU1373_OUTPUT_CTRL_LDIFF;
+ if (adau1373->lineout_ground_sense)
+ val |= ADAU1373_OUTPUT_CTRL_LNFBEN;
- lineout_differential = pdata->lineout_differential;
+ regmap_write(adau1373->regmap, ADAU1373_OUTPUT_CTRL, val);
- regmap_write(adau1373->regmap, ADAU1373_EP_CTRL,
- (pdata->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) |
- (pdata->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET));
- }
+ regmap_write(adau1373->regmap, ADAU1373_EP_CTRL,
+ (adau1373->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) |
+ (adau1373->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET));
- if (!lineout_differential) {
+ if (!adau1373->lineout_differential) {
snd_soc_add_component_controls(component, adau1373_lineout2_controls,
ARRAY_SIZE(adau1373_lineout2_controls));
}
@@ -1471,9 +1486,74 @@ static const struct snd_soc_component_driver adau1373_component_driver = {
.endianness = 1,
};
+static void adau1373_reset(void *reset_gpio)
+{
+ gpiod_set_value_cansleep(reset_gpio, 1);
+}
+
+static int adau1373_parse_fw(struct device *dev, struct adau1373 *adau1373)
+{
+ int ret, drc_count;
+ unsigned int val;
+
+ if (device_property_present(dev, "adi,input1-differential"))
+ adau1373->input_differential[0] = true;
+ if (device_property_present(dev, "adi,input2-differential"))
+ adau1373->input_differential[1] = true;
+ if (device_property_present(dev, "adi,input3-differential"))
+ adau1373->input_differential[2] = true;
+ if (device_property_present(dev, "adi,input4-differential"))
+ adau1373->input_differential[3] = true;
+
+ if (device_property_present(dev, "adi,lineout-differential"))
+ adau1373->lineout_differential = true;
+ if (device_property_present(dev, "adi,lineout-gnd-sense"))
+ adau1373->lineout_ground_sense = true;
+
+ ret = device_property_read_u32(dev, "adi,micbias1-microvolt", &val);
+ if (!ret) {
+ ret = adau1373_get_micbias(val, &adau1373->micbias1);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to get micbias1(%u)\n", val);
+ }
+
+ ret = device_property_read_u32(dev, "adi,micbias2-microvolt", &val);
+ if (!ret) {
+ ret = adau1373_get_micbias(val, &adau1373->micbias2);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to get micbias2(%u)\n", val);
+ }
+
+ drc_count = device_property_count_u8(dev, "adi,drc-settings");
+ if (drc_count < 0)
+ return 0;
+ if (drc_count % ADAU1373_DRC_SIZE != 0)
+ return dev_err_probe(dev, -EINVAL,
+ "DRC count(%u) not multiple of %u\n",
+ drc_count, ADAU1373_DRC_SIZE);
+
+ adau1373->num_drc = drc_count / ADAU1373_DRC_SIZE;
+ if (adau1373->num_drc > ARRAY_SIZE(adau1373->drc_setting))
+ return dev_err_probe(dev, -EINVAL,
+ "Too many DRC settings(%u)\n",
+ adau1373->num_drc);
+
+ ret = device_property_read_u8_array(dev, "adi,drc-settings",
+ (u8 *)&adau1373->drc_setting[0],
+ drc_count);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to read DRC settings\n");
+
+ return 0;
+}
+
static int adau1373_i2c_probe(struct i2c_client *client)
{
struct adau1373 *adau1373;
+ struct gpio_desc *gpiod;
int ret;
adau1373 = devm_kzalloc(&client->dev, sizeof(*adau1373), GFP_KERNEL);
@@ -1485,10 +1565,33 @@ static int adau1373_i2c_probe(struct i2c_client *client)
if (IS_ERR(adau1373->regmap))
return PTR_ERR(adau1373->regmap);
- regmap_write(adau1373->regmap, ADAU1373_SOFT_RESET, 0x00);
+ /*
+ * If the powerdown GPIO is specified, we use it for reset. Otherwise
+ * a software reset is done.
+ */
+ gpiod = devm_gpiod_get_optional(&client->dev, "powerdown",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(gpiod))
+ return PTR_ERR(gpiod);
+
+ if (gpiod) {
+ gpiod_set_value_cansleep(gpiod, 0);
+ fsleep(10);
+
+ ret = devm_add_action_or_reset(&client->dev, adau1373_reset,
+ gpiod);
+ if (ret)
+ return ret;
+ } else {
+ regmap_write(adau1373->regmap, ADAU1373_SOFT_RESET, 0x00);
+ }
dev_set_drvdata(&client->dev, adau1373);
+ ret = adau1373_parse_fw(&client->dev, adau1373);
+ if (ret)
+ return ret;
+
ret = devm_snd_soc_register_component(&client->dev,
&adau1373_component_driver,
adau1373_dai_driver, ARRAY_SIZE(adau1373_dai_driver));
@@ -1501,9 +1604,16 @@ static const struct i2c_device_id adau1373_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, adau1373_i2c_id);
+static const struct of_device_id adau1373_of_match[] = {
+ { .compatible = "adi,adau1373", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, adau1373_of_match);
+
static struct i2c_driver adau1373_i2c_driver = {
.driver = {
.name = "adau1373",
+ .of_match_table = adau1373_of_match,
},
.probe = adau1373_i2c_probe,
.id_table = adau1373_i2c_id,
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 8bd6067df7f7..291249e0a2a3 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -21,7 +21,7 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include "sigmadsp.h"
#include "adau1701.h"
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c
index f2932713b4de..4dcc984761e0 100644
--- a/sound/soc/codecs/adau17x1.c
+++ b/sound/soc/codecs/adau17x1.c
@@ -19,7 +19,7 @@
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/regmap.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include "sigmadsp.h"
#include "adau17x1.h"
diff --git a/sound/soc/codecs/aw88081.c b/sound/soc/codecs/aw88081.c
new file mode 100644
index 000000000000..58b8e002d76f
--- /dev/null
+++ b/sound/soc/codecs/aw88081.c
@@ -0,0 +1,1087 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// aw88081.c -- AW88081 ALSA SoC Audio driver
+//
+// Copyright (c) 2024 awinic Technology CO., LTD
+//
+// Author: Weidong Wang <wangweidong.a@awinic.com>
+//
+
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include "aw88081.h"
+#include "aw88395/aw88395_device.h"
+
+struct aw88081 {
+ struct aw_device *aw_pa;
+ struct mutex lock;
+ struct delayed_work start_work;
+ struct regmap *regmap;
+ struct aw_container *aw_cfg;
+
+ bool phase_sync;
+};
+
+static const struct regmap_config aw88081_regmap_config = {
+ .val_bits = 16,
+ .reg_bits = 8,
+ .max_register = AW88081_REG_MAX,
+ .reg_format_endian = REGMAP_ENDIAN_LITTLE,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+};
+
+static int aw88081_dev_get_iis_status(struct aw_device *aw_dev)
+{
+ unsigned int reg_val;
+ int ret;
+
+ ret = regmap_read(aw_dev->regmap, AW88081_SYSST_REG, &reg_val);
+ if (ret)
+ return ret;
+ if ((reg_val & AW88081_BIT_PLL_CHECK) != AW88081_BIT_PLL_CHECK) {
+ dev_err(aw_dev->dev, "check pll lock fail,reg_val:0x%04x", reg_val);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int aw88081_dev_check_mode1_pll(struct aw_device *aw_dev)
+{
+ int ret, i;
+
+ for (i = 0; i < AW88081_DEV_SYSST_CHECK_MAX; i++) {
+ ret = aw88081_dev_get_iis_status(aw_dev);
+ if (ret) {
+ dev_err(aw_dev->dev, "mode1 iis signal check error");
+ usleep_range(AW88081_2000_US, AW88081_2000_US + 10);
+ } else {
+ return 0;
+ }
+ }
+
+ return -EPERM;
+}
+
+static int aw88081_dev_check_mode2_pll(struct aw_device *aw_dev)
+{
+ unsigned int reg_val;
+ int ret, i;
+
+ ret = regmap_read(aw_dev->regmap, AW88081_PLLCTRL1_REG, &reg_val);
+ if (ret)
+ return ret;
+
+ reg_val &= (~AW88081_CCO_MUX_MASK);
+ if (reg_val == AW88081_CCO_MUX_DIVIDED_VALUE) {
+ dev_dbg(aw_dev->dev, "CCO_MUX is already divider");
+ return -EPERM;
+ }
+
+ /* change mode2 */
+ ret = regmap_update_bits(aw_dev->regmap, AW88081_PLLCTRL1_REG,
+ ~AW88081_CCO_MUX_MASK, AW88081_CCO_MUX_DIVIDED_VALUE);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < AW88081_DEV_SYSST_CHECK_MAX; i++) {
+ ret = aw88081_dev_get_iis_status(aw_dev);
+ if (ret) {
+ dev_err(aw_dev->dev, "mode2 iis check error");
+ usleep_range(AW88081_2000_US, AW88081_2000_US + 10);
+ } else {
+ break;
+ }
+ }
+
+ /* change mode1 */
+ ret = regmap_update_bits(aw_dev->regmap, AW88081_PLLCTRL1_REG,
+ ~AW88081_CCO_MUX_MASK, AW88081_CCO_MUX_BYPASS_VALUE);
+ if (ret == 0) {
+ usleep_range(AW88081_2000_US, AW88081_2000_US + 10);
+ for (i = 0; i < AW88081_DEV_SYSST_CHECK_MAX; i++) {
+ ret = aw88081_dev_check_mode1_pll(aw_dev);
+ if (ret) {
+ dev_err(aw_dev->dev, "mode2 switch to mode1, iis check error");
+ usleep_range(AW88081_2000_US, AW88081_2000_US + 10);
+ } else {
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int aw88081_dev_check_syspll(struct aw_device *aw_dev)
+{
+ int ret;
+
+ ret = aw88081_dev_check_mode1_pll(aw_dev);
+ if (ret) {
+ dev_dbg(aw_dev->dev, "mode1 check iis failed try switch to mode2 check");
+ ret = aw88081_dev_check_mode2_pll(aw_dev);
+ if (ret) {
+ dev_err(aw_dev->dev, "mode2 check iis failed");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int aw88081_dev_check_sysst(struct aw_device *aw_dev)
+{
+ unsigned int check_val;
+ unsigned int reg_val;
+ unsigned int value;
+ int ret, i;
+
+ ret = regmap_read(aw_dev->regmap, AW88081_PWMCTRL4_REG, &reg_val);
+ if (ret)
+ return ret;
+
+ if (reg_val & (~AW88081_NOISE_GATE_EN_MASK))
+ check_val = AW88081_NO_SWS_SYSST_CHECK;
+ else
+ check_val = AW88081_SWS_SYSST_CHECK;
+
+ for (i = 0; i < AW88081_DEV_SYSST_CHECK_MAX; i++) {
+ ret = regmap_read(aw_dev->regmap, AW88081_SYSST_REG, &reg_val);
+ if (ret)
+ return ret;
+
+ value = reg_val & (~AW88081_BIT_SYSST_CHECK_MASK) & check_val;
+ if (value != check_val) {
+ dev_err(aw_dev->dev, "check sysst fail, reg_val=0x%04x, check:0x%x",
+ reg_val, check_val);
+ usleep_range(AW88081_2000_US, AW88081_2000_US + 10);
+ } else {
+ return 0;
+ }
+ }
+
+ return -EPERM;
+}
+
+static void aw88081_dev_i2s_tx_enable(struct aw_device *aw_dev, bool flag)
+{
+ if (flag)
+ regmap_update_bits(aw_dev->regmap, AW88081_I2SCTRL3_REG,
+ ~AW88081_I2STXEN_MASK, AW88081_I2STXEN_ENABLE_VALUE);
+ else
+ regmap_update_bits(aw_dev->regmap, AW88081_I2SCTRL3_REG,
+ ~AW88081_I2STXEN_MASK, AW88081_I2STXEN_DISABLE_VALUE);
+}
+
+static void aw88081_dev_pwd(struct aw_device *aw_dev, bool pwd)
+{
+ if (pwd)
+ regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG,
+ ~AW88081_PWDN_MASK, AW88081_PWDN_POWER_DOWN_VALUE);
+ else
+ regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG,
+ ~AW88081_PWDN_MASK, AW88081_PWDN_WORKING_VALUE);
+}
+
+static void aw88081_dev_amppd(struct aw_device *aw_dev, bool amppd)
+{
+ if (amppd)
+ regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG,
+ ~AW88081_EN_PA_MASK, AW88081_EN_PA_POWER_DOWN_VALUE);
+ else
+ regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG,
+ ~AW88081_EN_PA_MASK, AW88081_EN_PA_WORKING_VALUE);
+}
+
+static void aw88081_dev_clear_int_status(struct aw_device *aw_dev)
+{
+ unsigned int int_status;
+
+ /* read int status and clear */
+ regmap_read(aw_dev->regmap, AW88081_SYSINT_REG, &int_status);
+ /* make sure int status is clear */
+ regmap_read(aw_dev->regmap, AW88081_SYSINT_REG, &int_status);
+
+ dev_dbg(aw_dev->dev, "read interrupt reg = 0x%04x", int_status);
+}
+
+static void aw88081_dev_set_volume(struct aw_device *aw_dev, unsigned int value)
+{
+ struct aw_volume_desc *vol_desc = &aw_dev->volume_desc;
+ unsigned int volume;
+
+ volume = min((value + vol_desc->init_volume), (unsigned int)AW88081_MUTE_VOL);
+
+ regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL2_REG, ~AW88081_VOL_MASK, volume);
+}
+
+static void aw88081_dev_fade_in(struct aw_device *aw_dev)
+{
+ struct aw_volume_desc *desc = &aw_dev->volume_desc;
+ int fade_in_vol = desc->ctl_volume;
+ int fade_step = aw_dev->fade_step;
+ int i;
+
+ if (fade_step == 0 || aw_dev->fade_in_time == 0) {
+ aw88081_dev_set_volume(aw_dev, fade_in_vol);
+ return;
+ }
+
+ for (i = AW88081_MUTE_VOL; i >= fade_in_vol; i -= fade_step) {
+ aw88081_dev_set_volume(aw_dev, i);
+ usleep_range(aw_dev->fade_in_time, aw_dev->fade_in_time + 10);
+ }
+
+ if (i != fade_in_vol)
+ aw88081_dev_set_volume(aw_dev, fade_in_vol);
+}
+
+static void aw88081_dev_fade_out(struct aw_device *aw_dev)
+{
+ struct aw_volume_desc *desc = &aw_dev->volume_desc;
+ int fade_step = aw_dev->fade_step;
+ int i;
+
+ if (fade_step == 0 || aw_dev->fade_out_time == 0) {
+ aw88081_dev_set_volume(aw_dev, AW88081_MUTE_VOL);
+ return;
+ }
+
+ for (i = desc->ctl_volume; i <= AW88081_MUTE_VOL; i += fade_step) {
+ aw88081_dev_set_volume(aw_dev, i);
+ usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10);
+ }
+
+ if (i != AW88081_MUTE_VOL)
+ aw88081_dev_set_volume(aw_dev, AW88081_MUTE_VOL);
+}
+
+static void aw88081_dev_mute(struct aw_device *aw_dev, bool is_mute)
+{
+ if (is_mute) {
+ aw88081_dev_fade_out(aw_dev);
+ regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG,
+ ~AW88081_HMUTE_MASK, AW88081_HMUTE_ENABLE_VALUE);
+ } else {
+ regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG,
+ ~AW88081_HMUTE_MASK, AW88081_HMUTE_DISABLE_VALUE);
+ aw88081_dev_fade_in(aw_dev);
+ }
+}
+
+static void aw88081_dev_uls_hmute(struct aw_device *aw_dev, bool uls_hmute)
+{
+ if (uls_hmute)
+ regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG,
+ ~AW88081_ULS_HMUTE_MASK,
+ AW88081_ULS_HMUTE_ENABLE_VALUE);
+ else
+ regmap_update_bits(aw_dev->regmap, AW88081_SYSCTRL_REG,
+ ~AW88081_ULS_HMUTE_MASK,
+ AW88081_ULS_HMUTE_DISABLE_VALUE);
+}
+
+static int aw88081_dev_reg_update(struct aw88081 *aw88081,
+ unsigned char *data, unsigned int len)
+{
+ struct aw_device *aw_dev = aw88081->aw_pa;
+ struct aw_volume_desc *vol_desc = &aw_dev->volume_desc;
+ unsigned int read_vol;
+ int data_len, i, ret;
+ int16_t *reg_data;
+ u16 reg_val;
+ u8 reg_addr;
+
+ if (!len || !data) {
+ dev_err(aw_dev->dev, "reg data is null or len is 0");
+ return -EINVAL;
+ }
+
+ reg_data = (int16_t *)data;
+ data_len = len >> 1;
+
+ if (data_len & 0x1) {
+ dev_err(aw_dev->dev, "data len:%d unsupported", data_len);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < data_len; i += 2) {
+ reg_addr = reg_data[i];
+ reg_val = reg_data[i + 1];
+
+ if (reg_addr == AW88081_SYSCTRL_REG) {
+ reg_val &= ~(~AW88081_EN_PA_MASK |
+ ~AW88081_PWDN_MASK |
+ ~AW88081_HMUTE_MASK |
+ ~AW88081_ULS_HMUTE_MASK);
+
+ reg_val |= AW88081_EN_PA_POWER_DOWN_VALUE |
+ AW88081_PWDN_POWER_DOWN_VALUE |
+ AW88081_HMUTE_ENABLE_VALUE |
+ AW88081_ULS_HMUTE_ENABLE_VALUE;
+ }
+
+ if (reg_addr == AW88081_SYSCTRL2_REG) {
+ read_vol = (reg_val & (~AW88081_VOL_MASK)) >>
+ AW88081_VOL_START_BIT;
+ aw_dev->volume_desc.init_volume = read_vol;
+ }
+
+ /* i2stxen */
+ if (reg_addr == AW88081_I2SCTRL3_REG) {
+ /* close tx */
+ reg_val &= AW88081_I2STXEN_MASK;
+ reg_val |= AW88081_I2STXEN_DISABLE_VALUE;
+ }
+
+ ret = regmap_write(aw_dev->regmap, reg_addr, reg_val);
+ if (ret)
+ return ret;
+ }
+
+ if (aw_dev->prof_cur != aw_dev->prof_index)
+ vol_desc->ctl_volume = 0;
+
+ /* keep min volume */
+ aw88081_dev_set_volume(aw_dev, vol_desc->mute_volume);
+
+ return 0;
+}
+
+static int aw88081_dev_get_prof_name(struct aw_device *aw_dev, int index, char **prof_name)
+{
+ struct aw_prof_info *prof_info = &aw_dev->prof_info;
+ struct aw_prof_desc *prof_desc;
+
+ if ((index >= aw_dev->prof_info.count) || (index < 0)) {
+ dev_err(aw_dev->dev, "index[%d] overflow count[%d]",
+ index, aw_dev->prof_info.count);
+ return -EINVAL;
+ }
+
+ prof_desc = &aw_dev->prof_info.prof_desc[index];
+
+ *prof_name = prof_info->prof_name_list[prof_desc->id];
+
+ return 0;
+}
+
+static int aw88081_dev_get_prof_data(struct aw_device *aw_dev, int index,
+ struct aw_prof_desc **prof_desc)
+{
+ if ((index >= aw_dev->prof_info.count) || (index < 0)) {
+ dev_err(aw_dev->dev, "%s: index[%d] overflow count[%d]\n",
+ __func__, index, aw_dev->prof_info.count);
+ return -EINVAL;
+ }
+
+ *prof_desc = &aw_dev->prof_info.prof_desc[index];
+
+ return 0;
+}
+
+static int aw88081_dev_fw_update(struct aw88081 *aw88081)
+{
+ struct aw_device *aw_dev = aw88081->aw_pa;
+ struct aw_prof_desc *prof_index_desc;
+ struct aw_sec_data_desc *sec_desc;
+ char *prof_name;
+ int ret;
+
+ ret = aw88081_dev_get_prof_name(aw_dev, aw_dev->prof_index, &prof_name);
+ if (ret) {
+ dev_err(aw_dev->dev, "get prof name failed");
+ return -EINVAL;
+ }
+
+ dev_dbg(aw_dev->dev, "start update %s", prof_name);
+
+ ret = aw88081_dev_get_prof_data(aw_dev, aw_dev->prof_index, &prof_index_desc);
+ if (ret)
+ return ret;
+
+ /* update reg */
+ sec_desc = prof_index_desc->sec_desc;
+ ret = aw88081_dev_reg_update(aw88081, sec_desc[AW88395_DATA_TYPE_REG].data,
+ sec_desc[AW88395_DATA_TYPE_REG].len);
+ if (ret) {
+ dev_err(aw_dev->dev, "update reg failed");
+ return ret;
+ }
+
+ aw_dev->prof_cur = aw_dev->prof_index;
+
+ return 0;
+}
+
+static int aw88081_dev_start(struct aw88081 *aw88081)
+{
+ struct aw_device *aw_dev = aw88081->aw_pa;
+ int ret;
+
+ if (aw_dev->status == AW88081_DEV_PW_ON) {
+ dev_dbg(aw_dev->dev, "already power on");
+ return 0;
+ }
+
+ /* power on */
+ aw88081_dev_pwd(aw_dev, false);
+ usleep_range(AW88081_2000_US, AW88081_2000_US + 10);
+
+ ret = aw88081_dev_check_syspll(aw_dev);
+ if (ret) {
+ dev_err(aw_dev->dev, "pll check failed cannot start");
+ goto pll_check_fail;
+ }
+
+ /* amppd on */
+ aw88081_dev_amppd(aw_dev, false);
+ usleep_range(AW88081_1000_US, AW88081_1000_US + 50);
+
+ /* check i2s status */
+ ret = aw88081_dev_check_sysst(aw_dev);
+ if (ret) {
+ dev_err(aw_dev->dev, "sysst check failed");
+ goto sysst_check_fail;
+ }
+
+ /* enable tx feedback */
+ aw88081_dev_i2s_tx_enable(aw_dev, true);
+
+ /* close uls mute */
+ aw88081_dev_uls_hmute(aw_dev, false);
+
+ /* close mute */
+ aw88081_dev_mute(aw_dev, false);
+
+ /* clear inturrupt */
+ aw88081_dev_clear_int_status(aw_dev);
+ aw_dev->status = AW88081_DEV_PW_ON;
+
+ return 0;
+
+sysst_check_fail:
+ aw88081_dev_i2s_tx_enable(aw_dev, false);
+ aw88081_dev_clear_int_status(aw_dev);
+ aw88081_dev_amppd(aw_dev, true);
+pll_check_fail:
+ aw88081_dev_pwd(aw_dev, true);
+ aw_dev->status = AW88081_DEV_PW_OFF;
+
+ return ret;
+}
+
+static int aw88081_dev_stop(struct aw_device *aw_dev)
+{
+ if (aw_dev->status == AW88081_DEV_PW_OFF) {
+ dev_dbg(aw_dev->dev, "already power off");
+ return 0;
+ }
+
+ aw_dev->status = AW88081_DEV_PW_OFF;
+
+ /* clear inturrupt */
+ aw88081_dev_clear_int_status(aw_dev);
+
+ aw88081_dev_uls_hmute(aw_dev, true);
+ /* set mute */
+ aw88081_dev_mute(aw_dev, true);
+
+ /* close tx feedback */
+ aw88081_dev_i2s_tx_enable(aw_dev, false);
+ usleep_range(AW88081_1000_US, AW88081_1000_US + 100);
+
+ /* enable amppd */
+ aw88081_dev_amppd(aw_dev, true);
+
+ /* set power down */
+ aw88081_dev_pwd(aw_dev, true);
+
+ return 0;
+}
+
+static int aw88081_reg_update(struct aw88081 *aw88081, bool force)
+{
+ struct aw_device *aw_dev = aw88081->aw_pa;
+ int ret;
+
+ if (force) {
+ ret = regmap_write(aw_dev->regmap,
+ AW88081_ID_REG, AW88081_SOFT_RESET_VALUE);
+ if (ret)
+ return ret;
+
+ ret = aw88081_dev_fw_update(aw88081);
+ if (ret)
+ return ret;
+ } else {
+ if (aw_dev->prof_cur != aw_dev->prof_index) {
+ ret = aw88081_dev_fw_update(aw88081);
+ if (ret)
+ return ret;
+ }
+ }
+
+ aw_dev->prof_cur = aw_dev->prof_index;
+
+ return 0;
+}
+
+static void aw88081_start_pa(struct aw88081 *aw88081)
+{
+ int ret, i;
+
+ for (i = 0; i < AW88081_START_RETRIES; i++) {
+ ret = aw88081_reg_update(aw88081, aw88081->phase_sync);
+ if (ret) {
+ dev_err(aw88081->aw_pa->dev, "fw update failed, cnt:%d\n", i);
+ continue;
+ }
+ ret = aw88081_dev_start(aw88081);
+ if (ret) {
+ dev_err(aw88081->aw_pa->dev, "aw88081 device start failed. retry = %d", i);
+ continue;
+ } else {
+ dev_dbg(aw88081->aw_pa->dev, "start success\n");
+ break;
+ }
+ }
+}
+
+static void aw88081_startup_work(struct work_struct *work)
+{
+ struct aw88081 *aw88081 =
+ container_of(work, struct aw88081, start_work.work);
+
+ mutex_lock(&aw88081->lock);
+ aw88081_start_pa(aw88081);
+ mutex_unlock(&aw88081->lock);
+}
+
+static void aw88081_start(struct aw88081 *aw88081, bool sync_start)
+{
+ if (aw88081->aw_pa->fw_status != AW88081_DEV_FW_OK)
+ return;
+
+ if (aw88081->aw_pa->status == AW88081_DEV_PW_ON)
+ return;
+
+ if (sync_start == AW88081_SYNC_START)
+ aw88081_start_pa(aw88081);
+ else
+ queue_delayed_work(system_wq,
+ &aw88081->start_work,
+ AW88081_START_WORK_DELAY_MS);
+}
+
+static struct snd_soc_dai_driver aw88081_dai[] = {
+ {
+ .name = "aw88081-aif",
+ .id = 1,
+ .playback = {
+ .stream_name = "Speaker_Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AW88081_RATES,
+ .formats = AW88081_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Speaker_Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AW88081_RATES,
+ .formats = AW88081_FORMATS,
+ },
+ },
+};
+
+static int aw88081_get_fade_in_time(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(component);
+ struct aw_device *aw_dev = aw88081->aw_pa;
+
+ ucontrol->value.integer.value[0] = aw_dev->fade_in_time;
+
+ return 0;
+}
+
+static int aw88081_set_fade_in_time(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(component);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct aw_device *aw_dev = aw88081->aw_pa;
+ int time;
+
+ time = ucontrol->value.integer.value[0];
+
+ if (time < mc->min || time > mc->max)
+ return -EINVAL;
+
+ if (time != aw_dev->fade_in_time) {
+ aw_dev->fade_in_time = time;
+ return 1;
+ }
+
+ return 0;
+}
+
+static int aw88081_get_fade_out_time(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(component);
+ struct aw_device *aw_dev = aw88081->aw_pa;
+
+ ucontrol->value.integer.value[0] = aw_dev->fade_out_time;
+
+ return 0;
+}
+
+static int aw88081_set_fade_out_time(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(component);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct aw_device *aw_dev = aw88081->aw_pa;
+ int time;
+
+ time = ucontrol->value.integer.value[0];
+ if (time < mc->min || time > mc->max)
+ return -EINVAL;
+
+ if (time != aw_dev->fade_out_time) {
+ aw_dev->fade_out_time = time;
+ return 1;
+ }
+
+ return 0;
+}
+
+static int aw88081_dev_set_profile_index(struct aw_device *aw_dev, int index)
+{
+ /* check the index whether is valid */
+ if ((index >= aw_dev->prof_info.count) || (index < 0))
+ return -EINVAL;
+ /* check the index whether change */
+ if (aw_dev->prof_index == index)
+ return -EPERM;
+
+ aw_dev->prof_index = index;
+
+ return 0;
+}
+
+static int aw88081_profile_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec);
+ char *prof_name;
+ int count, ret;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+
+ count = aw88081->aw_pa->prof_info.count;
+ if (count <= 0) {
+ uinfo->value.enumerated.items = 0;
+ return 0;
+ }
+
+ uinfo->value.enumerated.items = count;
+
+ if (uinfo->value.enumerated.item >= count)
+ uinfo->value.enumerated.item = count - 1;
+
+ count = uinfo->value.enumerated.item;
+
+ ret = aw88081_dev_get_prof_name(aw88081->aw_pa, count, &prof_name);
+ if (ret) {
+ strscpy(uinfo->value.enumerated.name, "null",
+ sizeof(uinfo->value.enumerated.name));
+ return 0;
+ }
+
+ strscpy(uinfo->value.enumerated.name, prof_name, sizeof(uinfo->value.enumerated.name));
+
+ return 0;
+}
+
+static int aw88081_profile_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = aw88081->aw_pa->prof_index;
+
+ return 0;
+}
+
+static int aw88081_profile_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec);
+ int ret;
+
+ /* pa stop or stopping just set profile */
+ mutex_lock(&aw88081->lock);
+ ret = aw88081_dev_set_profile_index(aw88081->aw_pa, ucontrol->value.integer.value[0]);
+ if (ret) {
+ dev_dbg(codec->dev, "profile index does not change");
+ mutex_unlock(&aw88081->lock);
+ return 0;
+ }
+
+ if (aw88081->aw_pa->status) {
+ aw88081_dev_stop(aw88081->aw_pa);
+ aw88081_start(aw88081, AW88081_SYNC_START);
+ }
+
+ mutex_unlock(&aw88081->lock);
+
+ return 1;
+}
+
+static int aw88081_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec);
+ struct aw_volume_desc *vol_desc = &aw88081->aw_pa->volume_desc;
+
+ ucontrol->value.integer.value[0] = vol_desc->ctl_volume;
+
+ return 0;
+}
+
+static int aw88081_volume_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec);
+ struct aw_volume_desc *vol_desc = &aw88081->aw_pa->volume_desc;
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int value;
+
+ value = ucontrol->value.integer.value[0];
+
+ if (value < mc->min || value > mc->max)
+ return -EINVAL;
+
+ if (vol_desc->ctl_volume != value) {
+ vol_desc->ctl_volume = value;
+ aw88081_dev_set_volume(aw88081->aw_pa, vol_desc->ctl_volume);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int aw88081_get_fade_step(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = aw88081->aw_pa->fade_step;
+
+ return 0;
+}
+
+static int aw88081_set_fade_step(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(codec);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int value;
+
+ value = ucontrol->value.integer.value[0];
+ if (value < mc->min || value > mc->max)
+ return -EINVAL;
+
+ if (aw88081->aw_pa->fade_step != value) {
+ aw88081->aw_pa->fade_step = value;
+ return 1;
+ }
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new aw88081_controls[] = {
+ SOC_SINGLE_EXT("PCM Playback Volume", AW88081_SYSCTRL2_REG,
+ 0, AW88081_MUTE_VOL, 0, aw88081_volume_get,
+ aw88081_volume_set),
+ SOC_SINGLE_EXT("Fade Step", 0, 0, AW88081_MUTE_VOL, 0,
+ aw88081_get_fade_step, aw88081_set_fade_step),
+ SOC_SINGLE_EXT("Volume Ramp Up Step", 0, 0, FADE_TIME_MAX, 0,
+ aw88081_get_fade_in_time, aw88081_set_fade_in_time),
+ SOC_SINGLE_EXT("Volume Ramp Down Step", 0, 0, FADE_TIME_MAX, 0,
+ aw88081_get_fade_out_time, aw88081_set_fade_out_time),
+ AW88081_PROFILE_EXT("Profile Set", aw88081_profile_info,
+ aw88081_profile_get, aw88081_profile_set),
+};
+
+static void aw88081_parse_channel_dt(struct aw88081 *aw88081)
+{
+ struct aw_device *aw_dev = aw88081->aw_pa;
+ struct device_node *np = aw_dev->dev->of_node;
+ u32 channel_value = AW88081_DEV_DEFAULT_CH;
+
+ of_property_read_u32(np, "awinic,audio-channel", &channel_value);
+ aw88081->phase_sync = of_property_read_bool(np, "awinic,sync-flag");
+
+ aw_dev->channel = channel_value;
+}
+
+static int aw88081_init(struct aw88081 *aw88081, struct i2c_client *i2c, struct regmap *regmap)
+{
+ struct aw_device *aw_dev;
+ unsigned int chip_id;
+ int ret;
+
+ /* read chip id */
+ ret = regmap_read(regmap, AW88081_ID_REG, &chip_id);
+ if (ret) {
+ dev_err(&i2c->dev, "%s read chipid error. ret = %d", __func__, ret);
+ return ret;
+ }
+ if (chip_id != AW88081_CHIP_ID) {
+ dev_err(&i2c->dev, "unsupported device");
+ return -ENXIO;
+ }
+
+ dev_dbg(&i2c->dev, "chip id = %x\n", chip_id);
+
+ aw_dev = devm_kzalloc(&i2c->dev, sizeof(*aw_dev), GFP_KERNEL);
+ if (!aw_dev)
+ return -ENOMEM;
+
+ aw88081->aw_pa = aw_dev;
+ aw_dev->i2c = i2c;
+ aw_dev->regmap = regmap;
+ aw_dev->dev = &i2c->dev;
+ aw_dev->chip_id = AW88081_CHIP_ID;
+ aw_dev->acf = NULL;
+ aw_dev->prof_info.prof_desc = NULL;
+ aw_dev->prof_info.prof_type = AW88395_DEV_NONE_TYPE_ID;
+ aw_dev->fade_step = AW88081_VOLUME_STEP_DB;
+ aw_dev->volume_desc.mute_volume = AW88081_MUTE_VOL;
+ aw88081_parse_channel_dt(aw88081);
+
+ return 0;
+}
+
+static int aw88081_dev_init(struct aw88081 *aw88081, struct aw_container *aw_cfg)
+{
+ struct aw_device *aw_dev = aw88081->aw_pa;
+ int ret;
+
+ ret = aw88395_dev_cfg_load(aw_dev, aw_cfg);
+ if (ret) {
+ dev_err(aw_dev->dev, "aw_dev acf parse failed");
+ return -EINVAL;
+ }
+
+ ret = regmap_write(aw_dev->regmap, AW88081_ID_REG, AW88081_SOFT_RESET_VALUE);
+ if (ret)
+ return ret;
+
+ aw_dev->fade_in_time = AW88081_500_US;
+ aw_dev->fade_out_time = AW88081_500_US;
+ aw_dev->prof_cur = AW88081_INIT_PROFILE;
+ aw_dev->prof_index = AW88081_INIT_PROFILE;
+
+ ret = aw88081_dev_fw_update(aw88081);
+ if (ret) {
+ dev_err(aw_dev->dev, "fw update failed ret = %d\n", ret);
+ return ret;
+ }
+
+ aw88081_dev_clear_int_status(aw_dev);
+
+ aw88081_dev_uls_hmute(aw_dev, true);
+
+ aw88081_dev_mute(aw_dev, true);
+
+ usleep_range(AW88081_5000_US, AW88081_5000_US + 10);
+
+ aw88081_dev_i2s_tx_enable(aw_dev, false);
+
+ usleep_range(AW88081_1000_US, AW88081_1000_US + 100);
+
+ aw88081_dev_amppd(aw_dev, true);
+
+ aw88081_dev_pwd(aw_dev, true);
+
+ return 0;
+}
+
+static int aw88081_request_firmware_file(struct aw88081 *aw88081)
+{
+ const struct firmware *cont = NULL;
+ int ret;
+
+ aw88081->aw_pa->fw_status = AW88081_DEV_FW_FAILED;
+
+ ret = request_firmware(&cont, AW88081_ACF_FILE, aw88081->aw_pa->dev);
+ if (ret)
+ return ret;
+
+ dev_dbg(aw88081->aw_pa->dev, "loaded %s - size: %zu\n",
+ AW88081_ACF_FILE, cont ? cont->size : 0);
+
+ aw88081->aw_cfg = devm_kzalloc(aw88081->aw_pa->dev, cont->size + sizeof(int), GFP_KERNEL);
+ if (!aw88081->aw_cfg) {
+ release_firmware(cont);
+ return -ENOMEM;
+ }
+ aw88081->aw_cfg->len = (int)cont->size;
+ memcpy(aw88081->aw_cfg->data, cont->data, cont->size);
+ release_firmware(cont);
+
+ ret = aw88395_dev_load_acf_check(aw88081->aw_pa, aw88081->aw_cfg);
+ if (ret)
+ return ret;
+
+ mutex_lock(&aw88081->lock);
+ ret = aw88081_dev_init(aw88081, aw88081->aw_cfg);
+ mutex_unlock(&aw88081->lock);
+
+ return ret;
+}
+
+static int aw88081_playback_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(component);
+
+ mutex_lock(&aw88081->lock);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ aw88081_start(aw88081, AW88081_ASYNC_START);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ aw88081_dev_stop(aw88081->aw_pa);
+ break;
+ default:
+ break;
+ }
+ mutex_unlock(&aw88081->lock);
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget aw88081_dapm_widgets[] = {
+ /* playback */
+ SND_SOC_DAPM_AIF_IN_E("AIF_RX", "Speaker_Playback", 0, SND_SOC_NOPM, 0, 0,
+ aw88081_playback_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_OUTPUT("DAC Output"),
+
+ /* capture */
+ SND_SOC_DAPM_AIF_OUT("AIF_TX", "Speaker_Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_INPUT("ADC Input"),
+};
+
+static const struct snd_soc_dapm_route aw88081_audio_map[] = {
+ {"DAC Output", NULL, "AIF_RX"},
+ {"AIF_TX", NULL, "ADC Input"},
+};
+
+static int aw88081_codec_probe(struct snd_soc_component *component)
+{
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ INIT_DELAYED_WORK(&aw88081->start_work, aw88081_startup_work);
+
+ ret = aw88081_request_firmware_file(aw88081);
+ if (ret)
+ dev_err(aw88081->aw_pa->dev, "%s: request firmware failed\n", __func__);
+
+ return ret;
+}
+
+static void aw88081_codec_remove(struct snd_soc_component *aw_codec)
+{
+ struct aw88081 *aw88081 = snd_soc_component_get_drvdata(aw_codec);
+
+ cancel_delayed_work_sync(&aw88081->start_work);
+}
+
+static const struct snd_soc_component_driver soc_codec_dev_aw88081 = {
+ .probe = aw88081_codec_probe,
+ .remove = aw88081_codec_remove,
+ .dapm_widgets = aw88081_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(aw88081_dapm_widgets),
+ .dapm_routes = aw88081_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(aw88081_audio_map),
+ .controls = aw88081_controls,
+ .num_controls = ARRAY_SIZE(aw88081_controls),
+};
+
+static int aw88081_i2c_probe(struct i2c_client *i2c)
+{
+ struct aw88081 *aw88081;
+ int ret;
+
+ ret = i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C);
+ if (!ret)
+ return dev_err_probe(&i2c->dev, -ENXIO, "check_functionality failed");
+
+ aw88081 = devm_kzalloc(&i2c->dev, sizeof(*aw88081), GFP_KERNEL);
+ if (!aw88081)
+ return -ENOMEM;
+
+ mutex_init(&aw88081->lock);
+
+ i2c_set_clientdata(i2c, aw88081);
+
+ aw88081->regmap = devm_regmap_init_i2c(i2c, &aw88081_regmap_config);
+ if (IS_ERR(aw88081->regmap))
+ return dev_err_probe(&i2c->dev, PTR_ERR(aw88081->regmap),
+ "failed to init regmap\n");
+
+ /* aw pa init */
+ ret = aw88081_init(aw88081, i2c, aw88081->regmap);
+ if (ret)
+ return ret;
+
+ return devm_snd_soc_register_component(&i2c->dev,
+ &soc_codec_dev_aw88081,
+ aw88081_dai, ARRAY_SIZE(aw88081_dai));
+}
+
+static const struct i2c_device_id aw88081_i2c_id[] = {
+ { AW88081_I2C_NAME },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, aw88081_i2c_id);
+
+static struct i2c_driver aw88081_i2c_driver = {
+ .driver = {
+ .name = AW88081_I2C_NAME,
+ },
+ .probe = aw88081_i2c_probe,
+ .id_table = aw88081_i2c_id,
+};
+module_i2c_driver(aw88081_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC AW88081 Smart PA Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/aw88081.h b/sound/soc/codecs/aw88081.h
new file mode 100644
index 000000000000..b4bf7288021a
--- /dev/null
+++ b/sound/soc/codecs/aw88081.h
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// aw88081.h -- AW88081 ALSA SoC Audio driver
+//
+// Copyright (c) 2024 awinic Technology CO., LTD
+//
+// Author: Weidong Wang <wangweidong.a@awinic.com>
+//
+
+#ifndef __AW88081_H__
+#define __AW88081_H__
+
+#define AW88081_ID_REG (0x00)
+#define AW88081_SYSST_REG (0x01)
+#define AW88081_SYSINT_REG (0x02)
+#define AW88081_SYSINTM_REG (0x03)
+#define AW88081_SYSCTRL_REG (0x04)
+#define AW88081_SYSCTRL2_REG (0x05)
+#define AW88081_I2SCTRL1_REG (0x06)
+#define AW88081_I2SCTRL2_REG (0x07)
+#define AW88081_I2SCTRL3_REG (0x08)
+#define AW88081_DACCFG1_REG (0x09)
+#define AW88081_DACCFG2_REG (0x0A)
+#define AW88081_DACCFG3_REG (0x0B)
+#define AW88081_DACCFG4_REG (0x0C)
+#define AW88081_DACCFG5_REG (0x0D)
+#define AW88081_DACCFG6_REG (0x0E)
+#define AW88081_DACCFG7_REG (0x11)
+#define AW88081_PWMCTRL1_REG (0x13)
+#define AW88081_PWMCTRL2_REG (0x14)
+#define AW88081_PWMCTRL3_REG (0x15)
+#define AW88081_PWMCTRL4_REG (0x16)
+#define AW88081_I2SCFG1_REG (0x17)
+#define AW88081_DBGCTRL_REG (0x18)
+#define AW88081_PDMCTRL_REG (0x19)
+#define AW88081_DACST_REG (0x20)
+#define AW88081_PATTERNST_REG (0x21)
+#define AW88081_I2SINT_REG (0x26)
+#define AW88081_I2SCAPCNT_REG (0x27)
+#define AW88081_ANASTA1_REG (0x28)
+#define AW88081_ANASTA2_REG (0x29)
+#define AW88081_ANASTA3_REG (0x2A)
+#define AW88081_VBAT_REG (0x21)
+#define AW88081_TEMP_REG (0x22)
+#define AW88081_PVDD_REG (0x23)
+#define AW88081_ISNDAT_REG (0x24)
+#define AW88081_VSNDAT_REG (0x25)
+#define AW88081_DSMCFG1_REG (0x30)
+#define AW88081_DSMCFG2_REG (0x31)
+#define AW88081_DSMCFG3_REG (0x32)
+#define AW88081_DSMCFG4_REG (0x33)
+#define AW88081_DSMCFG5_REG (0x34)
+#define AW88081_DSMCFG6_REG (0x35)
+#define AW88081_DSMCFG7_REG (0x36)
+#define AW88081_DSMCFG8_REG (0x37)
+#define AW88081_TESTIN_REG (0x38)
+#define AW88081_TESTOUT_REG (0x39)
+#define AW88081_BOPCTRL1_REG (0x40)
+#define AW88081_BOPCTRL2_REG (0x41)
+#define AW88081_BOPCTRL3_REG (0x42)
+#define AW88081_BOPSTA_REG (0x43)
+#define AW88081_PLLCTRL1_REG (0x54)
+#define AW88081_PLLCTRL2_REG (0x55)
+#define AW88081_PLLCTRL3_REG (0x56)
+#define AW88081_CDACTRL1_REG (0x57)
+#define AW88081_CDACTRL2_REG (0x58)
+#define AW88081_CDACTRL3_REG (0x59)
+#define AW88081_DITHERCFG1_REG (0x5A)
+#define AW88081_DITHERCFG2_REG (0x5B)
+#define AW88081_DITHERCFG3_REG (0x5C)
+#define AW88081_TM_REG (0x6E)
+#define AW88081_TM2_REG (0x6F)
+#define AW88081_TESTCTRL1_REG (0x70)
+#define AW88081_TESTCTRL2_REG (0x71)
+
+#define AW88081_REG_MAX (0x72)
+
+#define AW88081_UVLS_START_BIT (14)
+#define AW88081_UVLS_UVLO (1)
+#define AW88081_UVLS_UVLO_VALUE \
+ (AW88081_UVLS_UVLO << AW88081_UVLS_START_BIT)
+
+#define AW88081_SWS_START_BIT (8)
+#define AW88081_SWS_SWITCHING (1)
+#define AW88081_SWS_SWITCHING_VALUE \
+ (AW88081_SWS_SWITCHING << AW88081_SWS_START_BIT)
+
+#define AW88081_NOCLKS_START_BIT (5)
+#define AW88081_NOCLKS_NO_CLOCK (1)
+#define AW88081_NOCLKS_NO_CLOCK_VALUE \
+ (AW88081_NOCLKS_NO_CLOCK << AW88081_NOCLKS_START_BIT)
+
+#define AW88081_CLKS_START_BIT (4)
+#define AW88081_CLKS_STABLE (1)
+#define AW88081_CLKS_STABLE_VALUE \
+ (AW88081_CLKS_STABLE << AW88081_CLKS_START_BIT)
+
+#define AW88081_OCDS_START_BIT (3)
+#define AW88081_OCDS_OC (1)
+#define AW88081_OCDS_OC_VALUE \
+ (AW88081_OCDS_OC << AW88081_OCDS_START_BIT)
+
+#define AW88081_OTHS_START_BIT (1)
+#define AW88081_OTHS_OT (1)
+#define AW88081_OTHS_OT_VALUE \
+ (AW88081_OTHS_OT << AW88081_OTHS_START_BIT)
+
+#define AW88081_PLLS_START_BIT (0)
+#define AW88081_PLLS_LOCKED (1)
+#define AW88081_PLLS_LOCKED_VALUE \
+ (AW88081_PLLS_LOCKED << AW88081_PLLS_START_BIT)
+
+#define AW88081_BIT_PLL_CHECK \
+ (AW88081_CLKS_STABLE_VALUE | \
+ AW88081_PLLS_LOCKED_VALUE)
+
+#define AW88081_BIT_SYSST_CHECK_MASK \
+ (~(AW88081_UVLS_UVLO_VALUE | \
+ AW88081_SWS_SWITCHING_VALUE | \
+ AW88081_NOCLKS_NO_CLOCK_VALUE | \
+ AW88081_CLKS_STABLE_VALUE | \
+ AW88081_OCDS_OC_VALUE | \
+ AW88081_OTHS_OT_VALUE | \
+ AW88081_PLLS_LOCKED_VALUE))
+
+#define AW88081_NO_SWS_SYSST_CHECK \
+ (AW88081_CLKS_STABLE_VALUE | \
+ AW88081_PLLS_LOCKED_VALUE)
+
+#define AW88081_SWS_SYSST_CHECK \
+ (AW88081_SWS_SWITCHING_VALUE | \
+ AW88081_CLKS_STABLE_VALUE | \
+ AW88081_PLLS_LOCKED_VALUE)
+
+#define AW88081_ULS_HMUTE_START_BIT (14)
+#define AW88081_ULS_HMUTE_BITS_LEN (1)
+#define AW88081_ULS_HMUTE_MASK \
+ (~(((1<<AW88081_ULS_HMUTE_BITS_LEN)-1) << AW88081_ULS_HMUTE_START_BIT))
+
+#define AW88081_ULS_HMUTE_DISABLE (0)
+#define AW88081_ULS_HMUTE_DISABLE_VALUE \
+ (AW88081_ULS_HMUTE_DISABLE << AW88081_ULS_HMUTE_START_BIT)
+
+#define AW88081_ULS_HMUTE_ENABLE (1)
+#define AW88081_ULS_HMUTE_ENABLE_VALUE \
+ (AW88081_ULS_HMUTE_ENABLE << AW88081_ULS_HMUTE_START_BIT)
+
+#define AW88081_HMUTE_START_BIT (8)
+#define AW88081_HMUTE_BITS_LEN (1)
+#define AW88081_HMUTE_MASK \
+ (~(((1<<AW88081_HMUTE_BITS_LEN)-1) << AW88081_HMUTE_START_BIT))
+
+#define AW88081_HMUTE_DISABLE (0)
+#define AW88081_HMUTE_DISABLE_VALUE \
+ (AW88081_HMUTE_DISABLE << AW88081_HMUTE_START_BIT)
+
+#define AW88081_HMUTE_ENABLE (1)
+#define AW88081_HMUTE_ENABLE_VALUE \
+ (AW88081_HMUTE_ENABLE << AW88081_HMUTE_START_BIT)
+
+#define AW88081_EN_PA_START_BIT (1)
+#define AW88081_EN_PA_BITS_LEN (1)
+#define AW88081_EN_PA_MASK \
+ (~(((1<<AW88081_EN_PA_BITS_LEN)-1) << AW88081_EN_PA_START_BIT))
+
+#define AW88081_EN_PA_WORKING (1)
+#define AW88081_EN_PA_WORKING_VALUE \
+ (AW88081_EN_PA_WORKING << AW88081_EN_PA_START_BIT)
+
+#define AW88081_EN_PA_POWER_DOWN (0)
+#define AW88081_EN_PA_POWER_DOWN_VALUE \
+ (AW88081_EN_PA_POWER_DOWN << AW88081_EN_PA_START_BIT)
+
+#define AW88081_PWDN_START_BIT (0)
+#define AW88081_PWDN_BITS_LEN (1)
+#define AW88081_PWDN_MASK \
+ (~(((1<<AW88081_PWDN_BITS_LEN)-1) << AW88081_PWDN_START_BIT))
+
+#define AW88081_PWDN_WORKING (0)
+#define AW88081_PWDN_WORKING_VALUE \
+ (AW88081_PWDN_WORKING << AW88081_PWDN_START_BIT)
+
+#define AW88081_PWDN_POWER_DOWN (1)
+#define AW88081_PWDN_POWER_DOWN_VALUE \
+ (AW88081_PWDN_POWER_DOWN << AW88081_PWDN_START_BIT)
+
+#define AW88081_VOL_START_BIT (0)
+#define AW88081_VOL_BITS_LEN (10)
+#define AW88081_VOL_MASK \
+ (~(((1<<AW88081_VOL_BITS_LEN)-1) << AW88081_VOL_START_BIT))
+
+#define AW88081_VOLUME_STEP_DB (64)
+#define AW88081_MUTE_VOL (1023)
+
+#define AW88081_I2STXEN_START_BIT (6)
+#define AW88081_I2STXEN_BITS_LEN (1)
+#define AW88081_I2STXEN_MASK \
+ (~(((1<<AW88081_I2STXEN_BITS_LEN)-1) << AW88081_I2STXEN_START_BIT))
+
+#define AW88081_I2STXEN_DISABLE (0)
+#define AW88081_I2STXEN_DISABLE_VALUE \
+ (AW88081_I2STXEN_DISABLE << AW88081_I2STXEN_START_BIT)
+
+#define AW88081_I2STXEN_ENABLE (1)
+#define AW88081_I2STXEN_ENABLE_VALUE \
+ (AW88081_I2STXEN_ENABLE << AW88081_I2STXEN_START_BIT)
+
+#define AW88081_NOISE_GATE_EN_START_BIT (13)
+#define AW88081_NOISE_GATE_EN_BITS_LEN (1)
+#define AW88081_NOISE_GATE_EN_MASK \
+ (~(((1<<AW88081_NOISE_GATE_EN_BITS_LEN)-1) << AW88081_NOISE_GATE_EN_START_BIT))
+
+#define AW88081_NOISE_GATE_EN_DISABLE (0)
+#define AW88081_NOISE_GATE_EN_DISABLE_VALUE \
+ (AW88081_NOISE_GATE_EN_DISABLE << AW88081_NOISE_GATE_EN_START_BIT)
+
+#define AW88081_NOISE_GATE_EN_ENABLE (1)
+#define AW88081_NOISE_GATE_EN_ENABLE_VALUE \
+ (AW88081_NOISE_GATE_EN_ENABLE << AW88081_NOISE_GATE_EN_START_BIT)
+
+#define AW88081_CCO_MUX_START_BIT (13)
+#define AW88081_CCO_MUX_BITS_LEN (1)
+#define AW88081_CCO_MUX_MASK \
+ (~(((1<<AW88081_CCO_MUX_BITS_LEN)-1) << AW88081_CCO_MUX_START_BIT))
+
+#define AW88081_CCO_MUX_DIVIDED (0)
+#define AW88081_CCO_MUX_DIVIDED_VALUE \
+ (AW88081_CCO_MUX_DIVIDED << AW88081_CCO_MUX_START_BIT)
+
+#define AW88081_CCO_MUX_BYPASS (1)
+#define AW88081_CCO_MUX_BYPASS_VALUE \
+ (AW88081_CCO_MUX_BYPASS << AW88081_CCO_MUX_START_BIT)
+
+#define AW88081_START_RETRIES (5)
+#define AW88081_START_WORK_DELAY_MS (0)
+
+#define AW88081_I2C_NAME "aw88081"
+#define AW88081_CHIP_ID 0x2116
+
+#define AW88081_RATES (SNDRV_PCM_RATE_8000_48000 | \
+ SNDRV_PCM_RATE_96000)
+#define AW88081_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+#define FADE_TIME_MAX 100000
+
+#define AW88081_DEV_DEFAULT_CH (0)
+#define AW88081_ACF_FILE "aw88081_acf.bin"
+#define AW88081_DEV_SYSST_CHECK_MAX (10)
+#define AW88081_SOFT_RESET_VALUE (0x55aa)
+
+#define AW88081_INIT_PROFILE (0)
+
+#define AW88081_PROFILE_EXT(xname, profile_info, profile_get, profile_set) \
+{ \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = xname, \
+ .info = profile_info, \
+ .get = profile_get, \
+ .put = profile_set, \
+}
+
+enum {
+ AW88081_SYNC_START = 0,
+ AW88081_ASYNC_START,
+};
+
+enum {
+ AW88081_500_US = 500,
+ AW88081_1000_US = 1000,
+ AW88081_2000_US = 2000,
+ AW88081_5000_US = 5000,
+};
+
+enum {
+ AW88081_DEV_PW_OFF = 0,
+ AW88081_DEV_PW_ON,
+};
+
+enum {
+ AW88081_DEV_FW_FAILED = 0,
+ AW88081_DEV_FW_OK,
+};
+
+#endif
diff --git a/sound/soc/codecs/aw88395/aw88395_device.c b/sound/soc/codecs/aw88395/aw88395_device.c
index fd1f67d5f22f..6b333d1c6e94 100644
--- a/sound/soc/codecs/aw88395/aw88395_device.c
+++ b/sound/soc/codecs/aw88395/aw88395_device.c
@@ -703,7 +703,7 @@ static int aw_dev_set_vcalb(struct aw_device *aw_dev)
AW88395_VSCAL_FACTOR_DAC, icalk, vcalk);
break;
default:
- dev_err(aw_dev->dev, "unsupport vsense status");
+ dev_err(aw_dev->dev, "unsupported vsense status");
return -EINVAL;
}
diff --git a/sound/soc/codecs/aw88395/aw88395_lib.c b/sound/soc/codecs/aw88395/aw88395_lib.c
index 769ca32a5c8e..ceb7fc43d018 100644
--- a/sound/soc/codecs/aw88395/aw88395_lib.c
+++ b/sound/soc/codecs/aw88395/aw88395_lib.c
@@ -688,7 +688,7 @@ static int aw_dev_load_cfg_by_hdr(struct aw_device *aw_dev,
ret = aw_dev_cfg_get_reg_valid_prof(aw_dev, all_prof_info);
break;
default:
- dev_err(aw_dev->dev, "unsupport data type\n");
+ dev_err(aw_dev->dev, "unsupported data type\n");
ret = -EINVAL;
break;
}
diff --git a/sound/soc/codecs/aw88399.c b/sound/soc/codecs/aw88399.c
index 8dc2b8aa6832..ee3cc2a95f85 100644
--- a/sound/soc/codecs/aw88399.c
+++ b/sound/soc/codecs/aw88399.c
@@ -462,7 +462,7 @@ static int aw_dev_set_vcalb(struct aw88399 *aw88399)
vcal_k * aw88399->vcalb_init_val;
break;
default:
- dev_err(aw_dev->dev, "%s: unsupport vsense\n", __func__);
+ dev_err(aw_dev->dev, "%s: unsupported vsense\n", __func__);
ret = -EINVAL;
break;
}
@@ -656,7 +656,7 @@ static int aw_dev_get_dsp_status(struct aw_device *aw_dev)
if (ret)
return ret;
if (!(reg_val & (~AW88399_WDT_CNT_MASK)))
- ret = -EPERM;
+ return -EPERM;
return 0;
}
diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c
index 4f9dabd9d78a..04304a7ad915 100644
--- a/sound/soc/codecs/cpcap.c
+++ b/sound/soc/codecs/cpcap.c
@@ -1649,7 +1649,7 @@ static int cpcap_soc_probe(struct snd_soc_component *component)
return cpcap_audio_reset(component, false);
}
-static struct snd_soc_component_driver soc_codec_dev_cpcap = {
+static const struct snd_soc_component_driver soc_codec_dev_cpcap = {
.probe = cpcap_soc_probe,
.controls = cpcap_snd_controls,
.num_controls = ARRAY_SIZE(cpcap_snd_controls),
diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c
index e1cebb9e4dc6..405dab137b3b 100644
--- a/sound/soc/codecs/cs35l45-tables.c
+++ b/sound/soc/codecs/cs35l45-tables.c
@@ -315,7 +315,7 @@ static const struct {
{ 0x3B, 24576000 },
};
-unsigned int cs35l45_get_clk_freq_id(unsigned int freq)
+int cs35l45_get_clk_freq_id(unsigned int freq)
{
int i;
diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h
index e2ebcf58d7e0..7a790d2acac7 100644
--- a/sound/soc/codecs/cs35l45.h
+++ b/sound/soc/codecs/cs35l45.h
@@ -507,7 +507,7 @@ extern const struct dev_pm_ops cs35l45_pm_ops;
extern const struct regmap_config cs35l45_i2c_regmap;
extern const struct regmap_config cs35l45_spi_regmap;
int cs35l45_apply_patch(struct cs35l45_private *cs35l45);
-unsigned int cs35l45_get_clk_freq_id(unsigned int freq);
+int cs35l45_get_clk_freq_id(unsigned int freq);
int cs35l45_probe(struct cs35l45_private *cs35l45);
void cs35l45_remove(struct cs35l45_private *cs35l45);
diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c
index d0098b4558b5..3ede0e3110f3 100644
--- a/sound/soc/codecs/cs42l43.c
+++ b/sound/soc/codecs/cs42l43.c
@@ -2402,49 +2402,7 @@ static int cs42l43_codec_runtime_resume(struct device *dev)
return 0;
}
-static int cs42l43_codec_suspend(struct device *dev)
-{
- struct cs42l43_codec *priv = dev_get_drvdata(dev);
- struct cs42l43 *cs42l43 = priv->core;
-
- disable_irq(cs42l43->irq);
-
- return 0;
-}
-
-static int cs42l43_codec_suspend_noirq(struct device *dev)
-{
- struct cs42l43_codec *priv = dev_get_drvdata(dev);
- struct cs42l43 *cs42l43 = priv->core;
-
- enable_irq(cs42l43->irq);
-
- return 0;
-}
-
-static int cs42l43_codec_resume(struct device *dev)
-{
- struct cs42l43_codec *priv = dev_get_drvdata(dev);
- struct cs42l43 *cs42l43 = priv->core;
-
- enable_irq(cs42l43->irq);
-
- return 0;
-}
-
-static int cs42l43_codec_resume_noirq(struct device *dev)
-{
- struct cs42l43_codec *priv = dev_get_drvdata(dev);
- struct cs42l43 *cs42l43 = priv->core;
-
- disable_irq(cs42l43->irq);
-
- return 0;
-}
-
static const struct dev_pm_ops cs42l43_codec_pm_ops = {
- SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend, cs42l43_codec_resume)
- NOIRQ_SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend_noirq, cs42l43_codec_resume_noirq)
RUNTIME_PM_OPS(NULL, cs42l43_codec_runtime_resume, NULL)
};
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index e4827b8c2bde..6e51954bdb1e 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -747,8 +747,10 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap)
cs42l51->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_LOW);
- if (IS_ERR(cs42l51->reset_gpio))
- return PTR_ERR(cs42l51->reset_gpio);
+ if (IS_ERR(cs42l51->reset_gpio)) {
+ ret = PTR_ERR(cs42l51->reset_gpio);
+ goto error;
+ }
if (cs42l51->reset_gpio) {
dev_dbg(dev, "Release reset gpio\n");
@@ -780,6 +782,7 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap)
return 0;
error:
+ gpiod_set_value_cansleep(cs42l51->reset_gpio, 1);
regulator_bulk_disable(ARRAY_SIZE(cs42l51->supplies),
cs42l51->supplies);
return ret;
diff --git a/sound/soc/codecs/cs42l84.c b/sound/soc/codecs/cs42l84.c
new file mode 100644
index 000000000000..17d5c96e334d
--- /dev/null
+++ b/sound/soc/codecs/cs42l84.c
@@ -0,0 +1,1111 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * cs42l84.c -- CS42L84 ALSA SoC audio driver
+ *
+ * Copyright (C) The Asahi Linux Contributors
+ *
+ * Based on sound/soc/codecs/cs42l42{.c,.h}
+ * Copyright 2016 Cirrus Logic, Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_device.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "cs42l84.h"
+#include "cirrus_legacy.h"
+
+struct cs42l84_private {
+ struct regmap *regmap;
+ struct device *dev;
+ struct gpio_desc *reset_gpio;
+ struct snd_soc_jack *jack;
+ struct mutex irq_lock;
+ u8 tip_state;
+ u8 ring_state;
+ int pll_config;
+ int bclk;
+ u8 pll_mclk_f;
+ u32 srate;
+ u8 stream_use;
+ int hs_type;
+};
+
+static bool cs42l84_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS42L84_DEVID ... CS42L84_DEVID+5:
+ case CS42L84_TSRS_PLUG_INT_STATUS:
+ case CS42L84_PLL_LOCK_STATUS:
+ case CS42L84_TSRS_PLUG_STATUS:
+ case CS42L84_HS_DET_STATUS2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config cs42l84_regmap = {
+ .reg_bits = 16,
+ .val_bits = 8,
+
+ .volatile_reg = cs42l84_volatile_register,
+
+ .max_register = 0x73fe,
+
+ .cache_type = REGCACHE_MAPLE,
+
+ .use_single_read = true,
+ .use_single_write = true,
+};
+
+static int cs42l84_put_dac_vol(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *val)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kctl);
+ struct soc_mixer_control *mc = (struct soc_mixer_control *) kctl->private_value;
+ int vola, volb;
+ int ret, ret2, updated = 0;
+
+ vola = val->value.integer.value[0] + mc->min;
+ volb = val->value.integer.value[1] + mc->min;
+
+ if (vola < mc->min || vola > mc->max || volb < mc->min || volb > mc->max)
+ return -EINVAL;
+
+ ret = snd_soc_component_update_bits(component, CS42L84_FRZ_CTL,
+ CS42L84_FRZ_CTL_ENGAGE,
+ CS42L84_FRZ_CTL_ENGAGE);
+ if (ret < 0)
+ goto bail;
+ updated |= ret;
+
+ ret = snd_soc_component_update_bits(component, CS42L84_DAC_CHA_VOL_LSB,
+ 0xff, vola & 0xff);
+ if (ret < 0)
+ goto bail;
+ updated |= ret;
+
+ ret = snd_soc_component_update_bits(component, CS42L84_DAC_CHA_VOL_MSB,
+ 0xff, (vola >> 8) & 0x01);
+ if (ret < 0)
+ goto bail;
+ updated |= ret;
+
+ ret = snd_soc_component_update_bits(component, CS42L84_DAC_CHB_VOL_LSB,
+ 0xff, volb & 0xff);
+ if (ret < 0)
+ goto bail;
+ updated |= ret;
+
+ ret = snd_soc_component_update_bits(component, CS42L84_DAC_CHB_VOL_MSB,
+ 0xff, (volb >> 8) & 0x01);
+ if (ret < 0)
+ goto bail;
+ ret |= updated;
+
+bail:
+ ret2 = snd_soc_component_update_bits(component, CS42L84_FRZ_CTL,
+ CS42L84_FRZ_CTL_ENGAGE, 0);
+ if (ret2 < 0 && ret >= 0)
+ ret = ret2;
+
+ return ret;
+}
+
+static int cs42l84_get_dac_vol(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *val)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kctl);
+ struct soc_mixer_control *mc = (struct soc_mixer_control *) kctl->private_value;
+ int vola, volb;
+ int ret;
+
+ ret = snd_soc_component_read(component, CS42L84_DAC_CHA_VOL_LSB);
+ if (ret < 0)
+ return ret;
+ vola = ret;
+
+ ret = snd_soc_component_read(component, CS42L84_DAC_CHA_VOL_MSB);
+ if (ret < 0)
+ return ret;
+ vola |= (ret & 1) << 8;
+
+ ret = snd_soc_component_read(component, CS42L84_DAC_CHB_VOL_LSB);
+ if (ret < 0)
+ return ret;
+ volb = ret;
+
+ ret = snd_soc_component_read(component, CS42L84_DAC_CHB_VOL_MSB);
+ if (ret < 0)
+ return ret;
+ volb |= (ret & 1) << 8;
+
+ if (vola & BIT(8))
+ vola |= ~((int)(BIT(8) - 1));
+ if (volb & BIT(8))
+ volb |= ~((int)(BIT(8) - 1));
+
+ val->value.integer.value[0] = vola - mc->min;
+ val->value.integer.value[1] = volb - mc->min;
+
+ return 0;
+}
+
+static const DECLARE_TLV_DB_SCALE(cs42l84_dac_tlv, -12800, 50, true);
+static const DECLARE_TLV_DB_SCALE(cs42l84_adc_tlv, -1200, 50, false);
+static const DECLARE_TLV_DB_SCALE(cs42l84_pre_tlv, 0, 1000, false);
+
+static const struct snd_kcontrol_new cs42l84_snd_controls[] = {
+ SOC_DOUBLE_R_S_EXT_TLV("DAC Playback Volume", CS42L84_DAC_CHA_VOL_LSB,
+ CS42L84_DAC_CHB_VOL_LSB, 0, -256, 24, 8, 0,
+ cs42l84_get_dac_vol, cs42l84_put_dac_vol, cs42l84_dac_tlv),
+ SOC_SINGLE_TLV("ADC Preamp Capture Volume", CS42L84_ADC_CTL1,
+ CS42L84_ADC_CTL1_PREAMP_GAIN_SHIFT, 2, 0, cs42l84_pre_tlv),
+ SOC_SINGLE_TLV("ADC PGA Capture Volume", CS42L84_ADC_CTL1,
+ CS42L84_ADC_CTL1_PGA_GAIN_SHIFT, 24, 0, cs42l84_adc_tlv),
+ SOC_SINGLE("ADC WNF Switch", CS42L84_ADC_CTL4,
+ CS42L84_ADC_CTL4_WNF_EN_SHIFT, 1, 0),
+ SOC_SINGLE("WNF Corner Frequency", CS42L84_ADC_CTL4,
+ CS42L84_ADC_CTL4_WNF_CF_SHIFT, 3, 0),
+ SOC_SINGLE("ADC HPF Switch", CS42L84_ADC_CTL4,
+ CS42L84_ADC_CTL4_HPF_EN_SHIFT, 1, 0),
+ SOC_SINGLE("HPF Corner Frequency", CS42L84_ADC_CTL4,
+ CS42L84_ADC_CTL4_HPF_CF_SHIFT, 3, 0),
+};
+
+static const char * const cs42l84_mux_text[] = {
+ "Blank", "ADC", "ASP RX CH1", "ASP RX CH2",
+};
+
+static const unsigned int cs42l84_mux_values[] = {
+ 0b0000, 0b0111, 0b1101, 0b1110,
+};
+
+static SOC_VALUE_ENUM_SINGLE_DECL(cs42l84_daca_mux_enum,
+ CS42L84_BUS_DAC_SRC, CS42L84_BUS_DAC_SRC_DACA_SHIFT,
+ 0b1111, cs42l84_mux_text, cs42l84_mux_values);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(cs42l84_dacb_mux_enum,
+ CS42L84_BUS_DAC_SRC, CS42L84_BUS_DAC_SRC_DACB_SHIFT,
+ 0b1111, cs42l84_mux_text, cs42l84_mux_values);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(cs42l84_sdout1_mux_enum,
+ CS42L84_BUS_ASP_TX_SRC, CS42L84_BUS_ASP_TX_SRC_CH1_SHIFT,
+ 0b1111, cs42l84_mux_text, cs42l84_mux_values);
+
+static const struct snd_kcontrol_new cs42l84_daca_mux_ctrl =
+ SOC_DAPM_ENUM("DACA Select", cs42l84_daca_mux_enum);
+
+static const struct snd_kcontrol_new cs42l84_dacb_mux_ctrl =
+ SOC_DAPM_ENUM("DACB Select", cs42l84_dacb_mux_enum);
+
+static const struct snd_kcontrol_new cs42l84_sdout1_mux_ctrl =
+ SOC_DAPM_ENUM("SDOUT1 Select", cs42l84_sdout1_mux_enum);
+
+static const struct snd_soc_dapm_widget cs42l84_dapm_widgets[] = {
+ /* Playback Path */
+ SND_SOC_DAPM_OUTPUT("HP"),
+ SND_SOC_DAPM_DAC("DAC", NULL, CS42L84_MSM_BLOCK_EN2, CS42L84_MSM_BLOCK_EN2_DAC_SHIFT, 0),
+ SND_SOC_DAPM_MUX("DACA Select", SND_SOC_NOPM, 0, 0, &cs42l84_daca_mux_ctrl),
+ SND_SOC_DAPM_MUX("DACB Select", SND_SOC_NOPM, 0, 0, &cs42l84_dacb_mux_ctrl),
+ SND_SOC_DAPM_AIF_IN("SDIN1", NULL, 0, CS42L84_ASP_RX_EN, CS42L84_ASP_RX_EN_CH1_SHIFT, 0),
+ SND_SOC_DAPM_AIF_IN("SDIN2", NULL, 1, CS42L84_ASP_RX_EN, CS42L84_ASP_RX_EN_CH2_SHIFT, 0),
+
+ /* Capture Path */
+ SND_SOC_DAPM_INPUT("HS"),
+ SND_SOC_DAPM_ADC("ADC", NULL, CS42L84_MSM_BLOCK_EN2, CS42L84_MSM_BLOCK_EN2_ADC_SHIFT, 0),
+ SND_SOC_DAPM_MUX("SDOUT1 Select", SND_SOC_NOPM, 0, 0, &cs42l84_sdout1_mux_ctrl),
+ SND_SOC_DAPM_AIF_OUT("SDOUT1", NULL, 0, CS42L84_ASP_TX_EN, CS42L84_ASP_TX_EN_CH1_SHIFT, 0),
+
+ /* Playback/Capture Requirements */
+ SND_SOC_DAPM_SUPPLY("BUS", CS42L84_MSM_BLOCK_EN2, CS42L84_MSM_BLOCK_EN2_BUS_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("ASP", CS42L84_MSM_BLOCK_EN2, CS42L84_MSM_BLOCK_EN2_ASP_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("BCLK", CS42L84_ASP_CTL, CS42L84_ASP_CTL_BCLK_EN_SHIFT, 0, NULL, 0),
+};
+
+static const struct snd_soc_dapm_route cs42l84_audio_map[] = {
+ /* Playback Path */
+ {"HP", NULL, "DAC"},
+ {"DAC", NULL, "DACA Select"},
+ {"DAC", NULL, "DACB Select"},
+ {"DACA Select", "ASP RX CH1", "SDIN1"},
+ {"DACA Select", "ASP RX CH2", "SDIN2"},
+ {"DACB Select", "ASP RX CH1", "SDIN1"},
+ {"DACB Select", "ASP RX CH2", "SDIN2"},
+ {"SDIN1", NULL, "Playback"},
+ {"SDIN2", NULL, "Playback"},
+
+ {"ADC", NULL, "HS"},
+ {"SDOUT1 Select", "ADC", "ADC"},
+ {"SDOUT1", NULL, "SDOUT1 Select"},
+ {"Capture", NULL, "SDOUT1"},
+
+ /* Playback Requirements */
+ {"DAC", NULL, "BUS"},
+ {"SDIN1", NULL, "ASP"},
+ {"SDIN2", NULL, "ASP"},
+ {"SDIN1", NULL, "BCLK"},
+ {"SDIN2", NULL, "BCLK"},
+
+ /* Capture Requirements */
+ {"SDOUT1", NULL, "BUS"},
+ {"SDOUT1", NULL, "ASP"},
+ {"SDOUT1", NULL, "BCLK"},
+};
+
+static int cs42l84_set_jack(struct snd_soc_component *component, struct snd_soc_jack *jk, void *d)
+{
+ struct cs42l84_private *cs42l84 = snd_soc_component_get_drvdata(component);
+
+ /* Prevent race with interrupt handler */
+ mutex_lock(&cs42l84->irq_lock);
+ cs42l84->jack = jk;
+ snd_soc_jack_report(jk, cs42l84->hs_type, SND_JACK_HEADSET);
+ mutex_unlock(&cs42l84->irq_lock);
+
+ return 0;
+}
+
+static int cs42l84_component_probe(struct snd_soc_component *component)
+{
+ snd_soc_component_update_bits(component, CS42L84_ASP_CTL,
+ CS42L84_ASP_CTL_TDM_MODE, 0);
+ snd_soc_component_update_bits(component, CS42L84_HP_VOL_CTL,
+ CS42L84_HP_VOL_CTL_SOFT | CS42L84_HP_VOL_CTL_ZERO_CROSS,
+ CS42L84_HP_VOL_CTL_ZERO_CROSS);
+
+ /* TDM settings */
+ snd_soc_component_update_bits(component, CS42L84_ASP_RX_CH1_CTL1,
+ CS42L84_ASP_RX_CHx_CTL1_EDGE |
+ CS42L84_ASP_RX_CHx_CTL1_SLOT_START_LSB, 0);
+ snd_soc_component_update_bits(component, CS42L84_ASP_RX_CH1_CTL2,
+ CS42L84_ASP_RX_CHx_CTL2_SLOT_START_MSB, 0);
+ snd_soc_component_update_bits(component, CS42L84_ASP_RX_CH2_CTL1,
+ CS42L84_ASP_RX_CHx_CTL1_EDGE |
+ CS42L84_ASP_RX_CHx_CTL1_SLOT_START_LSB,
+ CS42L84_ASP_RX_CHx_CTL1_EDGE);
+ snd_soc_component_update_bits(component, CS42L84_ASP_RX_CH2_CTL2,
+ CS42L84_ASP_RX_CHx_CTL2_SLOT_START_MSB, 0);
+ snd_soc_component_update_bits(component, CS42L84_ASP_TX_CH1_CTL1,
+ CS42L84_ASP_RX_CHx_CTL1_EDGE | \
+ CS42L84_ASP_RX_CHx_CTL1_SLOT_START_LSB, 0);
+ snd_soc_component_update_bits(component, CS42L84_ASP_TX_CH1_CTL2,
+ CS42L84_ASP_RX_CHx_CTL2_SLOT_START_MSB, 0);
+ snd_soc_component_update_bits(component, CS42L84_ASP_TX_CH2_CTL1,
+ CS42L84_ASP_RX_CHx_CTL1_EDGE | \
+ CS42L84_ASP_RX_CHx_CTL1_SLOT_START_LSB,
+ CS42L84_ASP_RX_CHx_CTL1_EDGE);
+ snd_soc_component_update_bits(component, CS42L84_ASP_TX_CH2_CTL2,
+ CS42L84_ASP_RX_CHx_CTL2_SLOT_START_MSB, 0);
+ /* Routing defaults */
+ snd_soc_component_write(component, CS42L84_BUS_DAC_SRC,
+ 0b1101 << CS42L84_BUS_DAC_SRC_DACA_SHIFT |
+ 0b1110 << CS42L84_BUS_DAC_SRC_DACB_SHIFT);
+ snd_soc_component_write(component, CS42L84_BUS_ASP_TX_SRC,
+ 0b0111 << CS42L84_BUS_ASP_TX_SRC_CH1_SHIFT);
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver soc_component_dev_cs42l84 = {
+ .set_jack = cs42l84_set_jack,
+ .probe = cs42l84_component_probe,
+ .controls = cs42l84_snd_controls,
+ .num_controls = ARRAY_SIZE(cs42l84_snd_controls),
+ .dapm_widgets = cs42l84_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(cs42l84_dapm_widgets),
+ .dapm_routes = cs42l84_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(cs42l84_audio_map),
+ .endianness = 1,
+};
+
+struct cs42l84_pll_params {
+ u32 bclk;
+ u8 mclk_src_sel;
+ u8 bclk_prediv;
+ u8 pll_div_int;
+ u32 pll_div_frac;
+ u8 pll_mode;
+ u8 pll_divout;
+ u32 mclk_int;
+};
+
+/*
+ * Common PLL Settings for given BCLK
+ */
+static const struct cs42l84_pll_params pll_ratio_table[] = {
+ { 3072000, 1, 0, 0x40, 0x000000, 0x03, 0x10, 12288000},
+ { 6144000, 1, 1, 0x40, 0x000000, 0x03, 0x10, 12288000},
+ { 12288000, 0, 0, 0, 0, 0, 0, 12288000},
+ { 24576000, 1, 3, 0x40, 0x000000, 0x03, 0x10, 12288000},
+};
+
+static int cs42l84_pll_config(struct snd_soc_component *component)
+{
+ struct cs42l84_private *cs42l84 = snd_soc_component_get_drvdata(component);
+ int i;
+ u32 clk;
+ u32 fsync;
+
+ clk = cs42l84->bclk;
+
+ /* Don't reconfigure if there is an audio stream running */
+ if (cs42l84->stream_use) {
+ if (pll_ratio_table[cs42l84->pll_config].bclk == clk)
+ return 0;
+ else
+ return -EBUSY;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) {
+ if (pll_ratio_table[i].bclk == clk) {
+ cs42l84->pll_config = i;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(pll_ratio_table))
+ return -EINVAL;
+
+ /* Set up the LRCLK */
+ fsync = clk / cs42l84->srate;
+ if (((fsync * cs42l84->srate) != clk)
+ || ((fsync % 2) != 0)) {
+ dev_err(component->dev,
+ "Unsupported bclk %d/sample rate %d\n",
+ clk, cs42l84->srate);
+ return -EINVAL;
+ }
+
+ /* Set the LRCLK period */
+ snd_soc_component_update_bits(component, CS42L84_ASP_FSYNC_CTL2,
+ CS42L84_ASP_FSYNC_CTL2_BCLK_PERIOD_LO,
+ FIELD_PREP(CS42L84_ASP_FSYNC_CTL2_BCLK_PERIOD_LO, fsync & 0x7f));
+ snd_soc_component_update_bits(component, CS42L84_ASP_FSYNC_CTL3,
+ CS42L84_ASP_FSYNC_CTL3_BCLK_PERIOD_HI,
+ FIELD_PREP(CS42L84_ASP_FSYNC_CTL3_BCLK_PERIOD_HI, fsync >> 7));
+
+ /* Save what the MCLK will be */
+ switch (pll_ratio_table[i].mclk_int) {
+ case 12000000:
+ cs42l84->pll_mclk_f = CS42L84_CCM_CTL1_MCLK_F_12MHZ;
+ break;
+ case 12288000:
+ cs42l84->pll_mclk_f = CS42L84_CCM_CTL1_MCLK_F_12_288KHZ;
+ break;
+ case 24000000:
+ cs42l84->pll_mclk_f = CS42L84_CCM_CTL1_MCLK_F_24MHZ;
+ break;
+ case 24576000:
+ cs42l84->pll_mclk_f = CS42L84_CCM_CTL1_MCLK_F_24_576KHZ;
+ break;
+ }
+
+ snd_soc_component_update_bits(component, CS42L84_PLL_CTL1, CS42L84_PLL_CTL1_EN, 0);
+
+ if (pll_ratio_table[i].mclk_src_sel) {
+ /* Configure PLL */
+ snd_soc_component_update_bits(component,
+ CS42L84_CCM_CTL3, CS42L84_CCM_CTL3_REFCLK_DIV,
+ FIELD_PREP(CS42L84_CCM_CTL3_REFCLK_DIV, pll_ratio_table[i].bclk_prediv));
+ snd_soc_component_write(component,
+ CS42L84_PLL_DIV_INT,
+ pll_ratio_table[i].pll_div_int);
+ snd_soc_component_write(component,
+ CS42L84_PLL_DIV_FRAC0,
+ pll_ratio_table[i].pll_div_frac);
+ snd_soc_component_write(component,
+ CS42L84_PLL_DIV_FRAC1,
+ pll_ratio_table[i].pll_div_frac >> 8);
+ snd_soc_component_write(component,
+ CS42L84_PLL_DIV_FRAC2,
+ pll_ratio_table[i].pll_div_frac >> 16);
+ snd_soc_component_update_bits(component,
+ CS42L84_PLL_CTL1, CS42L84_PLL_CTL1_MODE,
+ FIELD_PREP(CS42L84_PLL_CTL1_MODE, pll_ratio_table[i].pll_mode));
+ snd_soc_component_write(component,
+ CS42L84_PLL_DIVOUT,
+ pll_ratio_table[i].pll_divout);
+ }
+
+ return 0;
+}
+
+static int cs42l84_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
+ case SND_SOC_DAIFMT_BC_FC:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Bitclock/frame inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_IB_IF:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cs42l84_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 cs42l84_private *cs42l84 = snd_soc_component_get_drvdata(component);
+ int ret;
+ u32 ccm_samp_rate;
+
+ cs42l84->srate = params_rate(params);
+
+ ret = cs42l84_pll_config(component);
+ if (ret)
+ return ret;
+
+ switch (params_rate(params)) {
+ case 44100:
+ ccm_samp_rate = CS42L84_CCM_SAMP_RATE_RATE_44K1HZ;
+ break;
+ case 48000:
+ ccm_samp_rate = CS42L84_CCM_SAMP_RATE_RATE_48KHZ;
+ break;
+ case 88200:
+ ccm_samp_rate = CS42L84_CCM_SAMP_RATE_RATE_88K2HZ;
+ break;
+ case 96000:
+ ccm_samp_rate = CS42L84_CCM_SAMP_RATE_RATE_96KHZ;
+ break;
+ case 176400:
+ ccm_samp_rate = CS42L84_CCM_SAMP_RATE_RATE_176K4HZ;
+ break;
+ case 192000:
+ ccm_samp_rate = CS42L84_CCM_SAMP_RATE_RATE_192KHZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_component_write(component, CS42L84_CCM_SAMP_RATE, ccm_samp_rate);
+
+ switch (substream->stream) {
+ case SNDRV_PCM_STREAM_PLAYBACK:
+ snd_soc_component_write(component, CS42L84_ASP_RX_CH1_WIDTH,
+ params_width(params) - 1);
+ snd_soc_component_write(component, CS42L84_ASP_RX_CH2_WIDTH,
+ params_width(params) - 1);
+ break;
+
+ case SNDRV_PCM_STREAM_CAPTURE:
+ snd_soc_component_write(component, CS42L84_ASP_TX_CH1_WIDTH,
+ params_width(params) - 1);
+ snd_soc_component_write(component, CS42L84_ASP_TX_CH2_WIDTH,
+ params_width(params) - 1);
+ break;
+ }
+
+ return 0;
+}
+
+static int cs42l84_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_component *component = dai->component;
+ struct cs42l84_private *cs42l84 = snd_soc_component_get_drvdata(component);
+ int i;
+
+ if (freq == 0) {
+ cs42l84->bclk = 0;
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) {
+ if (pll_ratio_table[i].bclk == freq) {
+ cs42l84->bclk = freq;
+ return 0;
+ }
+ }
+
+ dev_err(component->dev, "BCLK %u not supported\n", freq);
+
+ return -EINVAL;
+}
+
+static int cs42l84_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
+{
+ struct snd_soc_component *component = dai->component;
+ struct cs42l84_private *cs42l84 = snd_soc_component_get_drvdata(component);
+ unsigned int regval;
+ int ret;
+
+ if (mute) {
+ /* Mute the headphone */
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_component_update_bits(component, CS42L84_DAC_CTL1,
+ CS42L84_DAC_CTL1_UNMUTE, 0);
+ cs42l84->stream_use &= ~(1 << stream);
+ if (!cs42l84->stream_use) {
+ /* Must disconnect PLL before stopping it */
+ snd_soc_component_write(component, CS42L84_CCM_CTL1,
+ CS42L84_CCM_CTL1_RCO);
+
+ usleep_range(150, 300);
+
+ snd_soc_component_update_bits(component, CS42L84_PLL_CTL1,
+ CS42L84_PLL_CTL1_EN, 0);
+
+ snd_soc_component_update_bits(component, CS42L84_CCM_CTL4,
+ CS42L84_CCM_CTL4_REFCLK_EN, 0);
+ }
+ } else {
+ if (!cs42l84->stream_use) {
+ /* SCLK must be running before codec unmute.
+ *
+ * Note carried over from CS42L42:
+ *
+ * PLL must not be started with ADC and HP both off
+ * otherwise the FILT+ supply will not charge properly.
+ * DAPM widgets power-up before stream unmute so at least
+ * one of the "DAC" or "ADC" widgets will already have
+ * powered-up.
+ */
+
+ snd_soc_component_update_bits(component, CS42L84_CCM_CTL4,
+ CS42L84_CCM_CTL4_REFCLK_EN,
+ CS42L84_CCM_CTL4_REFCLK_EN);
+
+ if (pll_ratio_table[cs42l84->pll_config].mclk_src_sel) {
+ snd_soc_component_update_bits(component, CS42L84_PLL_CTL1,
+ CS42L84_PLL_CTL1_EN,
+ CS42L84_PLL_CTL1_EN);
+ /* TODO: should we be doing something with divout here? */
+
+ ret = regmap_read_poll_timeout(cs42l84->regmap,
+ CS42L84_PLL_LOCK_STATUS,
+ regval,
+ (regval & CS42L84_PLL_LOCK_STATUS_LOCKED),
+ CS42L84_PLL_LOCK_POLL_US,
+ CS42L84_PLL_LOCK_TIMEOUT_US);
+ if (ret < 0)
+ dev_warn(component->dev, "PLL failed to lock: %d\n", ret);
+
+ if (regval & CS42L84_PLL_LOCK_STATUS_ERROR)
+ dev_warn(component->dev, "PLL lock error\n");
+
+ /* PLL must be running to drive glitchless switch logic */
+ snd_soc_component_update_bits(component,
+ CS42L84_CCM_CTL1,
+ CS42L84_CCM_CTL1_MCLK_SRC | CS42L84_CCM_CTL1_MCLK_FREQ,
+ FIELD_PREP(CS42L84_CCM_CTL1_MCLK_SRC, CS42L84_CCM_CTL1_MCLK_SRC_PLL)
+ | FIELD_PREP(CS42L84_CCM_CTL1_MCLK_FREQ, cs42l84->pll_mclk_f));
+ usleep_range(CS42L84_CLOCK_SWITCH_DELAY_US, CS42L84_CLOCK_SWITCH_DELAY_US*2);
+ } else {
+ snd_soc_component_update_bits(component,
+ CS42L84_CCM_CTL1,
+ CS42L84_CCM_CTL1_MCLK_SRC | CS42L84_CCM_CTL1_MCLK_FREQ,
+ FIELD_PREP(CS42L84_CCM_CTL1_MCLK_SRC, CS42L84_CCM_CTL1_MCLK_SRC_BCLK)
+ | FIELD_PREP(CS42L84_CCM_CTL1_MCLK_FREQ, cs42l84->pll_mclk_f));
+ usleep_range(CS42L84_CLOCK_SWITCH_DELAY_US, CS42L84_CLOCK_SWITCH_DELAY_US*2);
+ }
+ }
+ cs42l84->stream_use |= 1 << stream;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ /* Un-mute the headphone */
+ snd_soc_component_update_bits(component, CS42L84_DAC_CTL1,
+ CS42L84_DAC_CTL1_UNMUTE,
+ CS42L84_DAC_CTL1_UNMUTE);
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops cs42l84_ops = {
+ .hw_params = cs42l84_pcm_hw_params,
+ .set_fmt = cs42l84_set_dai_fmt,
+ .set_sysclk = cs42l84_set_sysclk,
+ .mute_stream = cs42l84_mute_stream,
+};
+
+#define CS42L84_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver cs42l84_dai = {
+ .name = "cs42l84",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000,
+ .formats = CS42L84_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000,
+ .formats = CS42L84_FORMATS,
+ },
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
+ .ops = &cs42l84_ops,
+};
+
+struct cs42l84_irq_params {
+ u16 status_addr;
+ u16 mask_addr;
+ u8 mask;
+};
+
+static const struct cs42l84_irq_params irq_params_table[] = {
+ {CS42L84_TSRS_PLUG_INT_STATUS, CS42L84_TSRS_PLUG_INT_MASK,
+ CS42L84_TSRS_PLUG_VAL_MASK}
+};
+
+static void cs42l84_detect_hs(struct cs42l84_private *cs42l84)
+{
+ unsigned int reg;
+
+ /* Power up HSBIAS */
+ regmap_update_bits(cs42l84->regmap,
+ CS42L84_MISC_DET_CTL,
+ CS42L84_MISC_DET_CTL_HSBIAS_CTL | CS42L84_MISC_DET_CTL_DETECT_MODE,
+ FIELD_PREP(CS42L84_MISC_DET_CTL_HSBIAS_CTL, 3) | /* 2.7 V */
+ FIELD_PREP(CS42L84_MISC_DET_CTL_DETECT_MODE, 0));
+
+ /* Power up level detection circuitry */
+ regmap_update_bits(cs42l84->regmap,
+ CS42L84_MISC_DET_CTL,
+ CS42L84_MISC_DET_CTL_PDN_MIC_LVL_DET, 0);
+
+ /* TODO: Optimize */
+ msleep(50);
+
+ /* Connect HSBIAS in CTIA wiring */
+ /* TODO: Should likely be subject of detection */
+ regmap_write(cs42l84->regmap,
+ CS42L84_HS_SWITCH_CTL,
+ CS42L84_HS_SWITCH_CTL_REF_HS3 | \
+ CS42L84_HS_SWITCH_CTL_HSB_FILT_HS3 | \
+ CS42L84_HS_SWITCH_CTL_GNDHS_HS3 | \
+ CS42L84_HS_SWITCH_CTL_HSB_HS4);
+ regmap_update_bits(cs42l84->regmap,
+ CS42L84_HS_DET_CTL2,
+ CS42L84_HS_DET_CTL2_SET,
+ FIELD_PREP(CS42L84_HS_DET_CTL2_SET, 0));
+
+ regmap_update_bits(cs42l84->regmap,
+ CS42L84_MISC_DET_CTL,
+ CS42L84_MISC_DET_CTL_DETECT_MODE,
+ FIELD_PREP(CS42L84_MISC_DET_CTL_DETECT_MODE, 3));
+
+ /* TODO: Optimize */
+ msleep(50);
+
+ regmap_read(cs42l84->regmap, CS42L84_HS_DET_STATUS2, &reg);
+ regmap_update_bits(cs42l84->regmap,
+ CS42L84_MISC_DET_CTL,
+ CS42L84_MISC_DET_CTL_PDN_MIC_LVL_DET,
+ CS42L84_MISC_DET_CTL_PDN_MIC_LVL_DET);
+
+ switch (reg & 0b11) {
+ case 0b11: /* shorted */
+ case 0b00: /* open */
+ /* Power down HSBIAS */
+ regmap_update_bits(cs42l84->regmap,
+ CS42L84_MISC_DET_CTL,
+ CS42L84_MISC_DET_CTL_HSBIAS_CTL,
+ FIELD_PREP(CS42L84_MISC_DET_CTL_HSBIAS_CTL, 1)); /* 0.0 V */
+ break;
+ }
+
+ switch (reg & 0b11) {
+ case 0b10: /* load */
+ dev_dbg(cs42l84->dev, "Detected mic\n");
+ cs42l84->hs_type = SND_JACK_HEADSET;
+ snd_soc_jack_report(cs42l84->jack, SND_JACK_HEADSET,
+ SND_JACK_HEADSET);
+ break;
+
+ case 0b00: /* open */
+ dev_dbg(cs42l84->dev, "Detected open circuit on HS4\n");
+ fallthrough;
+ case 0b11: /* shorted */
+ default:
+ snd_soc_jack_report(cs42l84->jack, SND_JACK_HEADPHONE,
+ SND_JACK_HEADSET);
+ cs42l84->hs_type = SND_JACK_HEADPHONE;
+ dev_dbg(cs42l84->dev, "Detected bare headphone (no mic)\n");
+ break;
+ }
+}
+
+static void cs42l84_revert_hs(struct cs42l84_private *cs42l84)
+{
+ /* Power down HSBIAS */
+ regmap_update_bits(cs42l84->regmap,
+ CS42L84_MISC_DET_CTL,
+ CS42L84_MISC_DET_CTL_HSBIAS_CTL | CS42L84_MISC_DET_CTL_DETECT_MODE,
+ FIELD_PREP(CS42L84_MISC_DET_CTL_HSBIAS_CTL, 1) | /* 0.0 V */
+ FIELD_PREP(CS42L84_MISC_DET_CTL_DETECT_MODE, 0));
+
+ /* Disconnect HSBIAS */
+ regmap_write(cs42l84->regmap,
+ CS42L84_HS_SWITCH_CTL,
+ CS42L84_HS_SWITCH_CTL_REF_HS3 | \
+ CS42L84_HS_SWITCH_CTL_REF_HS4 | \
+ CS42L84_HS_SWITCH_CTL_HSB_FILT_HS3 | \
+ CS42L84_HS_SWITCH_CTL_HSB_FILT_HS4 | \
+ CS42L84_HS_SWITCH_CTL_GNDHS_HS3 | \
+ CS42L84_HS_SWITCH_CTL_GNDHS_HS4);
+ regmap_update_bits(cs42l84->regmap,
+ CS42L84_HS_DET_CTL2,
+ CS42L84_HS_DET_CTL2_SET,
+ FIELD_PREP(CS42L84_HS_DET_CTL2_SET, 2));
+}
+
+static void cs42l84_set_interrupt_masks(struct cs42l84_private *cs42l84,
+ unsigned int val)
+{
+ regmap_update_bits(cs42l84->regmap, CS42L84_TSRS_PLUG_INT_MASK,
+ CS42L84_RS_PLUG | CS42L84_RS_UNPLUG |
+ CS42L84_TS_PLUG | CS42L84_TS_UNPLUG,
+ val);
+}
+
+static irqreturn_t cs42l84_irq_thread(int irq, void *data)
+{
+ struct cs42l84_private *cs42l84 = (struct cs42l84_private *)data;
+ unsigned int stickies[1];
+ unsigned int masks[1];
+ unsigned int reg;
+ u8 current_tip_state;
+ u8 current_ring_state;
+ int i;
+
+ mutex_lock(&cs42l84->irq_lock);
+ /* Read sticky registers to clear interrupt */
+ for (i = 0; i < ARRAY_SIZE(stickies); i++) {
+ regmap_read(cs42l84->regmap, irq_params_table[i].status_addr,
+ &(stickies[i]));
+ regmap_read(cs42l84->regmap, irq_params_table[i].mask_addr,
+ &(masks[i]));
+ stickies[i] = stickies[i] & (~masks[i]) &
+ irq_params_table[i].mask;
+ }
+
+ /* When handling plug sene IRQs, we only care about EITHER tip OR ring.
+ * Ring is useless on remove, and is only useful on insert for
+ * detecting if the plug state has changed AFTER we have handled the
+ * tip sense IRQ, e.g. if the plug was not fully seated within the tip
+ * sense debounce time.
+ */
+
+ if ((~masks[0]) & irq_params_table[0].mask) {
+ regmap_read(cs42l84->regmap, CS42L84_TSRS_PLUG_STATUS, &reg);
+
+ current_tip_state = (((char) reg) &
+ (CS42L84_TS_PLUG | CS42L84_TS_UNPLUG)) >>
+ CS42L84_TS_PLUG_SHIFT;
+
+ if (current_tip_state != cs42l84->tip_state) {
+ cs42l84->tip_state = current_tip_state;
+ switch (current_tip_state) {
+ case CS42L84_PLUG:
+ dev_dbg(cs42l84->dev, "Plug event\n");
+
+ cs42l84_detect_hs(cs42l84);
+
+ /*
+ * Check the tip sense status again, and possibly invalidate
+ * the detection result
+ *
+ * Thanks to debounce, this should reliably indicate if the tip
+ * was disconnected at any point during the detection procedure.
+ */
+ regmap_read(cs42l84->regmap, CS42L84_TSRS_PLUG_STATUS, &reg);
+ current_tip_state = (((char) reg) &
+ (CS42L84_TS_PLUG | CS42L84_TS_UNPLUG)) >>
+ CS42L84_TS_PLUG_SHIFT;
+ if (current_tip_state != CS42L84_PLUG) {
+ dev_dbg(cs42l84->dev, "Wobbly connection, detection invalidated\n");
+ cs42l84->tip_state = CS42L84_UNPLUG;
+ cs42l84_revert_hs(cs42l84);
+ }
+
+ /* Unmask ring sense interrupts */
+ cs42l84_set_interrupt_masks(cs42l84, 0);
+ break;
+ case CS42L84_UNPLUG:
+ cs42l84->ring_state = CS42L84_UNPLUG;
+ dev_dbg(cs42l84->dev, "Unplug event\n");
+
+ cs42l84_revert_hs(cs42l84);
+ cs42l84->hs_type = 0;
+ snd_soc_jack_report(cs42l84->jack, 0,
+ SND_JACK_HEADSET);
+
+ /* Mask ring sense interrupts */
+ cs42l84_set_interrupt_masks(cs42l84,
+ CS42L84_RS_PLUG | CS42L84_RS_UNPLUG);
+ break;
+ default:
+ cs42l84->ring_state = CS42L84_TRANS;
+ break;
+ }
+
+ mutex_unlock(&cs42l84->irq_lock);
+
+ return IRQ_HANDLED;
+ }
+
+ /* Tip state didn't change, we must've got a ring sense IRQ */
+ current_ring_state = (((char) reg) &
+ (CS42L84_RS_PLUG | CS42L84_RS_UNPLUG)) >>
+ CS42L84_RS_PLUG_SHIFT;
+
+ if (current_ring_state != cs42l84->ring_state) {
+ cs42l84->ring_state = current_ring_state;
+ if (current_ring_state == CS42L84_PLUG)
+ cs42l84_detect_hs(cs42l84);
+ }
+ }
+
+ mutex_unlock(&cs42l84->irq_lock);
+
+ return IRQ_HANDLED;
+}
+
+static void cs42l84_setup_plug_detect(struct cs42l84_private *cs42l84)
+{
+ unsigned int reg;
+
+ /* Set up plug detection */
+ regmap_update_bits(cs42l84->regmap, CS42L84_MIC_DET_CTL4,
+ CS42L84_MIC_DET_CTL4_LATCH_TO_VP,
+ CS42L84_MIC_DET_CTL4_LATCH_TO_VP);
+ regmap_update_bits(cs42l84->regmap, CS42L84_TIP_SENSE_CTL2,
+ CS42L84_TIP_SENSE_CTL2_MODE,
+ FIELD_PREP(CS42L84_TIP_SENSE_CTL2_MODE, CS42L84_TIP_SENSE_CTL2_MODE_SHORT_DET));
+ regmap_update_bits(cs42l84->regmap, CS42L84_RING_SENSE_CTL,
+ CS42L84_RING_SENSE_CTL_INV | CS42L84_RING_SENSE_CTL_UNK1 |
+ CS42L84_RING_SENSE_CTL_RISETIME | CS42L84_RING_SENSE_CTL_FALLTIME,
+ CS42L84_RING_SENSE_CTL_INV | CS42L84_RING_SENSE_CTL_UNK1 |
+ FIELD_PREP(CS42L84_RING_SENSE_CTL_RISETIME, CS42L84_DEBOUNCE_TIME_125MS) |
+ FIELD_PREP(CS42L84_RING_SENSE_CTL_FALLTIME, CS42L84_DEBOUNCE_TIME_125MS));
+ regmap_update_bits(cs42l84->regmap, CS42L84_TIP_SENSE_CTL,
+ CS42L84_TIP_SENSE_CTL_INV |
+ CS42L84_TIP_SENSE_CTL_RISETIME | CS42L84_TIP_SENSE_CTL_FALLTIME,
+ CS42L84_TIP_SENSE_CTL_INV |
+ FIELD_PREP(CS42L84_TIP_SENSE_CTL_RISETIME, CS42L84_DEBOUNCE_TIME_500MS) |
+ FIELD_PREP(CS42L84_TIP_SENSE_CTL_FALLTIME, CS42L84_DEBOUNCE_TIME_125MS));
+ regmap_update_bits(cs42l84->regmap, CS42L84_MSM_BLOCK_EN3,
+ CS42L84_MSM_BLOCK_EN3_TR_SENSE,
+ CS42L84_MSM_BLOCK_EN3_TR_SENSE);
+
+ /* Save the initial status of the tip sense */
+ regmap_read(cs42l84->regmap, CS42L84_TSRS_PLUG_STATUS, &reg);
+ cs42l84->tip_state = (((char) reg) &
+ (CS42L84_TS_PLUG | CS42L84_TS_UNPLUG)) >>
+ CS42L84_TS_PLUG_SHIFT;
+
+ /* Set mic-detection threshold */
+ regmap_update_bits(cs42l84->regmap,
+ CS42L84_MIC_DET_CTL1, CS42L84_MIC_DET_CTL1_HS_DET_LEVEL,
+ FIELD_PREP(CS42L84_MIC_DET_CTL1_HS_DET_LEVEL, 0x2c)); /* ~1.9 V */
+
+ /* Disconnect HSBIAS (initially) */
+ regmap_write(cs42l84->regmap,
+ CS42L84_HS_SWITCH_CTL,
+ CS42L84_HS_SWITCH_CTL_REF_HS3 | \
+ CS42L84_HS_SWITCH_CTL_REF_HS4 | \
+ CS42L84_HS_SWITCH_CTL_HSB_FILT_HS3 | \
+ CS42L84_HS_SWITCH_CTL_HSB_FILT_HS4 | \
+ CS42L84_HS_SWITCH_CTL_GNDHS_HS3 | \
+ CS42L84_HS_SWITCH_CTL_GNDHS_HS4);
+ regmap_update_bits(cs42l84->regmap,
+ CS42L84_HS_DET_CTL2,
+ CS42L84_HS_DET_CTL2_SET | CS42L84_HS_DET_CTL2_CTL,
+ FIELD_PREP(CS42L84_HS_DET_CTL2_SET, 2) |
+ FIELD_PREP(CS42L84_HS_DET_CTL2_CTL, 0));
+ regmap_update_bits(cs42l84->regmap,
+ CS42L84_HS_CLAMP_DISABLE, 1, 1);
+
+}
+
+static int cs42l84_i2c_probe(struct i2c_client *i2c_client)
+{
+ struct cs42l84_private *cs42l84;
+ int ret, devid;
+ unsigned int reg;
+
+ cs42l84 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l84_private),
+ GFP_KERNEL);
+ if (!cs42l84)
+ return -ENOMEM;
+
+ cs42l84->dev = &i2c_client->dev;
+ i2c_set_clientdata(i2c_client, cs42l84);
+ mutex_init(&cs42l84->irq_lock);
+
+ cs42l84->regmap = devm_regmap_init_i2c(i2c_client, &cs42l84_regmap);
+ if (IS_ERR(cs42l84->regmap)) {
+ ret = PTR_ERR(cs42l84->regmap);
+ dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Reset the Device */
+ cs42l84->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
+ "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(cs42l84->reset_gpio)) {
+ ret = PTR_ERR(cs42l84->reset_gpio);
+ goto err_disable_noreset;
+ }
+
+ if (cs42l84->reset_gpio) {
+ dev_dbg(&i2c_client->dev, "Found reset GPIO\n");
+ gpiod_set_value_cansleep(cs42l84->reset_gpio, 1);
+ }
+ usleep_range(CS42L84_BOOT_TIME_US, CS42L84_BOOT_TIME_US * 2);
+
+ /* Request IRQ if one was specified */
+ if (i2c_client->irq) {
+ ret = request_threaded_irq(i2c_client->irq,
+ NULL, cs42l84_irq_thread,
+ IRQF_ONESHOT,
+ "cs42l84", cs42l84);
+ if (ret == -EPROBE_DEFER) {
+ goto err_disable_noirq;
+ } else if (ret != 0) {
+ dev_err(&i2c_client->dev,
+ "Failed to request IRQ: %d\n", ret);
+ goto err_disable_noirq;
+ }
+ }
+
+ /* initialize codec */
+ devid = cirrus_read_device_id(cs42l84->regmap, CS42L84_DEVID);
+ if (devid < 0) {
+ ret = devid;
+ dev_err(&i2c_client->dev, "Failed to read device ID: %d\n", ret);
+ goto err_disable;
+ }
+
+ if (devid != CS42L84_CHIP_ID) {
+ dev_err(&i2c_client->dev,
+ "CS42L84 Device ID (%X). Expected %X\n",
+ devid, CS42L84_CHIP_ID);
+ ret = -EINVAL;
+ goto err_disable;
+ }
+
+ ret = regmap_read(cs42l84->regmap, CS42L84_REVID, &reg);
+ if (ret < 0) {
+ dev_err(&i2c_client->dev, "Get Revision ID failed\n");
+ goto err_shutdown;
+ }
+
+ dev_info(&i2c_client->dev,
+ "Cirrus Logic CS42L84, Revision: %02X\n", reg & 0xFF);
+
+ /* Setup plug detection */
+ cs42l84_setup_plug_detect(cs42l84);
+
+ /* Mask ring sense interrupts */
+ cs42l84_set_interrupt_masks(cs42l84, CS42L84_RS_PLUG | CS42L84_RS_UNPLUG);
+
+ /* Register codec for machine driver */
+ ret = devm_snd_soc_register_component(&i2c_client->dev,
+ &soc_component_dev_cs42l84, &cs42l84_dai, 1);
+ if (ret < 0)
+ goto err_shutdown;
+
+ return 0;
+
+err_shutdown:
+ /* Nothing to do */
+
+err_disable:
+ if (i2c_client->irq)
+ free_irq(i2c_client->irq, cs42l84);
+
+err_disable_noirq:
+ gpiod_set_value_cansleep(cs42l84->reset_gpio, 0);
+err_disable_noreset:
+ return ret;
+}
+
+static void cs42l84_i2c_remove(struct i2c_client *i2c_client)
+{
+ struct cs42l84_private *cs42l84 = i2c_get_clientdata(i2c_client);
+
+ if (i2c_client->irq)
+ free_irq(i2c_client->irq, cs42l84);
+
+ gpiod_set_value_cansleep(cs42l84->reset_gpio, 0);
+}
+
+static const struct of_device_id cs42l84_of_match[] = {
+ { .compatible = "cirrus,cs42l84", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, cs42l84_of_match);
+
+static const struct i2c_device_id cs42l84_id[] = {
+ {"cs42l84", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, cs42l84_id);
+
+static struct i2c_driver cs42l84_i2c_driver = {
+ .driver = {
+ .name = "cs42l84",
+ .of_match_table = cs42l84_of_match,
+ },
+ .id_table = cs42l84_id,
+ .probe = cs42l84_i2c_probe,
+ .remove = cs42l84_i2c_remove,
+};
+
+module_i2c_driver(cs42l84_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC CS42L84 driver");
+MODULE_AUTHOR("Martin Povišer <povik+lin@cutebit.org>");
+MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
+MODULE_AUTHOR("James Calligeros <jcalligeros99@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l84.h b/sound/soc/codecs/cs42l84.h
new file mode 100644
index 000000000000..dbf778a902b9
--- /dev/null
+++ b/sound/soc/codecs/cs42l84.h
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) The Asahi Linux Contributors
+ *
+ * Based on sound/soc/codecs/cs42l42.h
+ *
+ * Copyright 2016 Cirrus Logic, Inc.
+ */
+
+
+#ifndef __CS42L84_H__
+#define __CS42L84_H__
+
+#include <linux/bits.h>
+
+#define CS42L84_CHIP_ID 0x42a84
+
+#define CS42L84_DEVID 0x0000
+#define CS42L84_REVID 0x73fe
+#define CS42L84_FRZ_CTL 0x0006
+#define CS42L84_FRZ_CTL_ENGAGE BIT(0)
+
+#define CS42L84_TSRS_PLUG_INT_STATUS 0x0400
+#define CS42L84_TSRS_PLUG_INT_MASK 0x0418
+#define CS42L84_RS_PLUG_SHIFT 0
+#define CS42L84_RS_PLUG BIT(0)
+#define CS42L84_RS_UNPLUG BIT(1)
+#define CS42L84_TS_PLUG_SHIFT 2
+#define CS42L84_TS_PLUG BIT(2)
+#define CS42L84_TS_UNPLUG BIT(3)
+#define CS42L84_TSRS_PLUG_VAL_MASK GENMASK(3, 0)
+#define CS42L84_PLL_LOCK_STATUS 0x040e // probably bit 0x10
+#define CS42L84_PLL_LOCK_STATUS_LOCKED BIT(4)
+#define CS42L84_PLL_LOCK_STATUS_ERROR BIT(5)
+
+#define CS42L84_PLUG 3
+#define CS42L84_UNPLUG 0
+#define CS42L84_TRANS 1
+
+#define CS42L84_CCM_CTL1 0x0600
+#define CS42L84_CCM_CTL1_MCLK_SRC GENMASK(1, 0)
+#define CS42L84_CCM_CTL1_MCLK_SRC_RCO 0
+#define CS42L84_CCM_CTL1_MCLK_SRC_MCLK 1
+#define CS42L84_CCM_CTL1_MCLK_SRC_BCLK 2
+#define CS42L84_CCM_CTL1_MCLK_SRC_PLL 3
+#define CS42L84_CCM_CTL1_MCLK_FREQ GENMASK(3, 2)
+#define CS42L84_CCM_CTL1_MCLK_F_12MHZ 0b00
+#define CS42L84_CCM_CTL1_MCLK_F_24MHZ 0b01
+#define CS42L84_CCM_CTL1_MCLK_F_12_288KHZ 0b10
+#define CS42L84_CCM_CTL1_MCLK_F_24_576KHZ 0b11
+#define CS42L84_CCM_CTL1_RCO \
+ (FIELD_PREP(CS42L84_CCM_CTL1_MCLK_SRC, CS42L84_CCM_CTL1_MCLK_SRC_RCO) \
+ | FIELD_PREP(CS42L84_CCM_CTL1_MCLK_FREQ, CS42L84_CCM_CTL1_MCLK_F_12MHZ))
+
+#define CS42L84_CCM_SAMP_RATE 0x0601
+#define CS42L84_CCM_SAMP_RATE_RATE_48KHZ 4
+#define CS42L84_CCM_SAMP_RATE_RATE_96KHZ 5
+#define CS42L84_CCM_SAMP_RATE_RATE_192KHZ 6
+#define CS42L84_CCM_SAMP_RATE_RATE_44K1HZ 12
+#define CS42L84_CCM_SAMP_RATE_RATE_88K2HZ 13
+#define CS42L84_CCM_SAMP_RATE_RATE_176K4HZ 14
+#define CS42L84_CCM_CTL3 0x0602
+#define CS42L84_CCM_CTL3_REFCLK_DIV GENMASK(2, 1)
+#define CS42L84_CCM_CTL4 0x0603
+#define CS42L84_CCM_CTL4_REFCLK_EN BIT(0)
+
+#define CS42L84_CCM_ASP_CLK_CTRL 0x0608
+
+#define CS42L84_PLL_CTL1 0x0800
+#define CS42L84_PLL_CTL1_EN BIT(0)
+#define CS42L84_PLL_CTL1_MODE GENMASK(2, 1)
+#define CS42L84_PLL_DIV_FRAC0 0x0804
+#define CS42L84_PLL_DIV_FRAC1 0x0805
+#define CS42L84_PLL_DIV_FRAC2 0x0806
+#define CS42L84_PLL_DIV_INT 0x0807
+#define CS42L84_PLL_DIVOUT 0x0808
+
+#define CS42L84_RING_SENSE_CTL 0x1282
+#define CS42L84_RING_SENSE_CTL_INV BIT(7)
+#define CS42L84_RING_SENSE_CTL_UNK1 BIT(6)
+#define CS42L84_RING_SENSE_CTL_FALLTIME GENMASK(5, 3)
+#define CS42L84_RING_SENSE_CTL_RISETIME GENMASK(2, 0)
+#define CS42L84_TIP_SENSE_CTL 0x1283
+#define CS42L84_TIP_SENSE_CTL_INV BIT(7)
+#define CS42L84_TIP_SENSE_CTL_FALLTIME GENMASK(5, 3)
+#define CS42L84_TIP_SENSE_CTL_RISETIME GENMASK(2, 0)
+
+#define CS42L84_TSRS_PLUG_STATUS 0x1288
+
+#define CS42L84_TIP_SENSE_CTL2 0x1473
+#define CS42L84_TIP_SENSE_CTL2_MODE GENMASK(7, 6)
+#define CS42L84_TIP_SENSE_CTL2_MODE_DISABLED 0b00
+#define CS42L84_TIP_SENSE_CTL2_MODE_DIG_INPUT 0b01
+#define CS42L84_TIP_SENSE_CTL2_MODE_SHORT_DET 0b11
+#define CS42L84_TIP_SENSE_CTL2_INV BIT(5)
+
+#define CS42L84_MISC_DET_CTL 0x1474
+#define CS42L84_MISC_DET_CTL_DETECT_MODE GENMASK(4, 3)
+#define CS42L84_MISC_DET_CTL_HSBIAS_CTL GENMASK(2, 1)
+#define CS42L84_MISC_DET_CTL_PDN_MIC_LVL_DET BIT(0)
+
+#define CS42L84_MIC_DET_CTL1 0x1475
+#define CS42L84_MIC_DET_CTL1_HS_DET_LEVEL GENMASK(5, 0)
+
+#define CS42L84_MIC_DET_CTL4 0x1477
+#define CS42L84_MIC_DET_CTL4_LATCH_TO_VP BIT(1)
+
+#define CS42L84_HS_DET_STATUS2 0x147d
+
+#define CS42L84_MSM_BLOCK_EN1 0x1800
+#define CS42L84_MSM_BLOCK_EN2 0x1801
+#define CS42L84_MSM_BLOCK_EN2_ASP_SHIFT 6
+#define CS42L84_MSM_BLOCK_EN2_BUS_SHIFT 5
+#define CS42L84_MSM_BLOCK_EN2_DAC_SHIFT 4
+#define CS42L84_MSM_BLOCK_EN2_ADC_SHIFT 3
+#define CS42L84_MSM_BLOCK_EN3 0x1802
+#define CS42L84_MSM_BLOCK_EN3_TR_SENSE BIT(3)
+
+#define CS42L84_HS_DET_CTL2 0x1811
+#define CS42L84_HS_DET_CTL2_CTL GENMASK(7, 6)
+#define CS42L84_HS_DET_CTL2_SET GENMASK(5, 4)
+#define CS42L84_HS_DET_CTL2_REF BIT(3)
+#define CS42L84_HS_DET_CTL2_AUTO_TIME GENMASK(1, 0)
+
+#define CS42L84_HS_SWITCH_CTL 0x1812
+#define CS42L84_HS_SWITCH_CTL_REF_HS3 BIT(7)
+#define CS42L84_HS_SWITCH_CTL_REF_HS4 BIT(6)
+#define CS42L84_HS_SWITCH_CTL_HSB_FILT_HS3 BIT(5)
+#define CS42L84_HS_SWITCH_CTL_HSB_FILT_HS4 BIT(4)
+#define CS42L84_HS_SWITCH_CTL_HSB_HS3 BIT(3)
+#define CS42L84_HS_SWITCH_CTL_HSB_HS4 BIT(2)
+#define CS42L84_HS_SWITCH_CTL_GNDHS_HS3 BIT(1)
+#define CS42L84_HS_SWITCH_CTL_GNDHS_HS4 BIT(0)
+
+#define CS42L84_HS_CLAMP_DISABLE 0x1813
+
+#define CS42L84_ADC_CTL1 0x2000
+#define CS42L84_ADC_CTL1_PREAMP_GAIN_SHIFT 6
+#define CS42L84_ADC_CTL1_PGA_GAIN_SHIFT 0
+#define CS42L84_ADC_CTL4 0x2003
+#define CS42L84_ADC_CTL4_WNF_CF_SHIFT 4
+#define CS42L84_ADC_CTL4_WNF_EN_SHIFT 3
+#define CS42L84_ADC_CTL4_HPF_CF_SHIFT 1
+#define CS42L84_ADC_CTL4_HPF_EN_SHIFT 0
+
+#define CS42L84_DAC_CTL1 0x3000
+#define CS42L84_DAC_CTL1_UNMUTE BIT(0)
+//#define CS42L84_DAC_CTL1_DACB_INV_SHIFT 1
+//#define CS42L84_DAC_CTL1_DACA_INV_SHIFT 0
+#define CS42L84_DAC_CTL2 0x3001
+
+#define CS42L84_DAC_CHA_VOL_LSB 0x3004
+#define CS42L84_DAC_CHA_VOL_MSB 0x3005
+#define CS42L84_DAC_CHB_VOL_LSB 0x3006
+#define CS42L84_DAC_CHB_VOL_MSB 0x3007
+#define CS42L84_HP_VOL_CTL 0x3020
+#define CS42L84_HP_VOL_CTL_ZERO_CROSS BIT(1)
+#define CS42L84_HP_VOL_CTL_SOFT BIT(0)
+
+#define CS42L84_SRC_ASP_RX_CH1 0b1101
+#define CS42L84_SRC_ASP_RX_CH2 0b1110
+
+#define CS42L84_BUS_ASP_TX_SRC 0x4000
+#define CS42L84_BUS_ASP_TX_SRC_CH1_SHIFT 0
+#define CS42L84_BUS_DAC_SRC 0x4001
+#define CS42L84_BUS_DAC_SRC_DACA_SHIFT 0
+#define CS42L84_BUS_DAC_SRC_DACB_SHIFT 4
+
+#define CS42L84_ASP_CTL 0x5000
+#define CS42L84_ASP_CTL_BCLK_EN_SHIFT 1
+#define CS42L84_ASP_CTL_TDM_MODE BIT(2)
+#define CS42L84_ASP_FSYNC_CTL2 0x5010
+#define CS42L84_ASP_FSYNC_CTL2_BCLK_PERIOD_LO GENMASK(7, 1)
+#define CS42L84_ASP_FSYNC_CTL3 0x5011
+#define CS42L84_ASP_FSYNC_CTL3_BCLK_PERIOD_HI GENMASK(4, 0)
+#define CS42L84_ASP_DATA_CTL 0x5018
+
+#define CS42L84_ASP_RX_EN 0x5020
+#define CS42L84_ASP_RX_EN_CH1_SHIFT 0
+#define CS42L84_ASP_RX_EN_CH2_SHIFT 1
+#define CS42L84_ASP_TX_EN 0x5024
+#define CS42L84_ASP_TX_EN_CH1_SHIFT 0
+
+#define CS42L84_ASP_RX_CH1_CTL1 0x5028
+#define CS42L84_ASP_RX_CH1_CTL2 0x5029
+#define CS42L84_ASP_RX_CH1_WIDTH 0x502a
+#define CS42L84_ASP_RX_CH2_CTL1 0x502c
+#define CS42L84_ASP_RX_CH2_CTL2 0x502d
+#define CS42L84_ASP_RX_CH2_WIDTH 0x502e
+
+#define CS42L84_ASP_RX_CHx_CTL1_EDGE BIT(0)
+#define CS42L84_ASP_RX_CHx_CTL1_SLOT_START_LSB GENMASK(7, 1)
+#define CS42L84_ASP_RX_CHx_CTL2_SLOT_START_MSB GENMASK(2, 0)
+
+#define CS42L84_ASP_TX_CH1_CTL1 0x5068
+#define CS42L84_ASP_TX_CH1_CTL2 0x5069
+#define CS42L84_ASP_TX_CH1_WIDTH 0x506a
+#define CS42L84_ASP_TX_CH2_CTL1 0x506c
+#define CS42L84_ASP_TX_CH2_CTL2 0x506d
+#define CS42L84_ASP_TX_CH2_WIDTH 0x506e
+
+#define CS42L84_DEBOUNCE_TIME_125MS 0b001
+#define CS42L84_DEBOUNCE_TIME_500MS 0b011
+
+#define CS42L84_BOOT_TIME_US 3000
+#define CS42L84_CLOCK_SWITCH_DELAY_US 150
+#define CS42L84_PLL_LOCK_POLL_US 250
+#define CS42L84_PLL_LOCK_TIMEOUT_US 1250
+
+#endif /* __CS42L84_H__ */
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c
index f3ef6fb55304..ca4cc954efa8 100644
--- a/sound/soc/codecs/da7213.c
+++ b/sound/soc/codecs/da7213.c
@@ -20,6 +20,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <linux/pm_runtime.h>
+#include <linux/units.h>
#include <sound/soc.h>
#include <sound/initval.h>
#include <sound/tlv.h>
@@ -1555,7 +1556,11 @@ static int da7213_set_component_sysclk(struct snd_soc_component *component,
if ((da7213->clk_src == clk_id) && (da7213->mclk_rate == freq))
return 0;
- if (((freq < 5000000) && (freq != 32768)) || (freq > 54000000)) {
+ /* Maybe audio stream is closing. */
+ if (freq == 0)
+ return 0;
+
+ if (((freq < da7213->fin_min_rate) && (freq != 32768)) || (freq > 54000000)) {
dev_err(component->dev, "Unsupported MCLK value %d\n",
freq);
return -EINVAL;
@@ -1854,11 +1859,14 @@ static int da7213_set_bias_level(struct snd_soc_component *component,
return 0;
}
+#define DA7213_FIN_MIN_RATE (5 * MEGA)
+#define DA7212_FIN_MIN_RATE (2 * MEGA)
+
#if defined(CONFIG_OF)
/* DT */
static const struct of_device_id da7213_of_match[] = {
- { .compatible = "dlg,da7212", },
- { .compatible = "dlg,da7213", },
+ { .compatible = "dlg,da7212", .data = (void *)DA7212_FIN_MIN_RATE },
+ { .compatible = "dlg,da7213", .data = (void *)DA7213_FIN_MIN_RATE },
{ }
};
MODULE_DEVICE_TABLE(of, da7213_of_match);
@@ -1866,8 +1874,8 @@ MODULE_DEVICE_TABLE(of, da7213_of_match);
#ifdef CONFIG_ACPI
static const struct acpi_device_id da7213_acpi_match[] = {
- { "DLGS7212", 0},
- { "DLGS7213", 0},
+ { "DLGS7212", DA7212_FIN_MIN_RATE },
+ { "DLGS7213", DA7213_FIN_MIN_RATE },
{ },
};
MODULE_DEVICE_TABLE(acpi, da7213_acpi_match);
@@ -2136,6 +2144,7 @@ static const struct regmap_config da7213_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
+ .max_register = DA7213_TONE_GEN_OFF_PER,
.reg_defaults = da7213_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(da7213_reg_defaults),
.volatile_reg = da7213_volatile_register,
@@ -2162,6 +2171,10 @@ static int da7213_i2c_probe(struct i2c_client *i2c)
if (!da7213)
return -ENOMEM;
+ da7213->fin_min_rate = (uintptr_t)i2c_get_match_data(i2c);
+ if (!da7213->fin_min_rate)
+ return -EINVAL;
+
i2c_set_clientdata(i2c, da7213);
/* Get required supplies */
@@ -2229,12 +2242,12 @@ static int __maybe_unused da7213_runtime_resume(struct device *dev)
if (ret < 0)
return ret;
regcache_cache_only(da7213->regmap, false);
- regcache_sync(da7213->regmap);
- return 0;
+ return regcache_sync(da7213->regmap);
}
static const struct dev_pm_ops da7213_pm = {
SET_RUNTIME_PM_OPS(da7213_runtime_suspend, da7213_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static const struct i2c_device_id da7213_i2c_id[] = {
diff --git a/sound/soc/codecs/da7213.h b/sound/soc/codecs/da7213.h
index 505b731c0adb..b9ab791d6b88 100644
--- a/sound/soc/codecs/da7213.h
+++ b/sound/soc/codecs/da7213.h
@@ -600,6 +600,7 @@ struct da7213_priv {
struct clk *mclk;
unsigned int mclk_rate;
unsigned int out_rate;
+ unsigned int fin_min_rate;
int clk_src;
bool master;
bool alc_calib_auto;
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index 311ea7918b31..e2da3e317b5a 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -1167,17 +1167,20 @@ static int da7219_set_dai_sysclk(struct snd_soc_dai *codec_dai,
struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
int ret = 0;
- if ((da7219->clk_src == clk_id) && (da7219->mclk_rate == freq))
+ mutex_lock(&da7219->pll_lock);
+
+ if ((da7219->clk_src == clk_id) && (da7219->mclk_rate == freq)) {
+ mutex_unlock(&da7219->pll_lock);
return 0;
+ }
if ((freq < 2000000) || (freq > 54000000)) {
+ mutex_unlock(&da7219->pll_lock);
dev_err(codec_dai->dev, "Unsupported MCLK value %d\n",
freq);
return -EINVAL;
}
- mutex_lock(&da7219->pll_lock);
-
switch (clk_id) {
case DA7219_CLKSRC_MCLK_SQR:
snd_soc_component_update_bits(component, DA7219_PLL_CTRL,
diff --git a/sound/soc/codecs/es8323.c b/sound/soc/codecs/es8323.c
new file mode 100644
index 000000000000..6f4fa36ea34d
--- /dev/null
+++ b/sound/soc/codecs/es8323.c
@@ -0,0 +1,792 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// es8323.c -- es8323 ALSA SoC audio driver
+//
+// Copyright 2024 Rockchip Electronics Co. Ltd.
+// Copyright 2024 Everest Semiconductor Co.,Ltd.
+// Copyright 2024 Loongson Technology Co.,Ltd.
+//
+// Author: Mark Brown <broonie@kernel.org>
+// Jianqun Xu <jay.xu@rock-chips.com>
+// Nickey Yang <nickey.yang@rock-chips.com>
+// Further cleanup and restructuring by:
+// Binbin Zhou <zhoubinbin@loongson.cn>
+
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+
+#include "es8323.h"
+
+struct es8323_priv {
+ unsigned int sysclk;
+ struct clk *mclk;
+ struct regmap *regmap;
+ struct snd_pcm_hw_constraint_list *sysclk_constraints;
+ struct snd_soc_component *component;
+};
+
+/* es8323 register cache */
+static const struct reg_default es8323_reg_defaults[] = {
+ { ES8323_CONTROL1, 0x06 },
+ { ES8323_CONTROL2, 0x1c },
+ { ES8323_CHIPPOWER, 0xc3 },
+ { ES8323_ADCPOWER, 0xfc },
+ { ES8323_DACPOWER, 0xc0 },
+ { ES8323_CHIPLOPOW1, 0x00 },
+ { ES8323_CHIPLOPOW2, 0x00 },
+ { ES8323_ANAVOLMANAG, 0x7c },
+ { ES8323_MASTERMODE, 0x80 },
+ { ES8323_ADCCONTROL1, 0x00 },
+ { ES8323_ADCCONTROL2, 0x00 },
+ { ES8323_ADCCONTROL3, 0x06 },
+ { ES8323_ADCCONTROL4, 0x00 },
+ { ES8323_ADCCONTROL5, 0x06 },
+ { ES8323_ADCCONTROL6, 0x30 },
+ { ES8323_ADC_MUTE, 0x30 },
+ { ES8323_LADC_VOL, 0xc0 },
+ { ES8323_RADC_VOL, 0xc0 },
+ { ES8323_ADCCONTROL10, 0x38 },
+ { ES8323_ADCCONTROL11, 0xb0 },
+ { ES8323_ADCCONTROL12, 0x32 },
+ { ES8323_ADCCONTROL13, 0x06 },
+ { ES8323_ADCCONTROL14, 0x00 },
+ { ES8323_DACCONTROL1, 0x00 },
+ { ES8323_DACCONTROL2, 0x06 },
+ { ES8323_DAC_MUTE, 0x30 },
+ { ES8323_LDAC_VOL, 0xc0 },
+ { ES8323_RDAC_VOL, 0xc0 },
+ { ES8323_DACCONTROL6, 0x08 },
+ { ES8323_DACCONTROL7, 0x06 },
+ { ES8323_DACCONTROL8, 0x1f },
+ { ES8323_DACCONTROL9, 0xf7 },
+ { ES8323_DACCONTROL10, 0xfd },
+ { ES8323_DACCONTROL11, 0xff },
+ { ES8323_DACCONTROL12, 0x1f },
+ { ES8323_DACCONTROL13, 0xf7 },
+ { ES8323_DACCONTROL14, 0xfd },
+ { ES8323_DACCONTROL15, 0xff },
+ { ES8323_DACCONTROL16, 0x00 },
+ { ES8323_DACCONTROL17, 0x38 },
+ { ES8323_DACCONTROL18, 0x38 },
+ { ES8323_DACCONTROL19, 0x38 },
+ { ES8323_DACCONTROL20, 0x38 },
+ { ES8323_DACCONTROL21, 0x38 },
+ { ES8323_DACCONTROL22, 0x38 },
+ { ES8323_DACCONTROL23, 0x00 },
+ { ES8323_LOUT1_VOL, 0x00 },
+ { ES8323_ROUT1_VOL, 0x00 },
+};
+
+static const char *const es8323_stereo_3d_texts[] = { "No 3D ", "Level 1", "Level 2", "Level 3",
+ "Level 4", "Level 5", "Level 6", "Level 7" };
+static SOC_ENUM_SINGLE_DECL(es8323_stereo_3d_enum, ES8323_DACCONTROL7, 2, es8323_stereo_3d_texts);
+
+static const char *const es8323_alc_func_texts[] = { "Off", "Right", "Left", "Stereo" };
+static SOC_ENUM_SINGLE_DECL(es8323_alc_function_enum,
+ ES8323_ADCCONTROL10, 6, es8323_alc_func_texts);
+
+static const char *const es8323_ng_type_texts[] = { "Constant PGA Gain", "Mute ADC Output" };
+static SOC_ENUM_SINGLE_DECL(es8323_alc_ng_type_enum, ES8323_ADCCONTROL14, 1, es8323_ng_type_texts);
+
+static const char *const es8323_deemph_texts[] = { "None", "32Khz", "44.1Khz", "48Khz" };
+static SOC_ENUM_SINGLE_DECL(es8323_playback_deemphasis_enum,
+ ES8323_DACCONTROL6, 6, es8323_deemph_texts);
+
+static const char *const es8323_adcpol_texts[] = { "Normal", "L Invert",
+ "R Invert", "L + R Invert" };
+static SOC_ENUM_SINGLE_DECL(es8323_capture_polarity_enum,
+ ES8323_ADCCONTROL6, 6, es8323_adcpol_texts);
+
+static const DECLARE_TLV_DB_SCALE(es8323_adc_tlv, -9600, 50, 1);
+static const DECLARE_TLV_DB_SCALE(es8323_dac_tlv, -9600, 50, 1);
+static const DECLARE_TLV_DB_SCALE(es8323_out_tlv, -4500, 150, 0);
+static const DECLARE_TLV_DB_SCALE(es8323_bypass_tlv, 0, 300, 0);
+static const DECLARE_TLV_DB_SCALE(es8323_bypass_tlv2, -15, 300, 0);
+
+static const struct snd_kcontrol_new es8323_snd_controls[] = {
+ SOC_ENUM("3D Mode", es8323_stereo_3d_enum),
+ SOC_ENUM("ALC Capture Function", es8323_alc_function_enum),
+ SOC_ENUM("ALC Capture NG Type", es8323_alc_ng_type_enum),
+ SOC_ENUM("Playback De-emphasis", es8323_playback_deemphasis_enum),
+ SOC_ENUM("Capture Polarity", es8323_capture_polarity_enum),
+ SOC_SINGLE("ALC Capture ZC Switch", ES8323_ADCCONTROL13, 6, 1, 0),
+ SOC_SINGLE("ALC Capture Decay Time", ES8323_ADCCONTROL12, 4, 15, 0),
+ SOC_SINGLE("ALC Capture Attack Time", ES8323_ADCCONTROL12, 0, 15, 0),
+ SOC_SINGLE("ALC Capture NG Threshold", ES8323_ADCCONTROL14, 3, 31, 0),
+ SOC_SINGLE("ALC Capture NG Switch", ES8323_ADCCONTROL14, 0, 1, 0),
+ SOC_SINGLE("ZC Timeout Switch", ES8323_ADCCONTROL13, 6, 1, 0),
+ SOC_SINGLE("Capture Mute Switch", ES8323_ADC_MUTE, 2, 1, 0),
+ SOC_SINGLE_TLV("Left Channel Capture Volume", ES8323_ADCCONTROL1, 4, 8,
+ 0, es8323_bypass_tlv),
+ SOC_SINGLE_TLV("Right Channel Capture Volume", ES8323_ADCCONTROL1, 0,
+ 8, 0, es8323_bypass_tlv),
+ SOC_SINGLE_TLV("Left Mixer Left Bypass Volume", ES8323_DACCONTROL17, 3,
+ 7, 1, es8323_bypass_tlv2),
+ SOC_SINGLE_TLV("Right Mixer Right Bypass Volume", ES8323_DACCONTROL20,
+ 3, 7, 1, es8323_bypass_tlv2),
+ SOC_DOUBLE_R_TLV("PCM Volume", ES8323_LDAC_VOL, ES8323_RDAC_VOL,
+ 0, 192, 1, es8323_dac_tlv),
+ SOC_DOUBLE_R_TLV("Capture Digital Volume", ES8323_LADC_VOL,
+ ES8323_RADC_VOL, 0, 192, 1, es8323_adc_tlv),
+ SOC_DOUBLE_R_TLV("Output 1 Playback Volume", ES8323_LOUT1_VOL,
+ ES8323_ROUT1_VOL, 0, 33, 0, es8323_out_tlv),
+ SOC_DOUBLE_R_TLV("Output 2 Playback Volume", ES8323_LOUT2_VOL,
+ ES8323_ROUT2_VOL, 0, 33, 0, es8323_out_tlv),
+};
+
+/* Left DAC Route */
+static const char *const es8323_pga_sell[] = { "Line 1L", "Line 2L", "NC", "DifferentialL" };
+static SOC_ENUM_SINGLE_DECL(es8323_left_dac_enum, ES8323_ADCCONTROL2, 6, es8323_pga_sell);
+static const struct snd_kcontrol_new es8323_left_dac_mux_controls =
+ SOC_DAPM_ENUM("Left DAC Route", es8323_left_dac_enum);
+
+/* Right DAC Route */
+static const char *const es8323_pga_selr[] = { "Line 1R", "Line 2R", "NC", "DifferentialR" };
+static SOC_ENUM_SINGLE_DECL(es8323_right_dac_enum, ES8323_ADCCONTROL2, 4, es8323_pga_selr);
+static const struct snd_kcontrol_new es8323_right_dac_mux_controls =
+ SOC_DAPM_ENUM("Right DAC Route", es8323_right_dac_enum);
+
+/* Left Line Mux */
+static const char *const es8323_lin_sell[] = { "Line 1L", "Line 2L", "NC", "MicL" };
+static SOC_ENUM_SINGLE_DECL(es8323_llin_enum, ES8323_DACCONTROL16, 3, es8323_lin_sell);
+static const struct snd_kcontrol_new es8323_left_line_controls =
+ SOC_DAPM_ENUM("LLIN Mux", es8323_llin_enum);
+
+/* Right Line Mux */
+static const char *const es8323_lin_selr[] = { "Line 1R", "Line 2R", "NC", "MicR" };
+static SOC_ENUM_SINGLE_DECL(es8323_rlin_enum, ES8323_DACCONTROL16, 0, es8323_lin_selr);
+static const struct snd_kcontrol_new es8323_right_line_controls =
+ SOC_DAPM_ENUM("RLIN Mux", es8323_rlin_enum);
+
+/* Differential Mux */
+static const char *const es8323_diffmux_sel[] = { "Line 1", "Line 2" };
+static SOC_ENUM_SINGLE_DECL(es8323_diffmux_enum, ES8323_ADCCONTROL3, 7, es8323_diffmux_sel);
+static const struct snd_kcontrol_new es8323_diffmux_controls =
+ SOC_DAPM_ENUM("Route2", es8323_diffmux_enum);
+
+/* Mono ADC Mux */
+static const char *const es8323_mono_adc_mux[] = { "Stereo", "Mono (Left)", "Mono (Right)" };
+static SOC_ENUM_SINGLE_DECL(es8323_mono_adc_mux_enum, ES8323_ADCCONTROL3, 3, es8323_mono_adc_mux);
+static const struct snd_kcontrol_new es8323_mono_adc_mux_controls =
+ SOC_DAPM_ENUM("Mono Mux", es8323_mono_adc_mux_enum);
+
+/* Left Mixer */
+static const struct snd_kcontrol_new es8323_left_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Left Playback Switch", SND_SOC_NOPM, 7, 1, 1),
+ SOC_DAPM_SINGLE("Left Bypass Switch", ES8323_DACCONTROL17, 6, 1, 0),
+};
+
+/* Right Mixer */
+static const struct snd_kcontrol_new es8323_right_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Right Playback Switch", SND_SOC_NOPM, 6, 1, 1),
+ SOC_DAPM_SINGLE("Right Bypass Switch", ES8323_DACCONTROL20, 6, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget es8323_dapm_widgets[] = {
+ SND_SOC_DAPM_INPUT("LINPUT1"),
+ SND_SOC_DAPM_INPUT("LINPUT2"),
+ SND_SOC_DAPM_INPUT("RINPUT1"),
+ SND_SOC_DAPM_INPUT("RINPUT2"),
+
+ SND_SOC_DAPM_MICBIAS("Mic Bias", SND_SOC_NOPM, 3, 1),
+
+ /* Muxes */
+ SND_SOC_DAPM_MUX("Left PGA Mux", SND_SOC_NOPM, 0, 0, &es8323_left_dac_mux_controls),
+ SND_SOC_DAPM_MUX("Right PGA Mux", SND_SOC_NOPM, 0, 0, &es8323_right_dac_mux_controls),
+ SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0, &es8323_diffmux_controls),
+ SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0, &es8323_mono_adc_mux_controls),
+ SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0, &es8323_mono_adc_mux_controls),
+ SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0, &es8323_left_line_controls),
+ SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0, &es8323_right_line_controls),
+
+ SND_SOC_DAPM_ADC("Right ADC", "Right Capture", SND_SOC_NOPM, 4, 1),
+ SND_SOC_DAPM_ADC("Left ADC", "Left Capture", SND_SOC_NOPM, 5, 1),
+ SND_SOC_DAPM_DAC("Right DAC", "Right Playback", SND_SOC_NOPM, 6, 1),
+ SND_SOC_DAPM_DAC("Left DAC", "Left Playback", SND_SOC_NOPM, 7, 1),
+
+ SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
+ &es8323_left_mixer_controls[0],
+ ARRAY_SIZE(es8323_left_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
+ &es8323_right_mixer_controls[0],
+ ARRAY_SIZE(es8323_right_mixer_controls)),
+
+ SND_SOC_DAPM_PGA("Right ADC Power", SND_SOC_NOPM, 6, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Left ADC Power", SND_SOC_NOPM, 7, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Right Out 2", SND_SOC_NOPM, 2, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Left Out 2", SND_SOC_NOPM, 3, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Right Out 1", SND_SOC_NOPM, 4, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Left Out 1", SND_SOC_NOPM, 5, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("LAMP", ES8323_ADCCONTROL1, 4, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("RAMP", ES8323_ADCCONTROL1, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_OUTPUT("LOUT1"),
+ SND_SOC_DAPM_OUTPUT("ROUT1"),
+ SND_SOC_DAPM_OUTPUT("LOUT2"),
+ SND_SOC_DAPM_OUTPUT("ROUT2"),
+ SND_SOC_DAPM_OUTPUT("VREF"),
+};
+
+static const struct snd_soc_dapm_route es8323_dapm_routes[] = {
+ /*12.22*/
+ {"Left PGA Mux", "Line 1L", "LINPUT1"},
+ {"Left PGA Mux", "Line 2L", "LINPUT2"},
+ {"Left PGA Mux", "DifferentialL", "Differential Mux"},
+
+ {"Right PGA Mux", "Line 1R", "RINPUT1"},
+ {"Right PGA Mux", "Line 2R", "RINPUT2"},
+ {"Right PGA Mux", "DifferentialR", "Differential Mux"},
+
+ {"Differential Mux", "Line 1", "LINPUT1"},
+ {"Differential Mux", "Line 1", "RINPUT1"},
+ {"Differential Mux", "Line 2", "LINPUT2"},
+ {"Differential Mux", "Line 2", "RINPUT2"},
+
+ {"Left ADC Mux", "Stereo", "Right PGA Mux"},
+ {"Left ADC Mux", "Stereo", "Left PGA Mux"},
+ {"Left ADC Mux", "Mono (Left)", "Left PGA Mux"},
+
+ {"Right ADC Mux", "Stereo", "Left PGA Mux"},
+ {"Right ADC Mux", "Stereo", "Right PGA Mux"},
+ {"Right ADC Mux", "Mono (Right)", "Right PGA Mux"},
+
+ {"Left ADC Power", NULL, "Left ADC Mux"},
+ {"Right ADC Power", NULL, "Right ADC Mux"},
+ {"Left ADC", NULL, "Left ADC Power"},
+ {"Right ADC", NULL, "Right ADC Power"},
+
+ {"Left Line Mux", "Line 1L", "LINPUT1"},
+ {"Left Line Mux", "Line 2L", "LINPUT2"},
+ {"Left Line Mux", "MicL", "Left PGA Mux"},
+
+ {"Right Line Mux", "Line 1R", "RINPUT1"},
+ {"Right Line Mux", "Line 2R", "RINPUT2"},
+ {"Right Line Mux", "MicR", "Right PGA Mux"},
+
+ {"Left Mixer", "Left Playback Switch", "Left DAC"},
+ {"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
+
+ {"Right Mixer", "Right Playback Switch", "Right DAC"},
+ {"Right Mixer", "Right Bypass Switch", "Right Line Mux"},
+
+ {"Left Out 1", NULL, "Left Mixer"},
+ {"LOUT1", NULL, "Left Out 1"},
+ {"Right Out 1", NULL, "Right Mixer"},
+ {"ROUT1", NULL, "Right Out 1"},
+
+ {"Left Out 2", NULL, "Left Mixer"},
+ {"LOUT2", NULL, "Left Out 2"},
+ {"Right Out 2", NULL, "Right Mixer"},
+ {"ROUT2", NULL, "Right Out 2"},
+};
+
+struct coeff_div {
+ u32 mclk;
+ u32 rate;
+ u16 fs;
+ u8 sr:4;
+ u8 usb:1;
+};
+
+/* codec hifi mclk clock divider coefficients */
+static const struct coeff_div es8323_coeff_div[] = {
+ /* 8k */
+ {12288000, 8000, 1536, 0xa, 0x0},
+ {11289600, 8000, 1408, 0x9, 0x0},
+ {18432000, 8000, 2304, 0xc, 0x0},
+ {16934400, 8000, 2112, 0xb, 0x0},
+ {12000000, 8000, 1500, 0xb, 0x1},
+
+ /* 11.025k */
+ {11289600, 11025, 1024, 0x7, 0x0},
+ {16934400, 11025, 1536, 0xa, 0x0},
+ {12000000, 11025, 1088, 0x9, 0x1},
+
+ /* 16k */
+ {12288000, 16000, 768, 0x6, 0x0},
+ {18432000, 16000, 1152, 0x8, 0x0},
+ {12000000, 16000, 750, 0x7, 0x1},
+
+ /* 22.05k */
+ {11289600, 22050, 512, 0x4, 0x0},
+ {16934400, 22050, 768, 0x6, 0x0},
+ {12000000, 22050, 544, 0x6, 0x1},
+
+ /* 32k */
+ {12288000, 32000, 384, 0x3, 0x0},
+ {18432000, 32000, 576, 0x5, 0x0},
+ {12000000, 32000, 375, 0x4, 0x1},
+
+ /* 44.1k */
+ {11289600, 44100, 256, 0x2, 0x0},
+ {16934400, 44100, 384, 0x3, 0x0},
+ {12000000, 44100, 272, 0x3, 0x1},
+
+ /* 48k */
+ {12288000, 48000, 256, 0x2, 0x0},
+ {18432000, 48000, 384, 0x3, 0x0},
+ {12000000, 48000, 250, 0x2, 0x1},
+
+ /* 88.2k */
+ {11289600, 88200, 128, 0x0, 0x0},
+ {16934400, 88200, 192, 0x1, 0x0},
+ {12000000, 88200, 136, 0x1, 0x1},
+
+ /* 96k */
+ {12288000, 96000, 128, 0x0, 0x0},
+ {18432000, 96000, 192, 0x1, 0x0},
+ {12000000, 96000, 125, 0x0, 0x1},
+};
+
+static unsigned int rates_12288[] = {
+ 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_12288 = {
+ .count = ARRAY_SIZE(rates_12288),
+ .list = rates_12288,
+};
+
+static unsigned int rates_112896[] = {
+ 8000, 11025, 22050, 44100,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_112896 = {
+ .count = ARRAY_SIZE(rates_112896),
+ .list = rates_112896,
+};
+
+static unsigned int rates_12[] = {
+ 8000, 11025, 12000, 16000, 22050, 24000,
+ 32000, 44100, 48000, 48000, 88235, 96000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_12 = {
+ .count = ARRAY_SIZE(rates_12),
+ .list = rates_12,
+};
+
+static inline int get_coeff(int mclk, int rate)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(es8323_coeff_div); i++) {
+ if (es8323_coeff_div[i].rate == rate &&
+ es8323_coeff_div[i].mclk == mclk)
+ return i;
+ }
+
+ return -EINVAL;
+}
+
+static int es8323_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_component *component = codec_dai->component;
+ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component);
+
+ switch (freq) {
+ case 11289600:
+ case 18432000:
+ case 22579200:
+ case 36864000:
+ es8323->sysclk_constraints = &constraints_112896;
+ break;
+ case 12288000:
+ case 16934400:
+ case 24576000:
+ case 33868800:
+ es8323->sysclk_constraints = &constraints_12288;
+ break;
+ case 12000000:
+ case 24000000:
+ es8323->sysclk_constraints = &constraints_12;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ es8323->sysclk = freq;
+ return 0;
+}
+
+static int es8323_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+ struct snd_soc_component *component = codec_dai->component;
+ u8 iface = snd_soc_component_read(component, ES8323_MASTERMODE);
+ u8 adciface = snd_soc_component_read(component, ES8323_ADC_IFACE);
+ u8 daciface = snd_soc_component_read(component, ES8323_DAC_IFACE);
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_BC_FP:
+ iface |= 0x80;
+ break;
+ case SND_SOC_DAIFMT_BC_FC:
+ iface &= 0x7f;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ adciface &= 0xfc;
+ daciface &= 0xf8;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ adciface &= 0xfd;
+ daciface &= 0xf9;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ adciface &= 0xfe;
+ daciface &= 0xfa;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ adciface &= 0xff;
+ daciface &= 0xfb;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ iface &= 0xdf;
+ adciface &= 0xdf;
+ daciface &= 0xbf;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ iface |= 0x20;
+ adciface |= 0x20;
+ daciface |= 0x40;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface |= 0x20;
+ adciface &= 0xdf;
+ daciface &= 0xbf;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ iface &= 0xdf;
+ adciface |= 0x20;
+ daciface |= 0x40;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_component_write(component, ES8323_MASTERMODE, iface);
+ snd_soc_component_write(component, ES8323_ADC_IFACE, adciface);
+ snd_soc_component_write(component, ES8323_DAC_IFACE, daciface);
+
+ return 0;
+}
+
+static int es8323_pcm_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component);
+
+ if (es8323->sysclk) {
+ snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ es8323->sysclk_constraints);
+ }
+
+ return 0;
+}
+
+static int es8323_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 es8323_priv *es8323 = snd_soc_component_get_drvdata(component);
+ u16 srate = snd_soc_component_read(component, ES8323_MASTERMODE) & 0x80;
+ u16 adciface = snd_soc_component_read(component, ES8323_ADC_IFACE) & 0xe3;
+ u16 daciface = snd_soc_component_read(component, ES8323_DAC_IFACE) & 0xc7;
+ int coeff;
+
+ coeff = get_coeff(es8323->sysclk, params_rate(params));
+ if (coeff < 0) {
+ coeff = get_coeff(es8323->sysclk / 2, params_rate(params));
+ srate |= 0x40;
+ }
+
+ if (coeff < 0) {
+ dev_err(component->dev,
+ "Unable to configure sample rate %dHz with %dHz MCLK\n",
+ params_rate(params), es8323->sysclk);
+ return coeff;
+ }
+
+ /* bit size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ adciface |= 0xc;
+ daciface |= 0x18;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ adciface |= 0x4;
+ daciface |= 0x8;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ adciface |= 0x10;
+ daciface |= 0x20;
+ break;
+ }
+
+ snd_soc_component_write(component, ES8323_DAC_IFACE, daciface);
+ snd_soc_component_write(component, ES8323_ADC_IFACE, adciface);
+
+ snd_soc_component_write(component, ES8323_MASTERMODE, srate);
+ snd_soc_component_write(component, ES8323_ADCCONTROL5,
+ es8323_coeff_div[coeff].sr |
+ (es8323_coeff_div[coeff].usb) << 4);
+ snd_soc_component_write(component, ES8323_DACCONTROL2,
+ es8323_coeff_div[coeff].sr |
+ (es8323_coeff_div[coeff].usb) << 4);
+
+ snd_soc_component_write(component, ES8323_DACPOWER, 0x3c);
+
+ return 0;
+}
+
+static int es8323_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
+{
+ struct snd_soc_component *component = dai->component;
+ u32 val = mute ? 0x6 : 0x2;
+
+ snd_soc_component_write(component, ES8323_DAC_MUTE, val);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops es8323_ops = {
+ .startup = es8323_pcm_startup,
+ .hw_params = es8323_pcm_hw_params,
+ .set_fmt = es8323_set_dai_fmt,
+ .set_sysclk = es8323_set_dai_sysclk,
+ .mute_stream = es8323_mute_stream,
+};
+
+#define ES8323_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_driver es8323_dai = {
+ .name = "ES8323 HiFi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = ES8323_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = ES8323_FORMATS,
+ },
+ .ops = &es8323_ops,
+ .symmetric_rate = 1,
+};
+
+static int es8323_probe(struct snd_soc_component *component)
+{
+ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ es8323->component = component;
+
+ es8323->mclk = devm_clk_get_optional(component->dev, "mclk");
+ if (IS_ERR(es8323->mclk)) {
+ dev_err(component->dev, "unable to get mclk\n");
+ return PTR_ERR(es8323->mclk);
+ }
+
+ if (!es8323->mclk)
+ dev_warn(component->dev, "assuming static mclk\n");
+
+ ret = clk_prepare_enable(es8323->mclk);
+ if (ret) {
+ dev_err(component->dev, "unable to enable mclk\n");
+ return ret;
+ }
+
+ snd_soc_component_write(component, ES8323_CONTROL2, 0x60);
+ snd_soc_component_write(component, ES8323_CHIPPOWER, 0x00);
+ snd_soc_component_write(component, ES8323_DACCONTROL17, 0xB8);
+
+ return 0;
+}
+
+static int es8323_set_bias_level(struct snd_soc_component *component,
+ enum snd_soc_bias_level level)
+{
+ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ ret = clk_prepare_enable(es8323->mclk);
+ if (ret)
+ return ret;
+
+ snd_soc_component_write(component, ES8323_CHIPPOWER, 0xf0);
+ usleep_range(18000, 20000);
+ snd_soc_component_write(component, ES8323_DACPOWER, 0x3c);
+ snd_soc_component_write(component, ES8323_ANAVOLMANAG, 0x7c);
+ snd_soc_component_write(component, ES8323_CHIPLOPOW1, 0x00);
+ snd_soc_component_write(component, ES8323_CHIPLOPOW2, 0x00);
+ snd_soc_component_write(component, ES8323_CHIPPOWER, 0x00);
+ snd_soc_component_write(component, ES8323_ADCPOWER, 0x09);
+ snd_soc_component_write(component, ES8323_ADCCONTROL14, 0x00);
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ snd_soc_component_write(component, ES8323_ANAVOLMANAG, 0x7c);
+ snd_soc_component_write(component, ES8323_CHIPLOPOW1, 0x00);
+ snd_soc_component_write(component, ES8323_CHIPLOPOW2, 0x00);
+ snd_soc_component_write(component, ES8323_CHIPPOWER, 0x00);
+ snd_soc_component_write(component, ES8323_ADCPOWER, 0x59);
+ break;
+ case SND_SOC_BIAS_OFF:
+ clk_disable_unprepare(es8323->mclk);
+ snd_soc_component_write(component, ES8323_ADCPOWER, 0xff);
+ snd_soc_component_write(component, ES8323_DACPOWER, 0xC0);
+ snd_soc_component_write(component, ES8323_CHIPLOPOW1, 0xff);
+ snd_soc_component_write(component, ES8323_CHIPLOPOW2, 0xff);
+ snd_soc_component_write(component, ES8323_CHIPPOWER, 0xff);
+ snd_soc_component_write(component, ES8323_ANAVOLMANAG, 0x7b);
+ break;
+ }
+
+ return 0;
+}
+
+static void es8323_remove(struct snd_soc_component *component)
+{
+ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component);
+
+ clk_disable_unprepare(es8323->mclk);
+ es8323_set_bias_level(component, SND_SOC_BIAS_OFF);
+}
+
+static int es8323_suspend(struct snd_soc_component *component)
+{
+ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component);
+
+ regcache_cache_only(es8323->regmap, true);
+ regcache_mark_dirty(es8323->regmap);
+
+ return 0;
+}
+
+static int es8323_resume(struct snd_soc_component *component)
+{
+ struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component);
+
+ regcache_cache_only(es8323->regmap, false);
+ regcache_sync(es8323->regmap);
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver soc_component_dev_es8323 = {
+ .probe = es8323_probe,
+ .remove = es8323_remove,
+ .suspend = es8323_suspend,
+ .resume = es8323_resume,
+ .set_bias_level = es8323_set_bias_level,
+ .controls = es8323_snd_controls,
+ .num_controls = ARRAY_SIZE(es8323_snd_controls),
+ .dapm_widgets = es8323_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(es8323_dapm_widgets),
+ .dapm_routes = es8323_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(es8323_dapm_routes),
+ .use_pmdown_time = 1,
+ .endianness = 1,
+};
+
+static const struct regmap_config es8323_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .use_single_read = true,
+ .use_single_write = true,
+ .max_register = 0x53,
+ .reg_defaults = es8323_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(es8323_reg_defaults),
+ .cache_type = REGCACHE_MAPLE,
+};
+
+static int es8323_i2c_probe(struct i2c_client *i2c_client)
+{
+ struct es8323_priv *es8323;
+ struct device *dev = &i2c_client->dev;
+
+ es8323 = devm_kzalloc(dev, sizeof(*es8323), GFP_KERNEL);
+ if (!es8323)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c_client, es8323);
+
+ es8323->regmap = devm_regmap_init_i2c(i2c_client, &es8323_regmap);
+ if (IS_ERR(es8323->regmap))
+ return PTR_ERR(es8323->regmap);
+
+ return devm_snd_soc_register_component(dev,
+ &soc_component_dev_es8323,
+ &es8323_dai, 1);
+}
+
+static const struct i2c_device_id es8323_i2c_id[] = {
+ { "es8323", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, es8323_i2c_id);
+
+static const struct acpi_device_id es8323_acpi_match[] = {
+ { "ESSX8323", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, es8323_acpi_match);
+
+static const struct of_device_id es8323_of_match[] = {
+ { .compatible = "everest,es8323" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, es8323_of_match);
+
+static struct i2c_driver es8323_i2c_driver = {
+ .driver = {
+ .name = "ES8323",
+ .acpi_match_table = es8323_acpi_match,
+ .of_match_table = es8323_of_match,
+ },
+ .probe = es8323_i2c_probe,
+ .id_table = es8323_i2c_id,
+};
+module_i2c_driver(es8323_i2c_driver);
+
+MODULE_DESCRIPTION("Everest Semi ES8323 ALSA SoC Codec Driver");
+MODULE_AUTHOR("Mark Brown <broonie@kernel.org>");
+MODULE_AUTHOR("Binbin Zhou <zhoubinbin@loongson.cn>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/es8323.h b/sound/soc/codecs/es8323.h
new file mode 100644
index 000000000000..f986c9301dc6
--- /dev/null
+++ b/sound/soc/codecs/es8323.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright Openedhand Ltd.
+ *
+ * Author: Richard Purdie <richard@openedhand.com>
+ * Binbin Zhou <zhoubinbin@loongson.cn>
+ *
+ */
+
+#ifndef _ES8323_H
+#define _ES8323_H
+
+/* ES8323 register space */
+
+/* Chip Control and Power Management */
+#define ES8323_CONTROL1 0x00
+#define ES8323_CONTROL2 0x01
+#define ES8323_CHIPPOWER 0x02
+#define ES8323_ADCPOWER 0x03
+#define ES8323_DACPOWER 0x04
+#define ES8323_CHIPLOPOW1 0x05
+#define ES8323_CHIPLOPOW2 0x06
+#define ES8323_ANAVOLMANAG 0x07
+#define ES8323_MASTERMODE 0x08
+
+/* ADC Control */
+#define ES8323_ADCCONTROL1 0x09
+#define ES8323_ADCCONTROL2 0x0a
+#define ES8323_ADCCONTROL3 0x0b
+#define ES8323_ADCCONTROL4 0x0c
+#define ES8323_ADCCONTROL5 0x0d
+#define ES8323_ADCCONTROL6 0x0e
+#define ES8323_ADC_MUTE 0x0f
+#define ES8323_LADC_VOL 0x10
+#define ES8323_RADC_VOL 0x11
+#define ES8323_ADCCONTROL10 0x12
+#define ES8323_ADCCONTROL11 0x13
+#define ES8323_ADCCONTROL12 0x14
+#define ES8323_ADCCONTROL13 0x15
+#define ES8323_ADCCONTROL14 0x16
+
+/* DAC Control */
+#define ES8323_DACCONTROL1 0x17
+#define ES8323_DACCONTROL2 0x18
+#define ES8323_DAC_MUTE 0x19
+#define ES8323_LDAC_VOL 0x1a
+#define ES8323_RDAC_VOL 0x1b
+#define ES8323_DACCONTROL6 0x1c
+#define ES8323_DACCONTROL7 0x1d
+#define ES8323_DACCONTROL8 0x1e
+#define ES8323_DACCONTROL9 0x1f
+#define ES8323_DACCONTROL10 0x20
+#define ES8323_DACCONTROL11 0x21
+#define ES8323_DACCONTROL12 0x22
+#define ES8323_DACCONTROL13 0x23
+#define ES8323_DACCONTROL14 0x24
+#define ES8323_DACCONTROL15 0x25
+#define ES8323_DACCONTROL16 0x26
+#define ES8323_DACCONTROL17 0x27
+#define ES8323_DACCONTROL18 0x28
+#define ES8323_DACCONTROL19 0x29
+#define ES8323_DACCONTROL20 0x2a
+#define ES8323_DACCONTROL21 0x2b
+#define ES8323_DACCONTROL22 0x2c
+#define ES8323_DACCONTROL23 0x2d
+#define ES8323_LOUT1_VOL 0x2e
+#define ES8323_ROUT1_VOL 0x2f
+#define ES8323_LOUT2_VOL 0x30
+#define ES8323_ROUT2_VOL 0x31
+#define ES8323_DACCONTROL28 0x32
+#define ES8323_DACCONTROL29 0x33
+#define ES8323_DACCONTROL30 0x34
+
+#define ES8323_ADC_IFACE ES8323_ADCCONTROL4
+#define ES8323_ADC_SRATE ES8323_ADCCONTROL5
+#define ES8323_DAC_IFACE ES8323_DACCONTROL1
+#define ES8323_DAC_SRATE ES8323_DACCONTROL2
+#endif
diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c
index d5362b3be484..a5603b617688 100644
--- a/sound/soc/codecs/es8326.c
+++ b/sound/soc/codecs/es8326.c
@@ -614,6 +614,10 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction)
} else {
regmap_update_bits(es8326->regmap, ES8326_ADC_MUTE,
0x0F, 0x0F);
+ if (es8326->version > ES8326_VERSION_B) {
+ regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40);
+ regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x10);
+ }
}
} else {
if (!es8326->calibrated) {
@@ -640,6 +644,10 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction)
ES8326_MUTE_MASK, ~(ES8326_MUTE));
} else {
msleep(300);
+ if (es8326->version > ES8326_VERSION_B) {
+ regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x70, 0x50);
+ regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x00);
+ }
regmap_update_bits(es8326->regmap, ES8326_ADC_MUTE,
0x0F, 0x00);
}
@@ -821,7 +829,7 @@ static void es8326_jack_detect_handler(struct work_struct *work)
iface = snd_soc_component_read(comp, ES8326_HPDET_STA);
dev_dbg(comp->dev, "gpio flag %#04x", iface);
- if ((es8326->jack_remove_retry == 1) && (es8326->version != ES8326_VERSION_B)) {
+ if ((es8326->jack_remove_retry == 1) && (es8326->version < ES8326_VERSION_B)) {
if (iface & ES8326_HPINSERT_FLAG)
es8326->jack_remove_retry = 2;
else
@@ -859,7 +867,7 @@ static void es8326_jack_detect_handler(struct work_struct *work)
/*
* Inverted HPJACK_POL bit to trigger one IRQ to double check HP Removal event
*/
- if ((es8326->jack_remove_retry == 0) && (es8326->version != ES8326_VERSION_B)) {
+ if ((es8326->jack_remove_retry == 0) && (es8326->version < ES8326_VERSION_B)) {
es8326->jack_remove_retry = 1;
dev_dbg(comp->dev, "remove event check, invert HPJACK_POL, cnt = %d\n",
es8326->jack_remove_retry);
@@ -954,7 +962,7 @@ static int es8326_calibrate(struct snd_soc_component *component)
regmap_read(es8326->regmap, ES8326_CHIP_VERSION, &reg);
es8326->version = reg;
- if ((es8326->version == ES8326_VERSION_B) && (es8326->calibrated == false)) {
+ if ((es8326->version >= ES8326_VERSION_B) && (es8326->calibrated == false)) {
dev_dbg(component->dev, "ES8326_VERSION_B, calibrating\n");
regmap_write(es8326->regmap, ES8326_CLK_INV, 0xc0);
regmap_write(es8326->regmap, ES8326_CLK_DIV1, 0x03);
@@ -1047,7 +1055,7 @@ static void es8326_init(struct snd_soc_component *component)
regmap_write(es8326->regmap, ES8326_DAC_VPPSCALE, 0x15);
regmap_write(es8326->regmap, ES8326_HPDET_TYPE, 0x80 |
- ((es8326->version == ES8326_VERSION_B) ?
+ ((es8326->version >= ES8326_VERSION_B) ?
(ES8326_HP_DET_SRC_PIN9 | es8326->jack_pol) :
(ES8326_HP_DET_SRC_PIN9 | es8326->jack_pol | 0x04)));
usleep_range(5000, 10000);
@@ -1073,6 +1081,10 @@ static void es8326_init(struct snd_soc_component *component)
regmap_write(es8326->regmap, ES8326_ADC1_SRC, 0x44);
regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x66);
es8326_disable_micbias(es8326->component);
+ if (es8326->version > ES8326_VERSION_B) {
+ regmap_update_bits(es8326->regmap, ES8326_ANA_MICBIAS, 0x73, 0x13);
+ regmap_update_bits(es8326->regmap, ES8326_VMIDSEL, 0x40, 0x40);
+ }
msleep(200);
regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9);
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 74caae52e127..d9df29a26f4f 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -185,84 +185,97 @@ static const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = {
/*
* hdmi_codec_channel_alloc: speaker configuration available for CEA
*
- * This is an ordered list that must match with hdmi_codec_8ch_chmaps struct
+ * This is an ordered list where ca_id must exist in hdmi_codec_8ch_chmaps
* The preceding ones have better chances to be selected by
* hdmi_codec_get_ch_alloc_table_idx().
*/
static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = {
{ .ca_id = 0x00, .n_ch = 2,
- .mask = FL | FR},
- /* 2.1 */
- { .ca_id = 0x01, .n_ch = 4,
- .mask = FL | FR | LFE},
- /* Dolby Surround */
+ .mask = FL | FR },
+ { .ca_id = 0x03, .n_ch = 4,
+ .mask = FL | FR | LFE | FC },
{ .ca_id = 0x02, .n_ch = 4,
.mask = FL | FR | FC },
- /* surround51 */
+ { .ca_id = 0x01, .n_ch = 4,
+ .mask = FL | FR | LFE },
{ .ca_id = 0x0b, .n_ch = 6,
- .mask = FL | FR | LFE | FC | RL | RR},
- /* surround40 */
- { .ca_id = 0x08, .n_ch = 6,
- .mask = FL | FR | RL | RR },
- /* surround41 */
- { .ca_id = 0x09, .n_ch = 6,
- .mask = FL | FR | LFE | RL | RR },
- /* surround50 */
+ .mask = FL | FR | LFE | FC | RL | RR },
{ .ca_id = 0x0a, .n_ch = 6,
.mask = FL | FR | FC | RL | RR },
- /* 6.1 */
- { .ca_id = 0x0f, .n_ch = 8,
- .mask = FL | FR | LFE | FC | RL | RR | RC },
- /* surround71 */
+ { .ca_id = 0x09, .n_ch = 6,
+ .mask = FL | FR | LFE | RL | RR },
+ { .ca_id = 0x08, .n_ch = 6,
+ .mask = FL | FR | RL | RR },
+ { .ca_id = 0x07, .n_ch = 6,
+ .mask = FL | FR | LFE | FC | RC },
+ { .ca_id = 0x06, .n_ch = 6,
+ .mask = FL | FR | FC | RC },
+ { .ca_id = 0x05, .n_ch = 6,
+ .mask = FL | FR | LFE | RC },
+ { .ca_id = 0x04, .n_ch = 6,
+ .mask = FL | FR | RC },
{ .ca_id = 0x13, .n_ch = 8,
.mask = FL | FR | LFE | FC | RL | RR | RLC | RRC },
- /* others */
- { .ca_id = 0x03, .n_ch = 8,
- .mask = FL | FR | LFE | FC },
- { .ca_id = 0x04, .n_ch = 8,
- .mask = FL | FR | RC},
- { .ca_id = 0x05, .n_ch = 8,
- .mask = FL | FR | LFE | RC },
- { .ca_id = 0x06, .n_ch = 8,
- .mask = FL | FR | FC | RC },
- { .ca_id = 0x07, .n_ch = 8,
- .mask = FL | FR | LFE | FC | RC },
- { .ca_id = 0x0c, .n_ch = 8,
- .mask = FL | FR | RC | RL | RR },
- { .ca_id = 0x0d, .n_ch = 8,
- .mask = FL | FR | LFE | RL | RR | RC },
- { .ca_id = 0x0e, .n_ch = 8,
- .mask = FL | FR | FC | RL | RR | RC },
- { .ca_id = 0x10, .n_ch = 8,
- .mask = FL | FR | RL | RR | RLC | RRC },
- { .ca_id = 0x11, .n_ch = 8,
- .mask = FL | FR | LFE | RL | RR | RLC | RRC },
+ { .ca_id = 0x1f, .n_ch = 8,
+ .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC },
{ .ca_id = 0x12, .n_ch = 8,
.mask = FL | FR | FC | RL | RR | RLC | RRC },
- { .ca_id = 0x14, .n_ch = 8,
- .mask = FL | FR | FLC | FRC },
- { .ca_id = 0x15, .n_ch = 8,
- .mask = FL | FR | LFE | FLC | FRC },
- { .ca_id = 0x16, .n_ch = 8,
- .mask = FL | FR | FC | FLC | FRC },
- { .ca_id = 0x17, .n_ch = 8,
- .mask = FL | FR | LFE | FC | FLC | FRC },
- { .ca_id = 0x18, .n_ch = 8,
- .mask = FL | FR | RC | FLC | FRC },
- { .ca_id = 0x19, .n_ch = 8,
- .mask = FL | FR | LFE | RC | FLC | FRC },
- { .ca_id = 0x1a, .n_ch = 8,
- .mask = FL | FR | RC | FC | FLC | FRC },
- { .ca_id = 0x1b, .n_ch = 8,
- .mask = FL | FR | LFE | RC | FC | FLC | FRC },
- { .ca_id = 0x1c, .n_ch = 8,
- .mask = FL | FR | RL | RR | FLC | FRC },
- { .ca_id = 0x1d, .n_ch = 8,
- .mask = FL | FR | LFE | RL | RR | FLC | FRC },
{ .ca_id = 0x1e, .n_ch = 8,
.mask = FL | FR | FC | RL | RR | FLC | FRC },
- { .ca_id = 0x1f, .n_ch = 8,
- .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC },
+ { .ca_id = 0x11, .n_ch = 8,
+ .mask = FL | FR | LFE | RL | RR | RLC | RRC },
+ { .ca_id = 0x1d, .n_ch = 8,
+ .mask = FL | FR | LFE | RL | RR | FLC | FRC },
+ { .ca_id = 0x10, .n_ch = 8,
+ .mask = FL | FR | RL | RR | RLC | RRC },
+ { .ca_id = 0x1c, .n_ch = 8,
+ .mask = FL | FR | RL | RR | FLC | FRC },
+ { .ca_id = 0x0f, .n_ch = 8,
+ .mask = FL | FR | LFE | FC | RL | RR | RC },
+ { .ca_id = 0x1b, .n_ch = 8,
+ .mask = FL | FR | LFE | RC | FC | FLC | FRC },
+ { .ca_id = 0x0e, .n_ch = 8,
+ .mask = FL | FR | FC | RL | RR | RC },
+ { .ca_id = 0x1a, .n_ch = 8,
+ .mask = FL | FR | RC | FC | FLC | FRC },
+ { .ca_id = 0x0d, .n_ch = 8,
+ .mask = FL | FR | LFE | RL | RR | RC },
+ { .ca_id = 0x19, .n_ch = 8,
+ .mask = FL | FR | LFE | RC | FLC | FRC },
+ { .ca_id = 0x0c, .n_ch = 8,
+ .mask = FL | FR | RC | RL | RR },
+ { .ca_id = 0x18, .n_ch = 8,
+ .mask = FL | FR | RC | FLC | FRC },
+ { .ca_id = 0x17, .n_ch = 8,
+ .mask = FL | FR | LFE | FC | FLC | FRC },
+ { .ca_id = 0x16, .n_ch = 8,
+ .mask = FL | FR | FC | FLC | FRC },
+ { .ca_id = 0x15, .n_ch = 8,
+ .mask = FL | FR | LFE | FLC | FRC },
+ { .ca_id = 0x14, .n_ch = 8,
+ .mask = FL | FR | FLC | FRC },
+ { .ca_id = 0x0b, .n_ch = 8,
+ .mask = FL | FR | LFE | FC | RL | RR },
+ { .ca_id = 0x0a, .n_ch = 8,
+ .mask = FL | FR | FC | RL | RR },
+ { .ca_id = 0x09, .n_ch = 8,
+ .mask = FL | FR | LFE | RL | RR },
+ { .ca_id = 0x08, .n_ch = 8,
+ .mask = FL | FR | RL | RR },
+ { .ca_id = 0x07, .n_ch = 8,
+ .mask = FL | FR | LFE | FC | RC },
+ { .ca_id = 0x06, .n_ch = 8,
+ .mask = FL | FR | FC | RC },
+ { .ca_id = 0x05, .n_ch = 8,
+ .mask = FL | FR | LFE | RC },
+ { .ca_id = 0x04, .n_ch = 8,
+ .mask = FL | FR | RC },
+ { .ca_id = 0x03, .n_ch = 8,
+ .mask = FL | FR | LFE | FC },
+ { .ca_id = 0x02, .n_ch = 8,
+ .mask = FL | FR | FC },
+ { .ca_id = 0x01, .n_ch = 8,
+ .mask = FL | FR | LFE },
};
struct hdmi_codec_priv {
@@ -371,7 +384,8 @@ static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol,
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
struct hdmi_codec_priv *hcp = info->private_data;
- map = info->chmap[hcp->chmap_idx].map;
+ if (hcp->chmap_idx != HDMI_CODEC_CHMAP_IDX_UNKNOWN)
+ map = info->chmap[hcp->chmap_idx].map;
for (i = 0; i < info->max_channels; i++) {
if (hcp->chmap_idx == HDMI_CODEC_CHMAP_IDX_UNKNOWN)
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c
index 71e0d3bffd3f..febbbe073962 100644
--- a/sound/soc/codecs/lpass-rx-macro.c
+++ b/sound/soc/codecs/lpass-rx-macro.c
@@ -202,12 +202,14 @@
#define CDC_RX_RXn_RX_PATH_SEC3(rx, n) (0x042c + rx->rxn_reg_stride * n)
#define CDC_RX_RX0_RX_PATH_SEC4 (0x0430)
#define CDC_RX_RX0_RX_PATH_SEC7 (0x0434)
-#define CDC_RX_RXn_RX_PATH_SEC7(rx, n) (0x0434 + rx->rxn_reg_stride * n)
+#define CDC_RX_RXn_RX_PATH_SEC7(rx, n) \
+ (0x0434 + (rx->rxn_reg_stride * n) + ((n > 1) ? rx->rxn_reg_stride2 : 0))
#define CDC_RX_DSM_OUT_DELAY_SEL_MASK GENMASK(2, 0)
#define CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE 0x2
#define CDC_RX_RX0_RX_PATH_MIX_SEC0 (0x0438)
#define CDC_RX_RX0_RX_PATH_MIX_SEC1 (0x043C)
-#define CDC_RX_RXn_RX_PATH_DSM_CTL(rx, n) (0x0440 + rx->rxn_reg_stride * n)
+#define CDC_RX_RXn_RX_PATH_DSM_CTL(rx, n) \
+ (0x0440 + (rx->rxn_reg_stride * n) + ((n > 1) ? rx->rxn_reg_stride2 : 0))
#define CDC_RX_RXn_DSM_CLK_EN_MASK BIT(0)
#define CDC_RX_RX0_RX_PATH_DSM_CTL (0x0440)
#define CDC_RX_RX0_RX_PATH_DSM_DATA1 (0x0444)
@@ -645,6 +647,7 @@ struct rx_macro {
int rx_mclk_cnt;
enum lpass_codec_version codec_version;
int rxn_reg_stride;
+ int rxn_reg_stride2;
bool is_ear_mode_on;
bool hph_pwr_mode;
bool hph_hd2_mode;
@@ -958,7 +961,7 @@ static const struct reg_default rx_defaults[] = {
{ CDC_RX_BCL_VBAT_PK_EST2, 0x01 },
{ CDC_RX_BCL_VBAT_PK_EST3, 0x40 },
{ CDC_RX_BCL_VBAT_RF_PROC1, 0x2A },
- { CDC_RX_BCL_VBAT_RF_PROC1, 0x00 },
+ { CDC_RX_BCL_VBAT_RF_PROC2, 0x00 },
{ CDC_RX_BCL_VBAT_TAC1, 0x00 },
{ CDC_RX_BCL_VBAT_TAC2, 0x18 },
{ CDC_RX_BCL_VBAT_TAC3, 0x18 },
@@ -1929,9 +1932,6 @@ static int rx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
}
- if (j == INTERP_AUX)
- dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(rx, 2);
-
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);
@@ -2702,9 +2702,6 @@ static int rx_macro_enable_interp_clk(struct snd_soc_component *component,
main_reg = CDC_RX_RXn_RX_PATH_CTL(rx, interp_idx);
dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(rx, interp_idx);
- if (interp_idx == INTERP_AUX)
- dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(rx, 2);
-
rx_cfg2_reg = CDC_RX_RXn_RX_PATH_CFG2(rx, interp_idx);
if (SND_SOC_DAPM_EVENT_ON(event)) {
@@ -3821,6 +3818,7 @@ static int rx_macro_probe(struct platform_device *pdev)
case LPASS_CODEC_VERSION_2_0:
case LPASS_CODEC_VERSION_2_1:
rx->rxn_reg_stride = 0x80;
+ rx->rxn_reg_stride2 = 0xc;
def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_pre_2_5_defaults);
reg_defaults = kmalloc_array(def_count, sizeof(struct reg_default), GFP_KERNEL);
if (!reg_defaults)
@@ -3834,6 +3832,7 @@ static int rx_macro_probe(struct platform_device *pdev)
case LPASS_CODEC_VERSION_2_7:
case LPASS_CODEC_VERSION_2_8:
rx->rxn_reg_stride = 0xc0;
+ rx->rxn_reg_stride2 = 0x0;
def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_2_5_defaults);
reg_defaults = kmalloc_array(def_count, sizeof(struct reg_default), GFP_KERNEL);
if (!reg_defaults)
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
index e4793a5d179e..8af3c7e5317f 100644
--- a/sound/soc/codecs/max9768.c
+++ b/sound/soc/codecs/max9768.c
@@ -54,10 +54,17 @@ static int max9768_set_gpio(struct snd_kcontrol *kcontrol,
{
struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
struct max9768 *max9768 = snd_soc_component_get_drvdata(c);
+ bool val = !ucontrol->value.integer.value[0];
+ int ret;
- gpiod_set_value_cansleep(max9768->mute, !ucontrol->value.integer.value[0]);
+ if (val != gpiod_get_value_cansleep(max9768->mute))
+ ret = 1;
+ else
+ ret = 0;
- return 0;
+ gpiod_set_value_cansleep(max9768->mute, val);
+
+ return ret;
}
static const DECLARE_TLV_DB_RANGE(volume_tlv,
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 8b0645c63462..8915f5250695 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -480,12 +480,18 @@ static const struct snd_kcontrol_new max98088_snd_controls[] = {
SOC_SINGLE("INA Volume", M98088_REG_37_LVL_INA, 0, 7, 1),
SOC_SINGLE("INB Volume", M98088_REG_38_LVL_INB, 0, 7, 1),
+ SOC_SINGLE("DACL Volume", M98088_REG_2F_LVL_DAI1_PLAY, 0, 15, 1),
+ SOC_SINGLE("DACR Volume", M98088_REG_31_LVL_DAI2_PLAY, 0, 15, 1),
+
SOC_SINGLE("ADCL Volume", M98088_REG_33_LVL_ADC_L, 0, 15, 0),
SOC_SINGLE("ADCR Volume", M98088_REG_34_LVL_ADC_R, 0, 15, 0),
SOC_SINGLE("ADCL Boost Volume", M98088_REG_33_LVL_ADC_L, 4, 3, 0),
SOC_SINGLE("ADCR Boost Volume", M98088_REG_34_LVL_ADC_R, 4, 3, 0),
+ SOC_SINGLE("Left HP Output Mixer Switch", M98088_REG_27_MIX_HP_CNTL, 4, 1, 0),
+ SOC_SINGLE("Right HP Output Mixer Switch", M98088_REG_27_MIX_HP_CNTL, 5, 1, 0),
+
SOC_SINGLE("EQ1 Switch", M98088_REG_49_CFG_LEVEL, 0, 1, 0),
SOC_SINGLE("EQ2 Switch", M98088_REG_49_CFG_LEVEL, 1, 1, 0),
@@ -515,10 +521,8 @@ static const struct snd_kcontrol_new max98088_snd_controls[] = {
/* Left speaker mixer switch */
static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = {
- SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0),
- SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0),
- SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0),
- SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0),
SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 5, 1, 0),
SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 6, 1, 0),
SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 1, 1, 0),
@@ -529,10 +533,8 @@ static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = {
/* Right speaker mixer switch */
static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = {
- SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0),
- SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0),
- SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0),
- SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0),
+ SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0),
SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 5, 1, 0),
SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 6, 1, 0),
SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 1, 1, 0),
@@ -543,10 +545,8 @@ static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = {
/* Left headphone mixer switch */
static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = {
- SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0),
- SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0),
- SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0),
- SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0),
SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_25_MIX_HP_LEFT, 5, 1, 0),
SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_25_MIX_HP_LEFT, 6, 1, 0),
SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_25_MIX_HP_LEFT, 1, 1, 0),
@@ -557,10 +557,8 @@ static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = {
/* Right headphone mixer switch */
static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = {
- SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0),
- SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0),
- SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0),
- SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0),
+ SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0),
SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 5, 1, 0),
SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 6, 1, 0),
SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_26_MIX_HP_RIGHT, 1, 1, 0),
@@ -571,10 +569,8 @@ static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = {
/* Left earpiece/receiver mixer switch */
static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = {
- SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0),
- SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0),
- SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0),
- SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0),
SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_28_MIX_REC_LEFT, 5, 1, 0),
SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_28_MIX_REC_LEFT, 6, 1, 0),
SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_28_MIX_REC_LEFT, 1, 1, 0),
@@ -585,10 +581,8 @@ static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = {
/* Right earpiece/receiver mixer switch */
static const struct snd_kcontrol_new max98088_right_rec_mixer_controls[] = {
- SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0),
- SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0),
- SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0),
- SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0),
+ SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0),
SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 5, 1, 0),
SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 6, 1, 0),
SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_29_MIX_REC_RIGHT, 1, 1, 0),
@@ -717,13 +711,9 @@ static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = {
SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 1, 0),
SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 0, 0),
- SND_SOC_DAPM_DAC("DACL1", "HiFi Playback",
- M98088_REG_4D_PWR_EN_OUT, 1, 0),
- SND_SOC_DAPM_DAC("DACR1", "HiFi Playback",
- M98088_REG_4D_PWR_EN_OUT, 0, 0),
- SND_SOC_DAPM_DAC("DACL2", "Aux Playback",
+ SND_SOC_DAPM_DAC("DACL", "HiFi Playback",
M98088_REG_4D_PWR_EN_OUT, 1, 0),
- SND_SOC_DAPM_DAC("DACR2", "Aux Playback",
+ SND_SOC_DAPM_DAC("DACR", "HiFi Playback",
M98088_REG_4D_PWR_EN_OUT, 0, 0),
SND_SOC_DAPM_PGA("HP Left Out", M98088_REG_4D_PWR_EN_OUT,
@@ -819,10 +809,8 @@ static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = {
static const struct snd_soc_dapm_route max98088_audio_map[] = {
/* Left headphone output mixer */
- {"Left HP Mixer", "Left DAC1 Switch", "DACL1"},
- {"Left HP Mixer", "Left DAC2 Switch", "DACL2"},
- {"Left HP Mixer", "Right DAC1 Switch", "DACR1"},
- {"Left HP Mixer", "Right DAC2 Switch", "DACR2"},
+ {"Left HP Mixer", "Left DAC Switch", "DACL"},
+ {"Left HP Mixer", "Right DAC Switch", "DACR"},
{"Left HP Mixer", "MIC1 Switch", "MIC1 Input"},
{"Left HP Mixer", "MIC2 Switch", "MIC2 Input"},
{"Left HP Mixer", "INA1 Switch", "INA1 Input"},
@@ -831,10 +819,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = {
{"Left HP Mixer", "INB2 Switch", "INB2 Input"},
/* Right headphone output mixer */
- {"Right HP Mixer", "Left DAC1 Switch", "DACL1"},
- {"Right HP Mixer", "Left DAC2 Switch", "DACL2" },
- {"Right HP Mixer", "Right DAC1 Switch", "DACR1"},
- {"Right HP Mixer", "Right DAC2 Switch", "DACR2"},
+ {"Right HP Mixer", "Left DAC Switch", "DACL"},
+ {"Right HP Mixer", "Right DAC Switch", "DACR"},
{"Right HP Mixer", "MIC1 Switch", "MIC1 Input"},
{"Right HP Mixer", "MIC2 Switch", "MIC2 Input"},
{"Right HP Mixer", "INA1 Switch", "INA1 Input"},
@@ -843,10 +829,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = {
{"Right HP Mixer", "INB2 Switch", "INB2 Input"},
/* Left speaker output mixer */
- {"Left SPK Mixer", "Left DAC1 Switch", "DACL1"},
- {"Left SPK Mixer", "Left DAC2 Switch", "DACL2"},
- {"Left SPK Mixer", "Right DAC1 Switch", "DACR1"},
- {"Left SPK Mixer", "Right DAC2 Switch", "DACR2"},
+ {"Left SPK Mixer", "Left DAC Switch", "DACL"},
+ {"Left SPK Mixer", "Right DAC Switch", "DACR"},
{"Left SPK Mixer", "MIC1 Switch", "MIC1 Input"},
{"Left SPK Mixer", "MIC2 Switch", "MIC2 Input"},
{"Left SPK Mixer", "INA1 Switch", "INA1 Input"},
@@ -855,10 +839,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = {
{"Left SPK Mixer", "INB2 Switch", "INB2 Input"},
/* Right speaker output mixer */
- {"Right SPK Mixer", "Left DAC1 Switch", "DACL1"},
- {"Right SPK Mixer", "Left DAC2 Switch", "DACL2"},
- {"Right SPK Mixer", "Right DAC1 Switch", "DACR1"},
- {"Right SPK Mixer", "Right DAC2 Switch", "DACR2"},
+ {"Right SPK Mixer", "Left DAC Switch", "DACL"},
+ {"Right SPK Mixer", "Right DAC Switch", "DACR"},
{"Right SPK Mixer", "MIC1 Switch", "MIC1 Input"},
{"Right SPK Mixer", "MIC2 Switch", "MIC2 Input"},
{"Right SPK Mixer", "INA1 Switch", "INA1 Input"},
@@ -867,10 +849,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = {
{"Right SPK Mixer", "INB2 Switch", "INB2 Input"},
/* Earpiece/Receiver output mixer */
- {"Left REC Mixer", "Left DAC1 Switch", "DACL1"},
- {"Left REC Mixer", "Left DAC2 Switch", "DACL2"},
- {"Left REC Mixer", "Right DAC1 Switch", "DACR1"},
- {"Left REC Mixer", "Right DAC2 Switch", "DACR2"},
+ {"Left REC Mixer", "Left DAC Switch", "DACL"},
+ {"Left REC Mixer", "Right DAC Switch", "DACR"},
{"Left REC Mixer", "MIC1 Switch", "MIC1 Input"},
{"Left REC Mixer", "MIC2 Switch", "MIC2 Input"},
{"Left REC Mixer", "INA1 Switch", "INA1 Input"},
@@ -879,10 +859,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = {
{"Left REC Mixer", "INB2 Switch", "INB2 Input"},
/* Earpiece/Receiver output mixer */
- {"Right REC Mixer", "Left DAC1 Switch", "DACL1"},
- {"Right REC Mixer", "Left DAC2 Switch", "DACL2"},
- {"Right REC Mixer", "Right DAC1 Switch", "DACR1"},
- {"Right REC Mixer", "Right DAC2 Switch", "DACR2"},
+ {"Right REC Mixer", "Left DAC Switch", "DACL"},
+ {"Right REC Mixer", "Right DAC Switch", "DACR"},
{"Right REC Mixer", "MIC1 Switch", "MIC1 Input"},
{"Right REC Mixer", "MIC2 Switch", "MIC2 Input"},
{"Right REC Mixer", "INA1 Switch", "INA1 Input"},
diff --git a/sound/soc/codecs/max98388.c b/sound/soc/codecs/max98388.c
index b847d7c59ec0..99986090b4a6 100644
--- a/sound/soc/codecs/max98388.c
+++ b/sound/soc/codecs/max98388.c
@@ -763,6 +763,7 @@ static int max98388_dai_tdm_slot(struct snd_soc_dai *dai,
addr = MAX98388_R2044_PCM_TX_CTRL1 + (cnt / 8);
bits = cnt % 8;
regmap_update_bits(max98388->regmap, addr, bits, bits);
+ slot_found++;
if (slot_found >= MAX_NUM_CH)
break;
}
diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c
index de5c4db05c8f..edb95f869a4a 100644
--- a/sound/soc/codecs/nau8821.c
+++ b/sound/soc/codecs/nau8821.c
@@ -287,10 +287,8 @@ static int nau8821_biq_coeff_get(struct snd_kcontrol *kcontrol,
if (!component->regmap)
return -EINVAL;
- regmap_raw_read(component->regmap, NAU8821_R21_BIQ0_COF1,
+ return regmap_raw_read(component->regmap, NAU8821_R21_BIQ0_COF1,
ucontrol->value.bytes.data, params->max);
-
- return 0;
}
static int nau8821_biq_coeff_put(struct snd_kcontrol *kcontrol,
@@ -299,6 +297,7 @@ static int nau8821_biq_coeff_put(struct snd_kcontrol *kcontrol,
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct soc_bytes_ext *params = (void *)kcontrol->private_value;
void *data;
+ int ret;
if (!component->regmap)
return -EINVAL;
@@ -308,12 +307,12 @@ static int nau8821_biq_coeff_put(struct snd_kcontrol *kcontrol,
if (!data)
return -ENOMEM;
- regmap_raw_write(component->regmap, NAU8821_R21_BIQ0_COF1,
+ ret = regmap_raw_write(component->regmap, NAU8821_R21_BIQ0_COF1,
data, params->max);
kfree(data);
- return 0;
+ return ret;
}
static const char * const nau8821_adc_decimation[] = {
diff --git a/sound/soc/codecs/ntp8835.c b/sound/soc/codecs/ntp8835.c
new file mode 100644
index 000000000000..796e1410496f
--- /dev/null
+++ b/sound/soc/codecs/ntp8835.c
@@ -0,0 +1,480 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for the NTP8835/NTP8835C Audio Amplifiers
+ *
+ * Copyright (c) 2024, SaluteDevices. All Rights Reserved.
+ *
+ * Author: Igor Prusov <ivprusov@salutedevices.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/bits.h>
+#include <linux/reset.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+#include <sound/initval.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-component.h>
+#include <sound/tlv.h>
+
+#include "ntpfw.h"
+
+#define NTP8835_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+#define NTP8835_INPUT_FMT 0x0
+#define NTP8835_INPUT_FMT_MASTER_MODE BIT(0)
+#define NTP8835_INPUT_FMT_GSA_MODE BIT(1)
+#define NTP8835_GSA_FMT 0x1
+#define NTP8835_GSA_BS_MASK GENMASK(3, 2)
+#define NTP8835_GSA_BS(x) ((x) << 2)
+#define NTP8835_GSA_RIGHT_J BIT(0)
+#define NTP8835_GSA_LSB BIT(1)
+#define NTP8835_MCLK_FREQ_CTRL 0x2
+#define NTP8835_MCLK_FREQ_MCF GENMASK(1, 0)
+#define NTP8835_SOFT_MUTE 0x26
+#define NTP8835_SOFT_MUTE_SM1 BIT(0)
+#define NTP8835_SOFT_MUTE_SM2 BIT(1)
+#define NTP8835_SOFT_MUTE_SM3 BIT(2)
+#define NTP8835_PWM_SWITCH 0x27
+#define NTP8835_PWM_SWITCH_POF1 BIT(0)
+#define NTP8835_PWM_SWITCH_POF2 BIT(1)
+#define NTP8835_PWM_SWITCH_POF3 BIT(2)
+#define NTP8835_PWM_MASK_CTRL0 0x28
+#define NTP8835_PWM_MASK_CTRL0_OUT_LOW BIT(1)
+#define NTP8835_PWM_MASK_CTRL0_FPMLD BIT(2)
+#define NTP8835_MASTER_VOL 0x2e
+#define NTP8835_CHNL_A_VOL 0x2f
+#define NTP8835_CHNL_B_VOL 0x30
+#define NTP8835_CHNL_C_VOL 0x31
+#define REG_MAX NTP8835_CHNL_C_VOL
+
+#define NTP8835_FW_NAME "eq_8835.bin"
+#define NTP8835_FW_MAGIC 0x38383335 /* "8835" */
+
+struct ntp8835_priv {
+ struct i2c_client *i2c;
+ struct reset_control *reset;
+ unsigned int format;
+ struct clk *mclk;
+ unsigned int mclk_rate;
+};
+
+static const DECLARE_TLV_DB_RANGE(ntp8835_vol_scale,
+ 0, 1, TLV_DB_SCALE_ITEM(-15000, 0, 0),
+ 2, 6, TLV_DB_SCALE_ITEM(-15000, 1000, 0),
+ 7, 0xff, TLV_DB_SCALE_ITEM(-10000, 50, 0),
+);
+
+static int ntp8835_mute_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->access =
+ (SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE);
+ uinfo->count = 1;
+
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ uinfo->value.integer.step = 1;
+
+ return 0;
+}
+
+static int ntp8835_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ unsigned int val;
+
+ val = snd_soc_component_read(component, NTP8835_SOFT_MUTE);
+
+ ucontrol->value.integer.value[0] = val ? 0 : 1;
+ return 0;
+}
+
+static int ntp8835_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ unsigned int val;
+
+ val = ucontrol->value.integer.value[0] ? 0 : 7;
+
+ snd_soc_component_write(component, NTP8835_SOFT_MUTE, val);
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new ntp8835_vol_control[] = {
+ SOC_SINGLE_TLV("Playback Volume", NTP8835_MASTER_VOL, 0,
+ 0xff, 0, ntp8835_vol_scale),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Playback Switch",
+ .info = ntp8835_mute_info,
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .get = ntp8835_mute_get,
+ .put = ntp8835_mute_put,
+ },
+};
+
+static void ntp8835_reset_gpio(struct ntp8835_priv *ntp8835)
+{
+ /*
+ * Proper initialization sequence for NTP835 amplifier requires driving
+ * /RESET signal low during power up for at least 0.1us. The sequence is,
+ * according to NTP8835 datasheet, 6.2 Timing Sequence (recommended):
+ * Deassert for T2 >= 1ms...
+ */
+ reset_control_deassert(ntp8835->reset);
+ fsleep(1000);
+
+ /* ...Assert for T3 >= 0.1us... */
+ reset_control_assert(ntp8835->reset);
+ fsleep(1);
+
+ /* ...Deassert, and wait for T4 >= 0.5ms before sound on sequence. */
+ reset_control_deassert(ntp8835->reset);
+ fsleep(500);
+}
+
+static const struct reg_sequence ntp8835_sound_on[] = {
+ { NTP8835_PWM_MASK_CTRL0, NTP8835_PWM_MASK_CTRL0_FPMLD },
+ { NTP8835_PWM_SWITCH, 0x00 },
+ { NTP8835_SOFT_MUTE, 0x00 },
+};
+
+static const struct reg_sequence ntp8835_sound_off[] = {
+ { NTP8835_SOFT_MUTE, NTP8835_SOFT_MUTE_SM1 |
+ NTP8835_SOFT_MUTE_SM2 |
+ NTP8835_SOFT_MUTE_SM3 },
+
+ { NTP8835_PWM_SWITCH, NTP8835_PWM_SWITCH_POF1 |
+ NTP8835_PWM_SWITCH_POF2 |
+ NTP8835_PWM_SWITCH_POF3 },
+
+ { NTP8835_PWM_MASK_CTRL0, NTP8835_PWM_MASK_CTRL0_OUT_LOW |
+ NTP8835_PWM_MASK_CTRL0_FPMLD },
+};
+
+static int ntp8835_load_firmware(struct ntp8835_priv *ntp8835)
+{
+ int ret;
+
+ ret = ntpfw_load(ntp8835->i2c, NTP8835_FW_NAME, NTP8835_FW_MAGIC);
+ if (ret == -ENOENT) {
+ dev_warn_once(&ntp8835->i2c->dev,
+ "Could not find firmware %s\n", NTP8835_FW_NAME);
+ return 0;
+ }
+
+ return ret;
+}
+
+static int ntp8835_snd_suspend(struct snd_soc_component *component)
+{
+ struct ntp8835_priv *ntp8835 = snd_soc_component_get_drvdata(component);
+
+ regcache_cache_only(component->regmap, true);
+
+ regmap_multi_reg_write_bypassed(component->regmap,
+ ntp8835_sound_off,
+ ARRAY_SIZE(ntp8835_sound_off));
+
+ /*
+ * According to NTP8835 datasheet, 6.2 Timing Sequence (recommended):
+ * wait after sound off for T6 >= 0.5ms
+ */
+ fsleep(500);
+ reset_control_assert(ntp8835->reset);
+
+ regcache_mark_dirty(component->regmap);
+ clk_disable_unprepare(ntp8835->mclk);
+
+ return 0;
+}
+
+static int ntp8835_snd_resume(struct snd_soc_component *component)
+{
+ struct ntp8835_priv *ntp8835 = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ ntp8835_reset_gpio(ntp8835);
+ ret = clk_prepare_enable(ntp8835->mclk);
+ if (ret)
+ return ret;
+
+ regmap_multi_reg_write_bypassed(component->regmap,
+ ntp8835_sound_on,
+ ARRAY_SIZE(ntp8835_sound_on));
+
+ ret = ntp8835_load_firmware(ntp8835);
+ if (ret) {
+ dev_err(&ntp8835->i2c->dev, "Failed to load firmware\n");
+ return ret;
+ }
+
+ regcache_cache_only(component->regmap, false);
+ snd_soc_component_cache_sync(component);
+
+ return 0;
+}
+
+static int ntp8835_probe(struct snd_soc_component *component)
+{
+ int ret;
+ struct ntp8835_priv *ntp8835 = snd_soc_component_get_drvdata(component);
+ struct device *dev = component->dev;
+
+ ret = snd_soc_add_component_controls(component, ntp8835_vol_control,
+ ARRAY_SIZE(ntp8835_vol_control));
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to add controls\n");
+
+ ret = ntp8835_load_firmware(ntp8835);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to load firmware\n");
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget ntp8835_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC("AIFIN", "Playback", SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_OUTPUT("OUT1"),
+ SND_SOC_DAPM_OUTPUT("OUT2"),
+ SND_SOC_DAPM_OUTPUT("OUT3"),
+};
+
+static const struct snd_soc_dapm_route ntp8835_dapm_routes[] = {
+ { "OUT1", NULL, "AIFIN" },
+ { "OUT2", NULL, "AIFIN" },
+ { "OUT3", NULL, "AIFIN" },
+};
+
+static int ntp8835_set_component_sysclk(struct snd_soc_component *component,
+ int clk_id, int source,
+ unsigned int freq, int dir)
+{
+ struct ntp8835_priv *ntp8835 = snd_soc_component_get_drvdata(component);
+
+ switch (freq) {
+ case 12288000:
+ case 24576000:
+ case 18432000:
+ ntp8835->mclk_rate = freq;
+ break;
+ default:
+ ntp8835->mclk_rate = 0;
+ dev_err(component->dev, "Unsupported MCLK value: %u", freq);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver soc_component_ntp8835 = {
+ .probe = ntp8835_probe,
+ .suspend = ntp8835_snd_suspend,
+ .resume = ntp8835_snd_resume,
+ .dapm_widgets = ntp8835_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(ntp8835_dapm_widgets),
+ .dapm_routes = ntp8835_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(ntp8835_dapm_routes),
+ .set_sysclk = ntp8835_set_component_sysclk,
+};
+
+static int ntp8835_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 ntp8835_priv *ntp8835 = snd_soc_component_get_drvdata(component);
+ unsigned int input_fmt = 0;
+ unsigned int gsa_fmt = 0;
+ unsigned int gsa_fmt_mask;
+ unsigned int mcf;
+ int ret;
+
+ switch (ntp8835->mclk_rate) {
+ case 12288000:
+ mcf = 0;
+ break;
+ case 24576000:
+ mcf = 1;
+ break;
+ case 18432000:
+ mcf = 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = snd_soc_component_update_bits(component, NTP8835_MCLK_FREQ_CTRL,
+ NTP8835_MCLK_FREQ_MCF, mcf);
+ if (ret)
+ return ret;
+
+ switch (ntp8835->format) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ input_fmt |= NTP8835_INPUT_FMT_GSA_MODE;
+ gsa_fmt |= NTP8835_GSA_RIGHT_J;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ input_fmt |= NTP8835_INPUT_FMT_GSA_MODE;
+ break;
+ }
+
+ ret = snd_soc_component_update_bits(component, NTP8835_INPUT_FMT,
+ NTP8835_INPUT_FMT_MASTER_MODE |
+ NTP8835_INPUT_FMT_GSA_MODE,
+ input_fmt);
+
+ if (!(input_fmt & NTP8835_INPUT_FMT_GSA_MODE) || ret < 0)
+ return ret;
+
+ switch (params_width(params)) {
+ case 24:
+ gsa_fmt |= NTP8835_GSA_BS(0);
+ break;
+ case 20:
+ gsa_fmt |= NTP8835_GSA_BS(1);
+ break;
+ case 18:
+ gsa_fmt |= NTP8835_GSA_BS(2);
+ break;
+ case 16:
+ gsa_fmt |= NTP8835_GSA_BS(3);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ gsa_fmt_mask = NTP8835_GSA_BS_MASK |
+ NTP8835_GSA_RIGHT_J |
+ NTP8835_GSA_LSB;
+ return snd_soc_component_update_bits(component, NTP8835_GSA_FMT,
+ gsa_fmt_mask, gsa_fmt);
+}
+
+static int ntp8835_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_component *component = dai->component;
+ struct ntp8835_priv *ntp8835 = snd_soc_component_get_drvdata(component);
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_RIGHT_J:
+ case SND_SOC_DAIFMT_LEFT_J:
+ ntp8835->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+};
+
+static const struct snd_soc_dai_ops ntp8835_dai_ops = {
+ .hw_params = ntp8835_hw_params,
+ .set_fmt = ntp8835_set_fmt,
+};
+
+static struct snd_soc_dai_driver ntp8835_dai = {
+ .name = "ntp8835-amplifier",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 3,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = NTP8835_FORMATS,
+ },
+ .ops = &ntp8835_dai_ops,
+};
+
+static const struct regmap_config ntp8835_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = REG_MAX,
+ .cache_type = REGCACHE_MAPLE,
+};
+
+static int ntp8835_i2c_probe(struct i2c_client *i2c)
+{
+ struct ntp8835_priv *ntp8835;
+ struct regmap *regmap;
+ int ret;
+
+ ntp8835 = devm_kzalloc(&i2c->dev, sizeof(*ntp8835), GFP_KERNEL);
+ if (!ntp8835)
+ return -ENOMEM;
+
+ ntp8835->i2c = i2c;
+
+ ntp8835->reset = devm_reset_control_get_shared(&i2c->dev, NULL);
+ if (IS_ERR(ntp8835->reset))
+ return dev_err_probe(&i2c->dev, PTR_ERR(ntp8835->reset),
+ "Failed to get reset\n");
+
+ ret = reset_control_deassert(ntp8835->reset);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret,
+ "Failed to deassert reset\n");
+
+ dev_set_drvdata(&i2c->dev, ntp8835);
+
+ ntp8835_reset_gpio(ntp8835);
+
+ regmap = devm_regmap_init_i2c(i2c, &ntp8835_regmap);
+ if (IS_ERR(regmap))
+ return dev_err_probe(&i2c->dev, PTR_ERR(regmap),
+ "Failed to allocate regmap\n");
+
+ ret = devm_snd_soc_register_component(&i2c->dev, &soc_component_ntp8835,
+ &ntp8835_dai, 1);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret,
+ "Failed to register component\n");
+
+ ntp8835->mclk = devm_clk_get_enabled(&i2c->dev, "mclk");
+ if (IS_ERR(ntp8835->mclk))
+ return dev_err_probe(&i2c->dev, PTR_ERR(ntp8835->mclk), "failed to get mclk\n");
+
+ return 0;
+}
+
+static const struct i2c_device_id ntp8835_i2c_id[] = {
+ { "ntp8835", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, ntp8835_i2c_id);
+
+static const struct of_device_id ntp8835_of_match[] = {
+ {.compatible = "neofidelity,ntp8835",},
+ {}
+};
+MODULE_DEVICE_TABLE(of, ntp8835_of_match);
+
+static struct i2c_driver ntp8835_i2c_driver = {
+ .probe = ntp8835_i2c_probe,
+ .id_table = ntp8835_i2c_id,
+ .driver = {
+ .name = "ntp8835",
+ .of_match_table = ntp8835_of_match,
+ },
+};
+module_i2c_driver(ntp8835_i2c_driver);
+
+MODULE_AUTHOR("Igor Prusov <ivprusov@salutedevices.com>");
+MODULE_DESCRIPTION("NTP8835 Audio Amplifier Driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ntp8918.c b/sound/soc/codecs/ntp8918.c
new file mode 100644
index 000000000000..0493ab6acbe4
--- /dev/null
+++ b/sound/soc/codecs/ntp8918.c
@@ -0,0 +1,397 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for the NTP8918 Audio Amplifier
+ *
+ * Copyright (c) 2024, SaluteDevices. All Rights Reserved.
+ *
+ * Author: Igor Prusov <ivprusov@salutedevices.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#include <sound/initval.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-component.h>
+#include <sound/tlv.h>
+
+#include "ntpfw.h"
+
+#define NTP8918_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
+
+#define NTP8918_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+#define NTP8918_INPUT_FMT 0x0
+#define NTP8918_INPUT_FMT_MASTER_MODE BIT(0)
+#define NTP8918_INPUT_FMT_GSA_MODE BIT(1)
+#define NTP8918_GSA_FMT 0x1
+#define NTP8918_GSA_BS_MASK GENMASK(3, 2)
+#define NTP8918_GSA_BS(x) ((x) << 2)
+#define NTP8918_GSA_RIGHT_J BIT(0)
+#define NTP8918_GSA_LSB BIT(1)
+#define NTP8918_MCLK_FREQ_CTRL 0x2
+#define NTP8918_MCLK_FREQ_MCF GENMASK(1, 0)
+#define NTP8918_MASTER_VOL 0x0C
+#define NTP8918_CHNL_A_VOL 0x17
+#define NTP8918_CHNL_B_VOL 0x18
+#define NTP8918_SOFT_MUTE 0x33
+#define NTP8918_SOFT_MUTE_SM1 BIT(0)
+#define NTP8918_SOFT_MUTE_SM2 BIT(1)
+#define NTP8918_PWM_SWITCH 0x34
+#define NTP8918_PWM_MASK_CTRL0 0x35
+#define REG_MAX NTP8918_PWM_MASK_CTRL0
+
+#define NTP8918_FW_NAME "eq_8918.bin"
+#define NTP8918_FW_MAGIC 0x38393138 /* "8918" */
+
+struct ntp8918_priv {
+ struct i2c_client *i2c;
+ struct clk *bck;
+ struct reset_control *reset;
+ unsigned int format;
+};
+
+static const DECLARE_TLV_DB_SCALE(ntp8918_master_vol_scale, -12550, 50, 0);
+
+static const struct snd_kcontrol_new ntp8918_vol_control[] = {
+ SOC_SINGLE_RANGE_TLV("Playback Volume", NTP8918_MASTER_VOL, 0,
+ 0x04, 0xff, 0, ntp8918_master_vol_scale),
+ SOC_SINGLE("Playback Switch", NTP8918_PWM_MASK_CTRL0, 1, 1, 1),
+};
+
+static void ntp8918_reset_gpio(struct ntp8918_priv *ntp8918)
+{
+ /*
+ * Proper initialization sequence for NTP8918 amplifier requires driving
+ * /RESET signal low during power up for at least 0.1us. The sequence is,
+ * according to NTP8918 datasheet, 6.2 Timing Sequence 1:
+ * Deassert for T2 >= 1ms...
+ */
+ reset_control_deassert(ntp8918->reset);
+ fsleep(1000);
+
+ /* ...Assert for T3 >= 0.1us... */
+ reset_control_assert(ntp8918->reset);
+ fsleep(1);
+
+ /* ...Deassert, and wait for T4 >= 0.5ms before sound on sequence. */
+ reset_control_deassert(ntp8918->reset);
+ fsleep(500);
+}
+
+static const struct reg_sequence ntp8918_sound_off[] = {
+ { NTP8918_MASTER_VOL, 0 },
+};
+
+static const struct reg_sequence ntp8918_sound_on[] = {
+ { NTP8918_MASTER_VOL, 0b11 },
+};
+
+static int ntp8918_load_firmware(struct ntp8918_priv *ntp8918)
+{
+ int ret;
+
+ ret = ntpfw_load(ntp8918->i2c, NTP8918_FW_NAME, NTP8918_FW_MAGIC);
+ if (ret == -ENOENT) {
+ dev_warn_once(&ntp8918->i2c->dev, "Could not find firmware %s\n",
+ NTP8918_FW_NAME);
+ return 0;
+ }
+
+ return ret;
+}
+
+static int ntp8918_snd_suspend(struct snd_soc_component *component)
+{
+ struct ntp8918_priv *ntp8918 = snd_soc_component_get_drvdata(component);
+
+ regcache_cache_only(component->regmap, true);
+
+ regmap_multi_reg_write_bypassed(component->regmap,
+ ntp8918_sound_off,
+ ARRAY_SIZE(ntp8918_sound_off));
+
+ /*
+ * According to NTP8918 datasheet, 6.2 Timing Sequence 1:
+ * wait after sound off for T6 >= 0.5ms
+ */
+ fsleep(500);
+ reset_control_assert(ntp8918->reset);
+
+ regcache_mark_dirty(component->regmap);
+ clk_disable_unprepare(ntp8918->bck);
+
+ return 0;
+}
+
+static int ntp8918_snd_resume(struct snd_soc_component *component)
+{
+ struct ntp8918_priv *ntp8918 = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ ret = clk_prepare_enable(ntp8918->bck);
+ if (ret)
+ return ret;
+
+ ntp8918_reset_gpio(ntp8918);
+
+ regmap_multi_reg_write_bypassed(component->regmap,
+ ntp8918_sound_on,
+ ARRAY_SIZE(ntp8918_sound_on));
+
+ ret = ntp8918_load_firmware(ntp8918);
+ if (ret) {
+ dev_err(&ntp8918->i2c->dev, "Failed to load firmware\n");
+ return ret;
+ }
+
+ regcache_cache_only(component->regmap, false);
+ snd_soc_component_cache_sync(component);
+
+ return 0;
+}
+
+static int ntp8918_probe(struct snd_soc_component *component)
+{
+ int ret;
+ struct ntp8918_priv *ntp8918 = snd_soc_component_get_drvdata(component);
+ struct device *dev = component->dev;
+
+ ret = snd_soc_add_component_controls(component, ntp8918_vol_control,
+ ARRAY_SIZE(ntp8918_vol_control));
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to add controls\n");
+
+ ret = ntp8918_load_firmware(ntp8918);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to load firmware\n");
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget ntp8918_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC("AIFIN", "Playback", SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_OUTPUT("OUT1"),
+ SND_SOC_DAPM_OUTPUT("OUT2"),
+};
+
+static const struct snd_soc_dapm_route ntp8918_dapm_routes[] = {
+ { "OUT1", NULL, "AIFIN" },
+ { "OUT2", NULL, "AIFIN" },
+};
+
+static const struct snd_soc_component_driver soc_component_ntp8918 = {
+ .probe = ntp8918_probe,
+ .suspend = ntp8918_snd_suspend,
+ .resume = ntp8918_snd_resume,
+ .dapm_widgets = ntp8918_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(ntp8918_dapm_widgets),
+ .dapm_routes = ntp8918_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(ntp8918_dapm_routes),
+};
+
+static int ntp8918_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 ntp8918_priv *ntp8918 = snd_soc_component_get_drvdata(component);
+ unsigned int input_fmt = 0;
+ unsigned int gsa_fmt = 0;
+ unsigned int gsa_fmt_mask;
+ unsigned int mcf;
+ int bclk;
+ int ret;
+
+ bclk = snd_soc_params_to_bclk(params);
+ switch (bclk) {
+ case 3072000:
+ case 2822400:
+ mcf = 0;
+ break;
+ case 6144000:
+ mcf = 1;
+ break;
+ case 2048000:
+ mcf = 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = snd_soc_component_update_bits(component, NTP8918_MCLK_FREQ_CTRL,
+ NTP8918_MCLK_FREQ_MCF, mcf);
+ if (ret)
+ return ret;
+
+ switch (ntp8918->format) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ input_fmt |= NTP8918_INPUT_FMT_GSA_MODE;
+ gsa_fmt |= NTP8918_GSA_RIGHT_J;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ input_fmt |= NTP8918_INPUT_FMT_GSA_MODE;
+ break;
+ }
+
+ ret = snd_soc_component_update_bits(component, NTP8918_INPUT_FMT,
+ NTP8918_INPUT_FMT_MASTER_MODE |
+ NTP8918_INPUT_FMT_GSA_MODE,
+ input_fmt);
+
+ if (!(input_fmt & NTP8918_INPUT_FMT_GSA_MODE) || ret < 0)
+ return ret;
+
+ switch (params_width(params)) {
+ case 24:
+ gsa_fmt |= NTP8918_GSA_BS(0);
+ break;
+ case 20:
+ gsa_fmt |= NTP8918_GSA_BS(1);
+ break;
+ case 18:
+ gsa_fmt |= NTP8918_GSA_BS(2);
+ break;
+ case 16:
+ gsa_fmt |= NTP8918_GSA_BS(3);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ gsa_fmt_mask = NTP8918_GSA_BS_MASK |
+ NTP8918_GSA_RIGHT_J |
+ NTP8918_GSA_LSB;
+ return snd_soc_component_update_bits(component, NTP8918_GSA_FMT,
+ gsa_fmt_mask, gsa_fmt);
+}
+
+static int ntp8918_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_component *component = dai->component;
+ struct ntp8918_priv *ntp8918 = snd_soc_component_get_drvdata(component);
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_RIGHT_J:
+ case SND_SOC_DAIFMT_LEFT_J:
+ ntp8918->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int ntp8918_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+ unsigned int mute_mask = NTP8918_SOFT_MUTE_SM1 |
+ NTP8918_SOFT_MUTE_SM2;
+
+ return snd_soc_component_update_bits(dai->component, NTP8918_SOFT_MUTE,
+ mute_mask, mute ? mute_mask : 0);
+}
+
+static const struct snd_soc_dai_ops ntp8918_dai_ops = {
+ .hw_params = ntp8918_hw_params,
+ .set_fmt = ntp8918_set_fmt,
+ .mute_stream = ntp8918_digital_mute,
+};
+
+static struct snd_soc_dai_driver ntp8918_dai = {
+ .name = "ntp8918-amplifier",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = NTP8918_RATES,
+ .formats = NTP8918_FORMATS,
+ },
+ .ops = &ntp8918_dai_ops,
+};
+
+static const struct regmap_config ntp8918_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = REG_MAX,
+ .cache_type = REGCACHE_MAPLE,
+};
+
+static int ntp8918_i2c_probe(struct i2c_client *i2c)
+{
+ struct ntp8918_priv *ntp8918;
+ int ret;
+ struct regmap *regmap;
+
+ ntp8918 = devm_kzalloc(&i2c->dev, sizeof(*ntp8918), GFP_KERNEL);
+ if (!ntp8918)
+ return -ENOMEM;
+
+ ntp8918->i2c = i2c;
+
+ ntp8918->reset = devm_reset_control_get_shared(&i2c->dev, NULL);
+ if (IS_ERR(ntp8918->reset))
+ return dev_err_probe(&i2c->dev, PTR_ERR(ntp8918->reset), "Failed to get reset\n");
+
+ dev_set_drvdata(&i2c->dev, ntp8918);
+
+ ntp8918_reset_gpio(ntp8918);
+
+ regmap = devm_regmap_init_i2c(i2c, &ntp8918_regmap);
+ if (IS_ERR(regmap))
+ return dev_err_probe(&i2c->dev, PTR_ERR(regmap),
+ "Failed to allocate regmap\n");
+
+ ret = devm_snd_soc_register_component(&i2c->dev, &soc_component_ntp8918,
+ &ntp8918_dai, 1);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret,
+ "Failed to register component\n");
+
+ ntp8918->bck = devm_clk_get_enabled(&i2c->dev, "bck");
+ if (IS_ERR(ntp8918->bck))
+ return dev_err_probe(&i2c->dev, PTR_ERR(ntp8918->bck), "failed to get bck clock\n");
+
+ return 0;
+}
+
+static const struct i2c_device_id ntp8918_i2c_id[] = {
+ { "ntp8918", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, ntp8918_i2c_id);
+
+static const struct of_device_id ntp8918_of_match[] = {
+ {.compatible = "neofidelity,ntp8918"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, ntp8918_of_match);
+
+static struct i2c_driver ntp8918_i2c_driver = {
+ .probe = ntp8918_i2c_probe,
+ .id_table = ntp8918_i2c_id,
+ .driver = {
+ .name = "ntp8918",
+ .of_match_table = ntp8918_of_match,
+ },
+};
+module_i2c_driver(ntp8918_i2c_driver);
+
+MODULE_AUTHOR("Igor Prusov <ivprusov@salutedevices.com>");
+MODULE_DESCRIPTION("NTP8918 Audio Amplifier Driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ntpfw.c b/sound/soc/codecs/ntpfw.c
new file mode 100644
index 000000000000..5ced2e966ab7
--- /dev/null
+++ b/sound/soc/codecs/ntpfw.c
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ntpfw.c - Firmware helper functions for Neofidelity codecs
+ *
+ * Copyright (c) 2024, SaluteDevices. All Rights Reserved.
+ */
+
+#include <linux/i2c.h>
+#include <linux/firmware.h>
+#include <linux/module.h>
+
+#include "ntpfw.h"
+
+struct ntpfw_chunk {
+ __be16 length;
+ u8 step;
+ u8 data[];
+} __packed;
+
+struct ntpfw_header {
+ __be32 magic;
+} __packed;
+
+static bool ntpfw_verify(struct device *dev, const u8 *buf, size_t buf_size, u32 magic)
+{
+ const struct ntpfw_header *header = (struct ntpfw_header *)buf;
+ u32 buf_magic;
+
+ if (buf_size <= sizeof(*header)) {
+ dev_err(dev, "Failed to load firmware: image too small\n");
+ return false;
+ }
+
+ buf_magic = be32_to_cpu(header->magic);
+ if (buf_magic != magic) {
+ dev_err(dev, "Failed to load firmware: invalid magic 0x%x:\n", buf_magic);
+ return false;
+ }
+
+ return true;
+}
+
+static bool ntpfw_verify_chunk(struct device *dev, const struct ntpfw_chunk *chunk, size_t buf_size)
+{
+ size_t chunk_size;
+
+ if (buf_size <= sizeof(*chunk)) {
+ dev_err(dev, "Failed to load firmware: chunk size too big\n");
+ return false;
+ }
+
+ if (chunk->step != 2 && chunk->step != 5) {
+ dev_err(dev, "Failed to load firmware: invalid chunk step: %d\n", chunk->step);
+ return false;
+ }
+
+ chunk_size = be16_to_cpu(chunk->length);
+ if (chunk_size > buf_size) {
+ dev_err(dev, "Failed to load firmware: invalid chunk length\n");
+ return false;
+ }
+
+ if (chunk_size % chunk->step) {
+ dev_err(dev, "Failed to load firmware: chunk length and step mismatch\n");
+ return false;
+ }
+
+ return true;
+}
+
+static int ntpfw_send_chunk(struct i2c_client *i2c, const struct ntpfw_chunk *chunk)
+{
+ int ret;
+ size_t i;
+ size_t length = be16_to_cpu(chunk->length);
+
+ for (i = 0; i < length; i += chunk->step) {
+ ret = i2c_master_send(i2c, &chunk->data[i], chunk->step);
+ if (ret != chunk->step) {
+ dev_err(&i2c->dev, "I2C send failed: %d\n", ret);
+ return ret < 0 ? ret : -EIO;
+ }
+ }
+
+ return 0;
+}
+
+int ntpfw_load(struct i2c_client *i2c, const char *name, u32 magic)
+{
+ struct device *dev = &i2c->dev;
+ const struct ntpfw_chunk *chunk;
+ const struct firmware *fw;
+ const u8 *data;
+ size_t leftover;
+ int ret;
+
+ ret = request_firmware(&fw, name, dev);
+ if (ret) {
+ dev_warn(dev, "request_firmware '%s' failed with %d\n",
+ name, ret);
+ return ret;
+ }
+
+ if (!ntpfw_verify(dev, fw->data, fw->size, magic)) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ data = fw->data + sizeof(struct ntpfw_header);
+ leftover = fw->size - sizeof(struct ntpfw_header);
+
+ while (leftover) {
+ chunk = (struct ntpfw_chunk *)data;
+
+ if (!ntpfw_verify_chunk(dev, chunk, leftover)) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = ntpfw_send_chunk(i2c, chunk);
+ if (ret)
+ goto done;
+
+ data += be16_to_cpu(chunk->length) + sizeof(*chunk);
+ leftover -= be16_to_cpu(chunk->length) + sizeof(*chunk);
+ }
+
+done:
+ release_firmware(fw);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ntpfw_load);
+
+MODULE_AUTHOR("Igor Prusov <ivprusov@salutedevices.com>");
+MODULE_DESCRIPTION("Helper for loading Neofidelity amplifiers firmware");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ntpfw.h b/sound/soc/codecs/ntpfw.h
new file mode 100644
index 000000000000..1cf10d5480ee
--- /dev/null
+++ b/sound/soc/codecs/ntpfw.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/**
+ * ntpfw.h - Firmware helper functions for Neofidelity codecs
+ *
+ * Copyright (c) 2024, SaluteDevices. All Rights Reserved.
+ */
+
+#ifndef __NTPFW_H__
+#define __NTPFW_H__
+#include <linux/i2c.h>
+#include <linux/firmware.h>
+
+/**
+ * ntpfw_load - load firmware to amplifier over i2c interface.
+ *
+ * @i2c Pointer to amplifier's I2C client.
+ * @name Firmware file name.
+ * @magic Magic number to validate firmware.
+ * @return 0 or error code upon error.
+ */
+int ntpfw_load(struct i2c_client *i2c, const char *name, const u32 magic);
+
+#endif /* __NTPFW_H__ */
diff --git a/sound/soc/codecs/pcm186x.c b/sound/soc/codecs/pcm186x.c
index 451a8fd8fac5..13443f569ddb 100644
--- a/sound/soc/codecs/pcm186x.c
+++ b/sound/soc/codecs/pcm186x.c
@@ -566,7 +566,7 @@ static int pcm186x_set_bias_level(struct snd_soc_component *component,
return 0;
}
-static struct snd_soc_component_driver soc_codec_dev_pcm1863 = {
+static const struct snd_soc_component_driver soc_codec_dev_pcm1863 = {
.set_bias_level = pcm186x_set_bias_level,
.controls = pcm1863_snd_controls,
.num_controls = ARRAY_SIZE(pcm1863_snd_controls),
@@ -579,7 +579,7 @@ static struct snd_soc_component_driver soc_codec_dev_pcm1863 = {
.endianness = 1,
};
-static struct snd_soc_component_driver soc_codec_dev_pcm1865 = {
+static const struct snd_soc_component_driver soc_codec_dev_pcm1865 = {
.set_bias_level = pcm186x_set_bias_level,
.controls = pcm1865_snd_controls,
.num_controls = ARRAY_SIZE(pcm1865_snd_controls),
diff --git a/sound/soc/codecs/pcm3060-i2c.c b/sound/soc/codecs/pcm3060-i2c.c
index 5330cf46b127..3816b25a8ead 100644
--- a/sound/soc/codecs/pcm3060-i2c.c
+++ b/sound/soc/codecs/pcm3060-i2c.c
@@ -2,7 +2,7 @@
//
// PCM3060 I2C driver
//
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
+// Copyright (C) 2018 Kirill Marinushkin <k.marinushkin@gmail.com>
#include <linux/i2c.h>
#include <linux/module.h>
@@ -55,5 +55,5 @@ static struct i2c_driver pcm3060_i2c_driver = {
module_i2c_driver(pcm3060_i2c_driver);
MODULE_DESCRIPTION("PCM3060 I2C driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
+MODULE_AUTHOR("Kirill Marinushkin <k.marinushkin@gmail.com>");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm3060-spi.c b/sound/soc/codecs/pcm3060-spi.c
index 3b79734b832b..6095841f2f56 100644
--- a/sound/soc/codecs/pcm3060-spi.c
+++ b/sound/soc/codecs/pcm3060-spi.c
@@ -2,7 +2,7 @@
//
// PCM3060 SPI driver
//
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
+// Copyright (C) 2018 Kirill Marinushkin <k.marinushkin@gmail.com>
#include <linux/module.h>
#include <linux/spi/spi.h>
@@ -55,5 +55,5 @@ static struct spi_driver pcm3060_spi_driver = {
module_spi_driver(pcm3060_spi_driver);
MODULE_DESCRIPTION("PCM3060 SPI driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
+MODULE_AUTHOR("Kirill Marinushkin <k.marinushkin@gmail.com>");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm3060.c b/sound/soc/codecs/pcm3060.c
index 586ec8c7246c..8974200652e7 100644
--- a/sound/soc/codecs/pcm3060.c
+++ b/sound/soc/codecs/pcm3060.c
@@ -2,7 +2,7 @@
//
// PCM3060 codec driver
//
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
+// Copyright (C) 2018 Kirill Marinushkin <k.marinushkin@gmail.com>
#include <linux/module.h>
#include <sound/pcm_params.h>
@@ -343,5 +343,5 @@ int pcm3060_probe(struct device *dev)
EXPORT_SYMBOL(pcm3060_probe);
MODULE_DESCRIPTION("PCM3060 codec driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
+MODULE_AUTHOR("Kirill Marinushkin <k.marinushkin@gmail.com>");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm3060.h b/sound/soc/codecs/pcm3060.h
index 5e1185e7b03d..1b96835600b4 100644
--- a/sound/soc/codecs/pcm3060.h
+++ b/sound/soc/codecs/pcm3060.h
@@ -2,7 +2,7 @@
/*
* PCM3060 codec driver
*
- * Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
+ * Copyright (C) 2018 Kirill Marinushkin <k.marinushkin@gmail.com>
*/
#ifndef _SND_SOC_PCM3060_H
diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c
index 3401a25341e6..9bca53de2475 100644
--- a/sound/soc/codecs/pcm5102a.c
+++ b/sound/soc/codecs/pcm5102a.c
@@ -24,7 +24,7 @@ static struct snd_soc_dai_driver pcm5102a_dai = {
},
};
-static struct snd_soc_component_driver soc_component_dev_pcm5102a = {
+static const struct snd_soc_component_driver soc_component_dev_pcm5102a = {
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
diff --git a/sound/soc/codecs/pcm6240.c b/sound/soc/codecs/pcm6240.c
index 6641e7c1ddf4..5d99877f8839 100644
--- a/sound/soc/codecs/pcm6240.c
+++ b/sound/soc/codecs/pcm6240.c
@@ -12,7 +12,7 @@
// Author: Shenghao Ding <shenghao-ding@ti.com>
//
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <linux/firmware.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
diff --git a/sound/soc/codecs/peb2466.c b/sound/soc/codecs/peb2466.c
index 74b628ae1964..bb9ca6354ae1 100644
--- a/sound/soc/codecs/peb2466.c
+++ b/sound/soc/codecs/peb2466.c
@@ -6,7 +6,7 @@
//
// Author: Herve Codina <herve.codina@bootlin.com>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <linux/clk.h>
#include <linux/firmware.h>
#include <linux/gpio/consumer.h>
diff --git a/sound/soc/codecs/rt-sdw-common.c b/sound/soc/codecs/rt-sdw-common.c
new file mode 100644
index 000000000000..ad61943ce75f
--- /dev/null
+++ b/sound/soc/codecs/rt-sdw-common.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// rt-sdw-common.c
+//
+// Copyright(c) 2024 Realtek Semiconductor Corp.
+//
+
+/*
+ * This file defines common functions used with Realtek soundwire codecs.
+ */
+
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/bitops.h>
+#include <linux/soundwire/sdw_registers.h>
+#include <sound/jack.h>
+
+#include "rt-sdw-common.h"
+
+/**
+ * rt_sdca_index_write - Write a value to Realtek defined register.
+ *
+ * @map: map for setting.
+ * @nid: Realtek-defined ID.
+ * @reg: register.
+ * @value: value.
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int rt_sdca_index_write(struct regmap *map, unsigned int nid,
+ unsigned int reg, unsigned int value)
+{
+ unsigned int addr = (nid << 20) | reg;
+ int ret;
+
+ ret = regmap_write(map, addr, value);
+ if (ret < 0)
+ pr_err("Failed to set value: %06x <= %04x ret=%d\n",
+ addr, value, ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rt_sdca_index_write);
+
+/**
+ * rt_sdca_index_read - Read value from Realtek defined register.
+ *
+ * @map: map for setting.
+ * @nid: Realtek-defined ID.
+ * @reg: register.
+ * @value: value.
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int rt_sdca_index_read(struct regmap *map, unsigned int nid,
+ unsigned int reg, unsigned int *value)
+{
+ unsigned int addr = (nid << 20) | reg;
+ int ret;
+
+ ret = regmap_read(map, addr, value);
+ if (ret < 0)
+ pr_err("Failed to get value: %06x => %04x ret=%d\n",
+ addr, *value, ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rt_sdca_index_read);
+
+/**
+ * rt_sdca_index_update_bits - Update value on Realtek defined register.
+ *
+ * @map: map for setting.
+ * @nid: Realtek-defined ID.
+ * @reg: register.
+ * @mask: Bitmask to change
+ * @val: New value for bitmask
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+
+int rt_sdca_index_update_bits(struct regmap *map,
+ unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val)
+{
+ unsigned int tmp;
+ int ret;
+
+ ret = rt_sdca_index_read(map, nid, reg, &tmp);
+ if (ret < 0)
+ return ret;
+
+ set_mask_bits(&tmp, mask, val);
+ return rt_sdca_index_write(map, nid, reg, tmp);
+}
+EXPORT_SYMBOL_GPL(rt_sdca_index_update_bits);
+
+/**
+ * rt_sdca_btn_type - Decision of button type.
+ *
+ * @buffer: UMP message buffer.
+ *
+ * A button type will be returned regarding to buffer,
+ * it returns zero if buffer cannot be recognized.
+ */
+int rt_sdca_btn_type(unsigned char *buffer)
+{
+ u8 btn_type = 0;
+ int ret = 0;
+
+ btn_type |= buffer[0] & 0xf;
+ btn_type |= (buffer[0] >> 4) & 0xf;
+ btn_type |= buffer[1] & 0xf;
+ btn_type |= (buffer[1] >> 4) & 0xf;
+
+ if (btn_type & BIT(0))
+ ret |= SND_JACK_BTN_2;
+ if (btn_type & BIT(1))
+ ret |= SND_JACK_BTN_3;
+ if (btn_type & BIT(2))
+ ret |= SND_JACK_BTN_0;
+ if (btn_type & BIT(3))
+ ret |= SND_JACK_BTN_1;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rt_sdca_btn_type);
+
+/**
+ * rt_sdca_headset_detect - Headset jack type detection.
+ *
+ * @map: map for setting.
+ * @entity_id: SDCA entity ID.
+ *
+ * A headset jack type will be returned, a negative errno will
+ * be returned in error cases.
+ */
+int rt_sdca_headset_detect(struct regmap *map, unsigned int entity_id)
+{
+ unsigned int det_mode, jack_type;
+ int ret;
+
+ /* get detected_mode */
+ ret = regmap_read(map, SDW_SDCA_CTL(SDCA_NUM_JACK_CODEC, entity_id,
+ RT_SDCA_CTL_DETECTED_MODE, 0), &det_mode);
+
+ if (ret < 0)
+ goto io_error;
+
+ switch (det_mode) {
+ case 0x03:
+ jack_type = SND_JACK_HEADPHONE;
+ break;
+ case 0x05:
+ jack_type = SND_JACK_HEADSET;
+ break;
+ default:
+ jack_type = 0;
+ break;
+ }
+
+ /* write selected_mode */
+ if (det_mode) {
+ ret = regmap_write(map, SDW_SDCA_CTL(SDCA_NUM_JACK_CODEC, entity_id,
+ RT_SDCA_CTL_SELECTED_MODE, 0), det_mode);
+ if (ret < 0)
+ goto io_error;
+ }
+
+ return jack_type;
+
+io_error:
+ pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rt_sdca_headset_detect);
+
+/**
+ * rt_sdca_button_detect - Read UMP message and decide button type.
+ *
+ * @map: map for setting.
+ * @entity_id: SDCA entity ID.
+ * @hid_buf_addr: HID buffer address.
+ * @hid_id: Report ID for HID.
+ *
+ * A button type will be returned regarding to buffer,
+ * it returns zero if buffer cannot be recognized.
+ */
+int rt_sdca_button_detect(struct regmap *map, unsigned int entity_id,
+ unsigned int hid_buf_addr, unsigned int hid_id)
+{
+ unsigned int btn_type = 0, offset, idx, val, owner;
+ unsigned char buf[3];
+ int ret;
+
+ /* get current UMP message owner */
+ ret = regmap_read(map, SDW_SDCA_CTL(SDCA_NUM_HID, entity_id,
+ RT_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), &owner);
+ if (ret < 0)
+ return 0;
+
+ /* if owner is device then there is no button event from device */
+ if (owner == 1)
+ return 0;
+
+ /* read UMP message offset */
+ ret = regmap_read(map, SDW_SDCA_CTL(SDCA_NUM_HID, entity_id,
+ RT_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), &offset);
+ if (ret < 0)
+ goto _end_btn_det_;
+
+ for (idx = 0; idx < sizeof(buf); idx++) {
+ ret = regmap_read(map, hid_buf_addr + offset + idx, &val);
+ if (ret < 0)
+ goto _end_btn_det_;
+ buf[idx] = val & 0xff;
+ }
+ /* Report ID for HID */
+ if (buf[0] == hid_id)
+ btn_type = rt_sdca_btn_type(&buf[1]);
+
+_end_btn_det_:
+ /* Host is owner, so set back to device */
+ if (owner == 0)
+ /* set owner to device */
+ regmap_write(map,
+ SDW_SDCA_CTL(SDCA_NUM_HID, entity_id,
+ RT_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), 0x01);
+
+ return btn_type;
+}
+EXPORT_SYMBOL_GPL(rt_sdca_button_detect);
+
+MODULE_DESCRIPTION("Realtek soundwire common functions");
+MODULE_AUTHOR("jack yu <jack.yu@realtek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt-sdw-common.h b/sound/soc/codecs/rt-sdw-common.h
new file mode 100644
index 000000000000..4759516feb38
--- /dev/null
+++ b/sound/soc/codecs/rt-sdw-common.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+//
+// rt-sdw-common.h
+//
+// Copyright(c) 2024 Realtek Semiconductor Corp.
+//
+
+/*
+ * This file defines common functions used with Realtek soundwire codecs.
+ */
+
+#ifndef __RT_SDW_COMMON_H__
+#define __RT_SDW_COMMON_H__
+
+#define SDCA_NUM_JACK_CODEC 0x01
+#define SDCA_NUM_MIC_ARRAY 0x02
+#define SDCA_NUM_HID 0x03
+#define SDCA_NUM_AMP 0x04
+#define RT_SDCA_CTL_SELECTED_MODE 0x01
+#define RT_SDCA_CTL_DETECTED_MODE 0x02
+#define RT_SDCA_CTL_HIDTX_CURRENT_OWNER 0x10
+#define RT_SDCA_CTL_HIDTX_MESSAGE_OFFSET 0x12
+
+struct rt_sdca_dmic_kctrl_priv {
+ unsigned int reg_base;
+ unsigned int count;
+ unsigned int max;
+ unsigned int invert;
+};
+
+#define RT_SDCA_PR_VALUE(xreg_base, xcount, xmax, xinvert) \
+ ((unsigned long)&(struct rt_sdca_dmic_kctrl_priv) \
+ {.reg_base = xreg_base, .count = xcount, .max = xmax, \
+ .invert = xinvert})
+
+#define RT_SDCA_FU_CTRL(xname, reg_base, xmax, xinvert, xcount, \
+ xinfo, xget, xput) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+ .info = xinfo, \
+ .get = xget, \
+ .put = xput, \
+ .private_value = RT_SDCA_PR_VALUE(reg_base, xcount, xmax, xinvert)}
+
+#define RT_SDCA_EXT_TLV(xname, reg_base, xhandler_get,\
+ xhandler_put, xcount, xmax, tlv_array, xinfo) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+ SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+ .tlv.p = (tlv_array), \
+ .info = xinfo, \
+ .get = xhandler_get, .put = xhandler_put, \
+ .private_value = RT_SDCA_PR_VALUE(reg_base, xcount, xmax, 0) }
+
+
+int rt_sdca_index_write(struct regmap *map, unsigned int nid,
+ unsigned int reg, unsigned int value);
+int rt_sdca_index_read(struct regmap *map, unsigned int nid,
+ unsigned int reg, unsigned int *value);
+int rt_sdca_index_update_bits(struct regmap *map,
+ unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val);
+int rt_sdca_btn_type(unsigned char *buffer);
+int rt_sdca_headset_detect(struct regmap *map, unsigned int entity_id);
+int rt_sdca_button_detect(struct regmap *map, unsigned int entity_id,
+ unsigned int hid_buf_addr, unsigned int hid_id);
+
+#endif /* __RT_SDW_COMMON_H__ */
diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c
index f4e1ea29c265..3510c3819074 100644
--- a/sound/soc/codecs/rt1320-sdw.c
+++ b/sound/soc/codecs/rt1320-sdw.c
@@ -21,6 +21,7 @@
#include <sound/tlv.h>
#include <sound/sdw.h>
#include "rt1320-sdw.h"
+#include "rt-sdw-common.h"
/*
* The 'blind writes' is an SDCA term to deal with platform-specific initialization.
@@ -89,6 +90,25 @@ static const struct reg_sequence rt1320_blind_write[] = {
{ 0xc019, 0x10 },
{ 0xd487, 0x3f },
{ 0xd486, 0xc3 },
+ { 0x3fc2bfc7, 0x00 },
+ { 0x3fc2bfc6, 0x00 },
+ { 0x3fc2bfc5, 0x00 },
+ { 0x3fc2bfc4, 0x01 },
+ { 0x0000d486, 0x43 },
+ { 0x1000db00, 0x02 },
+ { 0x1000db01, 0x00 },
+ { 0x1000db02, 0x11 },
+ { 0x1000db03, 0x00 },
+ { 0x1000db04, 0x00 },
+ { 0x1000db05, 0x82 },
+ { 0x1000db06, 0x04 },
+ { 0x1000db07, 0xf1 },
+ { 0x1000db08, 0x00 },
+ { 0x1000db09, 0x00 },
+ { 0x1000db0a, 0x40 },
+ { 0x0000d540, 0x01 },
+ { 0xd172, 0x2a },
+ { 0xc5d6, 0x01 },
};
static const struct reg_sequence rt1320_vc_blind_write[] = {
@@ -148,6 +168,12 @@ static const struct reg_sequence rt1320_vc_blind_write[] = {
{ 0xd487, 0x3b },
{ 0xd486, 0xc3 },
{ 0xc598, 0x04 },
+ { 0xdb03, 0xf0 },
+ { 0xdb09, 0x00 },
+ { 0xdb08, 0x7a },
+ { 0xdb19, 0x02 },
+ { 0xdb07, 0x5a },
+ { 0xdb05, 0x45 },
{ 0xd500, 0x00 },
{ 0xd500, 0x17 },
{ 0xd600, 0x01 },
@@ -164,1913 +190,6 @@ static const struct reg_sequence rt1320_vc_blind_write[] = {
{ 0xd610, 0x01 },
{ 0xd608, 0x03 },
{ 0xd609, 0x00 },
-};
-
-static const struct reg_sequence rt1320_vc_patch_code_write[] = {
- { 0x10007000, 0x37 },
- { 0x10007001, 0x77 },
- { 0x10007002, 0x00 },
- { 0x10007003, 0x10 },
- { 0x10007004, 0xb7 },
- { 0x10007005, 0xe7 },
- { 0x10007006, 0x00 },
- { 0x10007007, 0x10 },
- { 0x10007008, 0x13 },
- { 0x10007009, 0x07 },
- { 0x1000700a, 0x87 },
- { 0x1000700b, 0x48 },
- { 0x1000700c, 0x23 },
- { 0x1000700d, 0xa6 },
- { 0x1000700e, 0xe7 },
- { 0x1000700f, 0xee },
- { 0x10007010, 0x37 },
- { 0x10007011, 0x77 },
- { 0x10007012, 0x00 },
- { 0x10007013, 0x10 },
- { 0x10007014, 0x13 },
- { 0x10007015, 0x07 },
- { 0x10007016, 0x87 },
- { 0x10007017, 0x56 },
- { 0x10007018, 0x23 },
- { 0x10007019, 0xac },
- { 0x1000701a, 0xe7 },
- { 0x1000701b, 0xde },
- { 0x1000701c, 0x37 },
- { 0x1000701d, 0x77 },
- { 0x1000701e, 0x00 },
- { 0x1000701f, 0x10 },
- { 0x10007020, 0x13 },
- { 0x10007021, 0x07 },
- { 0x10007022, 0xc7 },
- { 0x10007023, 0x5f },
- { 0x10007024, 0x23 },
- { 0x10007025, 0xae },
- { 0x10007026, 0xe7 },
- { 0x10007027, 0xdc },
- { 0x10007028, 0x37 },
- { 0x10007029, 0x87 },
- { 0x1000702a, 0x00 },
- { 0x1000702b, 0x10 },
- { 0x1000702c, 0x13 },
- { 0x1000702d, 0x07 },
- { 0x1000702e, 0xc7 },
- { 0x1000702f, 0x86 },
- { 0x10007030, 0x23 },
- { 0x10007031, 0xae },
- { 0x10007032, 0xe7 },
- { 0x10007033, 0xe6 },
- { 0x10007034, 0x37 },
- { 0x10007035, 0x77 },
- { 0x10007036, 0x00 },
- { 0x10007037, 0x10 },
- { 0x10007038, 0x13 },
- { 0x10007039, 0x07 },
- { 0x1000703a, 0x07 },
- { 0x1000703b, 0x40 },
- { 0x1000703c, 0x23 },
- { 0x1000703d, 0xa6 },
- { 0x1000703e, 0xe7 },
- { 0x1000703f, 0xe8 },
- { 0x10007040, 0x37 },
- { 0x10007041, 0x77 },
- { 0x10007042, 0x00 },
- { 0x10007043, 0x10 },
- { 0x10007044, 0x13 },
- { 0x10007045, 0x07 },
- { 0x10007046, 0xc7 },
- { 0x10007047, 0x63 },
- { 0x10007048, 0x23 },
- { 0x10007049, 0xa2 },
- { 0x1000704a, 0xe7 },
- { 0x1000704b, 0xec },
- { 0x1000704c, 0x37 },
- { 0x1000704d, 0x77 },
- { 0x1000704e, 0x00 },
- { 0x1000704f, 0x10 },
- { 0x10007050, 0x13 },
- { 0x10007051, 0x07 },
- { 0x10007052, 0x47 },
- { 0x10007053, 0x6f },
- { 0x10007054, 0x23 },
- { 0x10007055, 0xa6 },
- { 0x10007056, 0xe7 },
- { 0x10007057, 0xec },
- { 0x10007058, 0x37 },
- { 0x10007059, 0x77 },
- { 0x1000705a, 0x00 },
- { 0x1000705b, 0x10 },
- { 0x1000705c, 0x13 },
- { 0x1000705d, 0x07 },
- { 0x1000705e, 0x07 },
- { 0x1000705f, 0x44 },
- { 0x10007060, 0x23 },
- { 0x10007061, 0xa8 },
- { 0x10007062, 0xe7 },
- { 0x10007063, 0xec },
- { 0x10007064, 0x37 },
- { 0x10007065, 0x87 },
- { 0x10007066, 0x00 },
- { 0x10007067, 0x10 },
- { 0x10007068, 0x13 },
- { 0x10007069, 0x07 },
- { 0x1000706a, 0x87 },
- { 0x1000706b, 0x84 },
- { 0x1000706c, 0x23 },
- { 0x1000706d, 0xa8 },
- { 0x1000706e, 0xe7 },
- { 0x1000706f, 0xee },
- { 0x10007070, 0x37 },
- { 0x10007071, 0x87 },
- { 0x10007072, 0x00 },
- { 0x10007073, 0x10 },
- { 0x10007074, 0x13 },
- { 0x10007075, 0x07 },
- { 0x10007076, 0x47 },
- { 0x10007077, 0x97 },
- { 0x10007078, 0x23 },
- { 0x10007079, 0xaa },
- { 0x1000707a, 0xe7 },
- { 0x1000707b, 0xee },
- { 0x1000707c, 0x67 },
- { 0x1000707d, 0x80 },
- { 0x1000707e, 0x00 },
- { 0x1000707f, 0x00 },
- { 0x10007400, 0xb7 },
- { 0x10007401, 0xd6 },
- { 0x10007402, 0x00 },
- { 0x10007403, 0x00 },
- { 0x10007404, 0x83 },
- { 0x10007405, 0xc7 },
- { 0x10007406, 0x06 },
- { 0x10007407, 0x47 },
- { 0x10007408, 0x93 },
- { 0x10007409, 0xf7 },
- { 0x1000740a, 0x87 },
- { 0x1000740b, 0x00 },
- { 0x1000740c, 0x63 },
- { 0x1000740d, 0x88 },
- { 0x1000740e, 0x07 },
- { 0x1000740f, 0x02 },
- { 0x10007410, 0x03 },
- { 0x10007411, 0xc7 },
- { 0x10007412, 0x31 },
- { 0x10007413, 0x43 },
- { 0x10007414, 0x63 },
- { 0x10007415, 0x14 },
- { 0x10007416, 0x07 },
- { 0x10007417, 0x02 },
- { 0x10007418, 0x13 },
- { 0x10007419, 0x07 },
- { 0x1000741a, 0x10 },
- { 0x1000741b, 0x00 },
- { 0x1000741c, 0xa3 },
- { 0x1000741d, 0x89 },
- { 0x1000741e, 0xe1 },
- { 0x1000741f, 0x42 },
- { 0x10007420, 0x37 },
- { 0x10007421, 0xc7 },
- { 0x10007422, 0x00 },
- { 0x10007423, 0x00 },
- { 0x10007424, 0x03 },
- { 0x10007425, 0x46 },
- { 0x10007426, 0x07 },
- { 0x10007427, 0x06 },
- { 0x10007428, 0x23 },
- { 0x10007429, 0x8a },
- { 0x1000742a, 0xc1 },
- { 0x1000742b, 0x42 },
- { 0x1000742c, 0x83 },
- { 0x1000742d, 0xc7 },
- { 0x1000742e, 0x46 },
- { 0x1000742f, 0x47 },
- { 0x10007430, 0x93 },
- { 0x10007431, 0xf7 },
- { 0x10007432, 0xf7 },
- { 0x10007433, 0x0f },
- { 0x10007434, 0x23 },
- { 0x10007435, 0x00 },
- { 0x10007436, 0xf7 },
- { 0x10007437, 0x06 },
- { 0x10007438, 0x23 },
- { 0x10007439, 0x89 },
- { 0x1000743a, 0x01 },
- { 0x1000743b, 0x42 },
- { 0x1000743c, 0x67 },
- { 0x1000743d, 0x80 },
- { 0x1000743e, 0x00 },
- { 0x1000743f, 0x00 },
- { 0x10007440, 0x37 },
- { 0x10007441, 0xc7 },
- { 0x10007442, 0x00 },
- { 0x10007443, 0x00 },
- { 0x10007444, 0x83 },
- { 0x10007445, 0x27 },
- { 0x10007446, 0xc7 },
- { 0x10007447, 0x5f },
- { 0x10007448, 0x13 },
- { 0x10007449, 0x05 },
- { 0x1000744a, 0x00 },
- { 0x1000744b, 0x00 },
- { 0x1000744c, 0x23 },
- { 0x1000744d, 0xa2 },
- { 0x1000744e, 0xf1 },
- { 0x1000744f, 0x42 },
- { 0x10007450, 0xb7 },
- { 0x10007451, 0x06 },
- { 0x10007452, 0x00 },
- { 0x10007453, 0x10 },
- { 0x10007454, 0xb3 },
- { 0x10007455, 0xf7 },
- { 0x10007456, 0xd7 },
- { 0x10007457, 0x00 },
- { 0x10007458, 0x63 },
- { 0x10007459, 0x86 },
- { 0x1000745a, 0x07 },
- { 0x1000745b, 0x02 },
- { 0x1000745c, 0x83 },
- { 0x1000745d, 0x47 },
- { 0x1000745e, 0x07 },
- { 0x1000745f, 0x56 },
- { 0x10007460, 0x93 },
- { 0x10007461, 0xf7 },
- { 0x10007462, 0x87 },
- { 0x10007463, 0x01 },
- { 0x10007464, 0x63 },
- { 0x10007465, 0x80 },
- { 0x10007466, 0x07 },
- { 0x10007467, 0x02 },
- { 0x10007468, 0x83 },
- { 0x10007469, 0x47 },
- { 0x1000746a, 0x17 },
- { 0x1000746b, 0x08 },
- { 0x1000746c, 0x93 },
- { 0x1000746d, 0xf7 },
- { 0x1000746e, 0x47 },
- { 0x1000746f, 0x00 },
- { 0x10007470, 0x63 },
- { 0x10007471, 0x8a },
- { 0x10007472, 0x07 },
- { 0x10007473, 0x00 },
- { 0x10007474, 0xb7 },
- { 0x10007475, 0xc7 },
- { 0x10007476, 0xc2 },
- { 0x10007477, 0x3f },
- { 0x10007478, 0x03 },
- { 0x10007479, 0xa5 },
- { 0x1000747a, 0x47 },
- { 0x1000747b, 0xfc },
- { 0x1000747c, 0x13 },
- { 0x1000747d, 0x55 },
- { 0x1000747e, 0x25 },
- { 0x1000747f, 0x00 },
- { 0x10007480, 0x13 },
- { 0x10007481, 0x75 },
- { 0x10007482, 0x15 },
- { 0x10007483, 0x00 },
- { 0x10007484, 0x67 },
- { 0x10007485, 0x80 },
- { 0x10007486, 0x00 },
- { 0x10007487, 0x00 },
- { 0x10007488, 0x03 },
- { 0x10007489, 0xa7 },
- { 0x1000748a, 0x81 },
- { 0x1000748b, 0x57 },
- { 0x1000748c, 0x13 },
- { 0x1000748d, 0x01 },
- { 0x1000748e, 0x01 },
- { 0x1000748f, 0xff },
- { 0x10007490, 0x23 },
- { 0x10007491, 0x26 },
- { 0x10007492, 0x11 },
- { 0x10007493, 0x00 },
- { 0x10007494, 0x23 },
- { 0x10007495, 0x24 },
- { 0x10007496, 0x81 },
- { 0x10007497, 0x00 },
- { 0x10007498, 0x23 },
- { 0x10007499, 0x22 },
- { 0x1000749a, 0x91 },
- { 0x1000749b, 0x00 },
- { 0x1000749c, 0x93 },
- { 0x1000749d, 0x07 },
- { 0x1000749e, 0xa0 },
- { 0x1000749f, 0x05 },
- { 0x100074a0, 0x63 },
- { 0x100074a1, 0x14 },
- { 0x100074a2, 0xf7 },
- { 0x100074a3, 0x04 },
- { 0x100074a4, 0x37 },
- { 0x100074a5, 0x07 },
- { 0x100074a6, 0x00 },
- { 0x100074a7, 0x11 },
- { 0x100074a8, 0x83 },
- { 0x100074a9, 0x47 },
- { 0x100074aa, 0x07 },
- { 0x100074ab, 0x01 },
- { 0x100074ac, 0x13 },
- { 0x100074ad, 0x06 },
- { 0x100074ae, 0x30 },
- { 0x100074af, 0x00 },
- { 0x100074b0, 0x93 },
- { 0x100074b1, 0xf7 },
- { 0x100074b2, 0xf7 },
- { 0x100074b3, 0x0f },
- { 0x100074b4, 0x63 },
- { 0x100074b5, 0x9a },
- { 0x100074b6, 0xc7 },
- { 0x100074b7, 0x02 },
- { 0x100074b8, 0x03 },
- { 0x100074b9, 0x47 },
- { 0x100074ba, 0x87 },
- { 0x100074bb, 0x01 },
- { 0x100074bc, 0x13 },
- { 0x100074bd, 0x77 },
- { 0x100074be, 0xf7 },
- { 0x100074bf, 0x0f },
- { 0x100074c0, 0x63 },
- { 0x100074c1, 0x14 },
- { 0x100074c2, 0xf7 },
- { 0x100074c3, 0x02 },
- { 0x100074c4, 0x37 },
- { 0x100074c5, 0xd7 },
- { 0x100074c6, 0x00 },
- { 0x100074c7, 0x00 },
- { 0x100074c8, 0x83 },
- { 0x100074c9, 0x47 },
- { 0x100074ca, 0x37 },
- { 0x100074cb, 0x54 },
- { 0x100074cc, 0x93 },
- { 0x100074cd, 0xf7 },
- { 0x100074ce, 0xf7 },
- { 0x100074cf, 0x0f },
- { 0x100074d0, 0x93 },
- { 0x100074d1, 0xe7 },
- { 0x100074d2, 0x07 },
- { 0x100074d3, 0x02 },
- { 0x100074d4, 0xa3 },
- { 0x100074d5, 0x01 },
- { 0x100074d6, 0xf7 },
- { 0x100074d7, 0x54 },
- { 0x100074d8, 0x83 },
- { 0x100074d9, 0x47 },
- { 0x100074da, 0x37 },
- { 0x100074db, 0x54 },
- { 0x100074dc, 0x93 },
- { 0x100074dd, 0xf7 },
- { 0x100074de, 0xf7 },
- { 0x100074df, 0x0d },
- { 0x100074e0, 0xa3 },
- { 0x100074e1, 0x01 },
- { 0x100074e2, 0xf7 },
- { 0x100074e3, 0x54 },
- { 0x100074e4, 0x23 },
- { 0x100074e5, 0xac },
- { 0x100074e6, 0x01 },
- { 0x100074e7, 0x56 },
- { 0x100074e8, 0x37 },
- { 0x100074e9, 0xd4 },
- { 0x100074ea, 0x00 },
- { 0x100074eb, 0x00 },
- { 0x100074ec, 0x83 },
- { 0x100074ed, 0x47 },
- { 0x100074ee, 0xd4 },
- { 0x100074ef, 0x47 },
- { 0x100074f0, 0x93 },
- { 0x100074f1, 0xf7 },
- { 0x100074f2, 0x17 },
- { 0x100074f3, 0x00 },
- { 0x100074f4, 0x63 },
- { 0x100074f5, 0x80 },
- { 0x100074f6, 0x07 },
- { 0x100074f7, 0x06 },
- { 0x100074f8, 0x37 },
- { 0x100074f9, 0xd7 },
- { 0x100074fa, 0x00 },
- { 0x100074fb, 0x10 },
- { 0x100074fc, 0x83 },
- { 0x100074fd, 0x47 },
- { 0x100074fe, 0x77 },
- { 0x100074ff, 0xd9 },
- { 0x10007500, 0x93 },
- { 0x10007501, 0x87 },
- { 0x10007502, 0x17 },
- { 0x10007503, 0x00 },
- { 0x10007504, 0x93 },
- { 0x10007505, 0xf7 },
- { 0x10007506, 0xf7 },
- { 0x10007507, 0x0f },
- { 0x10007508, 0xa3 },
- { 0x10007509, 0x0b },
- { 0x1000750a, 0xf7 },
- { 0x1000750b, 0xd8 },
- { 0x1000750c, 0x03 },
- { 0x1000750d, 0x47 },
- { 0x1000750e, 0x77 },
- { 0x1000750f, 0xd9 },
- { 0x10007510, 0x83 },
- { 0x10007511, 0x47 },
- { 0x10007512, 0xc4 },
- { 0x10007513, 0x47 },
- { 0x10007514, 0x13 },
- { 0x10007515, 0x77 },
- { 0x10007516, 0xf7 },
- { 0x10007517, 0x0f },
- { 0x10007518, 0x93 },
- { 0x10007519, 0xf7 },
- { 0x1000751a, 0xf7 },
- { 0x1000751b, 0x0f },
- { 0x1000751c, 0x63 },
- { 0x1000751d, 0x6c },
- { 0x1000751e, 0xf7 },
- { 0x1000751f, 0x02 },
- { 0x10007520, 0xb7 },
- { 0x10007521, 0xf4 },
- { 0x10007522, 0x00 },
- { 0x10007523, 0x00 },
- { 0x10007524, 0x93 },
- { 0x10007525, 0x05 },
- { 0x10007526, 0x00 },
- { 0x10007527, 0x01 },
- { 0x10007528, 0x13 },
- { 0x10007529, 0x85 },
- { 0x1000752a, 0x34 },
- { 0x1000752b, 0x52 },
- { 0x1000752c, 0xef },
- { 0x1000752d, 0xa0 },
- { 0x1000752e, 0x8f },
- { 0x1000752f, 0xc6 },
- { 0x10007530, 0x93 },
- { 0x10007531, 0x05 },
- { 0x10007532, 0x00 },
- { 0x10007533, 0x00 },
- { 0x10007534, 0x13 },
- { 0x10007535, 0x85 },
- { 0x10007536, 0x54 },
- { 0x10007537, 0x10 },
- { 0x10007538, 0xef },
- { 0x10007539, 0xa0 },
- { 0x1000753a, 0xcf },
- { 0x1000753b, 0xc5 },
- { 0x1000753c, 0x93 },
- { 0x1000753d, 0x05 },
- { 0x1000753e, 0x00 },
- { 0x1000753f, 0x00 },
- { 0x10007540, 0x13 },
- { 0x10007541, 0x85 },
- { 0x10007542, 0x74 },
- { 0x10007543, 0x10 },
- { 0x10007544, 0xef },
- { 0x10007545, 0xa0 },
- { 0x10007546, 0x0f },
- { 0x10007547, 0xc5 },
- { 0x10007548, 0x83 },
- { 0x10007549, 0x47 },
- { 0x1000754a, 0xd4 },
- { 0x1000754b, 0x47 },
- { 0x1000754c, 0x93 },
- { 0x1000754d, 0xf7 },
- { 0x1000754e, 0xe7 },
- { 0x1000754f, 0x0f },
- { 0x10007550, 0xa3 },
- { 0x10007551, 0x0e },
- { 0x10007552, 0xf4 },
- { 0x10007553, 0x46 },
- { 0x10007554, 0x83 },
- { 0x10007555, 0x20 },
- { 0x10007556, 0xc1 },
- { 0x10007557, 0x00 },
- { 0x10007558, 0x03 },
- { 0x10007559, 0x24 },
- { 0x1000755a, 0x81 },
- { 0x1000755b, 0x00 },
- { 0x1000755c, 0x83 },
- { 0x1000755d, 0x24 },
- { 0x1000755e, 0x41 },
- { 0x1000755f, 0x00 },
- { 0x10007560, 0x13 },
- { 0x10007561, 0x01 },
- { 0x10007562, 0x01 },
- { 0x10007563, 0x01 },
- { 0x10007564, 0x67 },
- { 0x10007565, 0x80 },
- { 0x10007566, 0x00 },
- { 0x10007567, 0x00 },
- { 0x10007568, 0x13 },
- { 0x10007569, 0x01 },
- { 0x1000756a, 0x01 },
- { 0x1000756b, 0xff },
- { 0x1000756c, 0x23 },
- { 0x1000756d, 0x24 },
- { 0x1000756e, 0x81 },
- { 0x1000756f, 0x00 },
- { 0x10007570, 0x23 },
- { 0x10007571, 0x26 },
- { 0x10007572, 0x11 },
- { 0x10007573, 0x00 },
- { 0x10007574, 0x23 },
- { 0x10007575, 0x22 },
- { 0x10007576, 0x91 },
- { 0x10007577, 0x00 },
- { 0x10007578, 0x37 },
- { 0x10007579, 0xd4 },
- { 0x1000757a, 0x00 },
- { 0x1000757b, 0x00 },
- { 0x1000757c, 0x83 },
- { 0x1000757d, 0x47 },
- { 0x1000757e, 0x04 },
- { 0x1000757f, 0x54 },
- { 0x10007580, 0x93 },
- { 0x10007581, 0x97 },
- { 0x10007582, 0x87 },
- { 0x10007583, 0x01 },
- { 0x10007584, 0x93 },
- { 0x10007585, 0xd7 },
- { 0x10007586, 0x87 },
- { 0x10007587, 0x41 },
- { 0x10007588, 0x63 },
- { 0x10007589, 0xd0 },
- { 0x1000758a, 0x07 },
- { 0x1000758b, 0x06 },
- { 0x1000758c, 0xb7 },
- { 0x1000758d, 0xf4 },
- { 0x1000758e, 0x00 },
- { 0x1000758f, 0x00 },
- { 0x10007590, 0x93 },
- { 0x10007591, 0x05 },
- { 0x10007592, 0x60 },
- { 0x10007593, 0x01 },
- { 0x10007594, 0x13 },
- { 0x10007595, 0x85 },
- { 0x10007596, 0x34 },
- { 0x10007597, 0x52 },
- { 0x10007598, 0xef },
- { 0x10007599, 0xa0 },
- { 0x1000759a, 0xcf },
- { 0x1000759b, 0xbf },
- { 0x1000759c, 0x93 },
- { 0x1000759d, 0x05 },
- { 0x1000759e, 0x00 },
- { 0x1000759f, 0x04 },
- { 0x100075a0, 0x13 },
- { 0x100075a1, 0x85 },
- { 0x100075a2, 0x54 },
- { 0x100075a3, 0x10 },
- { 0x100075a4, 0xef },
- { 0x100075a5, 0xa0 },
- { 0x100075a6, 0x0f },
- { 0x100075a7, 0xbf },
- { 0x100075a8, 0x93 },
- { 0x100075a9, 0x05 },
- { 0x100075aa, 0x00 },
- { 0x100075ab, 0x04 },
- { 0x100075ac, 0x13 },
- { 0x100075ad, 0x85 },
- { 0x100075ae, 0x74 },
- { 0x100075af, 0x10 },
- { 0x100075b0, 0xef },
- { 0x100075b1, 0xa0 },
- { 0x100075b2, 0x4f },
- { 0x100075b3, 0xbe },
- { 0x100075b4, 0x83 },
- { 0x100075b5, 0x47 },
- { 0x100075b6, 0xd4 },
- { 0x100075b7, 0x47 },
- { 0x100075b8, 0x37 },
- { 0x100075b9, 0xd7 },
- { 0x100075ba, 0x00 },
- { 0x100075bb, 0x10 },
- { 0x100075bc, 0x93 },
- { 0x100075bd, 0xf7 },
- { 0x100075be, 0xf7 },
- { 0x100075bf, 0x0f },
- { 0x100075c0, 0x93 },
- { 0x100075c1, 0xe7 },
- { 0x100075c2, 0x17 },
- { 0x100075c3, 0x00 },
- { 0x100075c4, 0xa3 },
- { 0x100075c5, 0x0e },
- { 0x100075c6, 0xf4 },
- { 0x100075c7, 0x46 },
- { 0x100075c8, 0xa3 },
- { 0x100075c9, 0x0b },
- { 0x100075ca, 0x07 },
- { 0x100075cb, 0xd8 },
- { 0x100075cc, 0x83 },
- { 0x100075cd, 0x47 },
- { 0x100075ce, 0x87 },
- { 0x100075cf, 0xd9 },
- { 0x100075d0, 0x93 },
- { 0x100075d1, 0x87 },
- { 0x100075d2, 0x17 },
- { 0x100075d3, 0x00 },
- { 0x100075d4, 0x93 },
- { 0x100075d5, 0xf7 },
- { 0x100075d6, 0xf7 },
- { 0x100075d7, 0x0f },
- { 0x100075d8, 0x23 },
- { 0x100075d9, 0x0c },
- { 0x100075da, 0xf7 },
- { 0x100075db, 0xd8 },
- { 0x100075dc, 0x83 },
- { 0x100075dd, 0x47 },
- { 0x100075de, 0x04 },
- { 0x100075df, 0x54 },
- { 0x100075e0, 0x93 },
- { 0x100075e1, 0xf7 },
- { 0x100075e2, 0xf7 },
- { 0x100075e3, 0x07 },
- { 0x100075e4, 0x23 },
- { 0x100075e5, 0x00 },
- { 0x100075e6, 0xf4 },
- { 0x100075e7, 0x54 },
- { 0x100075e8, 0x83 },
- { 0x100075e9, 0x20 },
- { 0x100075ea, 0xc1 },
- { 0x100075eb, 0x00 },
- { 0x100075ec, 0x03 },
- { 0x100075ed, 0x24 },
- { 0x100075ee, 0x81 },
- { 0x100075ef, 0x00 },
- { 0x100075f0, 0x83 },
- { 0x100075f1, 0x24 },
- { 0x100075f2, 0x41 },
- { 0x100075f3, 0x00 },
- { 0x100075f4, 0x13 },
- { 0x100075f5, 0x01 },
- { 0x100075f6, 0x01 },
- { 0x100075f7, 0x01 },
- { 0x100075f8, 0x67 },
- { 0x100075f9, 0x80 },
- { 0x100075fa, 0x00 },
- { 0x100075fb, 0x00 },
- { 0x100075fc, 0x13 },
- { 0x100075fd, 0x01 },
- { 0x100075fe, 0x01 },
- { 0x100075ff, 0xff },
- { 0x10007600, 0x23 },
- { 0x10007601, 0x24 },
- { 0x10007602, 0x81 },
- { 0x10007603, 0x00 },
- { 0x10007604, 0x37 },
- { 0x10007605, 0xd4 },
- { 0x10007606, 0x00 },
- { 0x10007607, 0x00 },
- { 0x10007608, 0x83 },
- { 0x10007609, 0x27 },
- { 0x1000760a, 0x04 },
- { 0x1000760b, 0x53 },
- { 0x1000760c, 0x23 },
- { 0x1000760d, 0x22 },
- { 0x1000760e, 0x91 },
- { 0x1000760f, 0x00 },
- { 0x10007610, 0xb7 },
- { 0x10007611, 0x04 },
- { 0x10007612, 0x00 },
- { 0x10007613, 0x40 },
- { 0x10007614, 0x23 },
- { 0x10007615, 0x26 },
- { 0x10007616, 0x11 },
- { 0x10007617, 0x00 },
- { 0x10007618, 0xb3 },
- { 0x10007619, 0xf7 },
- { 0x1000761a, 0x97 },
- { 0x1000761b, 0x00 },
- { 0x1000761c, 0x63 },
- { 0x1000761d, 0x86 },
- { 0x1000761e, 0x07 },
- { 0x1000761f, 0x00 },
- { 0x10007620, 0xef },
- { 0x10007621, 0xd0 },
- { 0x10007622, 0x5f },
- { 0x10007623, 0xc2 },
- { 0x10007624, 0x23 },
- { 0x10007625, 0x28 },
- { 0x10007626, 0x94 },
- { 0x10007627, 0x52 },
- { 0x10007628, 0x83 },
- { 0x10007629, 0x20 },
- { 0x1000762a, 0xc1 },
- { 0x1000762b, 0x00 },
- { 0x1000762c, 0x03 },
- { 0x1000762d, 0x24 },
- { 0x1000762e, 0x81 },
- { 0x1000762f, 0x00 },
- { 0x10007630, 0x83 },
- { 0x10007631, 0x24 },
- { 0x10007632, 0x41 },
- { 0x10007633, 0x00 },
- { 0x10007634, 0x13 },
- { 0x10007635, 0x01 },
- { 0x10007636, 0x01 },
- { 0x10007637, 0x01 },
- { 0x10007638, 0x67 },
- { 0x10007639, 0x80 },
- { 0x1000763a, 0x00 },
- { 0x1000763b, 0x00 },
- { 0x1000763c, 0x37 },
- { 0x1000763d, 0xc7 },
- { 0x1000763e, 0x00 },
- { 0x1000763f, 0x00 },
- { 0x10007640, 0x83 },
- { 0x10007641, 0x27 },
- { 0x10007642, 0xc7 },
- { 0x10007643, 0x5f },
- { 0x10007644, 0x23 },
- { 0x10007645, 0xa2 },
- { 0x10007646, 0xf1 },
- { 0x10007647, 0x42 },
- { 0x10007648, 0xb7 },
- { 0x10007649, 0x06 },
- { 0x1000764a, 0x00 },
- { 0x1000764b, 0x10 },
- { 0x1000764c, 0xb3 },
- { 0x1000764d, 0xf7 },
- { 0x1000764e, 0xd7 },
- { 0x1000764f, 0x00 },
- { 0x10007650, 0x63 },
- { 0x10007651, 0x80 },
- { 0x10007652, 0x07 },
- { 0x10007653, 0x0a },
- { 0x10007654, 0x83 },
- { 0x10007655, 0x47 },
- { 0x10007656, 0x07 },
- { 0x10007657, 0x56 },
- { 0x10007658, 0x93 },
- { 0x10007659, 0xf7 },
- { 0x1000765a, 0x87 },
- { 0x1000765b, 0x01 },
- { 0x1000765c, 0x63 },
- { 0x1000765d, 0x8a },
- { 0x1000765e, 0x07 },
- { 0x1000765f, 0x08 },
- { 0x10007660, 0x83 },
- { 0x10007661, 0x47 },
- { 0x10007662, 0x17 },
- { 0x10007663, 0x08 },
- { 0x10007664, 0x93 },
- { 0x10007665, 0xf7 },
- { 0x10007666, 0x47 },
- { 0x10007667, 0x00 },
- { 0x10007668, 0x63 },
- { 0x10007669, 0x84 },
- { 0x1000766a, 0x07 },
- { 0x1000766b, 0x08 },
- { 0x1000766c, 0x13 },
- { 0x1000766d, 0x01 },
- { 0x1000766e, 0x01 },
- { 0x1000766f, 0xff },
- { 0x10007670, 0x23 },
- { 0x10007671, 0x26 },
- { 0x10007672, 0x11 },
- { 0x10007673, 0x00 },
- { 0x10007674, 0xb7 },
- { 0x10007675, 0xc7 },
- { 0x10007676, 0xc2 },
- { 0x10007677, 0x3f },
- { 0x10007678, 0x03 },
- { 0x10007679, 0xa7 },
- { 0x1000767a, 0x07 },
- { 0x1000767b, 0xfc },
- { 0x1000767c, 0x63 },
- { 0x1000767d, 0x10 },
- { 0x1000767e, 0x05 },
- { 0x1000767f, 0x06 },
- { 0x10007680, 0x13 },
- { 0x10007681, 0x67 },
- { 0x10007682, 0x07 },
- { 0x10007683, 0x20 },
- { 0x10007684, 0x23 },
- { 0x10007685, 0xa0 },
- { 0x10007686, 0xe7 },
- { 0x10007687, 0xfc },
- { 0x10007688, 0x03 },
- { 0x10007689, 0xa7 },
- { 0x1000768a, 0x07 },
- { 0x1000768b, 0xfc },
- { 0x1000768c, 0x13 },
- { 0x1000768d, 0x67 },
- { 0x1000768e, 0x07 },
- { 0x1000768f, 0x40 },
- { 0x10007690, 0x23 },
- { 0x10007691, 0xa0 },
- { 0x10007692, 0xe7 },
- { 0x10007693, 0xfc },
- { 0x10007694, 0x37 },
- { 0x10007695, 0xc7 },
- { 0x10007696, 0xc2 },
- { 0x10007697, 0x3f },
- { 0x10007698, 0x83 },
- { 0x10007699, 0x27 },
- { 0x1000769a, 0x07 },
- { 0x1000769b, 0xfc },
- { 0x1000769c, 0x13 },
- { 0x1000769d, 0x75 },
- { 0x1000769e, 0x15 },
- { 0x1000769f, 0x00 },
- { 0x100076a0, 0x13 },
- { 0x100076a1, 0x15 },
- { 0x100076a2, 0x85 },
- { 0x100076a3, 0x00 },
- { 0x100076a4, 0x93 },
- { 0x100076a5, 0xf7 },
- { 0x100076a6, 0xf7 },
- { 0x100076a7, 0xef },
- { 0x100076a8, 0x33 },
- { 0x100076a9, 0xe5 },
- { 0x100076aa, 0xa7 },
- { 0x100076ab, 0x00 },
- { 0x100076ac, 0x23 },
- { 0x100076ad, 0x20 },
- { 0x100076ae, 0xa7 },
- { 0x100076af, 0xfc },
- { 0x100076b0, 0x93 },
- { 0x100076b1, 0x05 },
- { 0x100076b2, 0x00 },
- { 0x100076b3, 0x00 },
- { 0x100076b4, 0x13 },
- { 0x100076b5, 0x05 },
- { 0x100076b6, 0xa0 },
- { 0x100076b7, 0x00 },
- { 0x100076b8, 0xef },
- { 0x100076b9, 0xe0 },
- { 0x100076ba, 0xcf },
- { 0x100076bb, 0xb6 },
- { 0x100076bc, 0x37 },
- { 0x100076bd, 0xf7 },
- { 0x100076be, 0x00 },
- { 0x100076bf, 0x00 },
- { 0x100076c0, 0x83 },
- { 0x100076c1, 0x47 },
- { 0x100076c2, 0x57 },
- { 0x100076c3, 0x01 },
- { 0x100076c4, 0x93 },
- { 0x100076c5, 0xf7 },
- { 0x100076c6, 0xf7 },
- { 0x100076c7, 0x0f },
- { 0x100076c8, 0x93 },
- { 0x100076c9, 0xe7 },
- { 0x100076ca, 0x47 },
- { 0x100076cb, 0x00 },
- { 0x100076cc, 0xa3 },
- { 0x100076cd, 0x0a },
- { 0x100076ce, 0xf7 },
- { 0x100076cf, 0x00 },
- { 0x100076d0, 0x83 },
- { 0x100076d1, 0x20 },
- { 0x100076d2, 0xc1 },
- { 0x100076d3, 0x00 },
- { 0x100076d4, 0x13 },
- { 0x100076d5, 0x01 },
- { 0x100076d6, 0x01 },
- { 0x100076d7, 0x01 },
- { 0x100076d8, 0x67 },
- { 0x100076d9, 0x80 },
- { 0x100076da, 0x00 },
- { 0x100076db, 0x00 },
- { 0x100076dc, 0x13 },
- { 0x100076dd, 0x77 },
- { 0x100076de, 0xf7 },
- { 0x100076df, 0xdf },
- { 0x100076e0, 0x23 },
- { 0x100076e1, 0xa0 },
- { 0x100076e2, 0xe7 },
- { 0x100076e3, 0xfc },
- { 0x100076e4, 0x03 },
- { 0x100076e5, 0xa7 },
- { 0x100076e6, 0x07 },
- { 0x100076e7, 0xfc },
- { 0x100076e8, 0x13 },
- { 0x100076e9, 0x77 },
- { 0x100076ea, 0xf7 },
- { 0x100076eb, 0xbf },
- { 0x100076ec, 0x6f },
- { 0x100076ed, 0xf0 },
- { 0x100076ee, 0x5f },
- { 0x100076ef, 0xfa },
- { 0x100076f0, 0x67 },
- { 0x100076f1, 0x80 },
- { 0x100076f2, 0x00 },
- { 0x100076f3, 0x00 },
- { 0x100076f4, 0xb7 },
- { 0x100076f5, 0xc7 },
- { 0x100076f6, 0x00 },
- { 0x100076f7, 0x00 },
- { 0x100076f8, 0x03 },
- { 0x100076f9, 0xc7 },
- { 0x100076fa, 0x87 },
- { 0x100076fb, 0x59 },
- { 0x100076fc, 0x13 },
- { 0x100076fd, 0x77 },
- { 0x100076fe, 0xf7 },
- { 0x100076ff, 0x0f },
- { 0x10007700, 0x13 },
- { 0x10007701, 0x67 },
- { 0x10007702, 0x17 },
- { 0x10007703, 0x00 },
- { 0x10007704, 0x23 },
- { 0x10007705, 0x8c },
- { 0x10007706, 0xe7 },
- { 0x10007707, 0x58 },
- { 0x10007708, 0x03 },
- { 0x10007709, 0xc7 },
- { 0x1000770a, 0x77 },
- { 0x1000770b, 0x04 },
- { 0x1000770c, 0x13 },
- { 0x1000770d, 0x17 },
- { 0x1000770e, 0x87 },
- { 0x1000770f, 0x01 },
- { 0x10007710, 0x13 },
- { 0x10007711, 0x57 },
- { 0x10007712, 0x87 },
- { 0x10007713, 0x41 },
- { 0x10007714, 0x63 },
- { 0x10007715, 0x58 },
- { 0x10007716, 0x07 },
- { 0x10007717, 0x12 },
- { 0x10007718, 0x37 },
- { 0x10007719, 0xd7 },
- { 0x1000771a, 0x00 },
- { 0x1000771b, 0x00 },
- { 0x1000771c, 0x83 },
- { 0x1000771d, 0x26 },
- { 0x1000771e, 0x87 },
- { 0x1000771f, 0x53 },
- { 0x10007720, 0x37 },
- { 0x10007721, 0x06 },
- { 0x10007722, 0x00 },
- { 0x10007723, 0x40 },
- { 0x10007724, 0x93 },
- { 0x10007725, 0x05 },
- { 0x10007726, 0x80 },
- { 0x10007727, 0x01 },
- { 0x10007728, 0xb3 },
- { 0x10007729, 0xe6 },
- { 0x1000772a, 0xc6 },
- { 0x1000772b, 0x00 },
- { 0x1000772c, 0x23 },
- { 0x1000772d, 0x2c },
- { 0x1000772e, 0xd7 },
- { 0x1000772f, 0x52 },
- { 0x10007730, 0x83 },
- { 0x10007731, 0xc6 },
- { 0x10007732, 0x07 },
- { 0x10007733, 0x56 },
- { 0x10007734, 0x93 },
- { 0x10007735, 0xf6 },
- { 0x10007736, 0xf6 },
- { 0x10007737, 0x0f },
- { 0x10007738, 0x63 },
- { 0x10007739, 0x9c },
- { 0x1000773a, 0xb6 },
- { 0x1000773b, 0x0e },
- { 0x1000773c, 0x83 },
- { 0x1000773d, 0x27 },
- { 0x1000773e, 0x87 },
- { 0x1000773f, 0x53 },
- { 0x10007740, 0xb3 },
- { 0x10007741, 0xf7 },
- { 0x10007742, 0xc7 },
- { 0x10007743, 0x00 },
- { 0x10007744, 0x63 },
- { 0x10007745, 0x80 },
- { 0x10007746, 0x07 },
- { 0x10007747, 0x10 },
- { 0x10007748, 0x13 },
- { 0x10007749, 0x01 },
- { 0x1000774a, 0x01 },
- { 0x1000774b, 0xff },
- { 0x1000774c, 0x23 },
- { 0x1000774d, 0x24 },
- { 0x1000774e, 0x81 },
- { 0x1000774f, 0x00 },
- { 0x10007750, 0x83 },
- { 0x10007751, 0xa7 },
- { 0x10007752, 0x41 },
- { 0x10007753, 0x58 },
- { 0x10007754, 0x23 },
- { 0x10007755, 0x26 },
- { 0x10007756, 0x11 },
- { 0x10007757, 0x00 },
- { 0x10007758, 0x63 },
- { 0x10007759, 0x94 },
- { 0x1000775a, 0x07 },
- { 0x1000775b, 0x0c },
- { 0x1000775c, 0x83 },
- { 0x1000775d, 0x27 },
- { 0x1000775e, 0x07 },
- { 0x1000775f, 0x53 },
- { 0x10007760, 0x03 },
- { 0x10007761, 0xc6 },
- { 0x10007762, 0xb1 },
- { 0x10007763, 0x42 },
- { 0x10007764, 0x93 },
- { 0x10007765, 0xd7 },
- { 0x10007766, 0xe7 },
- { 0x10007767, 0x01 },
- { 0x10007768, 0x93 },
- { 0x10007769, 0xf7 },
- { 0x1000776a, 0x17 },
- { 0x1000776b, 0x00 },
- { 0x1000776c, 0x93 },
- { 0x1000776d, 0x06 },
- { 0x1000776e, 0x10 },
- { 0x1000776f, 0x00 },
- { 0x10007770, 0x63 },
- { 0x10007771, 0x14 },
- { 0x10007772, 0x06 },
- { 0x10007773, 0x00 },
- { 0x10007774, 0xb3 },
- { 0x10007775, 0x86 },
- { 0x10007776, 0xf6 },
- { 0x10007777, 0x40 },
- { 0x10007778, 0xa3 },
- { 0x10007779, 0x85 },
- { 0x1000777a, 0xd1 },
- { 0x1000777b, 0x42 },
- { 0x1000777c, 0x03 },
- { 0x1000777d, 0xc6 },
- { 0x1000777e, 0xa1 },
- { 0x1000777f, 0x42 },
- { 0x10007780, 0x93 },
- { 0x10007781, 0x06 },
- { 0x10007782, 0x10 },
- { 0x10007783, 0x00 },
- { 0x10007784, 0x63 },
- { 0x10007785, 0x14 },
- { 0x10007786, 0x06 },
- { 0x10007787, 0x00 },
- { 0x10007788, 0xb3 },
- { 0x10007789, 0x86 },
- { 0x1000778a, 0xf6 },
- { 0x1000778b, 0x40 },
- { 0x1000778c, 0x23 },
- { 0x1000778d, 0x85 },
- { 0x1000778e, 0xd1 },
- { 0x1000778f, 0x42 },
- { 0x10007790, 0x03 },
- { 0x10007791, 0xc6 },
- { 0x10007792, 0x91 },
- { 0x10007793, 0x42 },
- { 0x10007794, 0x93 },
- { 0x10007795, 0x06 },
- { 0x10007796, 0x10 },
- { 0x10007797, 0x00 },
- { 0x10007798, 0x63 },
- { 0x10007799, 0x14 },
- { 0x1000779a, 0x06 },
- { 0x1000779b, 0x00 },
- { 0x1000779c, 0xb3 },
- { 0x1000779d, 0x86 },
- { 0x1000779e, 0xf6 },
- { 0x1000779f, 0x40 },
- { 0x100077a0, 0xa3 },
- { 0x100077a1, 0x84 },
- { 0x100077a2, 0xd1 },
- { 0x100077a3, 0x42 },
- { 0x100077a4, 0x03 },
- { 0x100077a5, 0xc6 },
- { 0x100077a6, 0x81 },
- { 0x100077a7, 0x42 },
- { 0x100077a8, 0x93 },
- { 0x100077a9, 0x06 },
- { 0x100077aa, 0x10 },
- { 0x100077ab, 0x00 },
- { 0x100077ac, 0x63 },
- { 0x100077ad, 0x14 },
- { 0x100077ae, 0x06 },
- { 0x100077af, 0x00 },
- { 0x100077b0, 0xb3 },
- { 0x100077b1, 0x86 },
- { 0x100077b2, 0xf6 },
- { 0x100077b3, 0x40 },
- { 0x100077b4, 0x23 },
- { 0x100077b5, 0x84 },
- { 0x100077b6, 0xd1 },
- { 0x100077b7, 0x42 },
- { 0x100077b8, 0xb7 },
- { 0x100077b9, 0xd7 },
- { 0x100077ba, 0x00 },
- { 0x100077bb, 0x00 },
- { 0x100077bc, 0x83 },
- { 0x100077bd, 0xa7 },
- { 0x100077be, 0x07 },
- { 0x100077bf, 0x53 },
- { 0x100077c0, 0x37 },
- { 0x100077c1, 0x07 },
- { 0x100077c2, 0x00 },
- { 0x100077c3, 0x40 },
- { 0x100077c4, 0xb3 },
- { 0x100077c5, 0xf7 },
- { 0x100077c6, 0xe7 },
- { 0x100077c7, 0x00 },
- { 0x100077c8, 0x63 },
- { 0x100077c9, 0x8c },
- { 0x100077ca, 0x07 },
- { 0x100077cb, 0x04 },
- { 0x100077cc, 0xb7 },
- { 0x100077cd, 0x47 },
- { 0x100077ce, 0x0f },
- { 0x100077cf, 0x00 },
- { 0x100077d0, 0x93 },
- { 0x100077d1, 0x87 },
- { 0x100077d2, 0x17 },
- { 0x100077d3, 0x24 },
- { 0x100077d4, 0xb7 },
- { 0x100077d5, 0xf6 },
- { 0x100077d6, 0x00 },
- { 0x100077d7, 0x00 },
- { 0x100077d8, 0x03 },
- { 0x100077d9, 0xc7 },
- { 0x100077da, 0xf6 },
- { 0x100077db, 0x83 },
- { 0x100077dc, 0x13 },
- { 0x100077dd, 0x77 },
- { 0x100077de, 0x07 },
- { 0x100077df, 0x04 },
- { 0x100077e0, 0x63 },
- { 0x100077e1, 0x16 },
- { 0x100077e2, 0x07 },
- { 0x100077e3, 0x00 },
- { 0x100077e4, 0x93 },
- { 0x100077e5, 0x87 },
- { 0x100077e6, 0xf7 },
- { 0x100077e7, 0xff },
- { 0x100077e8, 0xe3 },
- { 0x100077e9, 0x98 },
- { 0x100077ea, 0x07 },
- { 0x100077eb, 0xfe },
- { 0x100077ec, 0x13 },
- { 0x100077ed, 0x05 },
- { 0x100077ee, 0x80 },
- { 0x100077ef, 0x3e },
- { 0x100077f0, 0x93 },
- { 0x100077f1, 0x05 },
- { 0x100077f2, 0x00 },
- { 0x100077f3, 0x00 },
- { 0x100077f4, 0xef },
- { 0x100077f5, 0xe0 },
- { 0x100077f6, 0x0f },
- { 0x100077f7, 0xa3 },
- { 0x100077f8, 0x37 },
- { 0x100077f9, 0xf7 },
- { 0x100077fa, 0x00 },
- { 0x100077fb, 0x00 },
- { 0x100077fc, 0x83 },
- { 0x100077fd, 0x47 },
- { 0x100077fe, 0xb7 },
- { 0x100077ff, 0x80 },
- { 0x10007800, 0x93 },
- { 0x10007801, 0xe7 },
- { 0x10007802, 0x07 },
- { 0x10007803, 0xf8 },
- { 0x10007804, 0x93 },
- { 0x10007805, 0xf7 },
- { 0x10007806, 0xf7 },
- { 0x10007807, 0x0f },
- { 0x10007808, 0xa3 },
- { 0x10007809, 0x05 },
- { 0x1000780a, 0xf7 },
- { 0x1000780b, 0x80 },
- { 0x1000780c, 0xb7 },
- { 0x1000780d, 0xd7 },
- { 0x1000780e, 0x00 },
- { 0x1000780f, 0x00 },
- { 0x10007810, 0x37 },
- { 0x10007811, 0x07 },
- { 0x10007812, 0x00 },
- { 0x10007813, 0x40 },
- { 0x10007814, 0x23 },
- { 0x10007815, 0xa8 },
- { 0x10007816, 0xe7 },
- { 0x10007817, 0x52 },
- { 0x10007818, 0x93 },
- { 0x10007819, 0x07 },
- { 0x1000781a, 0x10 },
- { 0x1000781b, 0x00 },
- { 0x1000781c, 0x23 },
- { 0x1000781d, 0xa2 },
- { 0x1000781e, 0xf1 },
- { 0x1000781f, 0x58 },
- { 0x10007820, 0x83 },
- { 0x10007821, 0x20 },
- { 0x10007822, 0xc1 },
- { 0x10007823, 0x00 },
- { 0x10007824, 0x03 },
- { 0x10007825, 0x24 },
- { 0x10007826, 0x81 },
- { 0x10007827, 0x00 },
- { 0x10007828, 0x13 },
- { 0x10007829, 0x01 },
- { 0x1000782a, 0x01 },
- { 0x1000782b, 0x01 },
- { 0x1000782c, 0x67 },
- { 0x1000782d, 0x80 },
- { 0x1000782e, 0x00 },
- { 0x1000782f, 0x00 },
- { 0x10007830, 0x83 },
- { 0x10007831, 0xc7 },
- { 0x10007832, 0x07 },
- { 0x10007833, 0x56 },
- { 0x10007834, 0x93 },
- { 0x10007835, 0xf7 },
- { 0x10007836, 0xf7 },
- { 0x10007837, 0x0f },
- { 0x10007838, 0x63 },
- { 0x10007839, 0x96 },
- { 0x1000783a, 0x07 },
- { 0x1000783b, 0x00 },
- { 0x1000783c, 0x23 },
- { 0x1000783d, 0xa2 },
- { 0x1000783e, 0x01 },
- { 0x1000783f, 0x58 },
- { 0x10007840, 0x67 },
- { 0x10007841, 0x80 },
- { 0x10007842, 0x00 },
- { 0x10007843, 0x00 },
- { 0x10007844, 0x67 },
- { 0x10007845, 0x80 },
- { 0x10007846, 0x00 },
- { 0x10007847, 0x00 },
- { 0x10007848, 0xb7 },
- { 0x10007849, 0xc7 },
- { 0x1000784a, 0x00 },
- { 0x1000784b, 0x00 },
- { 0x1000784c, 0x83 },
- { 0x1000784d, 0xc7 },
- { 0x1000784e, 0x07 },
- { 0x1000784f, 0x56 },
- { 0x10007850, 0x13 },
- { 0x10007851, 0x07 },
- { 0x10007852, 0x80 },
- { 0x10007853, 0x01 },
- { 0x10007854, 0x93 },
- { 0x10007855, 0xf7 },
- { 0x10007856, 0xf7 },
- { 0x10007857, 0x0f },
- { 0x10007858, 0x63 },
- { 0x10007859, 0x98 },
- { 0x1000785a, 0xe7 },
- { 0x1000785b, 0x00 },
- { 0x1000785c, 0x13 },
- { 0x1000785d, 0x05 },
- { 0x1000785e, 0x00 },
- { 0x1000785f, 0x7d },
- { 0x10007860, 0x93 },
- { 0x10007861, 0x05 },
- { 0x10007862, 0x00 },
- { 0x10007863, 0x00 },
- { 0x10007864, 0x6f },
- { 0x10007865, 0xe0 },
- { 0x10007866, 0x0f },
- { 0x10007867, 0x9c },
- { 0x10007868, 0x67 },
- { 0x10007869, 0x80 },
- { 0x1000786a, 0x00 },
- { 0x1000786b, 0x00 },
- { 0x1000786c, 0x13 },
- { 0x1000786d, 0x01 },
- { 0x1000786e, 0x01 },
- { 0x1000786f, 0xff },
- { 0x10007870, 0x23 },
- { 0x10007871, 0x26 },
- { 0x10007872, 0x11 },
- { 0x10007873, 0x00 },
- { 0x10007874, 0x23 },
- { 0x10007875, 0x24 },
- { 0x10007876, 0x81 },
- { 0x10007877, 0x00 },
- { 0x10007878, 0xef },
- { 0x10007879, 0xd0 },
- { 0x1000787a, 0x4f },
- { 0x1000787b, 0x91 },
- { 0x1000787c, 0x83 },
- { 0x1000787d, 0xc7 },
- { 0x1000787e, 0x81 },
- { 0x1000787f, 0x41 },
- { 0x10007880, 0x63 },
- { 0x10007881, 0x84 },
- { 0x10007882, 0x07 },
- { 0x10007883, 0x08 },
- { 0x10007884, 0xb7 },
- { 0x10007885, 0xd7 },
- { 0x10007886, 0x00 },
- { 0x10007887, 0x00 },
- { 0x10007888, 0x83 },
- { 0x10007889, 0xc7 },
- { 0x1000788a, 0x07 },
- { 0x1000788b, 0x47 },
- { 0x1000788c, 0x93 },
- { 0x1000788d, 0xf7 },
- { 0x1000788e, 0x07 },
- { 0x1000788f, 0x02 },
- { 0x10007890, 0x63 },
- { 0x10007891, 0x8a },
- { 0x10007892, 0x07 },
- { 0x10007893, 0x04 },
- { 0x10007894, 0x83 },
- { 0x10007895, 0xc7 },
- { 0x10007896, 0x11 },
- { 0x10007897, 0x44 },
- { 0x10007898, 0x93 },
- { 0x10007899, 0xf7 },
- { 0x1000789a, 0xd7 },
- { 0x1000789b, 0x0f },
- { 0x1000789c, 0x63 },
- { 0x1000789d, 0x90 },
- { 0x1000789e, 0x07 },
- { 0x1000789f, 0x02 },
- { 0x100078a0, 0x03 },
- { 0x100078a1, 0xc7 },
- { 0x100078a2, 0xd1 },
- { 0x100078a3, 0x58 },
- { 0x100078a4, 0xb7 },
- { 0x100078a5, 0x07 },
- { 0x100078a6, 0x00 },
- { 0x100078a7, 0x11 },
- { 0x100078a8, 0x23 },
- { 0x100078a9, 0x88 },
- { 0x100078aa, 0xe7 },
- { 0x100078ab, 0x00 },
- { 0x100078ac, 0x23 },
- { 0x100078ad, 0x88 },
- { 0x100078ae, 0xe7 },
- { 0x100078af, 0x20 },
- { 0x100078b0, 0x03 },
- { 0x100078b1, 0xc7 },
- { 0x100078b2, 0xc1 },
- { 0x100078b3, 0x58 },
- { 0x100078b4, 0x23 },
- { 0x100078b5, 0x8c },
- { 0x100078b6, 0xe7 },
- { 0x100078b7, 0x00 },
- { 0x100078b8, 0x6f },
- { 0x100078b9, 0x00 },
- { 0x100078ba, 0x80 },
- { 0x100078bb, 0x04 },
- { 0x100078bc, 0xb7 },
- { 0x100078bd, 0x07 },
- { 0x100078be, 0x00 },
- { 0x100078bf, 0x11 },
- { 0x100078c0, 0x23 },
- { 0x100078c1, 0x88 },
- { 0x100078c2, 0x07 },
- { 0x100078c3, 0x00 },
- { 0x100078c4, 0x23 },
- { 0x100078c5, 0x88 },
- { 0x100078c6, 0x07 },
- { 0x100078c7, 0x20 },
- { 0x100078c8, 0x23 },
- { 0x100078c9, 0x8c },
- { 0x100078ca, 0x07 },
- { 0x100078cb, 0x00 },
- { 0x100078cc, 0x23 },
- { 0x100078cd, 0x8c },
- { 0x100078ce, 0x07 },
- { 0x100078cf, 0x20 },
- { 0x100078d0, 0xef },
- { 0x100078d1, 0xb0 },
- { 0x100078d2, 0xcf },
- { 0x100078d3, 0xc4 },
- { 0x100078d4, 0x03 },
- { 0x100078d5, 0x24 },
- { 0x100078d6, 0x81 },
- { 0x100078d7, 0x00 },
- { 0x100078d8, 0x83 },
- { 0x100078d9, 0x20 },
- { 0x100078da, 0xc1 },
- { 0x100078db, 0x00 },
- { 0x100078dc, 0x13 },
- { 0x100078dd, 0x01 },
- { 0x100078de, 0x01 },
- { 0x100078df, 0x01 },
- { 0x100078e0, 0x6f },
- { 0x100078e1, 0xb0 },
- { 0x100078e2, 0xcf },
- { 0x100078e3, 0xcd },
- { 0x100078e4, 0x03 },
- { 0x100078e5, 0xc7 },
- { 0x100078e6, 0xd1 },
- { 0x100078e7, 0x58 },
- { 0x100078e8, 0xb7 },
- { 0x100078e9, 0x07 },
- { 0x100078ea, 0x00 },
- { 0x100078eb, 0x11 },
- { 0x100078ec, 0x23 },
- { 0x100078ed, 0x88 },
- { 0x100078ee, 0xe7 },
- { 0x100078ef, 0x00 },
- { 0x100078f0, 0x83 },
- { 0x100078f1, 0xc6 },
- { 0x100078f2, 0xc1 },
- { 0x100078f3, 0x58 },
- { 0x100078f4, 0x23 },
- { 0x100078f5, 0x88 },
- { 0x100078f6, 0xd7 },
- { 0x100078f7, 0x20 },
- { 0x100078f8, 0x23 },
- { 0x100078f9, 0x8c },
- { 0x100078fa, 0xd7 },
- { 0x100078fb, 0x00 },
- { 0x100078fc, 0x03 },
- { 0x100078fd, 0xc7 },
- { 0x100078fe, 0xc1 },
- { 0x100078ff, 0x58 },
- { 0x10007900, 0x23 },
- { 0x10007901, 0x8c },
- { 0x10007902, 0xe7 },
- { 0x10007903, 0x20 },
- { 0x10007904, 0x6f },
- { 0x10007905, 0xf0 },
- { 0x10007906, 0xdf },
- { 0x10007907, 0xfc },
- { 0x10007908, 0xb7 },
- { 0x10007909, 0x06 },
- { 0x1000790a, 0x00 },
- { 0x1000790b, 0x11 },
- { 0x1000790c, 0x03 },
- { 0x1000790d, 0xc7 },
- { 0x1000790e, 0x06 },
- { 0x1000790f, 0x21 },
- { 0x10007910, 0x03 },
- { 0x10007911, 0xc6 },
- { 0x10007912, 0xd1 },
- { 0x10007913, 0x58 },
- { 0x10007914, 0x13 },
- { 0x10007915, 0x84 },
- { 0x10007916, 0x07 },
- { 0x10007917, 0x00 },
- { 0x10007918, 0x13 },
- { 0x10007919, 0x77 },
- { 0x1000791a, 0xf7 },
- { 0x1000791b, 0x0f },
- { 0x1000791c, 0x63 },
- { 0x1000791d, 0x1a },
- { 0x1000791e, 0xe6 },
- { 0x1000791f, 0x00 },
- { 0x10007920, 0x83 },
- { 0x10007921, 0xc7 },
- { 0x10007922, 0x86 },
- { 0x10007923, 0x21 },
- { 0x10007924, 0x03 },
- { 0x10007925, 0xc7 },
- { 0x10007926, 0xc1 },
- { 0x10007927, 0x58 },
- { 0x10007928, 0x93 },
- { 0x10007929, 0xf7 },
- { 0x1000792a, 0xf7 },
- { 0x1000792b, 0x0f },
- { 0x1000792c, 0xe3 },
- { 0x1000792d, 0x02 },
- { 0x1000792e, 0xf7 },
- { 0x1000792f, 0xfa },
- { 0x10007930, 0xb7 },
- { 0x10007931, 0xc7 },
- { 0x10007932, 0x00 },
- { 0x10007933, 0x00 },
- { 0x10007934, 0x83 },
- { 0x10007935, 0xc7 },
- { 0x10007936, 0x07 },
- { 0x10007937, 0x56 },
- { 0x10007938, 0x13 },
- { 0x10007939, 0x07 },
- { 0x1000793a, 0xf0 },
- { 0x1000793b, 0x00 },
- { 0x1000793c, 0x93 },
- { 0x1000793d, 0xf7 },
- { 0x1000793e, 0xf7 },
- { 0x1000793f, 0x0f },
- { 0x10007940, 0xe3 },
- { 0x10007941, 0x78 },
- { 0x10007942, 0xf7 },
- { 0x10007943, 0xf8 },
- { 0x10007944, 0xb7 },
- { 0x10007945, 0xd7 },
- { 0x10007946, 0x00 },
- { 0x10007947, 0x00 },
- { 0x10007948, 0x83 },
- { 0x10007949, 0xc5 },
- { 0x1000794a, 0xa7 },
- { 0x1000794b, 0x47 },
- { 0x1000794c, 0x93 },
- { 0x1000794d, 0xf7 },
- { 0x1000794e, 0xf5 },
- { 0x1000794f, 0x0f },
- { 0x10007950, 0x93 },
- { 0x10007951, 0x95 },
- { 0x10007952, 0x57 },
- { 0x10007953, 0x00 },
- { 0x10007954, 0xb3 },
- { 0x10007955, 0x85 },
- { 0x10007956, 0xf5 },
- { 0x10007957, 0x40 },
- { 0x10007958, 0x93 },
- { 0x10007959, 0x95 },
- { 0x1000795a, 0x25 },
- { 0x1000795b, 0x00 },
- { 0x1000795c, 0xb3 },
- { 0x1000795d, 0x85 },
- { 0x1000795e, 0xf5 },
- { 0x1000795f, 0x00 },
- { 0x10007960, 0x13 },
- { 0x10007961, 0x95 },
- { 0x10007962, 0x35 },
- { 0x10007963, 0x00 },
- { 0x10007964, 0x93 },
- { 0x10007965, 0xd5 },
- { 0x10007966, 0xf5 },
- { 0x10007967, 0x41 },
- { 0x10007968, 0xef },
- { 0x10007969, 0xe0 },
- { 0x1000796a, 0xcf },
- { 0x1000796b, 0x8b },
- { 0x1000796c, 0x03 },
- { 0x1000796d, 0xc7 },
- { 0x1000796e, 0xd1 },
- { 0x1000796f, 0x58 },
- { 0x10007970, 0x6f },
- { 0x10007971, 0xf0 },
- { 0x10007972, 0x5f },
- { 0x10007973, 0xf3 },
- { 0x10007974, 0x13 },
- { 0x10007975, 0x01 },
- { 0x10007976, 0x01 },
- { 0x10007977, 0xfe },
- { 0x10007978, 0x23 },
- { 0x10007979, 0x2c },
- { 0x1000797a, 0x81 },
- { 0x1000797b, 0x00 },
- { 0x1000797c, 0x83 },
- { 0x1000797d, 0xc7 },
- { 0x1000797e, 0x21 },
- { 0x1000797f, 0x41 },
- { 0x10007980, 0x23 },
- { 0x10007981, 0x2e },
- { 0x10007982, 0x11 },
- { 0x10007983, 0x00 },
- { 0x10007984, 0x23 },
- { 0x10007985, 0x2a },
- { 0x10007986, 0x91 },
- { 0x10007987, 0x00 },
- { 0x10007988, 0x23 },
- { 0x10007989, 0x28 },
- { 0x1000798a, 0x21 },
- { 0x1000798b, 0x01 },
- { 0x1000798c, 0x23 },
- { 0x1000798d, 0x26 },
- { 0x1000798e, 0x31 },
- { 0x1000798f, 0x01 },
- { 0x10007990, 0x13 },
- { 0x10007991, 0x07 },
- { 0x10007992, 0x10 },
- { 0x10007993, 0x00 },
- { 0x10007994, 0x63 },
- { 0x10007995, 0x92 },
- { 0x10007996, 0xe7 },
- { 0x10007997, 0x02 },
- { 0x10007998, 0xa3 },
- { 0x10007999, 0x81 },
- { 0x1000799a, 0xf1 },
- { 0x1000799b, 0x40 },
- { 0x1000799c, 0x83 },
- { 0x1000799d, 0x20 },
- { 0x1000799e, 0xc1 },
- { 0x1000799f, 0x01 },
- { 0x100079a0, 0x03 },
- { 0x100079a1, 0x24 },
- { 0x100079a2, 0x81 },
- { 0x100079a3, 0x01 },
- { 0x100079a4, 0x83 },
- { 0x100079a5, 0x24 },
- { 0x100079a6, 0x41 },
- { 0x100079a7, 0x01 },
- { 0x100079a8, 0x03 },
- { 0x100079a9, 0x29 },
- { 0x100079aa, 0x01 },
- { 0x100079ab, 0x01 },
- { 0x100079ac, 0x83 },
- { 0x100079ad, 0x29 },
- { 0x100079ae, 0xc1 },
- { 0x100079af, 0x00 },
- { 0x100079b0, 0x13 },
- { 0x100079b1, 0x01 },
- { 0x100079b2, 0x01 },
- { 0x100079b3, 0x02 },
- { 0x100079b4, 0x67 },
- { 0x100079b5, 0x80 },
- { 0x100079b6, 0x00 },
- { 0x100079b7, 0x00 },
- { 0x100079b8, 0xe3 },
- { 0x100079b9, 0x92 },
- { 0x100079ba, 0x07 },
- { 0x100079bb, 0xfe },
- { 0x100079bc, 0x37 },
- { 0x100079bd, 0xc9 },
- { 0x100079be, 0x00 },
- { 0x100079bf, 0x00 },
- { 0x100079c0, 0x83 },
- { 0x100079c1, 0x47 },
- { 0x100079c2, 0x09 },
- { 0x100079c3, 0x56 },
- { 0x100079c4, 0x13 },
- { 0x100079c5, 0x07 },
- { 0x100079c6, 0x80 },
- { 0x100079c7, 0x01 },
- { 0x100079c8, 0x93 },
- { 0x100079c9, 0xf7 },
- { 0x100079ca, 0xf7 },
- { 0x100079cb, 0x0f },
- { 0x100079cc, 0xe3 },
- { 0x100079cd, 0x78 },
- { 0x100079ce, 0xf7 },
- { 0x100079cf, 0xfc },
- { 0x100079d0, 0x83 },
- { 0x100079d1, 0xc7 },
- { 0x100079d2, 0x31 },
- { 0x100079d3, 0x40 },
- { 0x100079d4, 0xe3 },
- { 0x100079d5, 0x84 },
- { 0x100079d6, 0x07 },
- { 0x100079d7, 0xfc },
- { 0x100079d8, 0xb7 },
- { 0x100079d9, 0xd4 },
- { 0x100079da, 0x00 },
- { 0x100079db, 0x00 },
- { 0x100079dc, 0x03 },
- { 0x100079dd, 0xc5 },
- { 0x100079de, 0x94 },
- { 0x100079df, 0x47 },
- { 0x100079e0, 0xb7 },
- { 0x100079e1, 0x15 },
- { 0x100079e2, 0x00 },
- { 0x100079e3, 0x00 },
- { 0x100079e4, 0x93 },
- { 0x100079e5, 0x85 },
- { 0x100079e6, 0x85 },
- { 0x100079e7, 0x38 },
- { 0x100079e8, 0x13 },
- { 0x100079e9, 0x75 },
- { 0x100079ea, 0xf5 },
- { 0x100079eb, 0x0f },
- { 0x100079ec, 0xef },
- { 0x100079ed, 0xe0 },
- { 0x100079ee, 0x5f },
- { 0x100079ef, 0xe0 },
- { 0x100079f0, 0x93 },
- { 0x100079f1, 0x55 },
- { 0x100079f2, 0xf5 },
- { 0x100079f3, 0x41 },
- { 0x100079f4, 0xef },
- { 0x100079f5, 0xe0 },
- { 0x100079f6, 0x0f },
- { 0x100079f7, 0x83 },
- { 0x100079f8, 0xa3 },
- { 0x100079f9, 0x81 },
- { 0x100079fa, 0x01 },
- { 0x100079fb, 0x40 },
- { 0x100079fc, 0x83 },
- { 0x100079fd, 0x27 },
- { 0x100079fe, 0xc9 },
- { 0x100079ff, 0x5f },
- { 0x10007a00, 0x37 },
- { 0x10007a01, 0x07 },
- { 0x10007a02, 0x00 },
- { 0x10007a03, 0x02 },
- { 0x10007a04, 0xb3 },
- { 0x10007a05, 0xf7 },
- { 0x10007a06, 0xe7 },
- { 0x10007a07, 0x00 },
- { 0x10007a08, 0xe3 },
- { 0x10007a09, 0x8a },
- { 0x10007a0a, 0x07 },
- { 0x10007a0b, 0xf8 },
- { 0x10007a0c, 0x03 },
- { 0x10007a0d, 0xc7 },
- { 0x10007a0e, 0x04 },
- { 0x10007a0f, 0x90 },
- { 0x10007a10, 0x93 },
- { 0x10007a11, 0x07 },
- { 0x10007a12, 0x10 },
- { 0x10007a13, 0x00 },
- { 0x10007a14, 0x13 },
- { 0x10007a15, 0x77 },
- { 0x10007a16, 0x17 },
- { 0x10007a17, 0x00 },
- { 0x10007a18, 0x63 },
- { 0x10007a19, 0x1c },
- { 0x10007a1a, 0x07 },
- { 0x10007a1b, 0x00 },
- { 0x10007a1c, 0x83 },
- { 0x10007a1d, 0xc7 },
- { 0x10007a1e, 0x34 },
- { 0x10007a1f, 0x54 },
- { 0x10007a20, 0x93 },
- { 0x10007a21, 0xf7 },
- { 0x10007a22, 0xf7 },
- { 0x10007a23, 0x0f },
- { 0x10007a24, 0x93 },
- { 0x10007a25, 0xd7 },
- { 0x10007a26, 0x17 },
- { 0x10007a27, 0x00 },
- { 0x10007a28, 0x93 },
- { 0x10007a29, 0xc7 },
- { 0x10007a2a, 0x17 },
- { 0x10007a2b, 0x00 },
- { 0x10007a2c, 0x93 },
- { 0x10007a2d, 0xf7 },
- { 0x10007a2e, 0x17 },
- { 0x10007a2f, 0x00 },
- { 0x10007a30, 0xa3 },
- { 0x10007a31, 0x85 },
- { 0x10007a32, 0xf1 },
- { 0x10007a33, 0x42 },
- { 0x10007a34, 0x37 },
- { 0x10007a35, 0xd6 },
- { 0x10007a36, 0x00 },
- { 0x10007a37, 0x00 },
- { 0x10007a38, 0x03 },
- { 0x10007a39, 0x47 },
- { 0x10007a3a, 0x06 },
- { 0x10007a3b, 0x90 },
- { 0x10007a3c, 0x93 },
- { 0x10007a3d, 0x06 },
- { 0x10007a3e, 0x10 },
- { 0x10007a3f, 0x00 },
- { 0x10007a40, 0x13 },
- { 0x10007a41, 0x77 },
- { 0x10007a42, 0x27 },
- { 0x10007a43, 0x00 },
- { 0x10007a44, 0x63 },
- { 0x10007a45, 0x18 },
- { 0x10007a46, 0x07 },
- { 0x10007a47, 0x00 },
- { 0x10007a48, 0x03 },
- { 0x10007a49, 0x47 },
- { 0x10007a4a, 0x36 },
- { 0x10007a4b, 0x54 },
- { 0x10007a4c, 0x13 },
- { 0x10007a4d, 0x77 },
- { 0x10007a4e, 0x17 },
- { 0x10007a4f, 0x00 },
- { 0x10007a50, 0xb3 },
- { 0x10007a51, 0x86 },
- { 0x10007a52, 0xe6 },
- { 0x10007a53, 0x40 },
- { 0x10007a54, 0x23 },
- { 0x10007a55, 0x85 },
- { 0x10007a56, 0xd1 },
- { 0x10007a57, 0x42 },
- { 0x10007a58, 0xb7 },
- { 0x10007a59, 0xd5 },
- { 0x10007a5a, 0x00 },
- { 0x10007a5b, 0x00 },
- { 0x10007a5c, 0x03 },
- { 0x10007a5d, 0xc6 },
- { 0x10007a5e, 0x05 },
- { 0x10007a5f, 0x92 },
- { 0x10007a60, 0x13 },
- { 0x10007a61, 0x07 },
- { 0x10007a62, 0x10 },
- { 0x10007a63, 0x00 },
- { 0x10007a64, 0x13 },
- { 0x10007a65, 0x76 },
- { 0x10007a66, 0x16 },
- { 0x10007a67, 0x00 },
- { 0x10007a68, 0x63 },
- { 0x10007a69, 0x1c },
- { 0x10007a6a, 0x06 },
- { 0x10007a6b, 0x00 },
- { 0x10007a6c, 0x03 },
- { 0x10007a6d, 0xc7 },
- { 0x10007a6e, 0x35 },
- { 0x10007a6f, 0x54 },
- { 0x10007a70, 0x13 },
- { 0x10007a71, 0x77 },
- { 0x10007a72, 0xf7 },
- { 0x10007a73, 0x0f },
- { 0x10007a74, 0x13 },
- { 0x10007a75, 0x57 },
- { 0x10007a76, 0x37 },
- { 0x10007a77, 0x00 },
- { 0x10007a78, 0x13 },
- { 0x10007a79, 0x47 },
- { 0x10007a7a, 0x17 },
- { 0x10007a7b, 0x00 },
- { 0x10007a7c, 0x13 },
- { 0x10007a7d, 0x77 },
- { 0x10007a7e, 0x17 },
- { 0x10007a7f, 0x00 },
- { 0x10007a80, 0xa3 },
- { 0x10007a81, 0x84 },
- { 0x10007a82, 0xe1 },
- { 0x10007a83, 0x42 },
- { 0x10007a84, 0xb7 },
- { 0x10007a85, 0xd5 },
- { 0x10007a86, 0x00 },
- { 0x10007a87, 0x00 },
- { 0x10007a88, 0x03 },
- { 0x10007a89, 0xc6 },
- { 0x10007a8a, 0x05 },
- { 0x10007a8b, 0x92 },
- { 0x10007a8c, 0x13 },
- { 0x10007a8d, 0x07 },
- { 0x10007a8e, 0x10 },
- { 0x10007a8f, 0x00 },
- { 0x10007a90, 0x13 },
- { 0x10007a91, 0x76 },
- { 0x10007a92, 0x26 },
- { 0x10007a93, 0x00 },
- { 0x10007a94, 0x63 },
- { 0x10007a95, 0x1c },
- { 0x10007a96, 0x06 },
- { 0x10007a97, 0x00 },
- { 0x10007a98, 0x03 },
- { 0x10007a99, 0xc7 },
- { 0x10007a9a, 0x35 },
- { 0x10007a9b, 0x54 },
- { 0x10007a9c, 0x13 },
- { 0x10007a9d, 0x77 },
- { 0x10007a9e, 0xf7 },
- { 0x10007a9f, 0x0f },
- { 0x10007aa0, 0x13 },
- { 0x10007aa1, 0x57 },
- { 0x10007aa2, 0x27 },
- { 0x10007aa3, 0x00 },
- { 0x10007aa4, 0x13 },
- { 0x10007aa5, 0x47 },
- { 0x10007aa6, 0x17 },
- { 0x10007aa7, 0x00 },
- { 0x10007aa8, 0x13 },
- { 0x10007aa9, 0x77 },
- { 0x10007aaa, 0x17 },
- { 0x10007aab, 0x00 },
- { 0x10007aac, 0x23 },
- { 0x10007aad, 0x84 },
- { 0x10007aae, 0xe1 },
- { 0x10007aaf, 0x42 },
- { 0x10007ab0, 0x63 },
- { 0x10007ab1, 0x84 },
- { 0x10007ab2, 0x07 },
- { 0x10007ab3, 0x00 },
- { 0x10007ab4, 0xe3 },
- { 0x10007ab5, 0x94 },
- { 0x10007ab6, 0x06 },
- { 0x10007ab7, 0xee },
- { 0x10007ab8, 0xef },
- { 0x10007ab9, 0x90 },
- { 0x10007aba, 0x0f },
- { 0x10007abb, 0x86 },
- { 0x10007abc, 0xef },
- { 0x10007abd, 0xd0 },
- { 0x10007abe, 0x0f },
- { 0x10007abf, 0x97 },
- { 0x10007ac0, 0x37 },
- { 0x10007ac1, 0x15 },
- { 0x10007ac2, 0x00 },
- { 0x10007ac3, 0x00 },
- { 0x10007ac4, 0x13 },
- { 0x10007ac5, 0x05 },
- { 0x10007ac6, 0x85 },
- { 0x10007ac7, 0xbb },
- { 0x10007ac8, 0x93 },
- { 0x10007ac9, 0x05 },
- { 0x10007aca, 0x00 },
- { 0x10007acb, 0x00 },
- { 0x10007acc, 0xef },
- { 0x10007acd, 0xd0 },
- { 0x10007ace, 0x9f },
- { 0x10007acf, 0xf5 },
- { 0x10007ad0, 0xb7 },
- { 0x10007ad1, 0xd7 },
- { 0x10007ad2, 0x00 },
- { 0x10007ad3, 0x00 },
- { 0x10007ad4, 0x83 },
- { 0x10007ad5, 0xc7 },
- { 0x10007ad6, 0x07 },
- { 0x10007ad7, 0x47 },
- { 0x10007ad8, 0x93 },
- { 0x10007ad9, 0xf7 },
- { 0x10007ada, 0x47 },
- { 0x10007adb, 0x00 },
- { 0x10007adc, 0xe3 },
- { 0x10007add, 0x80 },
- { 0x10007ade, 0x07 },
- { 0x10007adf, 0xec },
- { 0x10007ae0, 0xef },
- { 0x10007ae1, 0x80 },
- { 0x10007ae2, 0xdf },
- { 0x10007ae3, 0xf4 },
- { 0x10007ae4, 0x23 },
- { 0x10007ae5, 0x89 },
- { 0x10007ae6, 0xa1 },
- { 0x10007ae7, 0x40 },
- { 0x10007ae8, 0x6f },
- { 0x10007ae9, 0xf0 },
- { 0x10007aea, 0x5f },
- { 0x10007aeb, 0xeb },
- { 0x10007aec, 0x00 },
- { 0x10007aed, 0x00 },
- { 0x10007aee, 0x00 },
- { 0x10007aef, 0x00 },
{ 0x3fc2bf83, 0x00 },
{ 0x3fc2bf82, 0x00 },
{ 0x3fc2bf81, 0x00 },
@@ -2109,1346 +228,41 @@ static const struct reg_sequence rt1320_vc_patch_code_write[] = {
{ 0x0000d540, 0x01 },
{ 0x0000c081, 0xfc },
{ 0x0000f01e, 0x80 },
+ { 0xc01b, 0xfc },
+ { 0xc5d1, 0x89 },
+ { 0xc5d8, 0x0a },
+ { 0xc5f7, 0x22 },
+ { 0xc5f6, 0x22 },
+ { 0xc065, 0xa5 },
+ { 0xc06b, 0x0a },
+ { 0xd172, 0x2a },
+ { 0xc5d6, 0x01 },
{ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 },
};
-/*
- * The 'patch code' is written to the patch code area.
- * The patch code area is used for SDCA register expansion flexibility.
- */
-static const struct reg_sequence rt1320_patch_code_write[] = {
- { 0x10007000, 0x37 },
- { 0x10007001, 0x77 },
- { 0x10007002, 0x00 },
- { 0x10007003, 0x10 },
- { 0x10007004, 0xb7 },
- { 0x10007005, 0xe7 },
- { 0x10007006, 0x00 },
- { 0x10007007, 0x10 },
- { 0x10007008, 0x13 },
- { 0x10007009, 0x07 },
- { 0x1000700a, 0x07 },
- { 0x1000700b, 0x40 },
- { 0x1000700c, 0x23 },
- { 0x1000700d, 0xae },
- { 0x1000700e, 0xe7 },
- { 0x1000700f, 0xda },
- { 0x10007010, 0x37 },
- { 0x10007011, 0x77 },
- { 0x10007012, 0x00 },
- { 0x10007013, 0x10 },
- { 0x10007014, 0x13 },
- { 0x10007015, 0x07 },
- { 0x10007016, 0x47 },
- { 0x10007017, 0x61 },
- { 0x10007018, 0x23 },
- { 0x10007019, 0xa4 },
- { 0x1000701a, 0xe7 },
- { 0x1000701b, 0xde },
- { 0x1000701c, 0x37 },
- { 0x1000701d, 0x77 },
- { 0x1000701e, 0x00 },
- { 0x1000701f, 0x10 },
- { 0x10007020, 0x13 },
- { 0x10007021, 0x07 },
- { 0x10007022, 0x07 },
- { 0x10007023, 0x52 },
- { 0x10007024, 0x23 },
- { 0x10007025, 0xae },
- { 0x10007026, 0xe7 },
- { 0x10007027, 0xde },
- { 0x10007028, 0x37 },
- { 0x10007029, 0x77 },
- { 0x1000702a, 0x00 },
- { 0x1000702b, 0x10 },
- { 0x1000702c, 0x13 },
- { 0x1000702d, 0x07 },
- { 0x1000702e, 0x47 },
- { 0x1000702f, 0x54 },
- { 0x10007030, 0x23 },
- { 0x10007031, 0xaa },
- { 0x10007032, 0xe7 },
- { 0x10007033, 0xe4 },
- { 0x10007034, 0x37 },
- { 0x10007035, 0x87 },
- { 0x10007036, 0x00 },
- { 0x10007037, 0x10 },
- { 0x10007038, 0x13 },
- { 0x10007039, 0x07 },
- { 0x1000703a, 0x47 },
- { 0x1000703b, 0x81 },
- { 0x1000703c, 0x23 },
- { 0x1000703d, 0xa2 },
- { 0x1000703e, 0xe7 },
- { 0x1000703f, 0xe8 },
- { 0x10007040, 0x23 },
- { 0x10007041, 0xa4 },
- { 0x10007042, 0xe7 },
- { 0x10007043, 0xe8 },
- { 0x10007044, 0x37 },
- { 0x10007045, 0x77 },
- { 0x10007046, 0x00 },
- { 0x10007047, 0x10 },
- { 0x10007048, 0x13 },
- { 0x10007049, 0x07 },
- { 0x1000704a, 0x07 },
- { 0x1000704b, 0x59 },
- { 0x1000704c, 0x23 },
- { 0x1000704d, 0xa8 },
- { 0x1000704e, 0xe7 },
- { 0x1000704f, 0xea },
- { 0x10007050, 0x37 },
- { 0x10007051, 0x77 },
- { 0x10007052, 0x00 },
- { 0x10007053, 0x10 },
- { 0x10007054, 0x13 },
- { 0x10007055, 0x07 },
- { 0x10007056, 0x07 },
- { 0x10007057, 0x78 },
- { 0x10007058, 0x23 },
- { 0x10007059, 0xa6 },
- { 0x1000705a, 0xe7 },
- { 0x1000705b, 0xec },
- { 0x1000705c, 0x67 },
- { 0x1000705d, 0x80 },
- { 0x1000705e, 0x00 },
- { 0x1000705f, 0x00 },
- { 0x10007400, 0x37 },
- { 0x10007401, 0xd7 },
- { 0x10007402, 0x00 },
- { 0x10007403, 0x00 },
- { 0x10007404, 0x83 },
- { 0x10007405, 0x27 },
- { 0x10007406, 0x47 },
- { 0x10007407, 0x56 },
- { 0x10007408, 0xb7 },
- { 0x10007409, 0x06 },
- { 0x1000740a, 0x00 },
- { 0x1000740b, 0x02 },
- { 0x1000740c, 0xb3 },
- { 0x1000740d, 0xf7 },
- { 0x1000740e, 0xd7 },
- { 0x1000740f, 0x00 },
- { 0x10007410, 0x63 },
- { 0x10007411, 0x8a },
- { 0x10007412, 0x07 },
- { 0x10007413, 0x00 },
- { 0x10007414, 0x93 },
- { 0x10007415, 0x06 },
- { 0x10007416, 0x10 },
- { 0x10007417, 0x00 },
- { 0x10007418, 0x23 },
- { 0x10007419, 0x83 },
- { 0x1000741a, 0xd1 },
- { 0x1000741b, 0x44 },
- { 0x1000741c, 0x93 },
- { 0x1000741d, 0x07 },
- { 0x1000741e, 0xf0 },
- { 0x1000741f, 0xff },
- { 0x10007420, 0x23 },
- { 0x10007421, 0x22 },
- { 0x10007422, 0xf7 },
- { 0x10007423, 0x56 },
- { 0x10007424, 0x37 },
- { 0x10007425, 0xd7 },
- { 0x10007426, 0x00 },
- { 0x10007427, 0x00 },
- { 0x10007428, 0x83 },
- { 0x10007429, 0x27 },
- { 0x1000742a, 0x47 },
- { 0x1000742b, 0x58 },
- { 0x1000742c, 0x93 },
- { 0x1000742d, 0xf7 },
- { 0x1000742e, 0x17 },
- { 0x1000742f, 0x00 },
- { 0x10007430, 0x63 },
- { 0x10007431, 0x86 },
- { 0x10007432, 0x07 },
- { 0x10007433, 0x00 },
- { 0x10007434, 0x93 },
- { 0x10007435, 0x07 },
- { 0x10007436, 0x10 },
- { 0x10007437, 0x00 },
- { 0x10007438, 0x23 },
- { 0x10007439, 0x22 },
- { 0x1000743a, 0xf7 },
- { 0x1000743b, 0x58 },
- { 0x1000743c, 0xb7 },
- { 0x1000743d, 0xd7 },
- { 0x1000743e, 0x00 },
- { 0x1000743f, 0x00 },
- { 0x10007440, 0x03 },
- { 0x10007441, 0xa7 },
- { 0x10007442, 0x47 },
- { 0x10007443, 0x58 },
- { 0x10007444, 0xb7 },
- { 0x10007445, 0x07 },
- { 0x10007446, 0x00 },
- { 0x10007447, 0x04 },
- { 0x10007448, 0x33 },
- { 0x10007449, 0x77 },
- { 0x1000744a, 0xf7 },
- { 0x1000744b, 0x00 },
- { 0x1000744c, 0x93 },
- { 0x1000744d, 0x07 },
- { 0x1000744e, 0x00 },
- { 0x1000744f, 0x00 },
- { 0x10007450, 0x63 },
- { 0x10007451, 0x0e },
- { 0x10007452, 0x07 },
- { 0x10007453, 0x04 },
- { 0x10007454, 0x37 },
- { 0x10007455, 0x07 },
- { 0x10007456, 0x00 },
- { 0x10007457, 0x11 },
- { 0x10007458, 0x03 },
- { 0x10007459, 0x47 },
- { 0x1000745a, 0x87 },
- { 0x1000745b, 0x0e },
- { 0x1000745c, 0x93 },
- { 0x1000745d, 0x06 },
- { 0x1000745e, 0x40 },
- { 0x1000745f, 0x00 },
- { 0x10007460, 0x13 },
- { 0x10007461, 0x77 },
- { 0x10007462, 0xf7 },
- { 0x10007463, 0x0f },
- { 0x10007464, 0x63 },
- { 0x10007465, 0x02 },
- { 0x10007466, 0xd7 },
- { 0x10007467, 0x0a },
- { 0x10007468, 0x93 },
- { 0x10007469, 0x06 },
- { 0x1000746a, 0x70 },
- { 0x1000746b, 0x00 },
- { 0x1000746c, 0x63 },
- { 0x1000746d, 0x10 },
- { 0x1000746e, 0xd7 },
- { 0x1000746f, 0x04 },
- { 0x10007470, 0x93 },
- { 0x10007471, 0x07 },
- { 0x10007472, 0x60 },
- { 0x10007473, 0x06 },
- { 0x10007474, 0x37 },
- { 0x10007475, 0xd7 },
- { 0x10007476, 0x00 },
- { 0x10007477, 0x00 },
- { 0x10007478, 0x83 },
- { 0x10007479, 0x46 },
- { 0x1000747a, 0x77 },
- { 0x1000747b, 0xa6 },
- { 0x1000747c, 0x93 },
- { 0x1000747d, 0xe6 },
- { 0x1000747e, 0x06 },
- { 0x1000747f, 0xf8 },
- { 0x10007480, 0x93 },
- { 0x10007481, 0xf6 },
- { 0x10007482, 0xf6 },
- { 0x10007483, 0x0f },
- { 0x10007484, 0xa3 },
- { 0x10007485, 0x03 },
- { 0x10007486, 0xd7 },
- { 0x10007487, 0xa6 },
- { 0x10007488, 0x83 },
- { 0x10007489, 0x46 },
- { 0x1000748a, 0x77 },
- { 0x1000748b, 0xa8 },
- { 0x1000748c, 0x93 },
- { 0x1000748d, 0xe6 },
- { 0x1000748e, 0x06 },
- { 0x1000748f, 0xf8 },
- { 0x10007490, 0x93 },
- { 0x10007491, 0xf6 },
- { 0x10007492, 0xf6 },
- { 0x10007493, 0x0f },
- { 0x10007494, 0xa3 },
- { 0x10007495, 0x03 },
- { 0x10007496, 0xd7 },
- { 0x10007497, 0xa8 },
- { 0x10007498, 0xb7 },
- { 0x10007499, 0xc6 },
- { 0x1000749a, 0x00 },
- { 0x1000749b, 0x00 },
- { 0x1000749c, 0x23 },
- { 0x1000749d, 0x84 },
- { 0x1000749e, 0xf6 },
- { 0x1000749f, 0x06 },
- { 0x100074a0, 0xa3 },
- { 0x100074a1, 0x84 },
- { 0x100074a2, 0xf6 },
- { 0x100074a3, 0x06 },
- { 0x100074a4, 0xb7 },
- { 0x100074a5, 0x06 },
- { 0x100074a6, 0x00 },
- { 0x100074a7, 0x04 },
- { 0x100074a8, 0x23 },
- { 0x100074a9, 0x22 },
- { 0x100074aa, 0xd7 },
- { 0x100074ab, 0x58 },
- { 0x100074ac, 0x37 },
- { 0x100074ad, 0xd7 },
- { 0x100074ae, 0x00 },
- { 0x100074af, 0x00 },
- { 0x100074b0, 0x03 },
- { 0x100074b1, 0x27 },
- { 0x100074b2, 0x47 },
- { 0x100074b3, 0x58 },
- { 0x100074b4, 0xb7 },
- { 0x100074b5, 0x06 },
- { 0x100074b6, 0x00 },
- { 0x100074b7, 0x08 },
- { 0x100074b8, 0x33 },
- { 0x100074b9, 0x77 },
- { 0x100074ba, 0xd7 },
- { 0x100074bb, 0x00 },
- { 0x100074bc, 0x63 },
- { 0x100074bd, 0x04 },
- { 0x100074be, 0x07 },
- { 0x100074bf, 0x04 },
- { 0x100074c0, 0x37 },
- { 0x100074c1, 0x07 },
- { 0x100074c2, 0x00 },
- { 0x100074c3, 0x11 },
- { 0x100074c4, 0x03 },
- { 0x100074c5, 0x47 },
- { 0x100074c6, 0xc7 },
- { 0x100074c7, 0x0e },
- { 0x100074c8, 0x93 },
- { 0x100074c9, 0x06 },
- { 0x100074ca, 0x40 },
- { 0x100074cb, 0x00 },
- { 0x100074cc, 0x13 },
- { 0x100074cd, 0x77 },
- { 0x100074ce, 0xf7 },
- { 0x100074cf, 0x0f },
- { 0x100074d0, 0x63 },
- { 0x100074d1, 0x00 },
- { 0x100074d2, 0xd7 },
- { 0x100074d3, 0x04 },
- { 0x100074d4, 0x93 },
- { 0x100074d5, 0x06 },
- { 0x100074d6, 0x70 },
- { 0x100074d7, 0x00 },
- { 0x100074d8, 0x63 },
- { 0x100074d9, 0x00 },
- { 0x100074da, 0xd7 },
- { 0x100074db, 0x04 },
- { 0x100074dc, 0x63 },
- { 0x100074dd, 0x84 },
- { 0x100074de, 0x07 },
- { 0x100074df, 0x02 },
- { 0x100074e0, 0xb7 },
- { 0x100074e1, 0xd6 },
- { 0x100074e2, 0x00 },
- { 0x100074e3, 0x00 },
- { 0x100074e4, 0x03 },
- { 0x100074e5, 0xc7 },
- { 0x100074e6, 0x56 },
- { 0x100074e7, 0xa4 },
- { 0x100074e8, 0x13 },
- { 0x100074e9, 0x67 },
- { 0x100074ea, 0x07 },
- { 0x100074eb, 0xf8 },
- { 0x100074ec, 0x13 },
- { 0x100074ed, 0x77 },
- { 0x100074ee, 0xf7 },
- { 0x100074ef, 0x0f },
- { 0x100074f0, 0xa3 },
- { 0x100074f1, 0x82 },
- { 0x100074f2, 0xe6 },
- { 0x100074f3, 0xa4 },
- { 0x100074f4, 0x37 },
- { 0x100074f5, 0xc7 },
- { 0x100074f6, 0x00 },
- { 0x100074f7, 0x00 },
- { 0x100074f8, 0x23 },
- { 0x100074f9, 0x02 },
- { 0x100074fa, 0xf7 },
- { 0x100074fb, 0x06 },
- { 0x100074fc, 0xb7 },
- { 0x100074fd, 0x07 },
- { 0x100074fe, 0x00 },
- { 0x100074ff, 0x08 },
- { 0x10007500, 0x23 },
- { 0x10007501, 0xa2 },
- { 0x10007502, 0xf6 },
- { 0x10007503, 0x58 },
- { 0x10007504, 0x67 },
- { 0x10007505, 0x80 },
- { 0x10007506, 0x00 },
- { 0x10007507, 0x00 },
- { 0x10007508, 0x93 },
- { 0x10007509, 0x07 },
- { 0x1000750a, 0x80 },
- { 0x1000750b, 0x08 },
- { 0x1000750c, 0x6f },
- { 0x1000750d, 0xf0 },
- { 0x1000750e, 0x9f },
- { 0x1000750f, 0xf6 },
- { 0x10007510, 0x93 },
- { 0x10007511, 0x07 },
- { 0x10007512, 0x80 },
- { 0x10007513, 0x08 },
- { 0x10007514, 0x6f },
- { 0x10007515, 0xf0 },
- { 0x10007516, 0xdf },
- { 0x10007517, 0xfc },
- { 0x10007518, 0x93 },
- { 0x10007519, 0x07 },
- { 0x1000751a, 0x60 },
- { 0x1000751b, 0x06 },
- { 0x1000751c, 0x6f },
- { 0x1000751d, 0xf0 },
- { 0x1000751e, 0x5f },
- { 0x1000751f, 0xfc },
- { 0x10007520, 0x37 },
- { 0x10007521, 0xd7 },
- { 0x10007522, 0x00 },
- { 0x10007523, 0x00 },
- { 0x10007524, 0x83 },
- { 0x10007525, 0x27 },
- { 0x10007526, 0x07 },
- { 0x10007527, 0x53 },
- { 0x10007528, 0xb7 },
- { 0x10007529, 0x06 },
- { 0x1000752a, 0x02 },
- { 0x1000752b, 0x00 },
- { 0x1000752c, 0xb3 },
- { 0x1000752d, 0xf7 },
- { 0x1000752e, 0xd7 },
- { 0x1000752f, 0x00 },
- { 0x10007530, 0x63 },
- { 0x10007531, 0x88 },
- { 0x10007532, 0x07 },
- { 0x10007533, 0x00 },
- { 0x10007534, 0x13 },
- { 0x10007535, 0x06 },
- { 0x10007536, 0xa0 },
- { 0x10007537, 0x05 },
- { 0x10007538, 0x23 },
- { 0x10007539, 0xa8 },
- { 0x1000753a, 0xc1 },
- { 0x1000753b, 0x56 },
- { 0x1000753c, 0x23 },
- { 0x1000753d, 0x28 },
- { 0x1000753e, 0xd7 },
- { 0x1000753f, 0x52 },
- { 0x10007540, 0x67 },
- { 0x10007541, 0x80 },
- { 0x10007542, 0x00 },
- { 0x10007543, 0x00 },
- { 0x10007544, 0x37 },
- { 0x10007545, 0xd7 },
- { 0x10007546, 0x00 },
- { 0x10007547, 0x10 },
- { 0x10007548, 0x83 },
- { 0x10007549, 0x47 },
- { 0x1000754a, 0x07 },
- { 0x1000754b, 0xd9 },
- { 0x1000754c, 0x93 },
- { 0x1000754d, 0x06 },
- { 0x1000754e, 0x20 },
- { 0x1000754f, 0x00 },
- { 0x10007550, 0x93 },
- { 0x10007551, 0xf7 },
- { 0x10007552, 0xf7 },
- { 0x10007553, 0x0f },
- { 0x10007554, 0x63 },
- { 0x10007555, 0x9c },
- { 0x10007556, 0xd7 },
- { 0x10007557, 0x02 },
- { 0x10007558, 0xb7 },
- { 0x10007559, 0xc6 },
- { 0x1000755a, 0x00 },
- { 0x1000755b, 0x00 },
- { 0x1000755c, 0x83 },
- { 0x1000755d, 0xc7 },
- { 0x1000755e, 0x26 },
- { 0x1000755f, 0x04 },
- { 0x10007560, 0x93 },
- { 0x10007561, 0xf7 },
- { 0x10007562, 0xf7 },
- { 0x10007563, 0x07 },
- { 0x10007564, 0x23 },
- { 0x10007565, 0x81 },
- { 0x10007566, 0xf6 },
- { 0x10007567, 0x04 },
- { 0x10007568, 0xb7 },
- { 0x10007569, 0xd6 },
- { 0x1000756a, 0x00 },
- { 0x1000756b, 0x00 },
- { 0x1000756c, 0x83 },
- { 0x1000756d, 0xc7 },
- { 0x1000756e, 0xa6 },
- { 0x1000756f, 0xe1 },
- { 0x10007570, 0x93 },
- { 0x10007571, 0xf7 },
- { 0x10007572, 0xf7 },
- { 0x10007573, 0x07 },
- { 0x10007574, 0x23 },
- { 0x10007575, 0x8d },
- { 0x10007576, 0xf6 },
- { 0x10007577, 0xe0 },
- { 0x10007578, 0x23 },
- { 0x10007579, 0x08 },
- { 0x1000757a, 0x07 },
- { 0x1000757b, 0xd8 },
- { 0x1000757c, 0x83 },
- { 0x1000757d, 0x47 },
- { 0x1000757e, 0x47 },
- { 0x1000757f, 0xd9 },
- { 0x10007580, 0x93 },
- { 0x10007581, 0x87 },
- { 0x10007582, 0x17 },
- { 0x10007583, 0x00 },
- { 0x10007584, 0x93 },
- { 0x10007585, 0xf7 },
- { 0x10007586, 0xf7 },
- { 0x10007587, 0x0f },
- { 0x10007588, 0x23 },
- { 0x10007589, 0x0a },
- { 0x1000758a, 0xf7 },
- { 0x1000758b, 0xd8 },
- { 0x1000758c, 0x67 },
- { 0x1000758d, 0x80 },
- { 0x1000758e, 0x00 },
- { 0x1000758f, 0x00 },
- { 0x10007590, 0xb7 },
- { 0x10007591, 0xd7 },
- { 0x10007592, 0x00 },
- { 0x10007593, 0x00 },
- { 0x10007594, 0x83 },
- { 0x10007595, 0xc7 },
- { 0x10007596, 0x07 },
- { 0x10007597, 0x47 },
- { 0x10007598, 0x93 },
- { 0x10007599, 0xf7 },
- { 0x1000759a, 0x07 },
- { 0x1000759b, 0x01 },
- { 0x1000759c, 0x63 },
- { 0x1000759d, 0x8a },
- { 0x1000759e, 0x07 },
- { 0x1000759f, 0x06 },
- { 0x100075a0, 0x63 },
- { 0x100075a1, 0x02 },
- { 0x100075a2, 0x05 },
- { 0x100075a3, 0x06 },
- { 0x100075a4, 0x37 },
- { 0x100075a5, 0xc7 },
- { 0x100075a6, 0x00 },
- { 0x100075a7, 0x00 },
- { 0x100075a8, 0x83 },
- { 0x100075a9, 0x27 },
- { 0x100075aa, 0xc7 },
- { 0x100075ab, 0x5f },
- { 0x100075ac, 0x23 },
- { 0x100075ad, 0xae },
- { 0x100075ae, 0xf1 },
- { 0x100075af, 0x40 },
- { 0x100075b0, 0xb7 },
- { 0x100075b1, 0x06 },
- { 0x100075b2, 0x00 },
- { 0x100075b3, 0x10 },
- { 0x100075b4, 0xb3 },
- { 0x100075b5, 0xf7 },
- { 0x100075b6, 0xd7 },
- { 0x100075b7, 0x00 },
- { 0x100075b8, 0x63 },
- { 0x100075b9, 0x8c },
- { 0x100075ba, 0x07 },
- { 0x100075bb, 0x04 },
- { 0x100075bc, 0x83 },
- { 0x100075bd, 0x47 },
- { 0x100075be, 0x07 },
- { 0x100075bf, 0x56 },
- { 0x100075c0, 0x93 },
- { 0x100075c1, 0xf7 },
- { 0x100075c2, 0x87 },
- { 0x100075c3, 0x01 },
- { 0x100075c4, 0x63 },
- { 0x100075c5, 0x86 },
- { 0x100075c6, 0x07 },
- { 0x100075c7, 0x04 },
- { 0x100075c8, 0x83 },
- { 0x100075c9, 0x47 },
- { 0x100075ca, 0x17 },
- { 0x100075cb, 0x08 },
- { 0x100075cc, 0x93 },
- { 0x100075cd, 0xf7 },
- { 0x100075ce, 0x47 },
- { 0x100075cf, 0x00 },
- { 0x100075d0, 0x63 },
- { 0x100075d1, 0x80 },
- { 0x100075d2, 0x07 },
- { 0x100075d3, 0x04 },
- { 0x100075d4, 0xb7 },
- { 0x100075d5, 0xc7 },
- { 0x100075d6, 0xc2 },
- { 0x100075d7, 0x3f },
- { 0x100075d8, 0x93 },
- { 0x100075d9, 0x87 },
- { 0x100075da, 0x07 },
- { 0x100075db, 0xfc },
- { 0x100075dc, 0x83 },
- { 0x100075dd, 0xa7 },
- { 0x100075de, 0x47 },
- { 0x100075df, 0x00 },
- { 0x100075e0, 0x93 },
- { 0x100075e1, 0xd7 },
- { 0x100075e2, 0x17 },
- { 0x100075e3, 0x00 },
- { 0x100075e4, 0x93 },
- { 0x100075e5, 0xf7 },
- { 0x100075e6, 0x17 },
- { 0x100075e7, 0x00 },
- { 0x100075e8, 0x63 },
- { 0x100075e9, 0x84 },
- { 0x100075ea, 0x07 },
- { 0x100075eb, 0x02 },
- { 0x100075ec, 0x23 },
- { 0x100075ed, 0x8a },
- { 0x100075ee, 0xf1 },
- { 0x100075ef, 0x40 },
- { 0x100075f0, 0xb7 },
- { 0x100075f1, 0x07 },
- { 0x100075f2, 0x00 },
- { 0x100075f3, 0xc0 },
- { 0x100075f4, 0x37 },
- { 0x100075f5, 0xf7 },
- { 0x100075f6, 0x00 },
- { 0x100075f7, 0x00 },
- { 0x100075f8, 0x93 },
- { 0x100075f9, 0x87 },
- { 0x100075fa, 0xf7 },
- { 0x100075fb, 0xff },
- { 0x100075fc, 0x23 },
- { 0x100075fd, 0x2c },
- { 0x100075fe, 0xf7 },
- { 0x100075ff, 0x06 },
- { 0x10007600, 0x67 },
- { 0x10007601, 0x80 },
- { 0x10007602, 0x00 },
- { 0x10007603, 0x00 },
- { 0x10007604, 0x23 },
- { 0x10007605, 0x8a },
- { 0x10007606, 0x01 },
- { 0x10007607, 0x40 },
- { 0x10007608, 0xb7 },
- { 0x10007609, 0xf7 },
- { 0x1000760a, 0x00 },
- { 0x1000760b, 0x00 },
- { 0x1000760c, 0x23 },
- { 0x1000760d, 0xac },
- { 0x1000760e, 0x07 },
- { 0x1000760f, 0x06 },
- { 0x10007610, 0x67 },
- { 0x10007611, 0x80 },
- { 0x10007612, 0x00 },
- { 0x10007613, 0x00 },
- { 0x10007614, 0x13 },
- { 0x10007615, 0x01 },
- { 0x10007616, 0x01 },
- { 0x10007617, 0xff },
- { 0x10007618, 0x23 },
- { 0x10007619, 0x26 },
- { 0x1000761a, 0x11 },
- { 0x1000761b, 0x00 },
- { 0x1000761c, 0x23 },
- { 0x1000761d, 0x24 },
- { 0x1000761e, 0x81 },
- { 0x1000761f, 0x00 },
- { 0x10007620, 0x37 },
- { 0x10007621, 0xc7 },
- { 0x10007622, 0x00 },
- { 0x10007623, 0x00 },
- { 0x10007624, 0x83 },
- { 0x10007625, 0x47 },
- { 0x10007626, 0x07 },
- { 0x10007627, 0x56 },
- { 0x10007628, 0x93 },
- { 0x10007629, 0xf7 },
- { 0x1000762a, 0x17 },
- { 0x1000762b, 0x00 },
- { 0x1000762c, 0x63 },
- { 0x1000762d, 0x98 },
- { 0x1000762e, 0x07 },
- { 0x1000762f, 0x00 },
- { 0x10007630, 0x83 },
- { 0x10007631, 0x47 },
- { 0x10007632, 0x07 },
- { 0x10007633, 0x56 },
- { 0x10007634, 0x93 },
- { 0x10007635, 0xf7 },
- { 0x10007636, 0x27 },
- { 0x10007637, 0x00 },
- { 0x10007638, 0x63 },
- { 0x10007639, 0x82 },
- { 0x1000763a, 0x07 },
- { 0x1000763b, 0x08 },
- { 0x1000763c, 0x37 },
- { 0x1000763d, 0xd4 },
- { 0x1000763e, 0x00 },
- { 0x1000763f, 0x00 },
- { 0x10007640, 0x83 },
- { 0x10007641, 0x47 },
- { 0x10007642, 0x14 },
- { 0x10007643, 0x47 },
- { 0x10007644, 0x93 },
- { 0x10007645, 0xf7 },
- { 0x10007646, 0x27 },
- { 0x10007647, 0x00 },
- { 0x10007648, 0x63 },
- { 0x10007649, 0x8a },
- { 0x1000764a, 0x07 },
- { 0x1000764b, 0x06 },
- { 0x1000764c, 0x93 },
- { 0x1000764d, 0x05 },
- { 0x1000764e, 0x10 },
- { 0x1000764f, 0x00 },
- { 0x10007650, 0x13 },
- { 0x10007651, 0x05 },
- { 0x10007652, 0x20 },
- { 0x10007653, 0x10 },
- { 0x10007654, 0xef },
- { 0x10007655, 0xa0 },
- { 0x10007656, 0x8f },
- { 0x10007657, 0x9a },
- { 0x10007658, 0x37 },
- { 0x10007659, 0x05 },
- { 0x1000765a, 0x01 },
- { 0x1000765b, 0x00 },
- { 0x1000765c, 0x93 },
- { 0x1000765d, 0x05 },
- { 0x1000765e, 0x00 },
- { 0x1000765f, 0x01 },
- { 0x10007660, 0x13 },
- { 0x10007661, 0x05 },
- { 0x10007662, 0xb5 },
- { 0x10007663, 0xa0 },
- { 0x10007664, 0xef },
- { 0x10007665, 0xa0 },
- { 0x10007666, 0x8f },
- { 0x10007667, 0x99 },
- { 0x10007668, 0x83 },
- { 0x10007669, 0x47 },
- { 0x1000766a, 0x24 },
- { 0x1000766b, 0xe0 },
- { 0x1000766c, 0x13 },
- { 0x1000766d, 0x05 },
- { 0x1000766e, 0x80 },
- { 0x1000766f, 0x3e },
- { 0x10007670, 0x93 },
- { 0x10007671, 0x05 },
- { 0x10007672, 0x00 },
- { 0x10007673, 0x00 },
- { 0x10007674, 0x93 },
- { 0x10007675, 0xe7 },
- { 0x10007676, 0x07 },
- { 0x10007677, 0xf8 },
- { 0x10007678, 0x93 },
- { 0x10007679, 0xf7 },
- { 0x1000767a, 0xf7 },
- { 0x1000767b, 0x0f },
- { 0x1000767c, 0x23 },
- { 0x1000767d, 0x01 },
- { 0x1000767e, 0xf4 },
- { 0x1000767f, 0xe0 },
- { 0x10007680, 0x83 },
- { 0x10007681, 0x47 },
- { 0x10007682, 0x24 },
- { 0x10007683, 0xe0 },
- { 0x10007684, 0x93 },
- { 0x10007685, 0xf7 },
- { 0x10007686, 0xf7 },
- { 0x10007687, 0x0f },
- { 0x10007688, 0x93 },
- { 0x10007689, 0xe7 },
- { 0x1000768a, 0x07 },
- { 0x1000768b, 0x04 },
- { 0x1000768c, 0x23 },
- { 0x1000768d, 0x01 },
- { 0x1000768e, 0xf4 },
- { 0x1000768f, 0xe0 },
- { 0x10007690, 0xef },
- { 0x10007691, 0xe0 },
- { 0x10007692, 0x8f },
- { 0x10007693, 0xb9 },
- { 0x10007694, 0x83 },
- { 0x10007695, 0x47 },
- { 0x10007696, 0x34 },
- { 0x10007697, 0xe0 },
- { 0x10007698, 0x93 },
- { 0x10007699, 0xf7 },
- { 0x1000769a, 0x07 },
- { 0x1000769b, 0x02 },
- { 0x1000769c, 0xe3 },
- { 0x1000769d, 0x9c },
- { 0x1000769e, 0x07 },
- { 0x1000769f, 0xfe },
- { 0x100076a0, 0x37 },
- { 0x100076a1, 0x05 },
- { 0x100076a2, 0x01 },
- { 0x100076a3, 0x00 },
- { 0x100076a4, 0x93 },
- { 0x100076a5, 0x05 },
- { 0x100076a6, 0x00 },
- { 0x100076a7, 0x00 },
- { 0x100076a8, 0x13 },
- { 0x100076a9, 0x05 },
- { 0x100076aa, 0xb5 },
- { 0x100076ab, 0xa0 },
- { 0x100076ac, 0xef },
- { 0x100076ad, 0xa0 },
- { 0x100076ae, 0x0f },
- { 0x100076af, 0x95 },
- { 0x100076b0, 0x83 },
- { 0x100076b1, 0x47 },
- { 0x100076b2, 0x14 },
- { 0x100076b3, 0x47 },
- { 0x100076b4, 0x93 },
- { 0x100076b5, 0xf7 },
- { 0x100076b6, 0xd7 },
- { 0x100076b7, 0x0f },
- { 0x100076b8, 0xa3 },
- { 0x100076b9, 0x08 },
- { 0x100076ba, 0xf4 },
- { 0x100076bb, 0x46 },
- { 0x100076bc, 0x03 },
- { 0x100076bd, 0xa7 },
- { 0x100076be, 0x01 },
- { 0x100076bf, 0x57 },
- { 0x100076c0, 0x93 },
- { 0x100076c1, 0x07 },
- { 0x100076c2, 0xa0 },
- { 0x100076c3, 0x05 },
- { 0x100076c4, 0x63 },
- { 0x100076c5, 0x14 },
- { 0x100076c6, 0xf7 },
- { 0x100076c7, 0x04 },
- { 0x100076c8, 0x37 },
- { 0x100076c9, 0x07 },
- { 0x100076ca, 0x00 },
- { 0x100076cb, 0x11 },
- { 0x100076cc, 0x83 },
- { 0x100076cd, 0x47 },
- { 0x100076ce, 0x07 },
- { 0x100076cf, 0x01 },
- { 0x100076d0, 0x13 },
- { 0x100076d1, 0x06 },
- { 0x100076d2, 0x30 },
- { 0x100076d3, 0x00 },
- { 0x100076d4, 0x93 },
- { 0x100076d5, 0xf7 },
- { 0x100076d6, 0xf7 },
- { 0x100076d7, 0x0f },
- { 0x100076d8, 0x63 },
- { 0x100076d9, 0x9a },
- { 0x100076da, 0xc7 },
- { 0x100076db, 0x02 },
- { 0x100076dc, 0x03 },
- { 0x100076dd, 0x47 },
- { 0x100076de, 0x87 },
- { 0x100076df, 0x01 },
- { 0x100076e0, 0x13 },
- { 0x100076e1, 0x77 },
- { 0x100076e2, 0xf7 },
- { 0x100076e3, 0x0f },
- { 0x100076e4, 0x63 },
- { 0x100076e5, 0x14 },
- { 0x100076e6, 0xf7 },
- { 0x100076e7, 0x02 },
- { 0x100076e8, 0x37 },
- { 0x100076e9, 0xd7 },
- { 0x100076ea, 0x00 },
- { 0x100076eb, 0x00 },
- { 0x100076ec, 0x83 },
- { 0x100076ed, 0x47 },
- { 0x100076ee, 0x37 },
- { 0x100076ef, 0x54 },
- { 0x100076f0, 0x93 },
- { 0x100076f1, 0xf7 },
- { 0x100076f2, 0xf7 },
- { 0x100076f3, 0x0f },
- { 0x100076f4, 0x93 },
- { 0x100076f5, 0xe7 },
- { 0x100076f6, 0x07 },
- { 0x100076f7, 0x02 },
- { 0x100076f8, 0xa3 },
- { 0x100076f9, 0x01 },
- { 0x100076fa, 0xf7 },
- { 0x100076fb, 0x54 },
- { 0x100076fc, 0x83 },
- { 0x100076fd, 0x47 },
- { 0x100076fe, 0x37 },
- { 0x100076ff, 0x54 },
- { 0x10007700, 0x93 },
- { 0x10007701, 0xf7 },
- { 0x10007702, 0xf7 },
- { 0x10007703, 0x0d },
- { 0x10007704, 0xa3 },
- { 0x10007705, 0x01 },
- { 0x10007706, 0xf7 },
- { 0x10007707, 0x54 },
- { 0x10007708, 0x23 },
- { 0x10007709, 0xa8 },
- { 0x1000770a, 0x01 },
- { 0x1000770b, 0x56 },
- { 0x1000770c, 0xb7 },
- { 0x1000770d, 0xd7 },
- { 0x1000770e, 0x00 },
- { 0x1000770f, 0x10 },
- { 0x10007710, 0x03 },
- { 0x10007711, 0xc7 },
- { 0x10007712, 0x07 },
- { 0x10007713, 0xd9 },
- { 0x10007714, 0x93 },
- { 0x10007715, 0x06 },
- { 0x10007716, 0x10 },
- { 0x10007717, 0x00 },
- { 0x10007718, 0x13 },
- { 0x10007719, 0x77 },
- { 0x1000771a, 0xf7 },
- { 0x1000771b, 0x0f },
- { 0x1000771c, 0x63 },
- { 0x1000771d, 0x1a },
- { 0x1000771e, 0xd7 },
- { 0x1000771f, 0x04 },
- { 0x10007720, 0x03 },
- { 0x10007721, 0xc7 },
- { 0x10007722, 0x27 },
- { 0x10007723, 0xd9 },
- { 0x10007724, 0x13 },
- { 0x10007725, 0x07 },
- { 0x10007726, 0x17 },
- { 0x10007727, 0x00 },
- { 0x10007728, 0x13 },
- { 0x10007729, 0x77 },
- { 0x1000772a, 0xf7 },
- { 0x1000772b, 0x0f },
- { 0x1000772c, 0x23 },
- { 0x1000772d, 0x89 },
- { 0x1000772e, 0xe7 },
- { 0x1000772f, 0xd8 },
- { 0x10007730, 0x83 },
- { 0x10007731, 0xc6 },
- { 0x10007732, 0x27 },
- { 0x10007733, 0xd9 },
- { 0x10007734, 0x03 },
- { 0x10007735, 0xc7 },
- { 0x10007736, 0x17 },
- { 0x10007737, 0xd9 },
- { 0x10007738, 0x93 },
- { 0x10007739, 0xf6 },
- { 0x1000773a, 0xf6 },
- { 0x1000773b, 0x0f },
- { 0x1000773c, 0x13 },
- { 0x1000773d, 0x77 },
- { 0x1000773e, 0xf7 },
- { 0x1000773f, 0x0f },
- { 0x10007740, 0x63 },
- { 0x10007741, 0xe8 },
- { 0x10007742, 0xe6 },
- { 0x10007743, 0x02 },
- { 0x10007744, 0xb7 },
- { 0x10007745, 0xd6 },
- { 0x10007746, 0x00 },
- { 0x10007747, 0x00 },
- { 0x10007748, 0x03 },
- { 0x10007749, 0xc7 },
- { 0x1000774a, 0xa6 },
- { 0x1000774b, 0xe1 },
- { 0x1000774c, 0x13 },
- { 0x1000774d, 0x67 },
- { 0x1000774e, 0x07 },
- { 0x1000774f, 0xf8 },
- { 0x10007750, 0x13 },
- { 0x10007751, 0x77 },
- { 0x10007752, 0xf7 },
- { 0x10007753, 0x0f },
- { 0x10007754, 0x23 },
- { 0x10007755, 0x8d },
- { 0x10007756, 0xe6 },
- { 0x10007757, 0xe0 },
- { 0x10007758, 0x03 },
- { 0x10007759, 0xc7 },
- { 0x1000775a, 0x37 },
- { 0x1000775b, 0xd9 },
- { 0x1000775c, 0x13 },
- { 0x1000775d, 0x07 },
- { 0x1000775e, 0x17 },
- { 0x1000775f, 0x00 },
- { 0x10007760, 0x13 },
- { 0x10007761, 0x77 },
- { 0x10007762, 0xf7 },
- { 0x10007763, 0x0f },
- { 0x10007764, 0xa3 },
- { 0x10007765, 0x89 },
- { 0x10007766, 0xe7 },
- { 0x10007767, 0xd8 },
- { 0x10007768, 0x13 },
- { 0x10007769, 0x07 },
- { 0x1000776a, 0x20 },
- { 0x1000776b, 0x00 },
- { 0x1000776c, 0x23 },
- { 0x1000776d, 0x88 },
- { 0x1000776e, 0xe7 },
- { 0x1000776f, 0xd8 },
- { 0x10007770, 0x83 },
- { 0x10007771, 0x20 },
- { 0x10007772, 0xc1 },
- { 0x10007773, 0x00 },
- { 0x10007774, 0x03 },
- { 0x10007775, 0x24 },
- { 0x10007776, 0x81 },
- { 0x10007777, 0x00 },
- { 0x10007778, 0x13 },
- { 0x10007779, 0x01 },
- { 0x1000777a, 0x01 },
- { 0x1000777b, 0x01 },
- { 0x1000777c, 0x67 },
- { 0x1000777d, 0x80 },
- { 0x1000777e, 0x00 },
- { 0x1000777f, 0x00 },
- { 0x10007780, 0x03 },
- { 0x10007781, 0xc7 },
- { 0x10007782, 0xa1 },
- { 0x10007783, 0x40 },
- { 0x10007784, 0x93 },
- { 0x10007785, 0x06 },
- { 0x10007786, 0x10 },
- { 0x10007787, 0x00 },
- { 0x10007788, 0x63 },
- { 0x10007789, 0x16 },
- { 0x1000778a, 0xd7 },
- { 0x1000778b, 0x00 },
- { 0x1000778c, 0xb7 },
- { 0x1000778d, 0xd6 },
- { 0x1000778e, 0x00 },
- { 0x1000778f, 0x10 },
- { 0x10007790, 0xa3 },
- { 0x10007791, 0x8a },
- { 0x10007792, 0xe6 },
- { 0x10007793, 0xd8 },
- { 0x10007794, 0x83 },
- { 0x10007795, 0xc7 },
- { 0x10007796, 0xa1 },
- { 0x10007797, 0x40 },
- { 0x10007798, 0x63 },
- { 0x10007799, 0x9c },
- { 0x1000779a, 0x07 },
- { 0x1000779b, 0x06 },
- { 0x1000779c, 0x13 },
- { 0x1000779d, 0x01 },
- { 0x1000779e, 0x01 },
- { 0x1000779f, 0xff },
- { 0x100077a0, 0x23 },
- { 0x100077a1, 0x22 },
- { 0x100077a2, 0x91 },
- { 0x100077a3, 0x00 },
- { 0x100077a4, 0x23 },
- { 0x100077a5, 0x26 },
- { 0x100077a6, 0x11 },
- { 0x100077a7, 0x00 },
- { 0x100077a8, 0x23 },
- { 0x100077a9, 0x24 },
- { 0x100077aa, 0x81 },
- { 0x100077ab, 0x00 },
- { 0x100077ac, 0xb7 },
- { 0x100077ad, 0xc4 },
- { 0x100077ae, 0x00 },
- { 0x100077af, 0x00 },
- { 0x100077b0, 0x83 },
- { 0x100077b1, 0xc7 },
- { 0x100077b2, 0x04 },
- { 0x100077b3, 0x56 },
- { 0x100077b4, 0x13 },
- { 0x100077b5, 0x07 },
- { 0x100077b6, 0x80 },
- { 0x100077b7, 0x01 },
- { 0x100077b8, 0x93 },
- { 0x100077b9, 0xf7 },
- { 0x100077ba, 0xf7 },
- { 0x100077bb, 0x0f },
- { 0x100077bc, 0x63 },
- { 0x100077bd, 0x70 },
- { 0x100077be, 0xf7 },
- { 0x100077bf, 0x04 },
- { 0x100077c0, 0x37 },
- { 0x100077c1, 0xd4 },
- { 0x100077c2, 0x00 },
- { 0x100077c3, 0x10 },
- { 0x100077c4, 0x83 },
- { 0x100077c5, 0x47 },
- { 0x100077c6, 0x54 },
- { 0x100077c7, 0xd9 },
- { 0x100077c8, 0x93 },
- { 0x100077c9, 0xf7 },
- { 0x100077ca, 0xf7 },
- { 0x100077cb, 0x0f },
- { 0x100077cc, 0x63 },
- { 0x100077cd, 0x88 },
- { 0x100077ce, 0x07 },
- { 0x100077cf, 0x02 },
- { 0x100077d0, 0x93 },
- { 0x100077d1, 0x07 },
- { 0x100077d2, 0x10 },
- { 0x100077d3, 0x00 },
- { 0x100077d4, 0x23 },
- { 0x100077d5, 0x82 },
- { 0x100077d6, 0xf4 },
- { 0x100077d7, 0x58 },
- { 0x100077d8, 0x03 },
- { 0x100077d9, 0x45 },
- { 0x100077da, 0x64 },
- { 0x100077db, 0xd9 },
- { 0x100077dc, 0xb7 },
- { 0x100077dd, 0x15 },
- { 0x100077de, 0x00 },
- { 0x100077df, 0x00 },
- { 0x100077e0, 0x93 },
- { 0x100077e1, 0x85 },
- { 0x100077e2, 0x85 },
- { 0x100077e3, 0x38 },
- { 0x100077e4, 0x13 },
- { 0x100077e5, 0x75 },
- { 0x100077e6, 0xf5 },
- { 0x100077e7, 0x0f },
- { 0x100077e8, 0xef },
- { 0x100077e9, 0xe0 },
- { 0x100077ea, 0x9f },
- { 0x100077eb, 0xd0 },
- { 0x100077ec, 0x93 },
- { 0x100077ed, 0x55 },
- { 0x100077ee, 0xf5 },
- { 0x100077ef, 0x41 },
- { 0x100077f0, 0xef },
- { 0x100077f1, 0xe0 },
- { 0x100077f2, 0x8f },
- { 0x100077f3, 0xa3 },
- { 0x100077f4, 0x23 },
- { 0x100077f5, 0x82 },
- { 0x100077f6, 0x04 },
- { 0x100077f7, 0x58 },
- { 0x100077f8, 0xa3 },
- { 0x100077f9, 0x0a },
- { 0x100077fa, 0x04 },
- { 0x100077fb, 0xd8 },
- { 0x100077fc, 0x83 },
- { 0x100077fd, 0x20 },
- { 0x100077fe, 0xc1 },
- { 0x100077ff, 0x00 },
- { 0x10007800, 0x03 },
- { 0x10007801, 0x24 },
- { 0x10007802, 0x81 },
- { 0x10007803, 0x00 },
- { 0x10007804, 0x83 },
- { 0x10007805, 0x24 },
- { 0x10007806, 0x41 },
- { 0x10007807, 0x00 },
- { 0x10007808, 0x13 },
- { 0x10007809, 0x01 },
- { 0x1000780a, 0x01 },
- { 0x1000780b, 0x01 },
- { 0x1000780c, 0x67 },
- { 0x1000780d, 0x80 },
- { 0x1000780e, 0x00 },
- { 0x1000780f, 0x00 },
- { 0x10007810, 0x67 },
- { 0x10007811, 0x80 },
- { 0x10007812, 0x00 },
- { 0x10007813, 0x00 },
- { 0x10007814, 0x13 },
- { 0x10007815, 0x01 },
- { 0x10007816, 0x01 },
- { 0x10007817, 0xff },
- { 0x10007818, 0x23 },
- { 0x10007819, 0x26 },
- { 0x1000781a, 0x11 },
- { 0x1000781b, 0x00 },
- { 0x1000781c, 0xef },
- { 0x1000781d, 0xd0 },
- { 0x1000781e, 0x8f },
- { 0x1000781f, 0x86 },
- { 0x10007820, 0x83 },
- { 0x10007821, 0xc7 },
- { 0x10007822, 0x11 },
- { 0x10007823, 0x42 },
- { 0x10007824, 0x63 },
- { 0x10007825, 0x86 },
- { 0x10007826, 0x07 },
- { 0x10007827, 0x00 },
- { 0x10007828, 0x03 },
- { 0x10007829, 0xc7 },
- { 0x1000782a, 0x01 },
- { 0x1000782b, 0x42 },
- { 0x1000782c, 0x63 },
- { 0x1000782d, 0x10 },
- { 0x1000782e, 0x07 },
- { 0x1000782f, 0x02 },
- { 0x10007830, 0x83 },
- { 0x10007831, 0xc6 },
- { 0x10007832, 0x21 },
- { 0x10007833, 0x41 },
- { 0x10007834, 0x13 },
- { 0x10007835, 0x07 },
- { 0x10007836, 0xf0 },
- { 0x10007837, 0x01 },
- { 0x10007838, 0x13 },
- { 0x10007839, 0x05 },
- { 0x1000783a, 0xf0 },
- { 0x1000783b, 0x01 },
- { 0x1000783c, 0x63 },
- { 0x1000783d, 0x98 },
- { 0x1000783e, 0xe6 },
- { 0x1000783f, 0x02 },
- { 0x10007840, 0x63 },
- { 0x10007841, 0x8a },
- { 0x10007842, 0x07 },
- { 0x10007843, 0x02 },
- { 0x10007844, 0x83 },
- { 0x10007845, 0xc7 },
- { 0x10007846, 0x01 },
- { 0x10007847, 0x42 },
- { 0x10007848, 0x63 },
- { 0x10007849, 0x86 },
- { 0x1000784a, 0x07 },
- { 0x1000784b, 0x02 },
- { 0x1000784c, 0x83 },
- { 0x1000784d, 0xc7 },
- { 0x1000784e, 0x31 },
- { 0x1000784f, 0x42 },
- { 0x10007850, 0x63 },
- { 0x10007851, 0x86 },
- { 0x10007852, 0x07 },
- { 0x10007853, 0x00 },
- { 0x10007854, 0x83 },
- { 0x10007855, 0xc7 },
- { 0x10007856, 0x21 },
- { 0x10007857, 0x42 },
- { 0x10007858, 0x63 },
- { 0x10007859, 0x9e },
- { 0x1000785a, 0x07 },
- { 0x1000785b, 0x00 },
- { 0x1000785c, 0x03 },
- { 0x1000785d, 0xc7 },
- { 0x1000785e, 0x21 },
- { 0x1000785f, 0x41 },
- { 0x10007860, 0x93 },
- { 0x10007861, 0x07 },
- { 0x10007862, 0xb0 },
- { 0x10007863, 0x01 },
- { 0x10007864, 0x63 },
- { 0x10007865, 0x08 },
- { 0x10007866, 0xf7 },
- { 0x10007867, 0x00 },
- { 0x10007868, 0x13 },
- { 0x10007869, 0x05 },
- { 0x1000786a, 0xb0 },
- { 0x1000786b, 0x01 },
- { 0x1000786c, 0xef },
- { 0x1000786d, 0xd0 },
- { 0x1000786e, 0x0f },
- { 0x1000786f, 0xcf },
- { 0x10007870, 0xef },
- { 0x10007871, 0xd0 },
- { 0x10007872, 0x8f },
- { 0x10007873, 0xa4 },
- { 0x10007874, 0x93 },
- { 0x10007875, 0x06 },
- { 0x10007876, 0x10 },
- { 0x10007877, 0x00 },
- { 0x10007878, 0xa3 },
- { 0x10007879, 0x89 },
- { 0x1000787a, 0xd1 },
- { 0x1000787b, 0x40 },
- { 0x1000787c, 0x37 },
- { 0x1000787d, 0xd7 },
- { 0x1000787e, 0x00 },
- { 0x1000787f, 0x10 },
- { 0x10007880, 0x83 },
- { 0x10007881, 0x47 },
- { 0x10007882, 0x07 },
- { 0x10007883, 0xd9 },
- { 0x10007884, 0x93 },
- { 0x10007885, 0xf7 },
- { 0x10007886, 0xf7 },
- { 0x10007887, 0x0f },
- { 0x10007888, 0x63 },
- { 0x10007889, 0x90 },
- { 0x1000788a, 0x07 },
- { 0x1000788b, 0x02 },
- { 0x1000788c, 0x37 },
- { 0x1000788d, 0xc6 },
- { 0x1000788e, 0x00 },
- { 0x1000788f, 0x00 },
- { 0x10007890, 0x83 },
- { 0x10007891, 0x47 },
- { 0x10007892, 0x26 },
- { 0x10007893, 0x04 },
- { 0x10007894, 0x93 },
- { 0x10007895, 0xe7 },
- { 0x10007896, 0x07 },
- { 0x10007897, 0xf8 },
- { 0x10007898, 0x93 },
- { 0x10007899, 0xf7 },
- { 0x1000789a, 0xf7 },
- { 0x1000789b, 0x0f },
- { 0x1000789c, 0x23 },
- { 0x1000789d, 0x01 },
- { 0x1000789e, 0xf6 },
- { 0x1000789f, 0x04 },
- { 0x100078a0, 0x23 },
- { 0x100078a1, 0x08 },
- { 0x100078a2, 0xd7 },
- { 0x100078a3, 0xd8 },
- { 0x100078a4, 0x23 },
- { 0x100078a5, 0x09 },
- { 0x100078a6, 0x07 },
- { 0x100078a7, 0xd8 },
- { 0x100078a8, 0x83 },
- { 0x100078a9, 0x20 },
- { 0x100078aa, 0xc1 },
- { 0x100078ab, 0x00 },
- { 0x100078ac, 0x13 },
- { 0x100078ad, 0x01 },
- { 0x100078ae, 0x01 },
- { 0x100078af, 0x01 },
- { 0x100078b0, 0x67 },
- { 0x100078b1, 0x80 },
- { 0x100078b2, 0x00 },
- { 0x100078b3, 0x00 },
- { 0x3fc2bfc7, 0x00 },
- { 0x3fc2bfc6, 0x00 },
- { 0x3fc2bfc5, 0x00 },
- { 0x3fc2bfc4, 0x01 },
- { 0x0000d486, 0x43 },
- { 0x1000db00, 0x02 },
- { 0x1000db01, 0x00 },
- { 0x1000db02, 0x11 },
- { 0x1000db03, 0x00 },
- { 0x1000db04, 0x00 },
- { 0x1000db05, 0x82 },
- { 0x1000db06, 0x04 },
- { 0x1000db07, 0xf1 },
- { 0x1000db08, 0x00 },
- { 0x1000db09, 0x00 },
- { 0x1000db0a, 0x40 },
- { 0x0000d540, 0x01 },
-};
-
static const struct reg_default rt1320_reg_defaults[] = {
+ { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_01), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_02), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_MUTE, CH_01), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_MUTE, CH_02), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x0b },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0), 0x03 },
{ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_01), 0x01 },
{ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_02), 0x01 },
{ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE27, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 },
{ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 },
{ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PPU21, RT1320_SDCA_CTL_POSTURE_NUMBER, 0), 0x00 },
- { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 },
- { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x0b },
{ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS21, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 },
{ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0), 0x03 },
};
static const struct reg_default rt1320_mbq_defaults[] = {
+ { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01), 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_02), 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01), 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_02), 0x0000 },
{ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_01), 0x0000 },
{ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_02), 0x0000 },
};
@@ -3514,6 +328,17 @@ static bool rt1320_readable_register(struct device *dev, unsigned int reg)
case 0x1000f021:
case 0x3fe2e000 ... 0x3fe2e003:
case 0x3fc2ab80 ... 0x3fc2abd4:
+ /* 0x40801508/0x40801809/0x4080180a/0x40801909/0x4080190a */
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_REQ_POWER_STATE, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_01):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_02):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_MUTE, CH_01):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_MUTE, CH_02):
+ /* 0x40880900/0x40880980 */
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0):
+ /* 0x40881500 */
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0):
/* 0x41000189/0x4100018a */
case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_01):
case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_02):
@@ -3596,6 +421,7 @@ static bool rt1320_volatile_register(struct device *dev, unsigned int reg)
case 0x3fc2bf80 ... 0x3fc2bf83:
case 0x3fc2bfc0 ... 0x3fc2bfc7:
case 0x3fe2e000 ... 0x3fe2e003:
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0):
case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0):
case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_MODE, 0):
case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_STATUS, 0):
@@ -3609,6 +435,10 @@ static bool rt1320_volatile_register(struct device *dev, unsigned int reg)
static bool rt1320_mbq_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_02):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_02):
case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_01):
case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_02):
return true;
@@ -3664,7 +494,7 @@ static int rt1320_read_prop(struct sdw_slave *slave)
prop->lane_control_support = true;
/* first we need to allocate memory for set bits in port lists */
- prop->source_ports = BIT(4);
+ prop->source_ports = BIT(4) | BIT(8) | BIT(10);
prop->sink_ports = BIT(1);
nval = hweight32(prop->source_ports);
@@ -3708,7 +538,8 @@ static int rt1320_read_prop(struct sdw_slave *slave)
return 0;
}
-static int rt1320_pde_transition_delay(struct rt1320_sdw_priv *rt1320, unsigned char ps)
+static int rt1320_pde_transition_delay(struct rt1320_sdw_priv *rt1320, unsigned char func,
+ unsigned char entity, unsigned char ps)
{
unsigned int delay = 1000, val;
@@ -3717,8 +548,7 @@ static int rt1320_pde_transition_delay(struct rt1320_sdw_priv *rt1320, unsigned
/* waiting for Actual PDE becomes to PS0/PS3 */
while (delay) {
regmap_read(rt1320->regmap,
- SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23,
- RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0), &val);
+ SDW_SDCA_CTL(func, entity, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0), &val);
if (val == ps)
break;
@@ -3733,17 +563,88 @@ static int rt1320_pde_transition_delay(struct rt1320_sdw_priv *rt1320, unsigned
return 0;
}
+/*
+ * The 'patch code' is written to the patch code area.
+ * The patch code area is used for SDCA register expansion flexibility.
+ */
+static void rt1320_load_mcu_patch(struct rt1320_sdw_priv *rt1320)
+{
+ struct sdw_slave *slave = rt1320->sdw_slave;
+ const struct firmware *patch;
+ const char *filename;
+ unsigned int addr, val;
+ const unsigned char *ptr;
+ int ret, i;
+
+ if (rt1320->version_id <= RT1320_VB)
+ filename = RT1320_VAB_MCU_PATCH;
+ else
+ filename = RT1320_VC_MCU_PATCH;
+
+ /* load the patch code here */
+ ret = request_firmware(&patch, filename, &slave->dev);
+ if (ret) {
+ dev_err(&slave->dev, "%s: Failed to load %s firmware", __func__, filename);
+ regmap_write(rt1320->regmap, 0xc598, 0x00);
+ regmap_write(rt1320->regmap, 0x10007000, 0x67);
+ regmap_write(rt1320->regmap, 0x10007001, 0x80);
+ regmap_write(rt1320->regmap, 0x10007002, 0x00);
+ regmap_write(rt1320->regmap, 0x10007003, 0x00);
+ } else {
+ ptr = (const unsigned char *)patch->data;
+ if ((patch->size % 8) == 0) {
+ for (i = 0; i < patch->size; i += 8) {
+ addr = (ptr[i] & 0xff) | (ptr[i + 1] & 0xff) << 8 |
+ (ptr[i + 2] & 0xff) << 16 | (ptr[i + 3] & 0xff) << 24;
+ val = (ptr[i + 4] & 0xff) | (ptr[i + 5] & 0xff) << 8 |
+ (ptr[i + 6] & 0xff) << 16 | (ptr[i + 7] & 0xff) << 24;
+
+ if (addr > 0x10007fff || addr < 0x10007000) {
+ dev_err(&slave->dev, "%s: the address 0x%x is wrong", __func__, addr);
+ goto _exit_;
+ }
+ if (val > 0xff) {
+ dev_err(&slave->dev, "%s: the value 0x%x is wrong", __func__, val);
+ goto _exit_;
+ }
+ regmap_write(rt1320->regmap, addr, val);
+ }
+ }
+_exit_:
+ release_firmware(patch);
+ }
+}
+
+static void rt1320_vab_preset(struct rt1320_sdw_priv *rt1320)
+{
+ unsigned int i, reg, val, delay;
+
+ for (i = 0; i < ARRAY_SIZE(rt1320_blind_write); i++) {
+ reg = rt1320_blind_write[i].reg;
+ val = rt1320_blind_write[i].def;
+ delay = rt1320_blind_write[i].delay_us;
+
+ if (reg == 0x3fc2bfc7)
+ rt1320_load_mcu_patch(rt1320);
+
+ regmap_write(rt1320->regmap, reg, val);
+ if (delay)
+ usleep_range(delay, delay + 1000);
+ }
+}
+
static void rt1320_vc_preset(struct rt1320_sdw_priv *rt1320)
{
struct sdw_slave *slave = rt1320->sdw_slave;
unsigned int i, reg, val, delay, retry, tmp;
- regmap_multi_reg_write(rt1320->regmap, rt1320_vc_blind_write, ARRAY_SIZE(rt1320_vc_blind_write));
+ for (i = 0; i < ARRAY_SIZE(rt1320_vc_blind_write); i++) {
+ reg = rt1320_vc_blind_write[i].reg;
+ val = rt1320_vc_blind_write[i].def;
+ delay = rt1320_vc_blind_write[i].delay_us;
- for (i = 0; i < ARRAY_SIZE(rt1320_vc_patch_code_write); i++) {
- reg = rt1320_vc_patch_code_write[i].reg;
- val = rt1320_vc_patch_code_write[i].def;
- delay = rt1320_vc_patch_code_write[i].delay_us;
+ if (reg == 0x3fc2bf83)
+ rt1320_load_mcu_patch(rt1320);
if ((reg == SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0)) &&
(val == 0x00)) {
@@ -3762,6 +663,9 @@ static void rt1320_vc_preset(struct rt1320_sdw_priv *rt1320)
regmap_write(rt1320->regmap, reg, val);
if (delay)
usleep_range(delay, delay + 1000);
+
+ if (reg == SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0))
+ rt1320_pde_transition_delay(rt1320, FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, val);
}
}
@@ -3799,13 +703,10 @@ static int rt1320_io_init(struct device *dev, struct sdw_slave *slave)
/* initialization write */
if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION)) {
- if (rt1320->version_id < RT1320_VC) {
- regmap_multi_reg_write(rt1320->regmap, rt1320_blind_write, ARRAY_SIZE(rt1320_blind_write));
- regmap_multi_reg_write(rt1320->regmap, rt1320_patch_code_write,
- ARRAY_SIZE(rt1320_patch_code_write));
- } else if (rt1320->version_id == RT1320_VC) {
+ if (rt1320->version_id < RT1320_VC)
+ rt1320_vab_preset(rt1320);
+ else
rt1320_vc_preset(rt1320);
- }
regmap_write(rt1320->regmap,
SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0),
@@ -3870,6 +771,34 @@ static int rt1320_update_status(struct sdw_slave *slave,
return rt1320_io_init(&slave->dev, slave);
}
+static int rt1320_pde11_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct rt1320_sdw_priv *rt1320 = snd_soc_component_get_drvdata(component);
+ unsigned char ps0 = 0x0, ps3 = 0x3;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_write(rt1320->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11,
+ RT1320_SDCA_CTL_REQ_POWER_STATE, 0), ps0);
+ rt1320_pde_transition_delay(rt1320, FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, ps0);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ regmap_write(rt1320->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11,
+ RT1320_SDCA_CTL_REQ_POWER_STATE, 0), ps3);
+ rt1320_pde_transition_delay(rt1320, FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, ps3);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
static int rt1320_pde23_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -3883,13 +812,13 @@ static int rt1320_pde23_event(struct snd_soc_dapm_widget *w,
regmap_write(rt1320->regmap,
SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23,
RT1320_SDCA_CTL_REQ_POWER_STATE, 0), ps0);
- rt1320_pde_transition_delay(rt1320, ps0);
+ rt1320_pde_transition_delay(rt1320, FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, ps0);
break;
case SND_SOC_DAPM_PRE_PMD:
regmap_write(rt1320->regmap,
SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23,
RT1320_SDCA_CTL_REQ_POWER_STATE, 0), ps3);
- rt1320_pde_transition_delay(rt1320, ps3);
+ rt1320_pde_transition_delay(rt1320, FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, ps3);
break;
default:
break;
@@ -3908,6 +837,13 @@ static int rt1320_set_gain_put(struct snd_kcontrol *kcontrol,
unsigned int gain_l_val, gain_r_val;
unsigned int lvalue, rvalue;
const unsigned int interval_offset = 0xc0;
+ unsigned int changed = 0, reg_base;
+ struct rt_sdca_dmic_kctrl_priv *p;
+ unsigned int regvalue[4], gain_val[4], i;
+ int err;
+
+ if (strstr(ucontrol->id.name, "FU Capture Volume"))
+ goto _dmic_vol_;
regmap_read(rt1320->mbq_regmap, mc->reg, &lvalue);
regmap_read(rt1320->mbq_regmap, mc->rreg, &rvalue);
@@ -3933,7 +869,48 @@ static int rt1320_set_gain_put(struct snd_kcontrol *kcontrol,
regmap_write(rt1320->mbq_regmap, mc->reg, gain_l_val);
/* Rch */
regmap_write(rt1320->mbq_regmap, mc->rreg, gain_r_val);
+ goto _done_;
+
+_dmic_vol_:
+ p = (struct rt_sdca_dmic_kctrl_priv *)kcontrol->private_value;
+
+ /* check all channels */
+ for (i = 0; i < p->count; i++) {
+ if (i < 2) {
+ reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01);
+ regmap_read(rt1320->mbq_regmap, reg_base + i, &regvalue[i]);
+ } else {
+ reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01);
+ regmap_read(rt1320->mbq_regmap, reg_base + i - 2, &regvalue[i]);
+ }
+
+ gain_val[i] = ucontrol->value.integer.value[i];
+ if (gain_val[i] > p->max)
+ gain_val[i] = p->max;
+
+ gain_val[i] = 0x1e00 - ((p->max - gain_val[i]) * interval_offset);
+ gain_val[i] &= 0xffff;
+ if (regvalue[i] != gain_val[i])
+ changed = 1;
+ }
+
+ if (!changed)
+ return 0;
+ for (i = 0; i < p->count; i++) {
+ if (i < 2) {
+ reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01);
+ err = regmap_write(rt1320->mbq_regmap, reg_base + i, gain_val[i]);
+ } else {
+ reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01);
+ err = regmap_write(rt1320->mbq_regmap, reg_base + i - 2, gain_val[i]);
+ }
+
+ if (err < 0)
+ dev_err(&rt1320->sdw_slave->dev, "0x%08x can't be set\n", reg_base + i);
+ }
+
+_done_:
return 1;
}
@@ -3946,6 +923,11 @@ static int rt1320_set_gain_get(struct snd_kcontrol *kcontrol,
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int read_l, read_r, ctl_l = 0, ctl_r = 0;
const unsigned int interval_offset = 0xc0;
+ unsigned int reg_base, regvalue, ctl, i;
+ struct rt_sdca_dmic_kctrl_priv *p;
+
+ if (strstr(ucontrol->id.name, "FU Capture Volume"))
+ goto _dmic_vol_;
regmap_read(rt1320->mbq_regmap, mc->reg, &read_l);
regmap_read(rt1320->mbq_regmap, mc->rreg, &read_r);
@@ -3959,6 +941,121 @@ static int rt1320_set_gain_get(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[0] = ctl_l;
ucontrol->value.integer.value[1] = ctl_r;
+ goto _done_;
+
+_dmic_vol_:
+ p = (struct rt_sdca_dmic_kctrl_priv *)kcontrol->private_value;
+
+ /* check all channels */
+ for (i = 0; i < p->count; i++) {
+ if (i < 2) {
+ reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01);
+ regmap_read(rt1320->mbq_regmap, reg_base + i, &regvalue);
+ } else {
+ reg_base = SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01);
+ regmap_read(rt1320->mbq_regmap, reg_base + i - 2, &regvalue);
+ }
+
+ ctl = p->max - (((0x1e00 - regvalue) & 0xffff) / interval_offset);
+ ucontrol->value.integer.value[i] = ctl;
+ }
+_done_:
+ return 0;
+}
+
+static int rt1320_set_fu_capture_ctl(struct rt1320_sdw_priv *rt1320)
+{
+ int err, i;
+ unsigned int ch_mute;
+
+ for (i = 0; i < ARRAY_SIZE(rt1320->fu_mixer_mute); i++) {
+ ch_mute = (rt1320->fu_dapm_mute || rt1320->fu_mixer_mute[i]) ? 0x01 : 0x00;
+
+ if (i < 2)
+ err = regmap_write(rt1320->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113,
+ RT1320_SDCA_CTL_FU_MUTE, CH_01) + i, ch_mute);
+ else
+ err = regmap_write(rt1320->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14,
+ RT1320_SDCA_CTL_FU_MUTE, CH_01) + i - 2, ch_mute);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int rt1320_dmic_fu_capture_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct rt1320_sdw_priv *rt1320 = snd_soc_component_get_drvdata(component);
+ struct rt_sdca_dmic_kctrl_priv *p =
+ (struct rt_sdca_dmic_kctrl_priv *)kcontrol->private_value;
+ unsigned int i;
+
+ for (i = 0; i < p->count; i++)
+ ucontrol->value.integer.value[i] = !rt1320->fu_mixer_mute[i];
+
+ return 0;
+}
+
+static int rt1320_dmic_fu_capture_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct rt1320_sdw_priv *rt1320 = snd_soc_component_get_drvdata(component);
+ struct rt_sdca_dmic_kctrl_priv *p =
+ (struct rt_sdca_dmic_kctrl_priv *)kcontrol->private_value;
+ int err, changed = 0, i;
+
+ for (i = 0; i < p->count; i++) {
+ if (rt1320->fu_mixer_mute[i] != !ucontrol->value.integer.value[i])
+ changed = 1;
+ rt1320->fu_mixer_mute[i] = !ucontrol->value.integer.value[i];
+ }
+
+ err = rt1320_set_fu_capture_ctl(rt1320);
+ if (err < 0)
+ return err;
+
+ return changed;
+}
+
+static int rt1320_dmic_fu_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct rt_sdca_dmic_kctrl_priv *p =
+ (struct rt_sdca_dmic_kctrl_priv *)kcontrol->private_value;
+
+ if (p->max == 1)
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ else
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = p->count;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = p->max;
+ return 0;
+}
+
+static int rt1320_dmic_fu_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct rt1320_sdw_priv *rt1320 = snd_soc_component_get_drvdata(component);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ rt1320->fu_dapm_mute = false;
+ rt1320_set_fu_capture_ctl(rt1320);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ rt1320->fu_dapm_mute = true;
+ rt1320_set_fu_capture_ctl(rt1320);
+ break;
+ }
return 0;
}
@@ -3979,6 +1076,7 @@ static SOC_ENUM_SINGLE_DECL(rt1320_rx_data_ch_enum,
rt1320_rx_data_ch_select);
static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0);
static const struct snd_kcontrol_new rt1320_snd_controls[] = {
SOC_DOUBLE_R_EXT_TLV("FU21 Playback Volume",
@@ -3986,6 +1084,13 @@ static const struct snd_kcontrol_new rt1320_snd_controls[] = {
SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_02),
0, 0x57, 0, rt1320_set_gain_get, rt1320_set_gain_put, out_vol_tlv),
SOC_ENUM("RX Channel Select", rt1320_rx_data_ch_enum),
+
+ RT_SDCA_FU_CTRL("FU Capture Switch",
+ SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_01),
+ 1, 1, 4, rt1320_dmic_fu_info, rt1320_dmic_fu_capture_get, rt1320_dmic_fu_capture_put),
+ RT_SDCA_EXT_TLV("FU Capture Volume",
+ SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01),
+ rt1320_set_gain_get, rt1320_set_gain_put, 4, 0x3f, in_vol_tlv, rt1320_dmic_fu_info),
};
static const struct snd_kcontrol_new rt1320_spk_l_dac =
@@ -4001,12 +1106,19 @@ static const struct snd_soc_dapm_widget rt1320_dapm_widgets[] = {
/* Audio Interface */
SND_SOC_DAPM_AIF_IN("DP1RX", "DP1 Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("DP4TX", "DP4 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("DP8-10TX", "DP8-10 Capture", 0, SND_SOC_NOPM, 0, 0),
/* Digital Interface */
SND_SOC_DAPM_PGA("FU21", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("PDE 23", SND_SOC_NOPM, 0, 0,
rt1320_pde23_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_SUPPLY("PDE 11", SND_SOC_NOPM, 0, 0,
+ rt1320_pde11_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_ADC("FU 113", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_ADC("FU 14", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_PGA_E("FU", SND_SOC_NOPM, 0, 0, NULL, 0,
+ rt1320_dmic_fu_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
/* Output */
SND_SOC_DAPM_SWITCH("OT23 L", SND_SOC_NOPM, 0, 0, &rt1320_spk_l_dac),
@@ -4017,6 +1129,8 @@ static const struct snd_soc_dapm_widget rt1320_dapm_widgets[] = {
/* Input */
SND_SOC_DAPM_PGA("AEC Data", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_SIGGEN("AEC Gen"),
+ SND_SOC_DAPM_INPUT("DMIC1"),
+ SND_SOC_DAPM_INPUT("DMIC2"),
};
static const struct snd_soc_dapm_route rt1320_dapm_routes[] = {
@@ -4029,6 +1143,13 @@ static const struct snd_soc_dapm_route rt1320_dapm_routes[] = {
{ "AEC Data", NULL, "AEC Gen" },
{ "DP4TX", NULL, "AEC Data" },
+
+ {"DP8-10TX", NULL, "FU"},
+ {"FU", NULL, "PDE 11"},
+ {"FU", NULL, "FU 113"},
+ {"FU", NULL, "FU 14"},
+ {"FU 113", NULL, "DMIC1"},
+ {"FU 14", NULL, "DMIC2"},
};
static int rt1320_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
@@ -4052,6 +1173,7 @@ static int rt1320_sdw_hw_params(struct snd_pcm_substream *substream,
snd_soc_component_get_drvdata(component);
struct sdw_stream_config stream_config;
struct sdw_port_config port_config;
+ struct sdw_port_config dmic_port_config[2];
struct sdw_stream_runtime *sdw_stream;
int retval;
unsigned int sampling_rate;
@@ -4076,12 +1198,23 @@ static int rt1320_sdw_hw_params(struct snd_pcm_substream *substream,
} else {
if (dai->id == RT1320_AIF1)
port_config.num = 4;
- else
+ else if (dai->id == RT1320_AIF2) {
+ dmic_port_config[0].ch_mask = BIT(0) | BIT(1);
+ dmic_port_config[0].num = 8;
+ dmic_port_config[1].ch_mask = BIT(0) | BIT(1);
+ dmic_port_config[1].num = 10;
+ } else
return -EINVAL;
}
- retval = sdw_stream_add_slave(rt1320->sdw_slave, &stream_config,
+ if (dai->id == RT1320_AIF1)
+ retval = sdw_stream_add_slave(rt1320->sdw_slave, &stream_config,
&port_config, 1, sdw_stream);
+ else if (dai->id == RT1320_AIF2)
+ retval = sdw_stream_add_slave(rt1320->sdw_slave, &stream_config,
+ dmic_port_config, 2, sdw_stream);
+ else
+ return -EINVAL;
if (retval) {
dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
@@ -4114,9 +1247,18 @@ static int rt1320_sdw_hw_params(struct snd_pcm_substream *substream,
}
/* set sampling frequency */
- regmap_write(rt1320->regmap,
- SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS21, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0),
- sampling_rate);
+ if (dai->id == RT1320_AIF1)
+ regmap_write(rt1320->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS21, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0),
+ sampling_rate);
+ else {
+ regmap_write(rt1320->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0),
+ sampling_rate);
+ regmap_write(rt1320->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0),
+ sampling_rate);
+ }
return 0;
}
@@ -4207,6 +1349,19 @@ static struct snd_soc_dai_driver rt1320_sdw_dai[] = {
},
.ops = &rt1320_aif_dai_ops,
},
+ /* DMIC: DP8 2ch + DP10 2ch */
+ {
+ .name = "rt1320-aif2",
+ .id = RT1320_AIF2,
+ .capture = {
+ .stream_name = "DP8-10 Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = RT1320_STEREO_RATES,
+ .formats = RT1320_FORMATS,
+ },
+ .ops = &rt1320_aif_dai_ops,
+ },
};
static int rt1320_sdw_init(struct device *dev, struct regmap *regmap,
@@ -4234,6 +1389,9 @@ static int rt1320_sdw_init(struct device *dev, struct regmap *regmap,
rt1320->hw_init = false;
rt1320->first_hw_init = false;
rt1320->version_id = -1;
+ rt1320->fu_dapm_mute = true;
+ rt1320->fu_mixer_mute[0] = rt1320->fu_mixer_mute[1] =
+ rt1320->fu_mixer_mute[2] = rt1320->fu_mixer_mute[3] = true;
ret = devm_snd_soc_register_component(dev,
&soc_component_sdw_rt1320,
diff --git a/sound/soc/codecs/rt1320-sdw.h b/sound/soc/codecs/rt1320-sdw.h
index 1fbc1fcd71cf..23b321aee6a9 100644
--- a/sound/soc/codecs/rt1320-sdw.h
+++ b/sound/soc/codecs/rt1320-sdw.h
@@ -26,6 +26,7 @@
/* RT1320 SDCA Control - function number */
#define FUNC_NUM_AMP 0x04
+#define FUNC_NUM_MIC 0x02
/* RT1320 SDCA entity */
#define RT1320_SDCA_ENT0 0x00
@@ -69,6 +70,7 @@
enum {
RT1320_AIF1,
+ RT1320_AIF2,
};
/*
@@ -82,6 +84,8 @@ enum rt1320_version_id {
};
#define RT1320_VER_B_ID 0x07392238
+#define RT1320_VAB_MCU_PATCH "realtek/rt1320/rt1320-patch-code-vab.bin"
+#define RT1320_VC_MCU_PATCH "realtek/rt1320/rt1320-patch-code-vc.bin"
struct rt1320_sdw_priv {
struct snd_soc_component *component;
@@ -92,6 +96,8 @@ struct rt1320_sdw_priv {
bool hw_init;
bool first_hw_init;
int version_id;
+ bool fu_dapm_mute;
+ bool fu_mixer_mute[4];
};
#endif /* __RT1320_SDW_H__ */
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 16f3425a3e35..855139348edb 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -2419,10 +2419,20 @@ static irqreturn_t rt5640_jd_gpio_irq(int irq, void *data)
return IRQ_HANDLED;
}
-static void rt5640_cancel_work(void *data)
+static void rt5640_disable_irq_and_cancel_work(void *data)
{
struct rt5640_priv *rt5640 = data;
+ if (rt5640->jd_gpio_irq_requested) {
+ free_irq(rt5640->jd_gpio_irq, rt5640);
+ rt5640->jd_gpio_irq_requested = false;
+ }
+
+ if (rt5640->irq_requested) {
+ free_irq(rt5640->irq, rt5640);
+ rt5640->irq_requested = false;
+ }
+
cancel_delayed_work_sync(&rt5640->jack_work);
cancel_delayed_work_sync(&rt5640->bp_work);
}
@@ -2463,13 +2473,7 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component)
if (!rt5640->jack)
return;
- if (rt5640->jd_gpio_irq_requested)
- free_irq(rt5640->jd_gpio_irq, rt5640);
-
- if (rt5640->irq_requested)
- free_irq(rt5640->irq, rt5640);
-
- rt5640_cancel_work(rt5640);
+ rt5640_disable_irq_and_cancel_work(rt5640);
if (rt5640->jack->status & SND_JACK_MICROPHONE) {
rt5640_disable_micbias1_ovcd_irq(component);
@@ -2477,8 +2481,6 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component)
snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0);
}
- rt5640->jd_gpio_irq_requested = false;
- rt5640->irq_requested = false;
rt5640->jd_gpio = NULL;
rt5640->jack = NULL;
}
@@ -2798,7 +2800,8 @@ static int rt5640_suspend(struct snd_soc_component *component)
if (rt5640->jack) {
/* disable jack interrupts during system suspend */
disable_irq(rt5640->irq);
- rt5640_cancel_work(rt5640);
+ cancel_delayed_work_sync(&rt5640->jack_work);
+ cancel_delayed_work_sync(&rt5640->bp_work);
}
snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
@@ -3032,7 +3035,7 @@ static int rt5640_i2c_probe(struct i2c_client *i2c)
INIT_DELAYED_WORK(&rt5640->jack_work, rt5640_jack_work);
/* Make sure work is stopped on probe-error / remove */
- ret = devm_add_action_or_reset(&i2c->dev, rt5640_cancel_work, rt5640);
+ ret = devm_add_action_or_reset(&i2c->dev, rt5640_disable_irq_and_cancel_work, rt5640);
if (ret)
return ret;
diff --git a/sound/soc/codecs/rt712-sdca-sdw.c b/sound/soc/codecs/rt712-sdca-sdw.c
index 90d5aaddbd5b..549aa31faed4 100644
--- a/sound/soc/codecs/rt712-sdca-sdw.c
+++ b/sound/soc/codecs/rt712-sdca-sdw.c
@@ -507,3 +507,4 @@ module_sdw_driver(rt712_sdca_sdw_driver);
MODULE_DESCRIPTION("ASoC RT712 SDCA SDW driver");
MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>");
MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SND_SOC_SDCA);
diff --git a/sound/soc/codecs/rt712-sdca.c b/sound/soc/codecs/rt712-sdca.c
index e210c574bb74..78dbf9eed494 100644
--- a/sound/soc/codecs/rt712-sdca.c
+++ b/sound/soc/codecs/rt712-sdca.c
@@ -18,6 +18,7 @@
#include <linux/pm_runtime.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
+#include <sound/sdca.h>
#include <linux/soundwire/sdw_registers.h>
#include <linux/slab.h>
#include <sound/soc-dapm.h>
@@ -1652,6 +1653,17 @@ int rt712_sdca_init(struct device *dev, struct regmap *regmap,
if (ret < 0)
return ret;
+ /* only add the dmic component if a SMART_MIC function is exposed in ACPI */
+ if (sdca_device_quirk_match(slave, SDCA_QUIRKS_RT712_VB)) {
+ ret = devm_snd_soc_register_component(dev,
+ &soc_sdca_dev_rt712_dmic,
+ rt712_sdca_dmic_dai,
+ ARRAY_SIZE(rt712_sdca_dmic_dai));
+ if (ret < 0)
+ return ret;
+ rt712->dmic_function_found = true;
+ }
+
/* set autosuspend parameters */
pm_runtime_set_autosuspend_delay(dev, 3000);
pm_runtime_use_autosuspend(dev);
@@ -1799,7 +1811,6 @@ static void rt712_sdca_vb_io_init(struct rt712_sdca_priv *rt712)
int rt712_sdca_io_init(struct device *dev, struct sdw_slave *slave)
{
struct rt712_sdca_priv *rt712 = dev_get_drvdata(dev);
- int ret = 0;
unsigned int val;
struct sdw_slave_prop *prop = &slave->prop;
@@ -1829,15 +1840,22 @@ int rt712_sdca_io_init(struct device *dev, struct sdw_slave *slave)
rt712->version_id = (val & 0x0f00) >> 8;
dev_dbg(&slave->dev, "%s hw_id=0x%x, version_id=0x%x\n", __func__, rt712->hw_id, rt712->version_id);
- if (rt712->version_id == RT712_VA)
+ if (rt712->version_id == RT712_VA) {
+ if (rt712->dmic_function_found) {
+ dev_err(&slave->dev, "%s RT712 VA detected but SMART_MIC function exposed in ACPI\n",
+ __func__);
+ goto suspend;
+ }
+
rt712_sdca_va_io_init(rt712);
- else {
- /* multilanes and DMIC are supported by rt712vb */
- ret = devm_snd_soc_register_component(dev,
- &soc_sdca_dev_rt712_dmic, rt712_sdca_dmic_dai, ARRAY_SIZE(rt712_sdca_dmic_dai));
- if (ret < 0)
- return ret;
+ } else {
+ if (!rt712->dmic_function_found) {
+ dev_err(&slave->dev, "%s RT712 VB detected but no SMART_MIC function exposed in ACPI\n",
+ __func__);
+ goto suspend;
+ }
+ /* multilanes and DMIC are supported by rt712vb */
prop->lane_control_support = true;
rt712_sdca_vb_io_init(rt712);
}
@@ -1862,10 +1880,12 @@ int rt712_sdca_io_init(struct device *dev, struct sdw_slave *slave)
/* Mark Slave initialization complete */
rt712->hw_init = true;
+ dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
+
+suspend:
pm_runtime_mark_last_busy(&slave->dev);
pm_runtime_put_autosuspend(&slave->dev);
- dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
return 0;
}
diff --git a/sound/soc/codecs/rt712-sdca.h b/sound/soc/codecs/rt712-sdca.h
index 2169f2f726b9..a08491496d90 100644
--- a/sound/soc/codecs/rt712-sdca.h
+++ b/sound/soc/codecs/rt712-sdca.h
@@ -36,6 +36,7 @@ struct rt712_sdca_priv {
unsigned int scp_sdca_stat2;
unsigned int hw_id;
unsigned int version_id;
+ bool dmic_function_found;
bool fu0f_dapm_mute;
bool fu0f_mixer_l_mute;
bool fu0f_mixer_r_mute;
diff --git a/sound/soc/codecs/rt721-sdca-sdw.c b/sound/soc/codecs/rt721-sdca-sdw.c
new file mode 100644
index 000000000000..c71453da088a
--- /dev/null
+++ b/sound/soc/codecs/rt721-sdca-sdw.c
@@ -0,0 +1,546 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// rt721-sdca-sdw.c -- rt721 SDCA ALSA SoC audio driver
+//
+// Copyright(c) 2024 Realtek Semiconductor Corp.
+//
+//
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/pm_runtime.h>
+#include <linux/soundwire/sdw_registers.h>
+
+#include "rt721-sdca.h"
+#include "rt721-sdca-sdw.h"
+#include "rt-sdw-common.h"
+
+static bool rt721_sdca_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case 0x2f01 ... 0x2f0a:
+ case 0x2f35:
+ case 0x2f50:
+ case 0x2f51:
+ case 0x2f58 ... 0x2f5d:
+ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_XUV,
+ RT721_SDCA_CTL_XUV, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_GE49,
+ RT721_SDCA_CTL_SELECTED_MODE, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_GE49,
+ RT721_SDCA_CTL_DETECTED_MODE, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_HID, RT721_SDCA_ENT_HID01,
+ RT721_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... SDW_SDCA_CTL(FUNC_NUM_HID,
+ RT721_SDCA_ENT_HID01, RT721_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0):
+ case RT721_BUF_ADDR_HID1 ... RT721_BUF_ADDR_HID2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool rt721_sdca_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case 0x2f01:
+ case 0x2f51:
+ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_GE49,
+ RT721_SDCA_CTL_DETECTED_MODE, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_XUV,
+ RT721_SDCA_CTL_XUV, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_HID, RT721_SDCA_ENT_HID01,
+ RT721_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... SDW_SDCA_CTL(FUNC_NUM_HID,
+ RT721_SDCA_ENT_HID01, RT721_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0):
+ case RT721_BUF_ADDR_HID1 ... RT721_BUF_ADDR_HID2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool rt721_sdca_mbq_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case 0x0900007:
+ case 0x0a00005:
+ case 0x0c00005:
+ case 0x0d00014:
+ case 0x0310100:
+ case 0x2000001:
+ case 0x2000002:
+ case 0x2000003:
+ case 0x2000013:
+ case 0x200003c:
+ case 0x2000046:
+ case 0x5810000:
+ case 0x5810036:
+ case 0x5810037:
+ case 0x5810038:
+ case 0x5810039:
+ case 0x5b10018:
+ case 0x5b10019:
+ case 0x5f00045:
+ case 0x5f00048:
+ case 0x6100000:
+ case 0x6100005:
+ case 0x6100006:
+ case 0x610000d:
+ case 0x6100010:
+ case 0x6100011:
+ case 0x6100013:
+ case 0x6100015:
+ case 0x6100017:
+ case 0x6100025:
+ case 0x6100029:
+ case 0x610002c ... 0x610002f:
+ case 0x6100053 ... 0x6100055:
+ case 0x6100057:
+ case 0x610005a:
+ case 0x610005b:
+ case 0x610006a:
+ case 0x610006d:
+ case 0x6100092:
+ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, RT721_SDCA_CTL_FU_VOLUME,
+ CH_L):
+ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, RT721_SDCA_CTL_FU_VOLUME,
+ CH_R):
+ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, RT721_SDCA_CTL_FU_VOLUME,
+ CH_L):
+ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, RT721_SDCA_CTL_FU_VOLUME,
+ CH_R):
+ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44,
+ RT721_SDCA_CTL_FU_CH_GAIN, CH_L):
+ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44,
+ RT721_SDCA_CTL_FU_CH_GAIN, CH_R):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME,
+ CH_01):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME,
+ CH_02):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME,
+ CH_03):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME,
+ CH_04):
+ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, RT721_SDCA_CTL_FU_VOLUME, CH_L):
+ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, RT721_SDCA_CTL_FU_VOLUME, CH_R):
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool rt721_sdca_mbq_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case 0x0310100:
+ case 0x0a00005:
+ case 0x0c00005:
+ case 0x0d00014:
+ case 0x2000000:
+ case 0x200000d:
+ case 0x2000019:
+ case 0x2000020:
+ case 0x2000030:
+ case 0x2000046:
+ case 0x2000067:
+ case 0x2000084:
+ case 0x2000086:
+ case 0x5810000:
+ case 0x5810036:
+ case 0x5810037:
+ case 0x5810038:
+ case 0x5810039:
+ case 0x5b10018:
+ case 0x5b10019:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config rt721_sdca_regmap = {
+ .reg_bits = 32,
+ .val_bits = 8,
+ .readable_reg = rt721_sdca_readable_register,
+ .volatile_reg = rt721_sdca_volatile_register,
+ .max_register = 0x44ffffff,
+ .reg_defaults = rt721_sdca_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(rt721_sdca_reg_defaults),
+ .cache_type = REGCACHE_MAPLE,
+ .use_single_read = true,
+ .use_single_write = true,
+};
+
+static const struct regmap_config rt721_sdca_mbq_regmap = {
+ .name = "sdw-mbq",
+ .reg_bits = 32,
+ .val_bits = 16,
+ .readable_reg = rt721_sdca_mbq_readable_register,
+ .volatile_reg = rt721_sdca_mbq_volatile_register,
+ .max_register = 0x41000312,
+ .reg_defaults = rt721_sdca_mbq_defaults,
+ .num_reg_defaults = ARRAY_SIZE(rt721_sdca_mbq_defaults),
+ .cache_type = REGCACHE_MAPLE,
+ .use_single_read = true,
+ .use_single_write = true,
+};
+
+static int rt721_sdca_update_status(struct sdw_slave *slave,
+ enum sdw_slave_status status)
+{
+ struct rt721_sdca_priv *rt721 = dev_get_drvdata(&slave->dev);
+
+ if (status == SDW_SLAVE_UNATTACHED)
+ rt721->hw_init = false;
+
+ if (status == SDW_SLAVE_ATTACHED) {
+ if (rt721->hs_jack) {
+ /*
+ * Due to the SCP_SDCA_INTMASK will be cleared by any reset, and then
+ * if the device attached again, we will need to set the setting back.
+ * It could avoid losing the jack detection interrupt.
+ * This also could sync with the cache value as the rt721_sdca_jack_init set.
+ */
+ sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INTMASK1,
+ SDW_SCP_SDCA_INTMASK_SDCA_0);
+ sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INTMASK2,
+ SDW_SCP_SDCA_INTMASK_SDCA_8);
+ }
+ }
+
+ /*
+ * Perform initialization only if slave status is present and
+ * hw_init flag is false
+ */
+ if (rt721->hw_init || status != SDW_SLAVE_ATTACHED)
+ return 0;
+
+ /* perform I/O transfers required for Slave initialization */
+ return rt721_sdca_io_init(&slave->dev, slave);
+}
+
+static int rt721_sdca_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;
+
+ sdw_slave_read_prop(slave);
+ prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
+ prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY;
+
+ prop->paging_support = true;
+
+ /*
+ * port = 1 for headphone playback
+ * port = 2 for headset-mic capture
+ * port = 3 for speaker playback
+ * port = 6 for digital-mic capture
+ */
+ prop->source_ports = BIT(6) | BIT(2); /* BITMAP: 01000100 */
+ prop->sink_ports = BIT(3) | BIT(1); /* BITMAP: 00001010 */
+
+ 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;
+ dpn[i].ch_prep_timeout = 10;
+ 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;
+ dpn[j].ch_prep_timeout = 10;
+ j++;
+ }
+
+ /* set the timeout values */
+ prop->clk_stop_timeout = 1380;
+
+ /* wake-up event */
+ prop->wake_capable = 1;
+
+ /* Three data lanes are supported by rt721-sdca codec */
+ prop->lane_control_support = true;
+
+ return 0;
+}
+
+static int rt721_sdca_interrupt_callback(struct sdw_slave *slave,
+ struct sdw_slave_intr_status *status)
+{
+ struct rt721_sdca_priv *rt721 = dev_get_drvdata(&slave->dev);
+ int ret, stat;
+ int count = 0, retry = 3;
+ unsigned int sdca_cascade, scp_sdca_stat1, scp_sdca_stat2 = 0;
+
+ if (cancel_delayed_work_sync(&rt721->jack_detect_work)) {
+ dev_warn(&slave->dev, "%s the pending delayed_work was cancelled", __func__);
+ /* avoid the HID owner doesn't change to device */
+ if (rt721->scp_sdca_stat2)
+ scp_sdca_stat2 = rt721->scp_sdca_stat2;
+ }
+
+ /*
+ * The critical section below intentionally protects a rather large piece of code.
+ * We don't want to allow the system suspend to disable an interrupt while we are
+ * processing it, which could be problematic given the quirky SoundWire interrupt
+ * scheme. We do want however to prevent new workqueues from being scheduled if
+ * the disable_irq flag was set during system suspend.
+ */
+ mutex_lock(&rt721->disable_irq_lock);
+
+ ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT1);
+ if (ret < 0)
+ goto io_error;
+
+ rt721->scp_sdca_stat1 = ret;
+ ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT2);
+ if (ret < 0)
+ goto io_error;
+
+ rt721->scp_sdca_stat2 = ret;
+ if (scp_sdca_stat2)
+ rt721->scp_sdca_stat2 |= scp_sdca_stat2;
+ do {
+ /* clear flag */
+ ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT1);
+ if (ret < 0)
+ goto io_error;
+ if (ret & SDW_SCP_SDCA_INTMASK_SDCA_0) {
+ ret = sdw_update_no_pm(rt721->slave, SDW_SCP_SDCA_INT1,
+ SDW_SCP_SDCA_INT_SDCA_0, SDW_SCP_SDCA_INT_SDCA_0);
+ if (ret < 0)
+ goto io_error;
+ }
+ ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT2);
+ if (ret < 0)
+ goto io_error;
+ if (ret & SDW_SCP_SDCA_INTMASK_SDCA_8) {
+ ret = sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INT2,
+ SDW_SCP_SDCA_INTMASK_SDCA_8);
+ if (ret < 0)
+ goto io_error;
+ }
+
+ /* check if flag clear or not */
+ ret = sdw_read_no_pm(rt721->slave, SDW_DP0_INT);
+ if (ret < 0)
+ goto io_error;
+ sdca_cascade = ret & SDW_DP0_SDCA_CASCADE;
+
+ ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT1);
+ if (ret < 0)
+ goto io_error;
+ scp_sdca_stat1 = ret & SDW_SCP_SDCA_INTMASK_SDCA_0;
+
+ ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT2);
+ if (ret < 0)
+ goto io_error;
+ scp_sdca_stat2 = ret & SDW_SCP_SDCA_INTMASK_SDCA_8;
+
+ stat = scp_sdca_stat1 || scp_sdca_stat2 || sdca_cascade;
+
+ count++;
+ } while (stat != 0 && count < retry);
+
+ if (stat)
+ dev_warn(&slave->dev,
+ "%s scp_sdca_stat1=0x%x, scp_sdca_stat2=0x%x\n", __func__,
+ rt721->scp_sdca_stat1, rt721->scp_sdca_stat2);
+ ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT1);
+ ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT2);
+
+ if (status->sdca_cascade && !rt721->disable_irq)
+ mod_delayed_work(system_power_efficient_wq,
+ &rt721->jack_detect_work, msecs_to_jiffies(280));
+
+ mutex_unlock(&rt721->disable_irq_lock);
+
+ return 0;
+
+io_error:
+ mutex_unlock(&rt721->disable_irq_lock);
+ pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
+ return ret;
+}
+
+static const struct sdw_slave_ops rt721_sdca_slave_ops = {
+ .read_prop = rt721_sdca_read_prop,
+ .interrupt_callback = rt721_sdca_interrupt_callback,
+ .update_status = rt721_sdca_update_status,
+};
+
+static int rt721_sdca_sdw_probe(struct sdw_slave *slave,
+ const struct sdw_device_id *id)
+{
+ struct regmap *regmap, *mbq_regmap;
+
+ /* Regmap Initialization */
+ mbq_regmap = devm_regmap_init_sdw_mbq(slave, &rt721_sdca_mbq_regmap);
+ if (IS_ERR(mbq_regmap))
+ return PTR_ERR(mbq_regmap);
+
+ regmap = devm_regmap_init_sdw(slave, &rt721_sdca_regmap);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return rt721_sdca_init(&slave->dev, regmap, mbq_regmap, slave);
+}
+
+static int rt721_sdca_sdw_remove(struct sdw_slave *slave)
+{
+ struct rt721_sdca_priv *rt721 = dev_get_drvdata(&slave->dev);
+
+ if (rt721->hw_init) {
+ cancel_delayed_work_sync(&rt721->jack_detect_work);
+ cancel_delayed_work_sync(&rt721->jack_btn_check_work);
+ }
+
+ if (rt721->first_hw_init)
+ pm_runtime_disable(&slave->dev);
+
+ mutex_destroy(&rt721->calibrate_mutex);
+ mutex_destroy(&rt721->disable_irq_lock);
+
+ return 0;
+}
+
+static const struct sdw_device_id rt721_sdca_id[] = {
+ SDW_SLAVE_ENTRY_EXT(0x025d, 0x721, 0x3, 0x1, 0),
+ {},
+};
+MODULE_DEVICE_TABLE(sdw, rt721_sdca_id);
+
+static int __maybe_unused rt721_sdca_dev_suspend(struct device *dev)
+{
+ struct rt721_sdca_priv *rt721 = dev_get_drvdata(dev);
+
+ if (!rt721->hw_init)
+ return 0;
+
+ cancel_delayed_work_sync(&rt721->jack_detect_work);
+ cancel_delayed_work_sync(&rt721->jack_btn_check_work);
+
+ regcache_cache_only(rt721->regmap, true);
+ regcache_cache_only(rt721->mbq_regmap, true);
+
+ return 0;
+}
+
+static int __maybe_unused rt721_sdca_dev_system_suspend(struct device *dev)
+{
+ struct rt721_sdca_priv *rt721_sdca = dev_get_drvdata(dev);
+ struct sdw_slave *slave = dev_to_sdw_dev(dev);
+ int ret1, ret2;
+
+ if (!rt721_sdca->hw_init)
+ return 0;
+
+ /*
+ * prevent new interrupts from being handled after the
+ * deferred work completes and before the parent disables
+ * interrupts on the link
+ */
+ mutex_lock(&rt721_sdca->disable_irq_lock);
+ rt721_sdca->disable_irq = true;
+ ret1 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK1,
+ SDW_SCP_SDCA_INTMASK_SDCA_0, 0);
+ ret2 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK2,
+ SDW_SCP_SDCA_INTMASK_SDCA_8, 0);
+ mutex_unlock(&rt721_sdca->disable_irq_lock);
+
+ if (ret1 < 0 || ret2 < 0) {
+ /* log but don't prevent suspend from happening */
+ dev_dbg(&slave->dev, "%s: could not disable SDCA interrupts\n:", __func__);
+ }
+
+ return rt721_sdca_dev_suspend(dev);
+}
+
+#define RT721_PROBE_TIMEOUT 5000
+
+static int __maybe_unused rt721_sdca_dev_resume(struct device *dev)
+{
+ struct sdw_slave *slave = dev_to_sdw_dev(dev);
+ struct rt721_sdca_priv *rt721 = dev_get_drvdata(dev);
+ unsigned long time;
+
+ if (!rt721->first_hw_init)
+ return 0;
+
+ if (!slave->unattach_request) {
+ mutex_lock(&rt721->disable_irq_lock);
+ if (rt721->disable_irq == true) {
+ sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
+ sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
+ rt721->disable_irq = false;
+ }
+ mutex_unlock(&rt721->disable_irq_lock);
+ goto regmap_sync;
+ }
+
+ time = wait_for_completion_timeout(&slave->initialization_complete,
+ msecs_to_jiffies(RT721_PROBE_TIMEOUT));
+ if (!time) {
+ dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ sdw_show_ping_status(slave->bus, true);
+
+ return -ETIMEDOUT;
+ }
+
+regmap_sync:
+ slave->unattach_request = 0;
+ regcache_cache_only(rt721->regmap, false);
+ regcache_sync(rt721->regmap);
+ regcache_cache_only(rt721->mbq_regmap, false);
+ regcache_sync(rt721->mbq_regmap);
+ return 0;
+}
+
+static const struct dev_pm_ops rt721_sdca_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(rt721_sdca_dev_system_suspend, rt721_sdca_dev_resume)
+ SET_RUNTIME_PM_OPS(rt721_sdca_dev_suspend, rt721_sdca_dev_resume, NULL)
+};
+
+static struct sdw_driver rt721_sdca_sdw_driver = {
+ .driver = {
+ .name = "rt721-sdca",
+ .owner = THIS_MODULE,
+ .pm = &rt721_sdca_pm,
+ },
+ .probe = rt721_sdca_sdw_probe,
+ .remove = rt721_sdca_sdw_remove,
+ .ops = &rt721_sdca_slave_ops,
+ .id_table = rt721_sdca_id,
+};
+module_sdw_driver(rt721_sdca_sdw_driver);
+
+MODULE_DESCRIPTION("ASoC RT721 SDCA SDW driver");
+MODULE_AUTHOR("Jack Yu <jack.yu@realtek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt721-sdca-sdw.h b/sound/soc/codecs/rt721-sdca-sdw.h
new file mode 100644
index 000000000000..214b31b82583
--- /dev/null
+++ b/sound/soc/codecs/rt721-sdca-sdw.h
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * rt721-sdca-sdw.h -- RT721 SDCA ALSA SoC audio driver header
+ *
+ * Copyright(c) 2024 Realtek Semiconductor Corp.
+ */
+
+#ifndef __RT721_SDW_H__
+#define __RT721_SDW_H__
+
+#include <linux/regmap.h>
+#include <linux/soundwire/sdw_registers.h>
+
+static const struct reg_default rt721_sdca_reg_defaults[] = {
+ { 0x202d, 0x00 },
+ { 0x2f01, 0x00 },
+ { 0x2f02, 0x09 },
+ { 0x2f03, 0x08 },
+ { 0x2f04, 0x00 },
+ { 0x2f05, 0x0e },
+ { 0x2f06, 0x01 },
+ { 0x2f09, 0x00 },
+ { 0x2f0a, 0x00 },
+ { 0x2f35, 0x00 },
+ { 0x2f50, 0xf0 },
+ { 0x2f58, 0x07 },
+ { 0x2f59, 0x07 },
+ { 0x2f5a, 0x00 },
+ { 0x2f5b, 0x07 },
+ { 0x2f5c, 0x27 },
+ { 0x2f5d, 0x07 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_CS01,
+ RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_CS11,
+ RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PDE12,
+ RT721_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PDE40,
+ RT721_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05,
+ RT721_SDCA_CTL_FU_MUTE, CH_L), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05,
+ RT721_SDCA_CTL_FU_MUTE, CH_R), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F,
+ RT721_SDCA_CTL_FU_MUTE, CH_L), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F,
+ RT721_SDCA_CTL_FU_MUTE, CH_R), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E,
+ RT721_SDCA_CTL_FU_MUTE, CH_01), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E,
+ RT721_SDCA_CTL_FU_MUTE, CH_02), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E,
+ RT721_SDCA_CTL_FU_MUTE, CH_03), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E,
+ RT721_SDCA_CTL_FU_MUTE, CH_04), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_CS1F,
+ RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_IT26,
+ RT721_SDCA_CTL_VENDOR_DEF, 0), 0x00 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_PDE2A,
+ RT721_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 },
+ { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_CS31,
+ RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 },
+ { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06,
+ RT721_SDCA_CTL_FU_MUTE, CH_L), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06,
+ RT721_SDCA_CTL_FU_MUTE, CH_R), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23,
+ RT721_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 },
+ { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_OT23,
+ RT721_SDCA_CTL_VENDOR_DEF, 0), 0x00 },
+ { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23,
+ RT721_SDCA_CTL_FU_MUTE, CH_01), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23,
+ RT721_SDCA_CTL_FU_MUTE, CH_02), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_FU55,
+ RT721_SDCA_CTL_FU_MUTE, CH_01), 0x01 },
+ { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_FU55,
+ RT721_SDCA_CTL_FU_MUTE, CH_02), 0x01 },
+};
+
+static const struct reg_default rt721_sdca_mbq_defaults[] = {
+ { 0x0900007, 0xc004 },
+ { 0x2000001, 0x0000 },
+ { 0x2000002, 0x0000 },
+ { 0x2000003, 0x0000 },
+ { 0x2000013, 0x8001 },
+ { 0x200003c, 0x0000 },
+ { 0x2000046, 0x3400 },
+ { 0x5f00044, 0x6040 },
+ { 0x5f00045, 0x3333 },
+ { 0x5f00048, 0x0000 },
+ { 0x6100005, 0x0005 },
+ { 0x6100006, 0x0000 },
+ { 0x610000d, 0x0051 },
+ { 0x6100010, 0x0180 },
+ { 0x6100011, 0x0000 },
+ { 0x6100013, 0x0000 },
+ { 0x6100015, 0x0000 },
+ { 0x6100017, 0x8049 },
+ { 0x6100025, 0x1000 },
+ { 0x6100029, 0x0809 },
+ { 0x610002c, 0x2828 },
+ { 0x610002d, 0x2929 },
+ { 0x610002e, 0x3529 },
+ { 0x610002f, 0x2901 },
+ { 0x6100053, 0x2630 },
+ { 0x6100054, 0x2a2a },
+ { 0x6100055, 0x152f },
+ { 0x6100057, 0x2200 },
+ { 0x610005a, 0x2a4b },
+ { 0x610005b, 0x2a00 },
+ { 0x610006a, 0x0102 },
+ { 0x610006d, 0x0102 },
+ { 0x6100092, 0x4f61 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, RT721_SDCA_CTL_FU_VOLUME,
+ CH_L), 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, RT721_SDCA_CTL_FU_VOLUME,
+ CH_R), 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, RT721_SDCA_CTL_FU_VOLUME,
+ CH_L), 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, RT721_SDCA_CTL_FU_VOLUME,
+ CH_R), 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44, RT721_SDCA_CTL_FU_CH_GAIN,
+ CH_L), 0xfe00 },
+ { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44, RT721_SDCA_CTL_FU_CH_GAIN,
+ CH_R), 0xfe00 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_FU15, RT721_SDCA_CTL_FU_CH_GAIN, CH_01),
+ 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_FU15, RT721_SDCA_CTL_FU_CH_GAIN, CH_02),
+ 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_FU15, RT721_SDCA_CTL_FU_CH_GAIN, CH_03),
+ 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_FU15, RT721_SDCA_CTL_FU_CH_GAIN, CH_04),
+ 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME,
+ CH_01), 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME,
+ CH_02), 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME,
+ CH_03), 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME,
+ CH_04), 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, RT721_SDCA_CTL_FU_VOLUME, CH_L),
+ 0x0000 },
+ { SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, RT721_SDCA_CTL_FU_VOLUME, CH_R),
+ 0x0000 },
+};
+
+#endif /* __RT721_SDW_H__ */
diff --git a/sound/soc/codecs/rt721-sdca.c b/sound/soc/codecs/rt721-sdca.c
new file mode 100644
index 000000000000..1c9f32e405cf
--- /dev/null
+++ b/sound/soc/codecs/rt721-sdca.c
@@ -0,0 +1,1545 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// rt721-sdca.c -- rt721 SDCA ALSA SoC audio driver
+//
+// Copyright(c) 2024 Realtek Semiconductor Corp.
+//
+//
+
+#include <linux/bitops.h>
+#include <sound/core.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <sound/initval.h>
+#include <sound/jack.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <sound/pcm.h>
+#include <linux/pm_runtime.h>
+#include <sound/pcm_params.h>
+#include <linux/soundwire/sdw_registers.h>
+#include <linux/slab.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+
+#include "rt721-sdca.h"
+#include "rt-sdw-common.h"
+
+static void rt721_sdca_jack_detect_handler(struct work_struct *work)
+{
+ struct rt721_sdca_priv *rt721 =
+ container_of(work, struct rt721_sdca_priv, jack_detect_work.work);
+ int btn_type = 0;
+
+ if (!rt721->hs_jack)
+ return;
+
+ if (!rt721->component->card || !rt721->component->card->instantiated)
+ return;
+
+ /* SDW_SCP_SDCA_INT_SDCA_6 is used for jack detection */
+ if (rt721->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_0) {
+ rt721->jack_type = rt_sdca_headset_detect(rt721->regmap,
+ RT721_SDCA_ENT_GE49);
+ if (rt721->jack_type < 0)
+ return;
+ }
+
+ /* SDW_SCP_SDCA_INT_SDCA_8 is used for button detection */
+ if (rt721->scp_sdca_stat2 & SDW_SCP_SDCA_INT_SDCA_8)
+ btn_type = rt_sdca_button_detect(rt721->regmap,
+ RT721_SDCA_ENT_HID01, RT721_BUF_ADDR_HID1,
+ RT721_SDCA_HID_ID);
+
+ if (rt721->jack_type == 0)
+ btn_type = 0;
+
+ dev_dbg(&rt721->slave->dev,
+ "in %s, jack_type=%d\n", __func__, rt721->jack_type);
+ dev_dbg(&rt721->slave->dev,
+ "in %s, btn_type=0x%x\n", __func__, btn_type);
+ dev_dbg(&rt721->slave->dev,
+ "in %s, scp_sdca_stat1=0x%x, scp_sdca_stat2=0x%x\n", __func__,
+ rt721->scp_sdca_stat1, rt721->scp_sdca_stat2);
+
+ snd_soc_jack_report(rt721->hs_jack, rt721->jack_type | btn_type,
+ SND_JACK_HEADSET |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3);
+
+ if (btn_type) {
+ /* button released */
+ snd_soc_jack_report(rt721->hs_jack, rt721->jack_type,
+ SND_JACK_HEADSET |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3);
+
+ mod_delayed_work(system_power_efficient_wq,
+ &rt721->jack_btn_check_work, msecs_to_jiffies(200));
+ }
+}
+
+static void rt721_sdca_btn_check_handler(struct work_struct *work)
+{
+ struct rt721_sdca_priv *rt721 =
+ container_of(work, struct rt721_sdca_priv, jack_btn_check_work.work);
+ int btn_type = 0, ret, idx;
+ unsigned int det_mode, offset, val;
+ unsigned char buf[3];
+
+ ret = regmap_read(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_GE49,
+ RT721_SDCA_CTL_DETECTED_MODE, 0), &det_mode);
+ if (ret < 0)
+ goto io_error;
+
+ /* pin attached */
+ if (det_mode) {
+ /* read UMP message offset */
+ ret = regmap_read(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_HID, RT721_SDCA_ENT_HID01,
+ RT721_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), &offset);
+ if (ret < 0)
+ goto io_error;
+
+ for (idx = 0; idx < sizeof(buf); idx++) {
+ ret = regmap_read(rt721->regmap,
+ RT721_BUF_ADDR_HID1 + offset + idx, &val);
+ if (ret < 0)
+ goto io_error;
+ buf[idx] = val & 0xff;
+ }
+ /* Report ID for HID1 */
+ if (buf[0] == 0x11)
+ btn_type = rt_sdca_btn_type(&buf[1]);
+ } else
+ rt721->jack_type = 0;
+
+ dev_dbg(&rt721->slave->dev, "%s, btn_type=0x%x\n", __func__, btn_type);
+ snd_soc_jack_report(rt721->hs_jack, rt721->jack_type | btn_type,
+ SND_JACK_HEADSET |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3);
+
+ if (btn_type) {
+ /* button released */
+ snd_soc_jack_report(rt721->hs_jack, rt721->jack_type,
+ SND_JACK_HEADSET |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3);
+
+ mod_delayed_work(system_power_efficient_wq,
+ &rt721->jack_btn_check_work, msecs_to_jiffies(200));
+ }
+
+ return;
+
+io_error:
+ pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
+}
+
+static void rt721_sdca_dmic_preset(struct rt721_sdca_priv *rt721)
+{
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL,
+ RT721_MISC_POWER_CTL31, 0x8000);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_ANA_POW_PART,
+ RT721_VREF1_HV_CTRL1, 0xe000);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL,
+ RT721_MISC_POWER_CTL31, 0x8007);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_ENT_FLOAT_CTL9, 0x2a2a);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_ENT_FLOAT_CTL10, 0x2a00);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_ENT_FLOAT_CTL6, 0x2a2a);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_ENT_FLOAT_CTL5, 0x2626);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_ENT_FLOAT_CTL8, 0x1e00);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_ENT_FLOAT_CTL7, 0x1515);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_CH_FLOAT_CTL3, 0x0304);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_CH_FLOAT_CTL4, 0x0304);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_HDA_LEGACY_CTL1, 0x0000);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_IT26,
+ RT721_SDCA_CTL_VENDOR_DEF, 0), 0x01);
+ regmap_write(rt721->mbq_regmap, 0x5910009, 0x2e01);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_RC_CALIB_CTRL,
+ RT721_RC_CALIB_CTRL0, 0x0b00);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_RC_CALIB_CTRL,
+ RT721_RC_CALIB_CTRL0, 0x0b40);
+ regmap_write(rt721->regmap, 0x2f5c, 0x25);
+}
+
+static void rt721_sdca_amp_preset(struct rt721_sdca_priv *rt721)
+{
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL,
+ RT721_MISC_POWER_CTL31, 0x8000);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_ANA_POW_PART,
+ RT721_VREF1_HV_CTRL1, 0xe000);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL,
+ RT721_MISC_POWER_CTL31, 0x8007);
+ regmap_write(rt721->mbq_regmap, 0x5810000, 0x6420);
+ regmap_write(rt721->mbq_regmap, 0x5810000, 0x6421);
+ regmap_write(rt721->mbq_regmap, 0x5810000, 0xe421);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_CH_FLOAT_CTL6, 0x5561);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_REG,
+ RT721_GPIO_PAD_CTRL5, 0x8003);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_OT23,
+ RT721_SDCA_CTL_VENDOR_DEF, 0), 0x04);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23,
+ RT721_SDCA_CTL_FU_MUTE, CH_01), 0x00);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23,
+ RT721_SDCA_CTL_FU_MUTE, CH_02), 0x00);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_FU55,
+ RT721_SDCA_CTL_FU_MUTE, CH_01), 0x00);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_FU55,
+ RT721_SDCA_CTL_FU_MUTE, CH_02), 0x00);
+}
+
+static void rt721_sdca_jack_preset(struct rt721_sdca_priv *rt721)
+{
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL,
+ RT721_MISC_POWER_CTL31, 0x8000);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_ANA_POW_PART,
+ RT721_VREF1_HV_CTRL1, 0xe000);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL,
+ RT721_MISC_POWER_CTL31, 0x8007);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_GE_REL_CTRL1, 0x8011);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_UMP_HID_CTRL3, 0xcf00);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_UMP_HID_CTRL4, 0x000f);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_UMP_HID_CTRL1, 0x1100);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_UMP_HID_CTRL5, 0x0c12);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_JD_CTRL,
+ RT721_JD_1PIN_GAT_CTRL2, 0xc002);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_RC_CALIB_CTRL,
+ RT721_RC_CALIB_CTRL0, 0x0b00);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_RC_CALIB_CTRL,
+ RT721_RC_CALIB_CTRL0, 0x0b40);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL,
+ RT721_UAJ_TOP_TCON14, 0x3333);
+ regmap_write(rt721->mbq_regmap, 0x5810035, 0x0036);
+ regmap_write(rt721->mbq_regmap, 0x5810030, 0xee00);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_CAP_PORT_CTRL,
+ RT721_HP_AMP_2CH_CAL1, 0x0140);
+ regmap_write(rt721->mbq_regmap, 0x5810000, 0x0021);
+ regmap_write(rt721->mbq_regmap, 0x5810000, 0x8021);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_CAP_PORT_CTRL,
+ RT721_HP_AMP_2CH_CAL18, 0x5522);
+ regmap_write(rt721->mbq_regmap, 0x5b10007, 0x2000);
+ regmap_write(rt721->mbq_regmap, 0x5B10017, 0x1b0f);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_CBJ_CTRL,
+ RT721_CBJ_A0_GAT_CTRL1, 0x2a02);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_CAP_PORT_CTRL,
+ RT721_HP_AMP_2CH_CAL4, 0xa105);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL,
+ RT721_UAJ_TOP_TCON14, 0x3b33);
+ regmap_write(rt721->mbq_regmap, 0x310400, 0x3023);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL,
+ RT721_UAJ_TOP_TCON14, 0x3f33);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL,
+ RT721_UAJ_TOP_TCON13, 0x6048);
+ regmap_write(rt721->mbq_regmap, 0x310401, 0x3000);
+ regmap_write(rt721->mbq_regmap, 0x310402, 0x1b00);
+ regmap_write(rt721->mbq_regmap, 0x310300, 0x000f);
+ regmap_write(rt721->mbq_regmap, 0x310301, 0x3000);
+ regmap_write(rt721->mbq_regmap, 0x310302, 0x1b00);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_VENDOR_ANA_CTL,
+ RT721_UAJ_TOP_TCON17, 0x0008);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_DAC_CTRL,
+ RT721_DAC_2CH_CTRL3, 0x55ff);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_DAC_CTRL,
+ RT721_DAC_2CH_CTRL4, 0xcc00);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_ANA_POW_PART,
+ RT721_MBIAS_LV_CTRL2, 0x6677);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_ANA_POW_PART,
+ RT721_VREF2_LV_CTRL1, 0x7600);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_ENT_FLOAT_CTL2, 0x1234);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_ENT_FLOAT_CTL3, 0x3512);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_ENT_FLOAT_CTL1, 0x4040);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_ENT_FLOAT_CTL4, 0x1201);
+ regmap_write(rt721->regmap, 0x2f58, 0x07);
+}
+
+static void rt721_sdca_jack_init(struct rt721_sdca_priv *rt721)
+{
+ mutex_lock(&rt721->calibrate_mutex);
+ if (rt721->hs_jack) {
+ sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INTMASK1,
+ SDW_SCP_SDCA_INTMASK_SDCA_0);
+ sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INTMASK2,
+ SDW_SCP_SDCA_INTMASK_SDCA_8);
+ dev_dbg(&rt721->slave->dev, "in %s enable\n", __func__);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_HDA_LEGACY_UAJ_CTL, 0x036E);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_XU03,
+ RT721_SDCA_CTL_SELECTED_MODE, 0), 0);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_XU0D,
+ RT721_SDCA_CTL_SELECTED_MODE, 0), 0);
+ rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_XU_REL_CTRL, 0x0000);
+ rt_sdca_index_update_bits(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_GE_REL_CTRL1, 0x4000, 0x4000);
+ }
+ mutex_unlock(&rt721->calibrate_mutex);
+}
+
+static int rt721_sdca_set_jack_detect(struct snd_soc_component *component,
+ struct snd_soc_jack *hs_jack, void *data)
+{
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ rt721->hs_jack = hs_jack;
+
+ ret = pm_runtime_resume_and_get(component->dev);
+ if (ret < 0) {
+ if (ret != -EACCES) {
+ dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret);
+ return ret;
+ }
+ /* pm_runtime not enabled yet */
+ dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__);
+ return 0;
+ }
+
+ rt721_sdca_jack_init(rt721);
+
+ pm_runtime_mark_last_busy(component->dev);
+ pm_runtime_put_autosuspend(component->dev);
+
+ return 0;
+}
+
+/* For SDCA control DAC/ADC Gain */
+static int rt721_sdca_set_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ unsigned int read_l, read_r, gain_l_val, gain_r_val;
+ unsigned int adc_vol_flag = 0, changed = 0;
+ unsigned int lvalue, rvalue;
+ const unsigned int interval_offset = 0xc0;
+ const unsigned int tendA = 0x200;
+ const unsigned int tendB = 0xa00;
+
+ if (strstr(ucontrol->id.name, "FU1E Capture Volume") ||
+ strstr(ucontrol->id.name, "FU0F Capture Volume"))
+ adc_vol_flag = 1;
+
+ regmap_read(rt721->mbq_regmap, mc->reg, &lvalue);
+ regmap_read(rt721->mbq_regmap, mc->rreg, &rvalue);
+
+ /* L Channel */
+ gain_l_val = ucontrol->value.integer.value[0];
+ if (gain_l_val > mc->max)
+ gain_l_val = mc->max;
+
+ if (mc->shift == 8) {
+ /* boost gain */
+ gain_l_val = gain_l_val * tendB;
+ } else if (mc->shift == 1) {
+ /* FU33 boost gain */
+ if (gain_l_val == 0)
+ gain_l_val = 0x8000;
+ else
+ gain_l_val = (gain_l_val - 1) * tendA;
+ } else {
+ /* ADC/DAC gain */
+ if (adc_vol_flag)
+ gain_l_val = 0x1e00 - ((mc->max - gain_l_val) * interval_offset);
+ else
+ gain_l_val = 0 - ((mc->max - gain_l_val) * interval_offset);
+ gain_l_val &= 0xffff;
+ }
+
+ /* R Channel */
+ gain_r_val = ucontrol->value.integer.value[1];
+ if (gain_r_val > mc->max)
+ gain_r_val = mc->max;
+
+ if (mc->shift == 8) {
+ /* boost gain */
+ gain_r_val = gain_r_val * tendB;
+ } else if (mc->shift == 1) {
+ /* FU33 boost gain */
+ if (gain_r_val == 0)
+ gain_r_val = 0x8000;
+ else
+ gain_r_val = (gain_r_val - 1) * tendA;
+ } else {
+ /* ADC/DAC gain */
+ if (adc_vol_flag)
+ gain_r_val = 0x1e00 - ((mc->max - gain_r_val) * interval_offset);
+ else
+ gain_r_val = 0 - ((mc->max - gain_r_val) * interval_offset);
+ gain_r_val &= 0xffff;
+ }
+
+ if (lvalue != gain_l_val || rvalue != gain_r_val)
+ changed = 1;
+ else
+ return 0;
+
+ /* Lch*/
+ regmap_write(rt721->mbq_regmap, mc->reg, gain_l_val);
+
+ /* Rch */
+ regmap_write(rt721->mbq_regmap, mc->rreg, gain_r_val);
+
+ regmap_read(rt721->mbq_regmap, mc->reg, &read_l);
+ regmap_read(rt721->mbq_regmap, mc->rreg, &read_r);
+ if (read_r == gain_r_val && read_l == gain_l_val)
+ return changed;
+
+ return -EIO;
+}
+
+static int rt721_sdca_set_gain_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ unsigned int read_l, read_r, ctl_l = 0, ctl_r = 0;
+ unsigned int adc_vol_flag = 0;
+ const unsigned int interval_offset = 0xc0;
+ const unsigned int tendB = 0xa00;
+
+ if (strstr(ucontrol->id.name, "FU1E Capture Volume") ||
+ strstr(ucontrol->id.name, "FU0F Capture Volume"))
+ adc_vol_flag = 1;
+
+ regmap_read(rt721->mbq_regmap, mc->reg, &read_l);
+ regmap_read(rt721->mbq_regmap, mc->rreg, &read_r);
+
+ if (mc->shift == 8) /* boost gain */
+ ctl_l = read_l / tendB;
+ else {
+ if (adc_vol_flag)
+ ctl_l = mc->max - (((0x1e00 - read_l) & 0xffff) / interval_offset);
+ else
+ ctl_l = mc->max - (((0 - read_l) & 0xffff) / interval_offset);
+ }
+
+ if (read_l != read_r) {
+ if (mc->shift == 8) /* boost gain */
+ ctl_r = read_r / tendB;
+ else { /* ADC/DAC gain */
+ if (adc_vol_flag)
+ ctl_r = mc->max - (((0x1e00 - read_r) & 0xffff) / interval_offset);
+ else
+ ctl_r = mc->max - (((0 - read_r) & 0xffff) / interval_offset);
+ }
+ } else {
+ ctl_r = ctl_l;
+ }
+
+ ucontrol->value.integer.value[0] = ctl_l;
+ ucontrol->value.integer.value[1] = ctl_r;
+
+ return 0;
+}
+
+static int rt721_sdca_set_fu1e_capture_ctl(struct rt721_sdca_priv *rt721)
+{
+ int err, i;
+ unsigned int ch_mute;
+
+ for (i = 0; i < ARRAY_SIZE(rt721->fu1e_mixer_mute); i++) {
+ ch_mute = rt721->fu1e_dapm_mute || rt721->fu1e_mixer_mute[i];
+ err = regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E,
+ RT721_SDCA_CTL_FU_MUTE, CH_01) + i, ch_mute);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int rt721_sdca_fu1e_capture_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ struct rt721_sdca_dmic_kctrl_priv *p =
+ (struct rt721_sdca_dmic_kctrl_priv *)kcontrol->private_value;
+ unsigned int i;
+
+ for (i = 0; i < p->count; i++)
+ ucontrol->value.integer.value[i] = !rt721->fu1e_mixer_mute[i];
+
+ return 0;
+}
+
+static int rt721_sdca_fu1e_capture_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ struct rt721_sdca_dmic_kctrl_priv *p =
+ (struct rt721_sdca_dmic_kctrl_priv *)kcontrol->private_value;
+ int err, changed = 0, i;
+
+ for (i = 0; i < p->count; i++) {
+ if (rt721->fu1e_mixer_mute[i] != !ucontrol->value.integer.value[i])
+ changed = 1;
+ rt721->fu1e_mixer_mute[i] = !ucontrol->value.integer.value[i];
+ }
+
+ err = rt721_sdca_set_fu1e_capture_ctl(rt721);
+ if (err < 0)
+ return err;
+
+ return changed;
+}
+
+static int rt721_sdca_set_fu0f_capture_ctl(struct rt721_sdca_priv *rt721)
+{
+ int err;
+ unsigned int ch_l, ch_r;
+
+ ch_l = (rt721->fu0f_dapm_mute || rt721->fu0f_mixer_l_mute) ? 0x01 : 0x00;
+ ch_r = (rt721->fu0f_dapm_mute || rt721->fu0f_mixer_r_mute) ? 0x01 : 0x00;
+
+ err = regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F,
+ RT721_SDCA_CTL_FU_MUTE, CH_L), ch_l);
+ if (err < 0)
+ return err;
+
+ err = regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F,
+ RT721_SDCA_CTL_FU_MUTE, CH_R), ch_r);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int rt721_sdca_fu0f_capture_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = !rt721->fu0f_mixer_l_mute;
+ ucontrol->value.integer.value[1] = !rt721->fu0f_mixer_r_mute;
+ return 0;
+}
+
+static int rt721_sdca_fu0f_capture_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ int err, changed = 0;
+
+ if (rt721->fu0f_mixer_l_mute != !ucontrol->value.integer.value[0] ||
+ rt721->fu0f_mixer_r_mute != !ucontrol->value.integer.value[1])
+ changed = 1;
+
+ rt721->fu0f_mixer_l_mute = !ucontrol->value.integer.value[0];
+ rt721->fu0f_mixer_r_mute = !ucontrol->value.integer.value[1];
+ err = rt721_sdca_set_fu0f_capture_ctl(rt721);
+ if (err < 0)
+ return err;
+
+ return changed;
+}
+
+static int rt721_sdca_fu_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct rt721_sdca_dmic_kctrl_priv *p =
+ (struct rt721_sdca_dmic_kctrl_priv *)kcontrol->private_value;
+
+ if (p->max == 1)
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ else
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = p->count;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = p->max;
+ return 0;
+}
+
+static int rt721_sdca_dmic_set_gain_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ struct rt721_sdca_dmic_kctrl_priv *p =
+ (struct rt721_sdca_dmic_kctrl_priv *)kcontrol->private_value;
+ unsigned int boost_step = 0x0a00;
+ unsigned int vol_max = 0x1e00;
+ unsigned int regvalue, ctl, i;
+ unsigned int adc_vol_flag = 0;
+ const unsigned int interval_offset = 0xc0;
+
+ if (strstr(ucontrol->id.name, "FU1E Capture Volume"))
+ adc_vol_flag = 1;
+
+ /* check all channels */
+ for (i = 0; i < p->count; i++) {
+ regmap_read(rt721->mbq_regmap, p->reg_base + i, &regvalue);
+
+ if (!adc_vol_flag) /* boost gain */
+ ctl = regvalue / boost_step;
+ else /* ADC gain */
+ ctl = p->max - (((vol_max - regvalue) & 0xffff) / interval_offset);
+
+ ucontrol->value.integer.value[i] = ctl;
+ }
+
+ return 0;
+}
+
+static int rt721_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct rt721_sdca_dmic_kctrl_priv *p =
+ (struct rt721_sdca_dmic_kctrl_priv *)kcontrol->private_value;
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ unsigned int boost_step = 0x0a00;
+ unsigned int vol_max = 0x1e00;
+ unsigned int gain_val[4];
+ unsigned int i, adc_vol_flag = 0, changed = 0;
+ unsigned int regvalue[4];
+ const unsigned int interval_offset = 0xc0;
+ int err;
+
+ if (strstr(ucontrol->id.name, "FU1E Capture Volume"))
+ adc_vol_flag = 1;
+
+ /* check all channels */
+ for (i = 0; i < p->count; i++) {
+ regmap_read(rt721->mbq_regmap, p->reg_base + i, &regvalue[i]);
+
+ gain_val[i] = ucontrol->value.integer.value[i];
+ if (gain_val[i] > p->max)
+ gain_val[i] = p->max;
+
+ if (!adc_vol_flag) /* boost gain */
+ gain_val[i] = gain_val[i] * boost_step;
+ else { /* ADC gain */
+ gain_val[i] = vol_max - ((p->max - gain_val[i]) * interval_offset);
+ gain_val[i] &= 0xffff;
+ }
+
+ if (regvalue[i] != gain_val[i])
+ changed = 1;
+ }
+
+ if (!changed)
+ return 0;
+
+ for (i = 0; i < p->count; i++) {
+ err = regmap_write(rt721->mbq_regmap, p->reg_base + i, gain_val[i]);
+ if (err < 0)
+ dev_err(&rt721->slave->dev, "%#08x can't be set\n", p->reg_base + i);
+ }
+
+ return changed;
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0);
+static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, -1725, 75, 0);
+static const DECLARE_TLV_DB_SCALE(boost_vol_tlv, 0, 1000, 0);
+static const DECLARE_TLV_DB_SCALE(mic2_boost_vol_tlv, -200, 200, 0);
+
+static const struct snd_kcontrol_new rt721_sdca_controls[] = {
+ /* Headphone playback settings */
+ SOC_DOUBLE_R_EXT_TLV("FU05 Playback Volume",
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05,
+ RT721_SDCA_CTL_FU_VOLUME, CH_L),
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05,
+ RT721_SDCA_CTL_FU_VOLUME, CH_R), 0, 0x57, 0,
+ rt721_sdca_set_gain_get, rt721_sdca_set_gain_put, out_vol_tlv),
+ /* Headset mic capture settings */
+ SOC_DOUBLE_EXT("FU0F Capture Switch", SND_SOC_NOPM, 0, 1, 1, 0,
+ rt721_sdca_fu0f_capture_get, rt721_sdca_fu0f_capture_put),
+ SOC_DOUBLE_R_EXT_TLV("FU0F Capture Volume",
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F,
+ RT721_SDCA_CTL_FU_VOLUME, CH_L),
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F,
+ RT721_SDCA_CTL_FU_VOLUME, CH_R), 0, 0x3f, 0,
+ rt721_sdca_set_gain_get, rt721_sdca_set_gain_put, mic_vol_tlv),
+ SOC_DOUBLE_R_EXT_TLV("FU33 Boost Volume",
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44,
+ RT721_SDCA_CTL_FU_CH_GAIN, CH_L),
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44,
+ RT721_SDCA_CTL_FU_CH_GAIN, CH_R), 1, 0x15, 0,
+ rt721_sdca_set_gain_get, rt721_sdca_set_gain_put, mic2_boost_vol_tlv),
+ /* AMP playback settings */
+ SOC_DOUBLE_R_EXT_TLV("FU06 Playback Volume",
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06,
+ RT721_SDCA_CTL_FU_VOLUME, CH_L),
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06,
+ RT721_SDCA_CTL_FU_VOLUME, CH_R), 0, 0x57, 0,
+ rt721_sdca_set_gain_get, rt721_sdca_set_gain_put, out_vol_tlv),
+ /* DMIC capture settings */
+ RT_SDCA_FU_CTRL("FU1E Capture Switch",
+ SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E,
+ RT721_SDCA_CTL_FU_MUTE, CH_01), 1, 1, 4, rt721_sdca_fu_info,
+ rt721_sdca_fu1e_capture_get, rt721_sdca_fu1e_capture_put),
+ RT_SDCA_EXT_TLV("FU1E Capture Volume",
+ SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E,
+ RT721_SDCA_CTL_FU_VOLUME, CH_01),
+ rt721_sdca_dmic_set_gain_get, rt721_sdca_dmic_set_gain_put,
+ 4, 0x3f, mic_vol_tlv, rt721_sdca_fu_info),
+ RT_SDCA_EXT_TLV("FU15 Boost Volume",
+ SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_FU15,
+ RT721_SDCA_CTL_FU_CH_GAIN, CH_01),
+ rt721_sdca_dmic_set_gain_get, rt721_sdca_dmic_set_gain_put,
+ 4, 3, boost_vol_tlv, rt721_sdca_fu_info),
+};
+
+static int rt721_sdca_adc_mux_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_kcontrol_component(kcontrol);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ unsigned int val = 0, mask_sft, mask;
+
+ if (strstr(ucontrol->id.name, "ADC 09 Mux")) {
+ mask_sft = 12;
+ mask = 0x7;
+ } else if (strstr(ucontrol->id.name, "ADC 08 R Mux")) {
+ mask_sft = 10;
+ mask = 0x3;
+ } else if (strstr(ucontrol->id.name, "ADC 08 L Mux")) {
+ mask_sft = 8;
+ mask = 0x3;
+ } else if (strstr(ucontrol->id.name, "ADC 10 R Mux")) {
+ mask_sft = 6;
+ mask = 0x3;
+ } else if (strstr(ucontrol->id.name, "ADC 10 L Mux")) {
+ mask_sft = 4;
+ mask = 0x3;
+ } else if (strstr(ucontrol->id.name, "ADC 07 R Mux")) {
+ mask_sft = 2;
+ mask = 0x3;
+ } else if (strstr(ucontrol->id.name, "ADC 07 L Mux")) {
+ mask_sft = 0;
+ mask = 0x3;
+ } else
+ return -EINVAL;
+
+ rt_sdca_index_read(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_HDA_LEGACY_MUX_CTL0, &val);
+
+ ucontrol->value.enumerated.item[0] = (val >> mask_sft) & mask;
+
+ return 0;
+}
+
+static int rt721_sdca_adc_mux_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_kcontrol_component(kcontrol);
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int *item = ucontrol->value.enumerated.item;
+ unsigned int val, val2 = 0, change, mask_sft, mask;
+ unsigned int check;
+
+ if (item[0] >= e->items)
+ return -EINVAL;
+
+ if (strstr(ucontrol->id.name, "ADC 09 Mux")) {
+ mask_sft = 12;
+ mask = 0x7;
+ } else if (strstr(ucontrol->id.name, "ADC 08 R Mux")) {
+ mask_sft = 10;
+ mask = 0x3;
+ } else if (strstr(ucontrol->id.name, "ADC 08 L Mux")) {
+ mask_sft = 8;
+ mask = 0x3;
+ } else if (strstr(ucontrol->id.name, "ADC 10 R Mux")) {
+ mask_sft = 6;
+ mask = 0x3;
+ } else if (strstr(ucontrol->id.name, "ADC 10 L Mux")) {
+ mask_sft = 4;
+ mask = 0x3;
+ } else if (strstr(ucontrol->id.name, "ADC 07 R Mux")) {
+ mask_sft = 2;
+ mask = 0x3;
+ } else if (strstr(ucontrol->id.name, "ADC 07 L Mux")) {
+ mask_sft = 0;
+ mask = 0x3;
+ } else
+ return -EINVAL;
+
+ val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
+ rt_sdca_index_read(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_HDA_LEGACY_MUX_CTL0, &val2);
+
+ if (strstr(ucontrol->id.name, "ADC 09 Mux"))
+ val2 = (val2 >> mask_sft) & 0x7;
+ else
+ val2 = (val2 >> mask_sft) & 0x3;
+
+ if (val == val2)
+ change = 0;
+ else
+ change = 1;
+
+ if (change) {
+ rt_sdca_index_read(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_HDA_LEGACY_MUX_CTL0, &check);
+ rt_sdca_index_update_bits(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT,
+ RT721_HDA_LEGACY_MUX_CTL0, mask << mask_sft,
+ val << mask_sft);
+ }
+
+ snd_soc_dapm_mux_update_power(dapm, kcontrol,
+ item[0], e, NULL);
+
+ return change;
+}
+
+static const char * const adc09_mux_text[] = {
+ "MIC2",
+ "LINE1",
+ "LINE2",
+};
+static const char * const adc07_10_mux_text[] = {
+ "DMIC1 RE",
+ "DMIC1 FE",
+ "DMIC2 RE",
+ "DMIC2 FE",
+};
+
+static SOC_ENUM_SINGLE_DECL(
+ rt721_adc09_enum, SND_SOC_NOPM, 0, adc09_mux_text);
+static SOC_ENUM_SINGLE_DECL(
+ rt721_dmic_enum, SND_SOC_NOPM, 0, adc07_10_mux_text);
+
+static const struct snd_kcontrol_new rt721_sdca_adc09_mux =
+ SOC_DAPM_ENUM_EXT("ADC 09 Mux", rt721_adc09_enum,
+ rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put);
+static const struct snd_kcontrol_new rt721_sdca_adc08_r_mux =
+ SOC_DAPM_ENUM_EXT("ADC 08 R Mux", rt721_dmic_enum,
+ rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put);
+static const struct snd_kcontrol_new rt721_sdca_adc08_l_mux =
+ SOC_DAPM_ENUM_EXT("ADC 08 L Mux", rt721_dmic_enum,
+ rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put);
+static const struct snd_kcontrol_new rt721_sdca_adc10_r_mux =
+ SOC_DAPM_ENUM_EXT("ADC 10 R Mux", rt721_dmic_enum,
+ rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put);
+static const struct snd_kcontrol_new rt721_sdca_adc10_l_mux =
+ SOC_DAPM_ENUM_EXT("ADC 10 L Mux", rt721_dmic_enum,
+ rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put);
+static const struct snd_kcontrol_new rt721_sdca_adc07_r_mux =
+ SOC_DAPM_ENUM_EXT("ADC 07 R Mux", rt721_dmic_enum,
+ rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put);
+static const struct snd_kcontrol_new rt721_sdca_adc07_l_mux =
+ SOC_DAPM_ENUM_EXT("ADC 07 L Mux", rt721_dmic_enum,
+ rt721_sdca_adc_mux_get, rt721_sdca_adc_mux_put);
+
+
+static int rt721_sdca_fu42_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ unsigned char unmute = 0x0, mute = 0x1;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ msleep(100);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05,
+ RT721_SDCA_CTL_FU_MUTE, CH_L), unmute);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05,
+ RT721_SDCA_CTL_FU_MUTE, CH_R), unmute);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05,
+ RT721_SDCA_CTL_FU_MUTE, CH_L), mute);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05,
+ RT721_SDCA_CTL_FU_MUTE, CH_R), mute);
+ break;
+ }
+ return 0;
+}
+
+static int rt721_sdca_fu21_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ unsigned char unmute = 0x0, mute = 0x1;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06,
+ RT721_SDCA_CTL_FU_MUTE, CH_L), unmute);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06,
+ RT721_SDCA_CTL_FU_MUTE, CH_R), unmute);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06,
+ RT721_SDCA_CTL_FU_MUTE, CH_L), mute);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06,
+ RT721_SDCA_CTL_FU_MUTE, CH_R), mute);
+ break;
+ }
+ return 0;
+}
+
+static int rt721_sdca_fu23_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ unsigned char unmute = 0x0, mute = 0x1;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23,
+ RT721_SDCA_CTL_FU_MUTE, CH_L), unmute);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23,
+ RT721_SDCA_CTL_FU_MUTE, CH_R), unmute);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23,
+ RT721_SDCA_CTL_FU_MUTE, CH_L), mute);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE23,
+ RT721_SDCA_CTL_FU_MUTE, CH_R), mute);
+ break;
+ }
+ return 0;
+}
+
+static int rt721_sdca_fu113_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ rt721->fu1e_dapm_mute = false;
+ rt721_sdca_set_fu1e_capture_ctl(rt721);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ rt721->fu1e_dapm_mute = true;
+ rt721_sdca_set_fu1e_capture_ctl(rt721);
+ break;
+ }
+ return 0;
+}
+
+static int rt721_sdca_fu36_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ rt721->fu0f_dapm_mute = false;
+ rt721_sdca_set_fu0f_capture_ctl(rt721);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ rt721->fu0f_dapm_mute = true;
+ rt721_sdca_set_fu0f_capture_ctl(rt721);
+ break;
+ }
+ return 0;
+}
+
+static int rt721_sdca_pde47_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ unsigned char ps0 = 0x0, ps3 = 0x3;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PDE40,
+ RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps0);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PDE40,
+ RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps3);
+ break;
+ }
+ return 0;
+}
+
+static int rt721_sdca_pde41_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ unsigned char ps0 = 0x0, ps3 = 0x3;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE41,
+ RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps0);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_PDE41,
+ RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps3);
+ break;
+ }
+ return 0;
+}
+
+static int rt721_sdca_pde11_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ unsigned char ps0 = 0x0, ps3 = 0x3;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_PDE2A,
+ RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps0);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_PDE2A,
+ RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps3);
+ break;
+ }
+ return 0;
+}
+
+static int rt721_sdca_pde34_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ unsigned char ps0 = 0x0, ps3 = 0x3;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PDE12,
+ RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps0);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PDE12,
+ RT721_SDCA_CTL_REQ_POWER_STATE, 0), ps3);
+ break;
+ }
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget rt721_sdca_dapm_widgets[] = {
+ SND_SOC_DAPM_OUTPUT("HP"),
+ SND_SOC_DAPM_OUTPUT("SPK"),
+ SND_SOC_DAPM_INPUT("MIC2"),
+ SND_SOC_DAPM_INPUT("LINE1"),
+ SND_SOC_DAPM_INPUT("LINE2"),
+ SND_SOC_DAPM_INPUT("DMIC1_2"),
+ SND_SOC_DAPM_INPUT("DMIC3_4"),
+
+ SND_SOC_DAPM_SUPPLY("PDE 41", SND_SOC_NOPM, 0, 0,
+ rt721_sdca_pde41_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_SUPPLY("PDE 47", SND_SOC_NOPM, 0, 0,
+ rt721_sdca_pde47_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_SUPPLY("PDE 11", SND_SOC_NOPM, 0, 0,
+ rt721_sdca_pde11_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_SUPPLY("PDE 34", SND_SOC_NOPM, 0, 0,
+ rt721_sdca_pde34_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+ SND_SOC_DAPM_DAC_E("FU 21", NULL, SND_SOC_NOPM, 0, 0,
+ rt721_sdca_fu21_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_DAC_E("FU 23", NULL, SND_SOC_NOPM, 0, 0,
+ rt721_sdca_fu23_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_DAC_E("FU 42", NULL, SND_SOC_NOPM, 0, 0,
+ rt721_sdca_fu42_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_ADC_E("FU 36", NULL, SND_SOC_NOPM, 0, 0,
+ rt721_sdca_fu36_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_ADC_E("FU 113", NULL, SND_SOC_NOPM, 0, 0,
+ rt721_sdca_fu113_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_MUX("ADC 09 Mux", SND_SOC_NOPM, 0, 0,
+ &rt721_sdca_adc09_mux),
+ SND_SOC_DAPM_MUX("ADC 08 R Mux", SND_SOC_NOPM, 0, 0,
+ &rt721_sdca_adc08_r_mux),
+ SND_SOC_DAPM_MUX("ADC 08 L Mux", SND_SOC_NOPM, 0, 0,
+ &rt721_sdca_adc08_l_mux),
+ SND_SOC_DAPM_MUX("ADC 10 R Mux", SND_SOC_NOPM, 0, 0,
+ &rt721_sdca_adc10_r_mux),
+ SND_SOC_DAPM_MUX("ADC 10 L Mux", SND_SOC_NOPM, 0, 0,
+ &rt721_sdca_adc10_l_mux),
+ SND_SOC_DAPM_MUX("ADC 07 R Mux", SND_SOC_NOPM, 0, 0,
+ &rt721_sdca_adc07_r_mux),
+ SND_SOC_DAPM_MUX("ADC 07 L Mux", SND_SOC_NOPM, 0, 0,
+ &rt721_sdca_adc07_l_mux),
+
+ SND_SOC_DAPM_AIF_IN("DP1RX", "DP1 Headphone Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Headset Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("DP3RX", "DP3 Speaker Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("DP6TX", "DP6 DMic Capture", 0, SND_SOC_NOPM, 0, 0),
+};
+
+static const struct snd_soc_dapm_route rt721_sdca_audio_map[] = {
+ {"FU 42", NULL, "DP1RX"},
+ {"FU 21", NULL, "DP3RX"},
+ {"FU 23", NULL, "DP3RX"},
+
+ {"ADC 09 Mux", "MIC2", "MIC2"},
+ {"ADC 09 Mux", "LINE1", "LINE1"},
+ {"ADC 09 Mux", "LINE2", "LINE2"},
+ {"ADC 07 R Mux", "DMIC1 RE", "DMIC1_2"},
+ {"ADC 07 R Mux", "DMIC1 FE", "DMIC1_2"},
+ {"ADC 07 R Mux", "DMIC2 RE", "DMIC3_4"},
+ {"ADC 07 R Mux", "DMIC2 FE", "DMIC3_4"},
+ {"ADC 07 L Mux", "DMIC1 RE", "DMIC1_2"},
+ {"ADC 07 L Mux", "DMIC1 FE", "DMIC1_2"},
+ {"ADC 07 L Mux", "DMIC2 RE", "DMIC3_4"},
+ {"ADC 07 L Mux", "DMIC2 FE", "DMIC3_4"},
+ {"ADC 08 R Mux", "DMIC1 RE", "DMIC1_2"},
+ {"ADC 08 R Mux", "DMIC1 FE", "DMIC1_2"},
+ {"ADC 08 R Mux", "DMIC2 RE", "DMIC3_4"},
+ {"ADC 08 R Mux", "DMIC2 FE", "DMIC3_4"},
+ {"ADC 08 L Mux", "DMIC1 RE", "DMIC1_2"},
+ {"ADC 08 L Mux", "DMIC1 FE", "DMIC1_2"},
+ {"ADC 08 L Mux", "DMIC2 RE", "DMIC3_4"},
+ {"ADC 08 L Mux", "DMIC2 FE", "DMIC3_4"},
+ {"ADC 10 R Mux", "DMIC1 RE", "DMIC1_2"},
+ {"ADC 10 R Mux", "DMIC1 FE", "DMIC1_2"},
+ {"ADC 10 R Mux", "DMIC2 RE", "DMIC3_4"},
+ {"ADC 10 R Mux", "DMIC2 FE", "DMIC3_4"},
+ {"ADC 10 L Mux", "DMIC1 RE", "DMIC1_2"},
+ {"ADC 10 L Mux", "DMIC1 FE", "DMIC1_2"},
+ {"ADC 10 L Mux", "DMIC2 RE", "DMIC3_4"},
+ {"ADC 10 L Mux", "DMIC2 FE", "DMIC3_4"},
+ {"FU 36", NULL, "PDE 34"},
+ {"FU 36", NULL, "ADC 09 Mux"},
+ {"FU 113", NULL, "PDE 11"},
+ {"FU 113", NULL, "ADC 07 R Mux"},
+ {"FU 113", NULL, "ADC 07 L Mux"},
+ {"FU 113", NULL, "ADC 10 R Mux"},
+ {"FU 113", NULL, "ADC 10 L Mux"},
+ {"DP2TX", NULL, "FU 36"},
+ {"DP6TX", NULL, "FU 113"},
+
+ {"HP", NULL, "PDE 47"},
+ {"HP", NULL, "FU 42"},
+ {"SPK", NULL, "PDE 41"},
+ {"SPK", NULL, "FU 21"},
+ {"SPK", NULL, "FU 23"},
+};
+
+static int rt721_sdca_parse_dt(struct rt721_sdca_priv *rt721, struct device *dev)
+{
+ device_property_read_u32(dev, "realtek,jd-src", &rt721->jd_src);
+
+ return 0;
+}
+
+static int rt721_sdca_probe(struct snd_soc_component *component)
+{
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ rt721_sdca_parse_dt(rt721, &rt721->slave->dev);
+ rt721->component = component;
+
+ ret = pm_runtime_resume(component->dev);
+ if (ret < 0 && ret != -EACCES)
+ return ret;
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver soc_sdca_dev_rt721 = {
+ .probe = rt721_sdca_probe,
+ .controls = rt721_sdca_controls,
+ .num_controls = ARRAY_SIZE(rt721_sdca_controls),
+ .dapm_widgets = rt721_sdca_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(rt721_sdca_dapm_widgets),
+ .dapm_routes = rt721_sdca_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(rt721_sdca_audio_map),
+ .set_jack = rt721_sdca_set_jack_detect,
+ .endianness = 1,
+};
+
+static int rt721_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
+ int direction)
+{
+ snd_soc_dai_dma_data_set(dai, direction, sdw_stream);
+
+ return 0;
+}
+
+static void rt721_sdca_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ snd_soc_dai_set_dma_data(dai, substream, NULL);
+}
+
+static int rt721_sdca_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 rt721_sdca_priv *rt721 = 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_runtime *sdw_stream;
+ int retval, port, num_channels;
+ unsigned int sampling_rate;
+
+ dev_dbg(dai->dev, "%s %s", __func__, dai->name);
+ sdw_stream = snd_soc_dai_get_dma_data(dai, substream);
+
+ if (!sdw_stream)
+ return -EINVAL;
+
+ if (!rt721->slave)
+ return -EINVAL;
+
+ /*
+ * RT721_AIF1 with port = 1 for headphone playback
+ * RT721_AIF1 with port = 2 for headset-mic capture
+ * RT721_AIF2 with port = 3 for speaker playback
+ * RT721_AIF3 with port = 6 for digital-mic capture
+ */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ direction = SDW_DATA_DIR_RX;
+ if (dai->id == RT721_AIF1)
+ port = 1;
+ else if (dai->id == RT721_AIF2)
+ port = 3;
+ else
+ return -EINVAL;
+ } else {
+ direction = SDW_DATA_DIR_TX;
+ if (dai->id == RT721_AIF1)
+ port = 2;
+ else if (dai->id == RT721_AIF3)
+ port = 6;
+ else
+ return -EINVAL;
+ }
+ 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 = GENMASK(num_channels - 1, 0);
+ port_config.num = port;
+
+ retval = sdw_stream_add_slave(rt721->slave, &stream_config,
+ &port_config, 1, sdw_stream);
+ if (retval) {
+ dev_err(dai->dev, "Unable to configure port\n");
+ return retval;
+ }
+
+ if (params_channels(params) > 16) {
+ dev_err(component->dev, "Unsupported channels %d\n",
+ params_channels(params));
+ return -EINVAL;
+ }
+
+ /* sampling rate configuration */
+ switch (params_rate(params)) {
+ case 8000:
+ sampling_rate = RT721_SDCA_RATE_8000HZ;
+ break;
+ case 16000:
+ sampling_rate = RT721_SDCA_RATE_16000HZ;
+ break;
+ case 24000:
+ sampling_rate = RT721_SDCA_RATE_24000HZ;
+ break;
+ case 32000:
+ sampling_rate = RT721_SDCA_RATE_32000HZ;
+ break;
+ case 44100:
+ sampling_rate = RT721_SDCA_RATE_44100HZ;
+ break;
+ case 48000:
+ sampling_rate = RT721_SDCA_RATE_48000HZ;
+ break;
+ case 96000:
+ sampling_rate = RT721_SDCA_RATE_96000HZ;
+ break;
+ case 192000:
+ sampling_rate = RT721_SDCA_RATE_192000HZ;
+ break;
+ case 384000:
+ sampling_rate = RT721_SDCA_RATE_384000HZ;
+ break;
+ case 768000:
+ sampling_rate = RT721_SDCA_RATE_768000HZ;
+ break;
+ default:
+ dev_err(component->dev, "Rate %d is not supported\n",
+ params_rate(params));
+ return -EINVAL;
+ }
+
+ /* set sampling frequency */
+ if (dai->id == RT721_AIF1) {
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_CS01,
+ RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), sampling_rate);
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_CS11,
+ RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), sampling_rate);
+ }
+
+ if (dai->id == RT721_AIF2)
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_CS31,
+ RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), sampling_rate);
+
+ if (dai->id == RT721_AIF3)
+ regmap_write(rt721->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_CS1F,
+ RT721_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), sampling_rate);
+
+ return 0;
+}
+
+static int rt721_sdca_pcm_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct rt721_sdca_priv *rt721 = snd_soc_component_get_drvdata(component);
+ struct sdw_stream_runtime *sdw_stream =
+ snd_soc_dai_get_dma_data(dai, substream);
+
+ if (!rt721->slave)
+ return -EINVAL;
+
+ sdw_stream_remove_slave(rt721->slave, sdw_stream);
+ return 0;
+}
+
+#define RT721_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
+ SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+#define RT721_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+static const struct snd_soc_dai_ops rt721_sdca_ops = {
+ .hw_params = rt721_sdca_pcm_hw_params,
+ .hw_free = rt721_sdca_pcm_hw_free,
+ .set_stream = rt721_sdca_set_sdw_stream,
+ .shutdown = rt721_sdca_shutdown,
+};
+
+static struct snd_soc_dai_driver rt721_sdca_dai[] = {
+ {
+ .name = "rt721-sdca-aif1",
+ .id = RT721_AIF1,
+ .playback = {
+ .stream_name = "DP1 Headphone Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT721_STEREO_RATES,
+ .formats = RT721_FORMATS,
+ },
+ .capture = {
+ .stream_name = "DP2 Headset Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT721_STEREO_RATES,
+ .formats = RT721_FORMATS,
+ },
+ .ops = &rt721_sdca_ops,
+ },
+ {
+ .name = "rt721-sdca-aif2",
+ .id = RT721_AIF2,
+ .playback = {
+ .stream_name = "DP3 Speaker Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT721_STEREO_RATES,
+ .formats = RT721_FORMATS,
+ },
+ .ops = &rt721_sdca_ops,
+ },
+ {
+ .name = "rt721-sdca-aif3",
+ .id = RT721_AIF3,
+ .capture = {
+ .stream_name = "DP6 DMic Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = RT721_STEREO_RATES,
+ .formats = RT721_FORMATS,
+ },
+ .ops = &rt721_sdca_ops,
+ }
+};
+
+int rt721_sdca_init(struct device *dev, struct regmap *regmap,
+ struct regmap *mbq_regmap, struct sdw_slave *slave)
+{
+ struct rt721_sdca_priv *rt721;
+
+ rt721 = devm_kzalloc(dev, sizeof(*rt721), GFP_KERNEL);
+ if (!rt721)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, rt721);
+ rt721->slave = slave;
+ rt721->regmap = regmap;
+ rt721->mbq_regmap = mbq_regmap;
+
+ regcache_cache_only(rt721->regmap, true);
+ regcache_cache_only(rt721->mbq_regmap, true);
+
+ mutex_init(&rt721->calibrate_mutex);
+ mutex_init(&rt721->disable_irq_lock);
+
+ INIT_DELAYED_WORK(&rt721->jack_detect_work, rt721_sdca_jack_detect_handler);
+ INIT_DELAYED_WORK(&rt721->jack_btn_check_work, rt721_sdca_btn_check_handler);
+
+ /*
+ * Mark hw_init to false
+ * HW init will be performed when device reports present
+ */
+ rt721->hw_init = false;
+ rt721->first_hw_init = false;
+ rt721->fu1e_dapm_mute = true;
+ rt721->fu0f_dapm_mute = true;
+ rt721->fu0f_mixer_l_mute = rt721->fu0f_mixer_r_mute = true;
+ rt721->fu1e_mixer_mute[0] = rt721->fu1e_mixer_mute[1] =
+ rt721->fu1e_mixer_mute[2] = rt721->fu1e_mixer_mute[3] = true;
+
+ return devm_snd_soc_register_component(dev,
+ &soc_sdca_dev_rt721, rt721_sdca_dai, ARRAY_SIZE(rt721_sdca_dai));
+}
+
+int rt721_sdca_io_init(struct device *dev, struct sdw_slave *slave)
+{
+ struct rt721_sdca_priv *rt721 = dev_get_drvdata(dev);
+
+ rt721->disable_irq = false;
+
+ if (rt721->hw_init)
+ return 0;
+
+ regcache_cache_only(rt721->regmap, false);
+ regcache_cache_only(rt721->mbq_regmap, false);
+ if (rt721->first_hw_init) {
+ regcache_cache_bypass(rt721->regmap, true);
+ regcache_cache_bypass(rt721->mbq_regmap, true);
+ } else {
+ /*
+ * PM runtime is only enabled when a Slave reports as Attached
+ */
+
+ /* set autosuspend parameters */
+ pm_runtime_set_autosuspend_delay(&slave->dev, 3000);
+ pm_runtime_use_autosuspend(&slave->dev);
+
+ /* update count of parent 'active' children */
+ pm_runtime_set_active(&slave->dev);
+
+ /* make sure the device does not suspend immediately */
+ pm_runtime_mark_last_busy(&slave->dev);
+
+ pm_runtime_enable(&slave->dev);
+ }
+
+ pm_runtime_get_noresume(&slave->dev);
+ rt721_sdca_dmic_preset(rt721);
+ rt721_sdca_amp_preset(rt721);
+ rt721_sdca_jack_preset(rt721);
+ if (rt721->first_hw_init) {
+ regcache_cache_bypass(rt721->regmap, false);
+ regcache_mark_dirty(rt721->regmap);
+ regcache_cache_bypass(rt721->mbq_regmap, false);
+ regcache_mark_dirty(rt721->mbq_regmap);
+ } else
+ rt721->first_hw_init = true;
+
+ /* Mark Slave initialization complete */
+ rt721->hw_init = true;
+
+ pm_runtime_mark_last_busy(&slave->dev);
+ pm_runtime_put_autosuspend(&slave->dev);
+
+ dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
+ return 0;
+}
+
+MODULE_DESCRIPTION("ASoC RT721 SDCA SDW driver");
+MODULE_AUTHOR("Jack Yu <jack.yu@realtek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt721-sdca.h b/sound/soc/codecs/rt721-sdca.h
new file mode 100644
index 000000000000..0a82c107b19a
--- /dev/null
+++ b/sound/soc/codecs/rt721-sdca.h
@@ -0,0 +1,269 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * rt721-sdca.h -- RT721 SDCA ALSA SoC audio driver header
+ *
+ * Copyright(c) 2024 Realtek Semiconductor Corp.
+ */
+
+#ifndef __RT721_H__
+#define __RT721_H__
+
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_type.h>
+#include <sound/soc.h>
+#include <linux/workqueue.h>
+
+struct rt721_sdca_priv {
+ struct regmap *regmap;
+ struct regmap *mbq_regmap;
+ struct snd_soc_component *component;
+ struct sdw_slave *slave;
+ struct sdw_bus_params params;
+ bool hw_init;
+ bool first_hw_init;
+ struct mutex calibrate_mutex;
+ struct mutex disable_irq_lock;
+ bool disable_irq;
+ /* For Headset jack & Headphone */
+ unsigned int scp_sdca_stat1;
+ unsigned int scp_sdca_stat2;
+ struct snd_soc_jack *hs_jack;
+ struct delayed_work jack_detect_work;
+ struct delayed_work jack_btn_check_work;
+ int jack_type;
+ int jd_src;
+ bool fu0f_dapm_mute;
+ bool fu0f_mixer_l_mute;
+ bool fu0f_mixer_r_mute;
+ /* For DMIC */
+ bool fu1e_dapm_mute;
+ bool fu1e_mixer_mute[4];
+};
+
+struct rt721_sdca_dmic_kctrl_priv {
+ unsigned int reg_base;
+ unsigned int count;
+ unsigned int max;
+ unsigned int invert;
+};
+
+/* NID */
+#define RT721_ANA_POW_PART 0x01
+#define RT721_DAC_CTRL 0x04
+#define RT721_JD_CTRL 0x09
+#define RT721_CBJ_CTRL 0x0a
+#define RT721_CAP_PORT_CTRL 0x0c
+#define RT721_CLASD_AMP_CTRL 0x0d
+#define RT721_VENDOR_REG 0x20
+#define RT721_RC_CALIB_CTRL 0x40
+#define RT721_VENDOR_EQ_L 0x53
+#define RT721_VENDOR_EQ_R 0x54
+#define RT721_VENDOR_HP_CALI 0x56
+#define RT721_VENDOR_CHARGE_PUMP 0x57
+#define RT721_VENDOR_CLASD_CALI 0x58
+#define RT721_VENDOR_IMS_DRE 0x5b
+#define RT721_VENDOR_SPK_EFUSE 0x5c
+#define RT721_VENDOR_LEVEL_CTRL 0x5d
+#define RT721_VENDOR_ANA_CTL 0x5f
+#define RT721_HDA_SDCA_FLOAT 0x61
+
+/* Index (NID:01h) */
+#define RT721_MBIAS_LV_CTRL2 0x07
+#define RT721_VREF1_HV_CTRL1 0x0a
+#define RT721_VREF2_LV_CTRL1 0x0b
+
+/* Index (NID:04h) */
+#define RT721_DAC_2CH_CTRL3 0x02
+#define RT721_DAC_2CH_CTRL4 0x03
+
+/* Index (NID:09h) */
+#define RT721_JD_1PIN_GAT_CTRL2 0x07
+
+/* Index (NID:0ah) */
+#define RT721_CBJ_A0_GAT_CTRL1 0x04
+#define RT721_CBJ_A0_GAT_CTRL2 0x05
+
+/* Index (NID:0Ch) */
+#define RT721_HP_AMP_2CH_CAL1 0x05
+#define RT721_HP_AMP_2CH_CAL4 0x08
+#define RT721_HP_AMP_2CH_CAL18 0x1b
+
+/* Index (NID:0dh) */
+#define RT721_CLASD_AMP_2CH_CAL 0x14
+
+/* Index (NID:20h) */
+#define RT721_JD_PRODUCT_NUM 0x00
+#define RT721_ANALOG_BIAS_CTL3 0x04
+#define RT721_JD_CTRL1 0x09
+#define RT721_LDO2_3_CTL1 0x0e
+#define RT721_GPIO_PAD_CTRL5 0x13
+#define RT721_LDO1_CTL 0x1a
+#define RT721_HP_JD_CTRL 0x24
+#define RT721_VD_HIDDEN_CTRL 0x26
+#define RT721_CLSD_CTRL6 0x3c
+#define RT721_COMBO_JACK_AUTO_CTL1 0x45
+#define RT721_COMBO_JACK_AUTO_CTL2 0x46
+#define RT721_COMBO_JACK_AUTO_CTL3 0x47
+#define RT721_DIGITAL_MISC_CTRL4 0x4a
+#define RT721_VREFO_GAT 0x63
+#define RT721_FSM_CTL 0x67
+#define RT721_SDCA_INTR_REC 0x82
+#define RT721_SW_CONFIG1 0x8a
+#define RT721_SW_CONFIG2 0x8b
+
+/* Index (NID:40h) */
+#define RT721_RC_CALIB_CTRL0 0x00
+
+/* Index (NID:58h) */
+#define RT721_DAC_DC_CALI_CTL1 0x01
+#define RT721_DAC_DC_CALI_CTL2 0x02
+#define RT721_DAC_DC_CALI_CTL3 0x03
+
+/* Index (NID:5fh) */
+#define RT721_MISC_POWER_CTL0 0x00
+#define RT721_MISC_POWER_CTL31 0x31
+#define RT721_UAJ_TOP_TCON13 0x44
+#define RT721_UAJ_TOP_TCON14 0x45
+#define RT721_UAJ_TOP_TCON17 0x48
+
+/* Index (NID:61h) */
+#define RT721_HDA_LEGACY_MUX_CTL0 0x00
+#define RT721_HDA_LEGACY_UAJ_CTL 0x02
+#define RT721_HDA_LEGACY_CTL1 0x05
+#define RT721_HDA_LEGACY_RESET_CTL 0x06
+#define RT721_XU_REL_CTRL 0x0c
+#define RT721_GE_REL_CTRL1 0x0d
+#define RT721_HDA_LEGACY_GPIO_WAKE_EN_CTL 0x0e
+#define RT721_GE_SDCA_RST_CTRL 0x10
+#define RT721_INT_RST_EN_CTRL 0x11
+#define RT721_XU_EVENT_EN 0x13
+#define RT721_INLINE_CTL2 0x17
+#define RT721_UMP_HID_CTRL1 0x18
+#define RT721_UMP_HID_CTRL2 0x19
+#define RT721_UMP_HID_CTRL3 0x1a
+#define RT721_UMP_HID_CTRL4 0x1b
+#define RT721_UMP_HID_CTRL5 0x1c
+#define RT721_FUNC_FLOAT_CTL0 0x22
+#define RT721_FUNC_FLOAT_CTL1 0x23
+#define RT721_FUNC_FLOAT_CTL2 0x24
+#define RT721_FUNC_FLOAT_CTL3 0x25
+#define RT721_ENT_FLOAT_CTL0 0x29
+#define RT721_ENT_FLOAT_CTL1 0x2c
+#define RT721_ENT_FLOAT_CTL2 0x2d
+#define RT721_ENT_FLOAT_CTL3 0x2e
+#define RT721_ENT_FLOAT_CTL4 0x2f
+#define RT721_CH_FLOAT_CTL1 0x45
+#define RT721_CH_FLOAT_CTL2 0x46
+#define RT721_ENT_FLOAT_CTL5 0x53
+#define RT721_ENT_FLOAT_CTL6 0x54
+#define RT721_ENT_FLOAT_CTL7 0x55
+#define RT721_ENT_FLOAT_CTL8 0x57
+#define RT721_ENT_FLOAT_CTL9 0x5a
+#define RT721_ENT_FLOAT_CTL10 0x5b
+#define RT721_CH_FLOAT_CTL3 0x6a
+#define RT721_CH_FLOAT_CTL4 0x6d
+#define RT721_CH_FLOAT_CTL5 0x70
+#define RT721_CH_FLOAT_CTL6 0x92
+
+/* Parameter & Verb control 01 (0x26)(NID:20h) */
+#define RT721_HIDDEN_REG_SW_RESET (0x1 << 14)
+
+/* Buffer address for HID */
+#define RT721_BUF_ADDR_HID1 0x44030000
+#define RT721_BUF_ADDR_HID2 0x44030020
+
+/* RT721 SDCA Control - function number */
+#define FUNC_NUM_JACK_CODEC 0x01
+#define FUNC_NUM_MIC_ARRAY 0x02
+#define FUNC_NUM_HID 0x03
+#define FUNC_NUM_AMP 0x04
+
+/* RT721 SDCA entity */
+#define RT721_SDCA_ENT_HID01 0x01
+#define RT721_SDCA_ENT_XUV 0x03
+#define RT721_SDCA_ENT_GE49 0x49
+#define RT721_SDCA_ENT_USER_FU05 0x05
+#define RT721_SDCA_ENT_USER_FU06 0x06
+#define RT721_SDCA_ENT_USER_FU0F 0x0f
+#define RT721_SDCA_ENT_USER_FU10 0x19
+#define RT721_SDCA_ENT_USER_FU1E 0x1e
+#define RT721_SDCA_ENT_FU15 0x15
+#define RT721_SDCA_ENT_PDE23 0x23
+#define RT721_SDCA_ENT_PDE40 0x40
+#define RT721_SDCA_ENT_PDE41 0x41
+#define RT721_SDCA_ENT_PDE11 0x11
+#define RT721_SDCA_ENT_PDE12 0x12
+#define RT721_SDCA_ENT_PDE2A 0x2a
+#define RT721_SDCA_ENT_CS01 0x01
+#define RT721_SDCA_ENT_CS11 0x11
+#define RT721_SDCA_ENT_CS1F 0x1f
+#define RT721_SDCA_ENT_CS1C 0x1c
+#define RT721_SDCA_ENT_CS31 0x31
+#define RT721_SDCA_ENT_OT23 0x42
+#define RT721_SDCA_ENT_IT26 0x26
+#define RT721_SDCA_ENT_IT09 0x09
+#define RT721_SDCA_ENT_PLATFORM_FU15 0x15
+#define RT721_SDCA_ENT_PLATFORM_FU44 0x44
+#define RT721_SDCA_ENT_XU03 0x03
+#define RT721_SDCA_ENT_XU0D 0x0d
+#define RT721_SDCA_ENT_FU55 0x55
+
+/* RT721 SDCA control */
+#define RT721_SDCA_CTL_SAMPLE_FREQ_INDEX 0x10
+#define RT721_SDCA_CTL_FU_MUTE 0x01
+#define RT721_SDCA_CTL_FU_VOLUME 0x02
+#define RT721_SDCA_CTL_HIDTX_CURRENT_OWNER 0x10
+#define RT721_SDCA_CTL_HIDTX_SET_OWNER_TO_DEVICE 0x11
+#define RT721_SDCA_CTL_HIDTX_MESSAGE_OFFSET 0x12
+#define RT721_SDCA_CTL_HIDTX_MESSAGE_LENGTH 0x13
+#define RT721_SDCA_CTL_SELECTED_MODE 0x01
+#define RT721_SDCA_CTL_DETECTED_MODE 0x02
+#define RT721_SDCA_CTL_REQ_POWER_STATE 0x01
+#define RT721_SDCA_CTL_VENDOR_DEF 0x30
+#define RT721_SDCA_CTL_XUV 0x34
+#define RT721_SDCA_CTL_FU_CH_GAIN 0x0b
+
+/* RT721 SDCA channel */
+#define CH_L 0x01
+#define CH_R 0x02
+#define CH_01 0x01
+#define CH_02 0x02
+#define CH_03 0x03
+#define CH_04 0x04
+#define CH_08 0x08
+#define CH_09 0x09
+#define CH_0A 0x0a
+
+/* sample frequency index */
+#define RT721_SDCA_RATE_8000HZ 0x01
+#define RT721_SDCA_RATE_11025HZ 0x02
+#define RT721_SDCA_RATE_12000HZ 0x03
+#define RT721_SDCA_RATE_16000HZ 0x04
+#define RT721_SDCA_RATE_22050HZ 0x05
+#define RT721_SDCA_RATE_24000HZ 0x06
+#define RT721_SDCA_RATE_32000HZ 0x07
+#define RT721_SDCA_RATE_44100HZ 0x08
+#define RT721_SDCA_RATE_48000HZ 0x09
+#define RT721_SDCA_RATE_88200HZ 0x0a
+#define RT721_SDCA_RATE_96000HZ 0x0b
+#define RT721_SDCA_RATE_176400HZ 0x0c
+#define RT721_SDCA_RATE_192000HZ 0x0d
+#define RT721_SDCA_RATE_384000HZ 0x0e
+#define RT721_SDCA_RATE_768000HZ 0x0f
+
+/* RT721 HID ID */
+#define RT721_SDCA_HID_ID 0x11
+
+enum {
+ RT721_AIF1, /* For headset mic and headphone */
+ RT721_AIF2, /* For speaker */
+ RT721_AIF3, /* For dmic */
+ RT721_AIFS,
+};
+
+int rt721_sdca_io_init(struct device *dev, struct sdw_slave *slave);
+int rt721_sdca_init(struct device *dev, struct regmap *regmap,
+ struct regmap *mbq_regmap, struct sdw_slave *slave);
+#endif /* __RT721_H__ */
diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c
index 87354bb1564e..25fc13687bc8 100644
--- a/sound/soc/codecs/rt722-sdca-sdw.c
+++ b/sound/soc/codecs/rt722-sdca-sdw.c
@@ -177,7 +177,7 @@ static int rt722_sdca_update_status(struct sdw_slave *slave,
* This also could sync with the cache value as the rt722_sdca_jack_init set.
*/
sdw_write_no_pm(rt722->slave, SDW_SCP_SDCA_INTMASK1,
- SDW_SCP_SDCA_INTMASK_SDCA_6);
+ SDW_SCP_SDCA_INTMASK_SDCA_0);
sdw_write_no_pm(rt722->slave, SDW_SCP_SDCA_INTMASK2,
SDW_SCP_SDCA_INTMASK_SDCA_8);
}
@@ -253,7 +253,7 @@ static int rt722_sdca_read_prop(struct sdw_slave *slave)
}
/* set the timeout values */
- prop->clk_stop_timeout = 200;
+ prop->clk_stop_timeout = 900;
/* wake-up event */
prop->wake_capable = 1;
@@ -308,12 +308,8 @@ static int rt722_sdca_interrupt_callback(struct sdw_slave *slave,
SDW_SCP_SDCA_INT_SDCA_0, SDW_SCP_SDCA_INT_SDCA_0);
if (ret < 0)
goto io_error;
- } else if (ret & SDW_SCP_SDCA_INTMASK_SDCA_6) {
- ret = sdw_update_no_pm(rt722->slave, SDW_SCP_SDCA_INT1,
- SDW_SCP_SDCA_INT_SDCA_6, SDW_SCP_SDCA_INT_SDCA_6);
- if (ret < 0)
- goto io_error;
}
+
ret = sdw_read_no_pm(rt722->slave, SDW_SCP_SDCA_INT2);
if (ret < 0)
goto io_error;
@@ -444,7 +440,7 @@ static int __maybe_unused rt722_sdca_dev_system_suspend(struct device *dev)
mutex_lock(&rt722_sdca->disable_irq_lock);
rt722_sdca->disable_irq = true;
ret1 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK1,
- SDW_SCP_SDCA_INTMASK_SDCA_0 | SDW_SCP_SDCA_INTMASK_SDCA_6, 0);
+ SDW_SCP_SDCA_INTMASK_SDCA_0, 0);
ret2 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK2,
SDW_SCP_SDCA_INTMASK_SDCA_8, 0);
mutex_unlock(&rt722_sdca->disable_irq_lock);
@@ -471,7 +467,7 @@ static int __maybe_unused rt722_sdca_dev_resume(struct device *dev)
if (!slave->unattach_request) {
mutex_lock(&rt722->disable_irq_lock);
if (rt722->disable_irq == true) {
- sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_6);
+ sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
rt722->disable_irq = false;
}
diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c
index e5bd9ef812de..908846e994df 100644
--- a/sound/soc/codecs/rt722-sdca.c
+++ b/sound/soc/codecs/rt722-sdca.c
@@ -190,8 +190,8 @@ static void rt722_sdca_jack_detect_handler(struct work_struct *work)
if (!rt722->component->card || !rt722->component->card->instantiated)
return;
- /* SDW_SCP_SDCA_INT_SDCA_6 is used for jack detection */
- if (rt722->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_6) {
+ /* SDW_SCP_SDCA_INT_SDCA_0 is used for jack detection */
+ if (rt722->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_0) {
ret = rt722_sdca_headset_detect(rt722);
if (ret < 0)
return;
@@ -294,7 +294,7 @@ static void rt722_sdca_jack_init(struct rt722_sdca_priv *rt722)
if (rt722->hs_jack) {
/* set SCP_SDCA_IntMask1[0]=1 */
sdw_write_no_pm(rt722->slave, SDW_SCP_SDCA_INTMASK1,
- SDW_SCP_SDCA_INTMASK_SDCA_0 | SDW_SCP_SDCA_INTMASK_SDCA_6);
+ SDW_SCP_SDCA_INTMASK_SDCA_0);
/* set SCP_SDCA_IntMask2[0]=1 */
sdw_write_no_pm(rt722->slave, SDW_SCP_SDCA_INTMASK2,
SDW_SCP_SDCA_INTMASK_SDCA_8);
@@ -308,6 +308,7 @@ static void rt722_sdca_jack_init(struct rt722_sdca_priv *rt722)
regmap_write(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_XU0D,
RT722_SDCA_CTL_SELECTED_MODE, 0), 0);
+ rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_GE_RELATED_CTL1, 0x0000);
/* trigger GE interrupt */
rt722_sdca_index_update_bits(rt722, RT722_VENDOR_HDA_CTL,
RT722_GE_RELATED_CTL2, 0x4000, 0x4000);
@@ -607,12 +608,8 @@ static int rt722_sdca_dmic_set_gain_get(struct snd_kcontrol *kcontrol,
if (!adc_vol_flag) /* boost gain */
ctl = regvalue / boost_step;
- else { /* ADC gain */
- if (adc_vol_flag)
- ctl = p->max - (((vol_max - regvalue) & 0xffff) / interval_offset);
- else
- ctl = p->max - (((0 - regvalue) & 0xffff) / interval_offset);
- }
+ else /* ADC gain */
+ ctl = p->max - (((vol_max - regvalue) & 0xffff) / interval_offset);
ucontrol->value.integer.value[i] = ctl;
}
diff --git a/sound/soc/codecs/sigmadsp-i2c.c b/sound/soc/codecs/sigmadsp-i2c.c
index cb4c491078c2..07c9d89ab24a 100644
--- a/sound/soc/codecs/sigmadsp-i2c.c
+++ b/sound/soc/codecs/sigmadsp-i2c.c
@@ -9,7 +9,7 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include "sigmadsp.h"
diff --git a/sound/soc/codecs/simple-mux.c b/sound/soc/codecs/simple-mux.c
index 240af0563283..390696440155 100644
--- a/sound/soc/codecs/simple-mux.c
+++ b/sound/soc/codecs/simple-mux.c
@@ -6,6 +6,7 @@
#include <linux/gpio/consumer.h>
#include <linux/module.h>
+#include <linux/mux/driver.h>
#include <linux/regulator/consumer.h>
#include <sound/soc.h>
@@ -16,6 +17,7 @@ struct simple_mux {
struct gpio_desc *gpiod_mux;
unsigned int mux;
const char *mux_texts[MUX_TEXT_SIZE];
+ unsigned int idle_state;
struct soc_enum mux_enum;
struct snd_kcontrol_new mux_mux;
struct snd_soc_dapm_widget mux_widgets[MUX_WIDGET_SIZE];
@@ -57,6 +59,9 @@ static int simple_mux_control_put(struct snd_kcontrol *kcontrol,
priv->mux = ucontrol->value.enumerated.item[0];
+ if (priv->idle_state != MUX_IDLE_AS_IS && dapm->bias_level < SND_SOC_BIAS_PREPARE)
+ return 0;
+
gpiod_set_value_cansleep(priv->gpiod_mux, priv->mux);
return snd_soc_dapm_mux_update_power(dapm, kcontrol,
@@ -75,10 +80,33 @@ static unsigned int simple_mux_read(struct snd_soc_component *component,
static const struct snd_kcontrol_new simple_mux_mux =
SOC_DAPM_ENUM_EXT("Muxer", simple_mux_enum, simple_mux_control_get, simple_mux_control_put);
+static int simple_mux_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
+ struct simple_mux *priv = snd_soc_component_get_drvdata(c);
+
+ if (priv->idle_state != MUX_IDLE_AS_IS) {
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ gpiod_set_value_cansleep(priv->gpiod_mux, priv->mux);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ gpiod_set_value_cansleep(priv->gpiod_mux, priv->idle_state);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
static const struct snd_soc_dapm_widget simple_mux_dapm_widgets[MUX_WIDGET_SIZE] = {
SND_SOC_DAPM_INPUT("IN1"),
SND_SOC_DAPM_INPUT("IN2"),
- SND_SOC_DAPM_MUX("MUX", SND_SOC_NOPM, 0, 0, &simple_mux_mux), // see simple_mux_probe()
+ SND_SOC_DAPM_MUX_E("MUX", SND_SOC_NOPM, 0, 0, &simple_mux_mux, // see simple_mux_probe()
+ simple_mux_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_OUTPUT("OUT"),
};
@@ -93,6 +121,7 @@ static int simple_mux_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct simple_mux *priv;
+ int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -121,6 +150,14 @@ static int simple_mux_probe(struct platform_device *pdev)
/* Overwrite text ("Input 1", "Input 2") if property exists */
of_property_read_string_array(np, "state-labels", priv->mux_texts, MUX_TEXT_SIZE);
+ ret = of_property_read_u32(np, "idle-state", &priv->idle_state);
+ if (ret < 0) {
+ priv->idle_state = MUX_IDLE_AS_IS;
+ } else if (priv->idle_state != MUX_IDLE_AS_IS && priv->idle_state >= 2) {
+ dev_err(dev, "invalid idle-state %u\n", priv->idle_state);
+ return -EINVAL;
+ }
+
/* switch to use priv data instead of default */
priv->mux_enum.texts = priv->mux_texts;
priv->mux_mux.private_value = (unsigned long)&priv->mux_enum;
diff --git a/sound/soc/codecs/sma1307.c b/sound/soc/codecs/sma1307.c
new file mode 100644
index 000000000000..f2cea6186d98
--- /dev/null
+++ b/sound/soc/codecs/sma1307.c
@@ -0,0 +1,2049 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// sma1307.c -- sma1307 ALSA SoC Audio driver
+//
+// Copyright 2024 Iron Device Corporation
+//
+// Auther: Gyuhwa Park <gyuwha.park@irondevice.com>
+// Auther: Kiseok Jo <kiseok.jo@irondevice.com>
+
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include "sma1307.h"
+
+#define CHECK_PERIOD_TIME 1 /* sec per HZ */
+#define PLL_MATCH(_input_clk_name, _output_clk_name, _input_clk,\
+ _post_n, _n, _vco, _p_cp)\
+{\
+ .input_clk_name = _input_clk_name,\
+ .output_clk_name = _output_clk_name,\
+ .input_clk = _input_clk,\
+ .post_n = _post_n,\
+ .n = _n,\
+ .vco = _vco,\
+ .p_cp = _p_cp,\
+}
+
+static const char *setting_file = "sma1307_setting.bin";
+#define SMA1307_SETTING_CHECKSUM 0x100000
+
+/* PLL clock setting Table */
+struct sma1307_pll_match {
+ char *input_clk_name;
+ char *output_clk_name;
+ unsigned int input_clk;
+ unsigned int post_n;
+ unsigned int n;
+ unsigned int vco;
+ unsigned int p_cp;
+};
+
+struct sma1307_data {
+ char *name;
+ void (*init)(struct regmap *regmap);
+};
+
+struct sma1307_priv {
+ bool check_fault_status;
+ bool force_mute_status;
+ bool sw_ot1_prot;
+ char *name;
+ enum sma1307_mode amp_mode;
+ int binary_mode;
+ int dapm_aif_in;
+ int dapm_aif_out0;
+ int dapm_aif_out1;
+ int dapm_sdo_en;
+ int dapm_sdo_setting;
+ int num_of_pll_matches;
+ int check_fault_period;
+ struct delayed_work check_fault_work;
+ struct device *dev;
+ struct kobject *kobj;
+ struct mutex default_lock;
+ struct regmap *regmap;
+ struct sma1307_setting_file set;
+ const struct sma1307_pll_match *pll_matches;
+ const struct sma1307_data *data;
+ unsigned int cur_vol;
+ unsigned int format;
+ unsigned int frame_size;
+ unsigned int init_vol;
+ unsigned int last_bclk;
+ unsigned int otp_trm2;
+ unsigned int otp_trm3;
+ unsigned int rev_num;
+ unsigned int sys_clk_id;
+ unsigned int tdm_slot0_rx;
+ unsigned int tdm_slot1_rx;
+ unsigned int tdm_slot0_tx;
+ unsigned int tdm_slot1_tx;
+ unsigned int tsdw_cnt;
+};
+
+static const struct sma1307_pll_match sma1307_pll_matches[] = {
+ /* in_clk_name, out_clk_name, input_clk post_n, n, vco, p_cp */
+ PLL_MATCH("1.411MHz", "24.554MHz",
+ 1411200, 0x06, 0xD1, 0x88, 0x00),
+ PLL_MATCH("1.536MHz", "24.576MHz",
+ 1536000, 0x06, 0xC0, 0x88, 0x00),
+ PLL_MATCH("2.822MHz", "24.554MHz",
+ 2822400, 0x06, 0xD1, 0x88, 0x04),
+ PLL_MATCH("3.072MHz", "24.576MHz",
+ 3072000, 0x06, 0x60, 0x88, 0x00),
+ PLL_MATCH("6.144MHz", "24.576MHz",
+ 6144000, 0x06, 0x60, 0x88, 0x04),
+ PLL_MATCH("12.288MHz", "24.576MHz",
+ 12288000, 0x06, 0x60, 0x88, 0x08),
+ PLL_MATCH("19.2MHz", "24.48MHz",
+ 19200000, 0x06, 0x7B, 0x88, 0x0C),
+ PLL_MATCH("24.576MHz", "24.576MHz",
+ 24576000, 0x06, 0x60, 0x88, 0x0C),
+};
+
+static struct snd_soc_component *sma1307_amp_component;
+
+static void sma1307_startup(struct snd_soc_component *);
+static void sma1307_shutdown(struct snd_soc_component *);
+static void sma1307_reset(struct snd_soc_component *);
+static void sma1307_set_binary(struct snd_soc_component *);
+static void sma1307_set_default(struct snd_soc_component *);
+
+/* Initial register value - 6.0W SPK (8ohm load) */
+static const struct reg_default sma1307_reg_def[] = {
+ { 0x00, 0x80 },
+ { 0x01, 0x00 },
+ { 0x02, 0x52 },
+ { 0x03, 0x4C },
+ { 0x04, 0x47 },
+ { 0x05, 0x42 },
+ { 0x06, 0x40 },
+ { 0x07, 0x40 },
+ { 0x08, 0x3C },
+ { 0x09, 0x2F },
+ { 0x0A, 0x32 },
+ { 0x0B, 0x50 },
+ { 0x0C, 0x8C },
+ { 0x0D, 0x00 },
+ { 0x0E, 0x3F },
+ { 0x0F, 0x00 },
+ { 0x10, 0x00 },
+ { 0x11, 0x00 },
+ { 0x12, 0x00 },
+ { 0x13, 0x09 },
+ { 0x14, 0x12 },
+ { 0x1C, 0x00 },
+ { 0x1D, 0x85 },
+ { 0x1E, 0xA1 },
+ { 0x1F, 0x67 },
+ { 0x22, 0x00 },
+ { 0x23, 0x1F },
+ { 0x24, 0x7A },
+ { 0x25, 0x00 },
+ { 0x26, 0xFF },
+ { 0x27, 0x39 },
+ { 0x28, 0x54 },
+ { 0x29, 0x92 },
+ { 0x2A, 0xB0 },
+ { 0x2B, 0xED },
+ { 0x2C, 0xED },
+ { 0x2D, 0xFF },
+ { 0x2E, 0xFF },
+ { 0x2F, 0xFF },
+ { 0x30, 0xFF },
+ { 0x31, 0xFF },
+ { 0x32, 0xFF },
+ { 0x34, 0x01 },
+ { 0x35, 0x17 },
+ { 0x36, 0x92 },
+ { 0x37, 0x00 },
+ { 0x38, 0x01 },
+ { 0x39, 0x10 },
+ { 0x3E, 0x01 },
+ { 0x3F, 0x08 },
+ { 0x8B, 0x05 },
+ { 0x8C, 0x50 },
+ { 0x8D, 0x80 },
+ { 0x8E, 0x10 },
+ { 0x8F, 0x02 },
+ { 0x90, 0x02 },
+ { 0x91, 0x83 },
+ { 0x92, 0xC0 },
+ { 0x93, 0x00 },
+ { 0x94, 0xA4 },
+ { 0x95, 0x74 },
+ { 0x96, 0x57 },
+ { 0xA2, 0xCC },
+ { 0xA3, 0x28 },
+ { 0xA4, 0x40 },
+ { 0xA5, 0x01 },
+ { 0xA6, 0x41 },
+ { 0xA7, 0x08 },
+ { 0xA8, 0x04 },
+ { 0xA9, 0x27 },
+ { 0xAA, 0x10 },
+ { 0xAB, 0x10 },
+ { 0xAC, 0x10 },
+ { 0xAD, 0x0F },
+ { 0xAE, 0xCD },
+ { 0xAF, 0x70 },
+ { 0xB0, 0x03 },
+ { 0xB1, 0xEF },
+ { 0xB2, 0x03 },
+ { 0xB3, 0xEF },
+ { 0xB4, 0xF3 },
+ { 0xB5, 0x3D },
+};
+
+static bool sma1307_readable_register(struct device *dev, unsigned int reg)
+{
+ if (reg > SMA1307_FF_DEVICE_INDEX)
+ return false;
+
+ switch (reg) {
+ case SMA1307_00_SYSTEM_CTRL ... SMA1307_1F_TONE_FINE_VOLUME:
+ case SMA1307_22_COMP_HYS_SEL ... SMA1307_32_BROWN_OUT_PROT19:
+ case SMA1307_34_OCP_SPK ... SMA1307_39_PMT_NZ_VAL:
+ case SMA1307_3B_TEST1 ... SMA1307_3F_ATEST2:
+ case SMA1307_8B_PLL_POST_N ... SMA1307_9A_OTP_TRM3:
+ case SMA1307_A0_PAD_CTRL0 ... SMA1307_BE_MCBS_CTRL2:
+ case SMA1307_F5_READY_FOR_V_SAR:
+ case SMA1307_F7_READY_FOR_T_SAR ... SMA1307_FF_DEVICE_INDEX:
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+static bool sma1307_writeable_register(struct device *dev, unsigned int reg)
+{
+ if (reg > SMA1307_FF_DEVICE_INDEX)
+ return false;
+
+ switch (reg) {
+ case SMA1307_00_SYSTEM_CTRL ... SMA1307_1F_TONE_FINE_VOLUME:
+ case SMA1307_22_COMP_HYS_SEL ... SMA1307_32_BROWN_OUT_PROT19:
+ case SMA1307_34_OCP_SPK ... SMA1307_39_PMT_NZ_VAL:
+ case SMA1307_3B_TEST1 ... SMA1307_3F_ATEST2:
+ case SMA1307_8B_PLL_POST_N ... SMA1307_9A_OTP_TRM3:
+ case SMA1307_A0_PAD_CTRL0 ... SMA1307_BE_MCBS_CTRL2:
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+static bool sma1307_volatile_register(struct device *dev, unsigned int reg)
+{
+ if (reg > SMA1307_FF_DEVICE_INDEX)
+ return false;
+
+ switch (reg) {
+ case SMA1307_F8_STATUS_T1 ... SMA1307_FF_DEVICE_INDEX:
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+/* DB scale conversion of speaker volume */
+static const DECLARE_TLV_DB_SCALE(sma1307_spk_tlv, -6000, 50, 0);
+
+static const char *const sma1307_aif_in_source_text[] = {
+ "Mono", "Left", "Right"
+};
+
+static const char *const sma1307_sdo_setting_text[] = {
+ "Data_One_48k", "Data_Two_48k", "Data_Two_24k",
+ "Clk_PLL", "Clk_OSC"
+};
+
+static const char *const sma1307_aif_out_source_text[] = {
+ "Disable", "After_FmtC", "After_Mixer", "After_DSP",
+ "Vrms2_Avg", "Battery", "Temperature", "After_Delay"
+};
+
+static const char *const sma1307_tdm_slot_text[] = {
+ "Slot0", "Slot1", "Slot2", "Slot3",
+ "Slot4", "Slot5", "Slot6", "Slot7"
+};
+
+static const char *const sma1307_binary_mode_text[] = {
+ "Mode0", "Mode1", "Mode2", "Mode3", "Mode4"
+};
+
+static const char *const sma1307_reset_text[] = {
+ "Reset"
+};
+
+static const struct soc_enum sma1307_aif_in_source_enum =
+SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_aif_in_source_text),
+ sma1307_aif_in_source_text);
+static const struct soc_enum sma1307_sdo_setting_enum =
+SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_sdo_setting_text),
+ sma1307_sdo_setting_text);
+static const struct soc_enum sma1307_aif_out_source_enum =
+SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_aif_out_source_text),
+ sma1307_aif_out_source_text);
+static const struct soc_enum sma1307_tdm_slot_enum =
+SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_tdm_slot_text),
+ sma1307_tdm_slot_text);
+static const struct soc_enum sma1307_binary_mode_enum =
+SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_binary_mode_text),
+ sma1307_binary_mode_text);
+static const struct soc_enum sma1307_reset_enum =
+SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_reset_text),
+ sma1307_reset_text);
+
+static int sma1307_force_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = (int)sma1307->force_mute_status;
+
+ return 0;
+}
+
+static int sma1307_force_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+ bool change = false, val = (bool)ucontrol->value.integer.value[0];
+
+ if (sma1307->force_mute_status == val) {
+ change = false;
+ } else {
+ change = true;
+ sma1307->force_mute_status = val;
+ }
+
+ return change;
+}
+
+static int sma1307_tdm_slot_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+ int val1, val2;
+
+ regmap_read(sma1307->regmap, SMA1307_A5_TDM1, &val1);
+ regmap_read(sma1307->regmap, SMA1307_A6_TDM2, &val2);
+
+ if (!strcmp(kcontrol->id.name, SMA1307_TDM_RX0_POS_NAME)) {
+ ucontrol->value.integer.value[0]
+ = (val1 & SMA1307_TDM_SLOT0_RX_POS_MASK) >> 3;
+ sma1307->tdm_slot0_rx = ucontrol->value.integer.value[0];
+ } else if (!strcmp(kcontrol->id.name, SMA1307_TDM_RX1_POS_NAME)) {
+ ucontrol->value.integer.value[0]
+ = val1 & SMA1307_TDM_SLOT1_RX_POS_MASK;
+ sma1307->tdm_slot1_rx = ucontrol->value.integer.value[0];
+ } else if (!strcmp(kcontrol->id.name, SMA1307_TDM_TX0_POS_NAME)) {
+ ucontrol->value.integer.value[0]
+ = (val2 & SMA1307_TDM_SLOT0_TX_POS_MASK) >> 3;
+ sma1307->tdm_slot0_tx = ucontrol->value.integer.value[0];
+ } else if (!strcmp(kcontrol->id.name, SMA1307_TDM_TX1_POS_NAME)) {
+ ucontrol->value.integer.value[0]
+ = val2 & SMA1307_TDM_SLOT1_TX_POS_MASK;
+ sma1307->tdm_slot1_tx = ucontrol->value.integer.value[0];
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int sma1307_tdm_slot_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+ int val = (int)ucontrol->value.integer.value[0];
+ bool change;
+
+ if (!strcmp(kcontrol->id.name, SMA1307_TDM_RX0_POS_NAME)) {
+ if (sma1307->tdm_slot0_rx == val)
+ change = false;
+ else {
+ change = true;
+ sma1307->tdm_slot0_rx = val;
+ regmap_update_bits(sma1307->regmap, SMA1307_A5_TDM1,
+ SMA1307_TDM_SLOT0_RX_POS_MASK, val << 3);
+ }
+ } else if (!strcmp(kcontrol->id.name, SMA1307_TDM_RX1_POS_NAME)) {
+ if (sma1307->tdm_slot1_rx == val)
+ change = false;
+ else {
+ change = true;
+ sma1307->tdm_slot1_rx = val;
+ regmap_update_bits(sma1307->regmap, SMA1307_A5_TDM1,
+ SMA1307_TDM_SLOT1_RX_POS_MASK, val);
+ }
+ } else if (!strcmp(kcontrol->id.name, SMA1307_TDM_TX0_POS_NAME)) {
+ if (sma1307->tdm_slot0_tx == val)
+ change = false;
+ else {
+ change = true;
+ sma1307->tdm_slot0_tx = val;
+ regmap_update_bits(sma1307->regmap, SMA1307_A6_TDM2,
+ SMA1307_TDM_SLOT0_TX_POS_MASK, val << 3);
+ }
+ } else if (!strcmp(kcontrol->id.name, SMA1307_TDM_TX1_POS_NAME)) {
+ if (sma1307->tdm_slot1_tx == val)
+ change = false;
+ else {
+ change = true;
+ sma1307->tdm_slot1_tx = val;
+ regmap_update_bits(sma1307->regmap, SMA1307_A6_TDM2,
+ SMA1307_TDM_SLOT1_TX_POS_MASK, val);
+ }
+ } else {
+ dev_err(sma1307->dev, "%s: Invalid Control ID - %s\n",
+ __func__, kcontrol->id.name);
+ return -EINVAL;
+ }
+
+ return change;
+}
+
+static int sma1307_sw_ot1_prot_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = (int)sma1307->sw_ot1_prot;
+
+ return 0;
+}
+
+static int sma1307_sw_ot1_prot_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+ bool change = false, val = (bool)ucontrol->value.integer.value[0];
+
+ if (sma1307->sw_ot1_prot == val)
+ change = false;
+ else {
+ change = true;
+ sma1307->sw_ot1_prot = val;
+ }
+
+ return change;
+}
+
+static int sma1307_check_fault_status_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = (int)sma1307->check_fault_status;
+
+ return 0;
+}
+
+static int sma1307_check_fault_status_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+ bool change = false, val = (bool)ucontrol->value.integer.value[0];
+
+ if (sma1307->check_fault_status == val) {
+ change = false;
+ } else {
+ change = true;
+ sma1307->check_fault_status = val;
+ }
+
+ return change;
+}
+
+static int sma1307_check_fault_period_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = sma1307->check_fault_period;
+
+ return 0;
+}
+
+static int sma1307_check_fault_period_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ bool change = false;
+ int val = ucontrol->value.integer.value[0];
+
+ if (val < mc->min || val > mc->max)
+ return -EINVAL;
+ if (sma1307->check_fault_period == val) {
+ change = false;
+ } else {
+ change = true;
+ sma1307->check_fault_period = val;
+ }
+
+ return change;
+}
+
+static int sma1307_reset_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+
+ regmap_update_bits(sma1307->regmap, SMA1307_00_SYSTEM_CTRL,
+ SMA1307_RESET_MASK, SMA1307_RESET_ON);
+ sma1307_reset(component);
+
+ snd_ctl_notify(component->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &kcontrol->id);
+
+ return true;
+}
+
+static int sma1307_binary_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct sma1307_priv *sma1307 = snd_kcontrol_chip(kcontrol);
+
+ sma1307->binary_mode = (int)ucontrol->value.enumerated.item[0];
+ if (sma1307->set.status)
+ sma1307_set_binary(component);
+
+ return snd_soc_put_enum_double(kcontrol, ucontrol);
+}
+
+static void sma1307_startup(struct snd_soc_component *component)
+{
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+
+ regmap_update_bits(sma1307->regmap, SMA1307_A2_TOP_MAN1,
+ SMA1307_PLL_MASK, SMA1307_PLL_ON);
+ regmap_update_bits(sma1307->regmap, SMA1307_00_SYSTEM_CTRL,
+ SMA1307_POWER_MASK, SMA1307_POWER_ON);
+
+ if (sma1307->amp_mode == SMA1307_MONO_MODE) {
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_10_SYSTEM_CTRL1,
+ SMA1307_SPK_MODE_MASK,
+ SMA1307_SPK_MONO);
+ } else {
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_10_SYSTEM_CTRL1,
+ SMA1307_SPK_MODE_MASK,
+ SMA1307_SPK_STEREO);
+ }
+
+ if (sma1307->check_fault_status) {
+ if (sma1307->check_fault_period > 0)
+ queue_delayed_work(system_freezable_wq,
+ &sma1307->check_fault_work,
+ sma1307->check_fault_period * HZ);
+ else
+ queue_delayed_work(system_freezable_wq,
+ &sma1307->check_fault_work,
+ CHECK_PERIOD_TIME * HZ);
+ }
+}
+
+static void sma1307_shutdown(struct snd_soc_component *component)
+{
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+
+ /* for SMA1307A */
+ cancel_delayed_work_sync(&sma1307->check_fault_work);
+
+ regmap_update_bits(sma1307->regmap, SMA1307_0E_MUTE_VOL_CTRL,
+ SMA1307_SPK_MUTE_MASK, SMA1307_SPK_MUTE);
+ /* Need to wait time for mute slope */
+ msleep(55);
+
+ regmap_update_bits(sma1307->regmap, SMA1307_10_SYSTEM_CTRL1,
+ SMA1307_SPK_MODE_MASK, SMA1307_SPK_OFF);
+ regmap_update_bits(sma1307->regmap, SMA1307_A2_TOP_MAN1,
+ SMA1307_PLL_MASK, SMA1307_PLL_OFF);
+ regmap_update_bits(sma1307->regmap, SMA1307_00_SYSTEM_CTRL,
+ SMA1307_POWER_MASK, SMA1307_POWER_OFF);
+}
+
+static int sma1307_aif_in_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+ unsigned int mux = sma1307->dapm_aif_in;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ switch (mux) {
+ case SMA1307_MONO_MODE:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_11_SYSTEM_CTRL2,
+ SMA1307_MONOMIX_MASK,
+ SMA1307_MONOMIX_ON);
+ break;
+ case SMA1307_LEFT_MODE:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_11_SYSTEM_CTRL2,
+ SMA1307_MONOMIX_MASK,
+ SMA1307_MONOMIX_OFF);
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_11_SYSTEM_CTRL2,
+ SMA1307_LR_DATA_SW_MASK,
+ SMA1307_LR_DATA_SW_NORMAL);
+ break;
+ case SMA1307_RIGHT_MODE:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_11_SYSTEM_CTRL2,
+ SMA1307_MONOMIX_MASK,
+ SMA1307_MONOMIX_OFF);
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_11_SYSTEM_CTRL2,
+ SMA1307_LR_DATA_SW_MASK,
+ SMA1307_LR_DATA_SW_SWAP);
+ break;
+ default:
+
+ dev_err(sma1307->dev, "%s: Invalid value (%d)\n",
+ __func__, mux);
+ return -EINVAL;
+ }
+ sma1307->amp_mode = mux;
+ break;
+ }
+ return 0;
+}
+
+static int sma1307_sdo_setting_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+ unsigned int mux = sma1307->dapm_sdo_setting;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ switch (mux) {
+ case SMA1307_OUT_DATA_ONE_48K:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A2_TOP_MAN1,
+ SMA1307_SDO_OUTPUT2_MASK,
+ SMA1307_ONE_SDO_PER_CH);
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A3_TOP_MAN2,
+ SMA1307_SDO_OUTPUT3_MASK
+ |
+ SMA1307_DATA_CLK_SEL_MASK,
+ SMA1307_SDO_OUTPUT3_DIS
+ | SMA1307_SDO_DATA);
+ break;
+ case SMA1307_OUT_DATA_TWO_48K:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A2_TOP_MAN1,
+ SMA1307_SDO_OUTPUT2_MASK,
+ SMA1307_TWO_SDO_PER_CH);
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A3_TOP_MAN2,
+ SMA1307_SDO_OUTPUT3_MASK
+ |
+ SMA1307_DATA_CLK_SEL_MASK,
+ SMA1307_SDO_OUTPUT3_DIS
+ | SMA1307_SDO_DATA);
+ break;
+ case SMA1307_OUT_DATA_TWO_24K:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A2_TOP_MAN1,
+ SMA1307_SDO_OUTPUT2_MASK,
+ SMA1307_TWO_SDO_PER_CH);
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A3_TOP_MAN2,
+ SMA1307_SDO_OUTPUT3_MASK
+ |
+ SMA1307_DATA_CLK_SEL_MASK,
+ SMA1307_TWO_SDO_PER_CH_24K
+ | SMA1307_SDO_DATA);
+ break;
+ case SMA1307_OUT_CLK_PLL:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A3_TOP_MAN2,
+ SMA1307_DATA_CLK_SEL_MASK,
+ SMA1307_SDO_CLK_PLL);
+
+ break;
+ case SMA1307_OUT_CLK_OSC:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A3_TOP_MAN2,
+ SMA1307_DATA_CLK_SEL_MASK,
+ SMA1307_SDO_CLK_OSC);
+
+ break;
+ default:
+ dev_err(sma1307->dev, "%s: Invalid value (%d)\n",
+ __func__, mux);
+ return -EINVAL;
+ }
+ break;
+ }
+ return 0;
+}
+
+static int sma1307_aif_out_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+ unsigned int mux = 0, val = 0, mask = 0;
+
+ if (!strcmp(w->name, SMA1307_AIF_OUT0_NAME)) {
+ mux = sma1307->dapm_aif_out0;
+ val = mux;
+ mask = SMA1307_SDO_OUT0_SEL_MASK;
+ } else if (!strcmp(w->name, SMA1307_AIF_OUT1_NAME)) {
+ mux = sma1307->dapm_aif_out1;
+ val = mux << 3;
+ mask = SMA1307_SDO_OUT1_SEL_MASK;
+ } else {
+ dev_err(sma1307->dev, "%s: Invalid widget - %s\n",
+ __func__, w->name);
+ return -EINVAL;
+ }
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ regmap_update_bits(sma1307->regmap, SMA1307_09_OUTPUT_CTRL,
+ mask, val);
+ break;
+ }
+ return 0;
+}
+
+static int sma1307_sdo_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_09_OUTPUT_CTRL,
+ SMA1307_PORT_CONFIG_MASK,
+ SMA1307_OUTPUT_PORT_ENABLE);
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A3_TOP_MAN2,
+ SMA1307_SDO_OUTPUT_MASK,
+ SMA1307_LOGIC_OUTPUT);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_09_OUTPUT_CTRL,
+ SMA1307_PORT_CONFIG_MASK,
+ SMA1307_INPUT_PORT_ONLY);
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A3_TOP_MAN2,
+ SMA1307_SDO_OUTPUT_MASK,
+ SMA1307_HIGH_Z_OUTPUT);
+ break;
+ }
+ return 0;
+}
+
+static int sma1307_power_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ sma1307_startup(component);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ sma1307_shutdown(component);
+ break;
+ }
+ return 0;
+}
+
+static int sma1307_dapm_aif_in_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct sma1307_priv *sma1307 =
+ snd_soc_component_get_drvdata(dapm->component);
+
+ ucontrol->value.enumerated.item[0] = (unsigned int)sma1307->dapm_aif_in;
+ snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+ return 0;
+}
+
+static int sma1307_dapm_aif_in_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct sma1307_priv *sma1307 =
+ snd_soc_component_get_drvdata(dapm->component);
+ int val = (int)ucontrol->value.enumerated.item[0];
+ bool change;
+
+ if ((val < 0) || (val >= ARRAY_SIZE(sma1307_aif_in_source_text))) {
+ dev_err(sma1307->dev, "%s: Out of range\n", __func__);
+ return -EINVAL;
+ }
+
+ if (sma1307->dapm_aif_in != val) {
+ change = true;
+ sma1307->dapm_aif_in = val;
+ } else
+ change = false;
+
+ snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+ return change;
+}
+
+static int sma1307_dapm_sdo_setting_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct sma1307_priv *sma1307 =
+ snd_soc_component_get_drvdata(dapm->component);
+
+ ucontrol->value.enumerated.item[0] =
+ (unsigned int)sma1307->dapm_sdo_setting;
+ snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+ return 0;
+}
+
+static int sma1307_dapm_sdo_setting_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct sma1307_priv *sma1307 =
+ snd_soc_component_get_drvdata(dapm->component);
+ int val = (int)ucontrol->value.enumerated.item[0];
+ bool change;
+
+ if ((val < 0) || (val >= ARRAY_SIZE(sma1307_sdo_setting_text))) {
+ dev_err(sma1307->dev, "%s: Out of range\n", __func__);
+ return -EINVAL;
+ }
+
+ if (sma1307->dapm_sdo_setting != val) {
+ change = true;
+ sma1307->dapm_sdo_setting = val;
+ } else
+ change = false;
+
+ snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+ return change;
+}
+
+static int sma1307_dapm_aif_out_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct sma1307_priv *sma1307 =
+ snd_soc_component_get_drvdata(dapm->component);
+ unsigned int val = 0;
+
+ if (!strcmp(kcontrol->id.name, SMA1307_AIF_OUT0_NAME)) {
+ val = (unsigned int)sma1307->dapm_aif_out0;
+ } else if (!strcmp(kcontrol->id.name, SMA1307_AIF_OUT1_NAME)) {
+ val = (unsigned int)sma1307->dapm_aif_out1;
+ } else {
+ dev_err(sma1307->dev, "%s: Invalid Control ID - %s\n",
+ __func__, kcontrol->id.name);
+ return -EINVAL;
+ }
+ ucontrol->value.enumerated.item[0] = val;
+ snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+ return 0;
+}
+
+static int sma1307_dapm_aif_out_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct sma1307_priv *sma1307 =
+ snd_soc_component_get_drvdata(dapm->component);
+ int val = (int)ucontrol->value.enumerated.item[0];
+ bool change;
+
+ if ((val < 0) || (val >= ARRAY_SIZE(sma1307_aif_out_source_text))) {
+ dev_err(sma1307->dev, "%s: Out of range\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!strcmp(kcontrol->id.name, SMA1307_AIF_OUT0_NAME)) {
+ if (sma1307->dapm_aif_out0 != val) {
+ change = true;
+ sma1307->dapm_aif_out0 = val;
+ } else
+ change = false;
+ } else if (!strcmp(kcontrol->id.name, SMA1307_AIF_OUT1_NAME)) {
+ if (sma1307->dapm_aif_out1 != val) {
+ change = true;
+ sma1307->dapm_aif_out1 = val;
+ } else
+ change = false;
+ } else {
+ dev_err(sma1307->dev, "%s: Invalid Control ID - %s\n",
+ __func__, kcontrol->id.name);
+ return -EINVAL;
+ }
+
+ snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+ return change;
+}
+
+static int sma1307_dapm_sdo_enable_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct sma1307_priv *sma1307 =
+ snd_soc_component_get_drvdata(dapm->component);
+
+ ucontrol->value.integer.value[0] = (long)sma1307->dapm_sdo_en;
+ snd_soc_dapm_put_volsw(kcontrol, ucontrol);
+
+ return 0;
+}
+
+static int sma1307_dapm_sdo_enable_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct sma1307_priv *sma1307 =
+ snd_soc_component_get_drvdata(dapm->component);
+ int val = (int)ucontrol->value.integer.value[0];
+ bool change;
+
+ if ((val < 0) || (val > 1)) {
+ dev_err(sma1307->dev, "%s: Out of range\n", __func__);
+ return -EINVAL;
+ }
+
+ if (sma1307->dapm_sdo_en != val) {
+ change = true;
+ sma1307->dapm_sdo_en = val;
+ } else
+ change = false;
+
+ snd_soc_dapm_put_volsw(kcontrol, ucontrol);
+
+ return change;
+}
+
+static const struct snd_kcontrol_new sma1307_aif_in_source_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SMA1307_AIF_IN_NAME,
+ .info = snd_soc_info_enum_double,
+ .get = sma1307_dapm_aif_in_get,
+ .put = sma1307_dapm_aif_in_put,
+ .private_value = (unsigned long)&sma1307_aif_in_source_enum
+};
+
+static const struct snd_kcontrol_new sma1307_sdo_setting_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "SDO Setting",
+ .info = snd_soc_info_enum_double,
+ .get = sma1307_dapm_sdo_setting_get,
+ .put = sma1307_dapm_sdo_setting_put,
+ .private_value = (unsigned long)&sma1307_sdo_setting_enum
+};
+
+static const struct snd_kcontrol_new sma1307_aif_out0_source_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SMA1307_AIF_OUT0_NAME,
+ .info = snd_soc_info_enum_double,
+ .get = sma1307_dapm_aif_out_get,
+ .put = sma1307_dapm_aif_out_put,
+ .private_value = (unsigned long)&sma1307_aif_out_source_enum
+};
+
+static const struct snd_kcontrol_new sma1307_aif_out1_source_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SMA1307_AIF_OUT1_NAME,
+ .info = snd_soc_info_enum_double,
+ .get = sma1307_dapm_aif_out_get,
+ .put = sma1307_dapm_aif_out_put,
+ .private_value = (unsigned long)&sma1307_aif_out_source_enum
+};
+
+static const struct snd_kcontrol_new sma1307_sdo_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Switch",
+ .info = snd_soc_info_volsw,
+ .get = sma1307_dapm_sdo_enable_get,
+ .put = sma1307_dapm_sdo_enable_put,
+ .private_value = SOC_SINGLE_VALUE(SND_SOC_NOPM, 0, 1, 0, 0)
+};
+
+static const struct snd_kcontrol_new sma1307_enable_control =
+ SOC_DAPM_SINGLE("Switch", SMA1307_00_SYSTEM_CTRL, 0, 1, 0);
+
+static const struct snd_kcontrol_new sma1307_binary_mode_control[] = {
+ SOC_ENUM_EXT("Binary Mode", sma1307_binary_mode_enum,
+ snd_soc_get_enum_double, sma1307_binary_mode_put),
+};
+
+static const struct snd_kcontrol_new sma1307_snd_controls[] = {
+ SOC_SINGLE_TLV(SMA1307_VOL_CTRL_NAME, SMA1307_0A_SPK_VOL,
+ 0, 167, 1, sma1307_spk_tlv),
+ SOC_ENUM_EXT(SMA1307_TDM_RX0_POS_NAME, sma1307_tdm_slot_enum,
+ sma1307_tdm_slot_get, sma1307_tdm_slot_put),
+ SOC_ENUM_EXT(SMA1307_TDM_RX1_POS_NAME, sma1307_tdm_slot_enum,
+ sma1307_tdm_slot_get, sma1307_tdm_slot_put),
+ SOC_ENUM_EXT(SMA1307_TDM_TX0_POS_NAME, sma1307_tdm_slot_enum,
+ sma1307_tdm_slot_get, sma1307_tdm_slot_put),
+ SOC_ENUM_EXT(SMA1307_TDM_TX1_POS_NAME, sma1307_tdm_slot_enum,
+ sma1307_tdm_slot_get, sma1307_tdm_slot_put),
+ SOC_ENUM_EXT(SMA1307_RESET_CTRL_NAME, sma1307_reset_enum,
+ snd_soc_get_enum_double, sma1307_reset_put),
+ SOC_SINGLE_BOOL_EXT(SMA1307_FORCE_MUTE_CTRL_NAME, 0,
+ sma1307_force_mute_get, sma1307_force_mute_put),
+ SOC_SINGLE_BOOL_EXT(SMA1307_OT1_SW_PROT_CTRL_NAME, 0,
+ sma1307_sw_ot1_prot_get, sma1307_sw_ot1_prot_put),
+ SOC_SINGLE_BOOL_EXT(SMA1307_CHECK_FAULT_STATUS_NAME, 0,
+ sma1307_check_fault_status_get,
+ sma1307_check_fault_status_put),
+ SOC_SINGLE_EXT(SMA1307_CHECK_FAULT_PERIOD_NAME, SND_SOC_NOPM, 0, 600, 0,
+ sma1307_check_fault_period_get,
+ sma1307_check_fault_period_put),
+};
+
+static const struct snd_soc_dapm_widget sma1307_dapm_widgets[] = {
+ /* platform domain */
+ SND_SOC_DAPM_OUTPUT("SPK"),
+ SND_SOC_DAPM_INPUT("SDO"),
+
+ /* path domain */
+ SND_SOC_DAPM_MUX_E(SMA1307_AIF_IN_NAME, SND_SOC_NOPM, 0, 0,
+ &sma1307_aif_in_source_control,
+ sma1307_aif_in_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MUX_E("SDO Setting", SND_SOC_NOPM, 0, 0,
+ &sma1307_sdo_setting_control,
+ sma1307_sdo_setting_event,
+ SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MUX_E(SMA1307_AIF_OUT0_NAME, SND_SOC_NOPM, 0, 0,
+ &sma1307_aif_out0_source_control,
+ sma1307_aif_out_event,
+ SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MUX_E(SMA1307_AIF_OUT1_NAME, SND_SOC_NOPM, 0, 0,
+ &sma1307_aif_out1_source_control,
+ sma1307_aif_out_event,
+ SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_SWITCH_E("SDO Enable", SND_SOC_NOPM, 0, 0,
+ &sma1307_sdo_control,
+ sma1307_sdo_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER("Entry", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV_E("AMP Power", SND_SOC_NOPM, 0, 0, NULL, 0,
+ sma1307_power_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_SWITCH("AMP Enable", SND_SOC_NOPM, 0, 0,
+ &sma1307_enable_control),
+
+ /* stream domain */
+ SND_SOC_DAPM_AIF_IN("AIF IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF OUT", "Capture", 0, SND_SOC_NOPM, 0, 0),
+};
+
+static const struct snd_soc_dapm_route sma1307_audio_map[] = {
+ /* Playback */
+ { "AIF IN Source", "Mono", "AIF IN" },
+ { "AIF IN Source", "Left", "AIF IN" },
+ { "AIF IN Source", "Right", "AIF IN" },
+
+ { "SDO Enable", "Switch", "AIF IN" },
+
+ { "SDO Setting", "Data_One_48k", "SDO Enable" },
+ { "SDO Setting", "Data_Two_48k", "SDO Enable" },
+ { "SDO Setting", "Data_Two_24k", "SDO Enable" },
+ { "SDO Setting", "Clk_PLL", "SDO Enable" },
+ { "SDO Setting", "Clk_OSC", "SDO Enable" },
+
+ { "AIF OUT0 Source", "Disable", "SDO Setting" },
+ { "AIF OUT0 Source", "After_FmtC", "SDO Setting" },
+ { "AIF OUT0 Source", "After_Mixer", "SDO Setting" },
+ { "AIF OUT0 Source", "After_DSP", "SDO Setting" },
+ { "AIF OUT0 Source", "Vrms2_Avg", "SDO Setting" },
+ { "AIF OUT0 Source", "Battery", "SDO Setting" },
+ { "AIF OUT0 Source", "Temperature", "SDO Setting" },
+ { "AIF OUT0 Source", "After_Delay", "SDO Setting" },
+
+ { "AIF OUT1 Source", "Disable", "SDO Setting" },
+ { "AIF OUT1 Source", "After_FmtC", "SDO Setting" },
+ { "AIF OUT1 Source", "After_Mixer", "SDO Setting" },
+ { "AIF OUT1 Source", "After_DSP", "SDO Setting" },
+ { "AIF OUT1 Source", "Vrms2_Avg", "SDO Setting" },
+ { "AIF OUT1 Source", "Battery", "SDO Setting" },
+ { "AIF OUT1 Source", "Temperature", "SDO Setting" },
+ { "AIF OUT1 Source", "After_Delay", "SDO Setting" },
+
+ { "Entry", NULL, "AIF OUT0 Source" },
+ { "Entry", NULL, "AIF OUT1 Source" },
+ { "Entry", NULL, "AIF IN Source" },
+
+ { "AMP Power", NULL, "Entry" },
+
+ { "AMP Enable", "Switch", "AMP Power" },
+ { "SPK", NULL, "AMP Enable" },
+
+ /* Capture */
+ { "AIF OUT", NULL, "AMP Enable" },
+};
+
+static void sma1307_setup_pll(struct snd_soc_component *component,
+ unsigned int bclk)
+{
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+
+ int i = 0;
+
+ dev_dbg(component->dev, "%s: BCLK = %dHz\n", __func__, bclk);
+
+ if (sma1307->sys_clk_id == SMA1307_PLL_CLKIN_MCLK) {
+ dev_warn(component->dev, "%s: MCLK is not supported\n",
+ __func__);
+ } else if (sma1307->sys_clk_id == SMA1307_PLL_CLKIN_BCLK) {
+ for (i = 0; i < sma1307->num_of_pll_matches; i++) {
+ if (sma1307->pll_matches[i].input_clk == bclk)
+ break;
+ }
+ if (i == sma1307->num_of_pll_matches) {
+ dev_warn(component->dev,
+ "%s: No matching value between pll table and SCK\n",
+ __func__);
+ return;
+ }
+
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A2_TOP_MAN1,
+ SMA1307_PLL_MASK, SMA1307_PLL_ON);
+ }
+
+ regmap_write(sma1307->regmap, SMA1307_8B_PLL_POST_N,
+ sma1307->pll_matches[i].post_n);
+ regmap_write(sma1307->regmap, SMA1307_8C_PLL_N,
+ sma1307->pll_matches[i].n);
+ regmap_write(sma1307->regmap, SMA1307_8D_PLL_A_SETTING,
+ sma1307->pll_matches[i].vco);
+ regmap_write(sma1307->regmap, SMA1307_8E_PLL_P_CP,
+ sma1307->pll_matches[i].p_cp);
+}
+
+static int sma1307_dai_hw_params_amp(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+ unsigned int bclk = 0;
+
+ if (sma1307->format == SND_SOC_DAIFMT_DSP_A)
+ bclk = params_rate(params) * sma1307->frame_size;
+ else
+ bclk = params_rate(params) * params_physical_width(params)
+ * params_channels(params);
+
+ dev_dbg(component->dev,
+ "%s: rate = %d : bit size = %d : channel = %d\n",
+ __func__, params_rate(params), params_width(params),
+ params_channels(params));
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (sma1307->sys_clk_id == SMA1307_PLL_CLKIN_BCLK) {
+ if (sma1307->last_bclk != bclk) {
+ sma1307_setup_pll(component, bclk);
+ sma1307->last_bclk = bclk;
+ }
+ }
+
+ switch (params_rate(params)) {
+ case 8000:
+ case 12000:
+ case 16000:
+ case 24000:
+ case 32000:
+ case 44100:
+ case 48000:
+ break;
+
+ case 96000:
+ dev_warn(component->dev,
+ "%s: %d rate not support SDO\n", __func__,
+ params_rate(params));
+ break;
+
+ default:
+ dev_err(component->dev, "%s: not support rate : %d\n",
+ __func__, params_rate(params));
+
+ return -EINVAL;
+ }
+
+ /* substream->stream is SNDRV_PCM_STREAM_CAPTURE */
+ } else {
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A4_TOP_MAN3,
+ SMA1307_SCK_RATE_MASK
+ |
+ SMA1307_DATA_WIDTH_MASK,
+ SMA1307_SCK_32FS |
+ SMA1307_DATA_16BIT);
+ break;
+
+ case SNDRV_PCM_FORMAT_S24_LE:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A4_TOP_MAN3,
+ SMA1307_SCK_RATE_MASK
+ |
+ SMA1307_DATA_WIDTH_MASK,
+ SMA1307_SCK_64FS |
+ SMA1307_DATA_24BIT);
+ break;
+
+ case SNDRV_PCM_FORMAT_S32_LE:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A4_TOP_MAN3,
+ SMA1307_SCK_RATE_MASK
+ |
+ SMA1307_DATA_WIDTH_MASK,
+ SMA1307_SCK_64FS |
+ SMA1307_DATA_24BIT);
+ break;
+ default:
+ dev_err(component->dev,
+ "%s: not support data bit : %d\n", __func__,
+ params_format(params));
+ return -EINVAL;
+ }
+ }
+
+ switch (sma1307->format) {
+ case SND_SOC_DAIFMT_I2S:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_01_INPUT_CTRL1,
+ SMA1307_I2S_MODE_MASK,
+ SMA1307_STANDARD_I2S);
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A4_TOP_MAN3,
+ SMA1307_INTERFACE_MASK,
+ SMA1307_I2S_FORMAT);
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_01_INPUT_CTRL1,
+ SMA1307_I2S_MODE_MASK, SMA1307_LJ);
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A4_TOP_MAN3,
+ SMA1307_INTERFACE_MASK,
+ SMA1307_LJ_FORMAT);
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ switch (params_width(params)) {
+ case 16:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_01_INPUT_CTRL1,
+ SMA1307_I2S_MODE_MASK,
+ SMA1307_RJ_16BIT);
+ break;
+ case 24:
+ case 32:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_01_INPUT_CTRL1,
+ SMA1307_I2S_MODE_MASK,
+ SMA1307_RJ_24BIT);
+ break;
+ }
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_01_INPUT_CTRL1,
+ SMA1307_I2S_MODE_MASK,
+ SMA1307_STANDARD_I2S);
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A4_TOP_MAN3,
+ SMA1307_INTERFACE_MASK,
+ SMA1307_TDM_FORMAT);
+ break;
+ }
+
+ switch (params_width(params)) {
+ case 16:
+ case 24:
+ case 32:
+ break;
+ default:
+ dev_err(component->dev,
+ "%s: not support data bit : %d\n", __func__,
+ params_format(params));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int sma1307_dai_set_sysclk_amp(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_component *component = dai->component;
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+
+ switch (clk_id) {
+ case SMA1307_EXTERNAL_CLOCK_19_2:
+ case SMA1307_EXTERNAL_CLOCK_24_576:
+ case SMA1307_PLL_CLKIN_MCLK:
+ case SMA1307_PLL_CLKIN_BCLK:
+ break;
+ default:
+ dev_err(component->dev, "%s: Invalid clk id: %d\n",
+ __func__, clk_id);
+ return -EINVAL;
+ }
+ sma1307->sys_clk_id = clk_id;
+
+ return 0;
+}
+
+static int sma1307_dai_set_fmt_amp(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_component *component = dai->component;
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+
+ case SND_SOC_DAIFMT_CBC_CFC:
+ dev_dbg(component->dev,
+ "%s: %s\n", __func__, "I2S/TDM Device mode");
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_01_INPUT_CTRL1,
+ SMA1307_CONTROLLER_DEVICE_MASK,
+ SMA1307_DEVICE_MODE);
+ break;
+
+ case SND_SOC_DAIFMT_CBP_CFP:
+ dev_dbg(component->dev,
+ "%s: %s\n", __func__, "I2S/TDM Controller mode");
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_01_INPUT_CTRL1,
+ SMA1307_CONTROLLER_DEVICE_MASK,
+ SMA1307_CONTROLLER_MODE);
+ break;
+
+ default:
+ dev_err(component->dev,
+ "%s: Unsupported Controller/Device : 0x%x\n",
+ __func__, fmt);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_RIGHT_J:
+ case SND_SOC_DAIFMT_LEFT_J:
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ sma1307->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+ break;
+ default:
+ dev_err(component->dev,
+ "%s: Unsupported Audio Interface Format : 0x%x\n",
+ __func__, fmt);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+
+ case SND_SOC_DAIFMT_IB_NF:
+ dev_dbg(component->dev, "%s: %s\n",
+ __func__, "Invert BCLK + Normal Frame");
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_01_INPUT_CTRL1,
+ SMA1307_SCK_RISING_MASK,
+ SMA1307_SCK_RISING_EDGE);
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ dev_dbg(component->dev, "%s: %s\n",
+ __func__, "Invert BCLK + Invert Frame");
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_01_INPUT_CTRL1,
+ SMA1307_LEFTPOL_MASK
+ | SMA1307_SCK_RISING_MASK,
+ SMA1307_HIGH_FIRST_CH
+ | SMA1307_SCK_RISING_EDGE);
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ dev_dbg(component->dev, "%s: %s\n",
+ __func__, "Normal BCLK + Invert Frame");
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_01_INPUT_CTRL1,
+ SMA1307_LEFTPOL_MASK,
+ SMA1307_HIGH_FIRST_CH);
+ break;
+ case SND_SOC_DAIFMT_NB_NF:
+ dev_dbg(component->dev, "%s: %s\n",
+ __func__, "Normal BCLK + Normal Frame");
+ break;
+ default:
+ dev_err(component->dev,
+ "%s: Unsupported Bit & Frameclock : 0x%x\n",
+ __func__, fmt);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int sma1307_dai_set_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int tx_mask, unsigned int rx_mask,
+ int slots, int slot_width)
+{
+ struct snd_soc_component *component = dai->component;
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+
+ dev_dbg(component->dev, "%s: slots = %d, slot_width - %d\n",
+ __func__, slots, slot_width);
+
+ sma1307->frame_size = slot_width * slots;
+
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A4_TOP_MAN3,
+ SMA1307_INTERFACE_MASK, SMA1307_TDM_FORMAT);
+
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A5_TDM1,
+ SMA1307_TDM_TX_MODE_MASK,
+ SMA1307_TDM_TX_MONO);
+
+ switch (slot_width) {
+ case 16:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A6_TDM2,
+ SMA1307_TDM_DL_MASK,
+ SMA1307_TDM_DL_16);
+ break;
+ case 32:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A6_TDM2,
+ SMA1307_TDM_DL_MASK,
+ SMA1307_TDM_DL_32);
+ break;
+ default:
+ dev_err(component->dev, "%s: not support TDM %d slot_width\n",
+ __func__, slot_width);
+ return -EINVAL;
+ }
+
+ switch (slots) {
+ case 4:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A6_TDM2,
+ SMA1307_TDM_N_SLOT_MASK,
+ SMA1307_TDM_N_SLOT_4);
+ break;
+ case 8:
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A6_TDM2,
+ SMA1307_TDM_N_SLOT_MASK,
+ SMA1307_TDM_N_SLOT_8);
+ break;
+ default:
+ dev_err(component->dev, "%s: not support TDM %d slots\n",
+ __func__, slots);
+ return -EINVAL;
+ }
+
+ if (sma1307->tdm_slot0_rx < slots)
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A5_TDM1,
+ SMA1307_TDM_SLOT0_RX_POS_MASK,
+ sma1307->tdm_slot0_rx << 3);
+ else
+ dev_err(component->dev, "%s: Incorrect tdm-slot0-rx %d set\n",
+ __func__, sma1307->tdm_slot0_rx);
+
+ if (sma1307->tdm_slot1_rx < slots)
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A5_TDM1,
+ SMA1307_TDM_SLOT1_RX_POS_MASK,
+ sma1307->tdm_slot1_rx);
+ else
+ dev_err(component->dev, "%s: Incorrect tdm-slot1-rx %d set\n",
+ __func__, sma1307->tdm_slot1_rx);
+
+ if (sma1307->tdm_slot0_tx < slots)
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A6_TDM2,
+ SMA1307_TDM_SLOT0_TX_POS_MASK,
+ sma1307->tdm_slot0_tx << 3);
+ else
+ dev_err(component->dev, "%s: Incorrect tdm-slot0-tx %d set\n",
+ __func__, sma1307->tdm_slot0_tx);
+
+ if (sma1307->tdm_slot1_tx < slots)
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_A6_TDM2,
+ SMA1307_TDM_SLOT1_TX_POS_MASK,
+ sma1307->tdm_slot1_tx);
+ else
+ dev_err(component->dev, "%s: Incorrect tdm-slot1-tx %d set\n",
+ __func__, sma1307->tdm_slot1_tx);
+
+ return 0;
+}
+
+static int sma1307_dai_mute_stream(struct snd_soc_dai *dai, int mute,
+ int stream)
+{
+ struct snd_soc_component *component = dai->component;
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+
+ if (stream == SNDRV_PCM_STREAM_CAPTURE)
+ return 0;
+ if (mute) {
+ dev_dbg(component->dev, "%s: %s\n", __func__, "MUTE");
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_0E_MUTE_VOL_CTRL,
+ SMA1307_SPK_MUTE_MASK,
+ SMA1307_SPK_MUTE);
+ } else {
+ if (!sma1307->force_mute_status) {
+ dev_dbg(component->dev, "%s: %s\n", __func__,
+ "UNMUTE");
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_0E_MUTE_VOL_CTRL,
+ SMA1307_SPK_MUTE_MASK,
+ SMA1307_SPK_UNMUTE);
+ } else {
+ dev_dbg(sma1307->dev, "%s: FORCE MUTE!!!\n", __func__);
+ }
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops sma1307_dai_ops_amp = {
+ .hw_params = sma1307_dai_hw_params_amp,
+ .set_fmt = sma1307_dai_set_fmt_amp,
+ .set_sysclk = sma1307_dai_set_sysclk_amp,
+ .set_tdm_slot = sma1307_dai_set_tdm_slot,
+ .mute_stream = sma1307_dai_mute_stream,
+};
+
+#define SMA1307_RATES_PLAYBACK SNDRV_PCM_RATE_8000_96000
+#define SMA1307_RATES_CAPTURE SNDRV_PCM_RATE_8000_48000
+#define SMA1307_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver sma1307_dai[] = {
+ {
+ .name = "sma1307-amplifier",
+ .id = 0,
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SMA1307_RATES_PLAYBACK,
+ .formats = SMA1307_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SMA1307_RATES_CAPTURE,
+ .formats = SMA1307_FORMATS,
+ },
+ .ops = &sma1307_dai_ops_amp,
+ },
+};
+
+static void sma1307_check_fault_worker(struct work_struct *work)
+{
+ struct sma1307_priv *sma1307 =
+ container_of(work, struct sma1307_priv, check_fault_work.work);
+ unsigned int status1_val, status2_val;
+ char *envp[3] = { NULL, NULL, NULL };
+
+ if (sma1307->tsdw_cnt)
+ regmap_read(sma1307->regmap,
+ SMA1307_0A_SPK_VOL, &sma1307->cur_vol);
+ else
+ regmap_read(sma1307->regmap,
+ SMA1307_0A_SPK_VOL, &sma1307->init_vol);
+
+ regmap_read(sma1307->regmap, SMA1307_FA_STATUS1, &status1_val);
+ regmap_read(sma1307->regmap, SMA1307_FB_STATUS2, &status2_val);
+
+ if (~status1_val & SMA1307_OT1_OK_STATUS) {
+ dev_crit(sma1307->dev,
+ "%s: OT1(Over Temperature Level 1)\n", __func__);
+ envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT1");
+ if (sma1307->sw_ot1_prot) {
+ /* Volume control (Current Volume -3dB) */
+ if ((sma1307->cur_vol + 6) <= 0xFA) {
+ sma1307->cur_vol += 6;
+ regmap_write(sma1307->regmap,
+ SMA1307_0A_SPK_VOL,
+ sma1307->cur_vol);
+ envp[1] = kasprintf(GFP_KERNEL,
+ "VOLUME=0x%02X", sma1307->cur_vol);
+ }
+ }
+ sma1307->tsdw_cnt++;
+ } else if (sma1307->tsdw_cnt) {
+ regmap_write(sma1307->regmap,
+ SMA1307_0A_SPK_VOL, sma1307->init_vol);
+ sma1307->tsdw_cnt = 0;
+ sma1307->cur_vol = sma1307->init_vol;
+ envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT1_CLEAR");
+ envp[1] = kasprintf(GFP_KERNEL,
+ "VOLUME=0x%02X", sma1307->cur_vol);
+ }
+
+ if (~status1_val & SMA1307_OT2_OK_STATUS) {
+ dev_crit(sma1307->dev,
+ "%s: OT2(Over Temperature Level 2)\n", __func__);
+ envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT2");
+ }
+ if (status1_val & SMA1307_UVLO_STATUS) {
+ dev_crit(sma1307->dev,
+ "%s: UVLO(Under Voltage Lock Out)\n", __func__);
+ envp[0] = kasprintf(GFP_KERNEL, "STATUS=UVLO");
+ }
+ if (status1_val & SMA1307_OVP_BST_STATUS) {
+ dev_crit(sma1307->dev,
+ "%s: OVP_BST(Over Voltage Protection)\n", __func__);
+ envp[0] = kasprintf(GFP_KERNEL, "STATUS=OVP_BST");
+ }
+ if (status2_val & SMA1307_OCP_SPK_STATUS) {
+ dev_crit(sma1307->dev,
+ "%s: OCP_SPK(Over Current Protect SPK)\n", __func__);
+ envp[0] = kasprintf(GFP_KERNEL, "STATUS=OCP_SPK");
+ }
+ if (status2_val & SMA1307_OCP_BST_STATUS) {
+ dev_crit(sma1307->dev,
+ "%s: OCP_BST(Over Current Protect Boost)\n", __func__);
+ envp[0] = kasprintf(GFP_KERNEL, "STATUS=OCP_BST");
+ }
+ if (status2_val & SMA1307_CLK_MON_STATUS) {
+ dev_crit(sma1307->dev,
+ "%s: CLK_FAULT(No clock input)\n", __func__);
+ envp[0] = kasprintf(GFP_KERNEL, "STATUS=CLK_FAULT");
+ }
+
+ if (envp[0] != NULL) {
+ if (kobject_uevent_env(sma1307->kobj, KOBJ_CHANGE, envp))
+ dev_err(sma1307->dev,
+ "%s: Error sending uevent\n", __func__);
+ kfree(envp[0]);
+ kfree(envp[1]);
+ }
+
+ if (sma1307->check_fault_status) {
+ if (sma1307->check_fault_period > 0)
+ queue_delayed_work(system_freezable_wq,
+ &sma1307->check_fault_work,
+ sma1307->check_fault_period * HZ);
+ else
+ queue_delayed_work(system_freezable_wq,
+ &sma1307->check_fault_work,
+ CHECK_PERIOD_TIME * HZ);
+ }
+}
+
+static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *file)
+{
+ const struct firmware *fw;
+ int *data, size, offset, num_mode;
+ int ret;
+
+ ret = request_firmware(&fw, file, sma1307->dev);
+
+ if (ret) {
+ dev_err(sma1307->dev, "%s: failed to read \"%s\": %pe\n",
+ __func__, setting_file, ERR_PTR(ret));
+ sma1307->set.status = false;
+ return;
+ } else if ((fw->size) < SMA1307_SETTING_HEADER_SIZE) {
+ dev_err(sma1307->dev, "%s: Invalid file\n", __func__);
+ release_firmware(fw);
+ sma1307->set.status = false;
+ return;
+ }
+
+ data = kzalloc(fw->size, GFP_KERNEL);
+ size = fw->size >> 2;
+ memcpy(data, fw->data, fw->size);
+
+ release_firmware(fw);
+
+ /* HEADER */
+ sma1307->set.header_size = SMA1307_SETTING_HEADER_SIZE;
+ sma1307->set.checksum = data[sma1307->set.header_size - 2];
+ sma1307->set.num_mode = data[sma1307->set.header_size - 1];
+ num_mode = sma1307->set.num_mode;
+ sma1307->set.header = devm_kzalloc(sma1307->dev,
+ sma1307->set.header_size,
+ GFP_KERNEL);
+ memcpy(sma1307->set.header, data,
+ sma1307->set.header_size * sizeof(int));
+
+ if ((sma1307->set.checksum >> 8) != SMA1307_SETTING_CHECKSUM) {
+ dev_err(sma1307->dev, "%s: failed by dismatch \"%s\"\n",
+ __func__, setting_file);
+ sma1307->set.status = false;
+ return;
+ }
+
+ /* DEFAULT */
+ sma1307->set.def_size = SMA1307_SETTING_DEFAULT_SIZE;
+ sma1307->set.def
+ = devm_kzalloc(sma1307->dev,
+ sma1307->set.def_size * sizeof(int), GFP_KERNEL);
+ memcpy(sma1307->set.def,
+ &data[sma1307->set.header_size],
+ sma1307->set.def_size * sizeof(int));
+
+ /* MODE */
+ offset = sma1307->set.header_size + sma1307->set.def_size;
+ sma1307->set.mode_size = DIV_ROUND_CLOSEST(size - offset, num_mode + 1);
+ for (int i = 0; i < num_mode; i++) {
+ sma1307->set.mode_set[i]
+ = devm_kzalloc(sma1307->dev,
+ sma1307->set.mode_size * 2 * sizeof(int),
+ GFP_KERNEL);
+ for (int j = 0; j < sma1307->set.mode_size; j++) {
+ sma1307->set.mode_set[i][2 * j]
+ = data[offset + ((num_mode + 1) * j)];
+ sma1307->set.mode_set[i][2 * j + 1]
+ = data[offset + ((num_mode + 1) * j + i + 1)];
+ }
+ }
+
+ kfree(data);
+ sma1307->set.status = true;
+
+}
+
+static void sma1307_reset(struct snd_soc_component *component)
+{
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+ unsigned int status = 0;
+
+ regmap_read(sma1307->regmap, SMA1307_FF_DEVICE_INDEX, &status);
+
+ sma1307->rev_num = status & SMA1307_REV_NUM_STATUS;
+ dev_dbg(component->dev, "%s: SMA1307 Revision %d\n",
+ __func__, sma1307->rev_num);
+ regmap_read(sma1307->regmap, SMA1307_99_OTP_TRM2, &sma1307->otp_trm2);
+ regmap_read(sma1307->regmap, SMA1307_9A_OTP_TRM3, &sma1307->otp_trm3);
+
+ if ((sma1307->otp_trm2 & SMA1307_OTP_STAT_MASK) != SMA1307_OTP_STAT_1)
+ dev_warn(component->dev, "%s: SMA1307 OTP Status Fail\n",
+ __func__);
+
+ /* Register Initial Value Setting */
+ sma1307_setting_loaded(sma1307, setting_file);
+ if (sma1307->set.status)
+ sma1307_set_binary(component);
+ else
+ sma1307_set_default(component);
+
+ regmap_update_bits(sma1307->regmap,
+ SMA1307_93_INT_CTRL,
+ SMA1307_DIS_INT_MASK, SMA1307_HIGH_Z_INT);
+ regmap_write(sma1307->regmap, SMA1307_0A_SPK_VOL, sma1307->init_vol);
+}
+
+static void sma1307_set_binary(struct snd_soc_component *component)
+{
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+ int i = 0, mode = 0;
+
+ for (i = 0; i < (sma1307->set.def_size); i++) {
+ if (sma1307_writeable_register(sma1307->dev, i)
+ && ((i < SMA1307_97_OTP_TRM0)
+ || (i > SMA1307_9A_OTP_TRM3))) {
+ regmap_write(sma1307->regmap, i, sma1307->set.def[i]);
+
+ }
+ }
+ for (i = 0; i < (sma1307->set.mode_size); i++) {
+ if (sma1307_writeable_register(sma1307->dev, i)
+ && ((i < SMA1307_97_OTP_TRM0)
+ || (i > SMA1307_9A_OTP_TRM3))) {
+ mode = sma1307->binary_mode;
+ regmap_write(sma1307->regmap,
+ sma1307->set.mode_set[mode][2 * i],
+ sma1307->set.mode_set[mode][2 * i +
+ 1]);
+ }
+ }
+}
+
+static void sma1307_set_default(struct snd_soc_component *component)
+{
+ struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
+ int i = 0;
+
+ for (i = 0; i < (unsigned int)ARRAY_SIZE(sma1307_reg_def); i++)
+ regmap_write(sma1307->regmap,
+ sma1307_reg_def[i].reg,
+ sma1307_reg_def[i].def);
+
+ if (!strcmp(sma1307->name, DEVICE_NAME_SMA1307AQ))
+ sma1307->data->init(sma1307->regmap);
+}
+
+static int sma1307_probe(struct snd_soc_component *component)
+{
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_component_get_dapm(component);
+
+ snd_soc_dapm_sync(dapm);
+
+ sma1307_amp_component = component;
+
+ snd_soc_add_component_controls(component, sma1307_binary_mode_control,
+ ARRAY_SIZE(sma1307_binary_mode_control));
+ sma1307_reset(component);
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver sma1307_component = {
+ .probe = sma1307_probe,
+ .controls = sma1307_snd_controls,
+ .num_controls = ARRAY_SIZE(sma1307_snd_controls),
+ .dapm_widgets = sma1307_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sma1307_dapm_widgets),
+ .dapm_routes = sma1307_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(sma1307_audio_map),
+};
+
+static const struct regmap_config sma_i2c_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = SMA1307_FF_DEVICE_INDEX,
+ .readable_reg = sma1307_readable_register,
+ .writeable_reg = sma1307_writeable_register,
+ .volatile_reg = sma1307_volatile_register,
+
+ .reg_defaults = sma1307_reg_def,
+ .num_reg_defaults = ARRAY_SIZE(sma1307_reg_def),
+};
+
+static void sma1307aq_init(struct regmap *regmap)
+{
+ /* Guidelines for driving 4ohm load */
+ /* Brown Out Protection */
+ regmap_write(regmap, SMA1307_02_BROWN_OUT_PROT1, 0x62);
+ regmap_write(regmap, SMA1307_03_BROWN_OUT_PROT2, 0x5D);
+ regmap_write(regmap, SMA1307_04_BROWN_OUT_PROT3, 0x57);
+ regmap_write(regmap, SMA1307_05_BROWN_OUT_PROT8, 0x54);
+ regmap_write(regmap, SMA1307_06_BROWN_OUT_PROT9, 0x51);
+ regmap_write(regmap,
+ SMA1307_07_BROWN_OUT_PROT10, 0x4D);
+ regmap_write(regmap,
+ SMA1307_08_BROWN_OUT_PROT11, 0x4B);
+ regmap_write(regmap, SMA1307_27_BROWN_OUT_PROT4, 0x3C);
+ regmap_write(regmap, SMA1307_28_BROWN_OUT_PROT5, 0x5B);
+ regmap_write(regmap,
+ SMA1307_29_BROWN_OUT_PROT12, 0x78);
+ regmap_write(regmap,
+ SMA1307_2A_BROWN_OUT_PROT13, 0x96);
+ regmap_write(regmap,
+ SMA1307_2B_BROWN_OUT_PROT14, 0xB4);
+ regmap_write(regmap,
+ SMA1307_2C_BROWN_OUT_PROT15, 0xD3);
+ /* FDPEC Gain */
+ regmap_write(regmap, SMA1307_35_FDPEC_CTRL0, 0x16);
+ /* FLT Vdd */
+ regmap_write(regmap, SMA1307_92_FDPEC_CTRL1, 0xA0);
+ /* Boost Max */
+ regmap_write(regmap, SMA1307_AB_BOOST_CTRL4, 0x0F);
+}
+
+static const struct sma1307_data sma1307aq_data = {
+ .name = DEVICE_NAME_SMA1307AQ,
+ .init = sma1307aq_init,
+};
+
+static int sma1307_i2c_probe(struct i2c_client *client)
+{
+ struct sma1307_priv *sma1307;
+ const struct sma1307_data *data;
+ int ret = 0;
+ unsigned int device_info;
+
+ sma1307 = devm_kzalloc(&client->dev,
+ sizeof(*sma1307), GFP_KERNEL);
+ if (!sma1307)
+ return -ENOMEM;
+
+ sma1307->regmap = devm_regmap_init_i2c(client, &sma_i2c_regmap);
+ if (IS_ERR(sma1307->regmap)) {
+ return dev_err_probe(&client->dev, PTR_ERR(sma1307->regmap),
+ "%s: failed to allocate register map\n", __func__);
+ }
+
+ data = device_get_match_data(&client->dev);
+ if (!data)
+ return -ENODEV;
+
+ sma1307->data = data;
+
+ /* set initial value as normal AMP IC status */
+ sma1307->name = client->name;
+ sma1307->format = SND_SOC_DAIFMT_I2S;
+ sma1307->sys_clk_id = SMA1307_PLL_CLKIN_BCLK;
+ sma1307->num_of_pll_matches = ARRAY_SIZE(sma1307_pll_matches);
+
+ sma1307->check_fault_period = CHECK_PERIOD_TIME;
+ sma1307->check_fault_status = true;
+ sma1307->init_vol = 0x32;
+ sma1307->cur_vol = sma1307->init_vol;
+ sma1307->sw_ot1_prot = true;
+
+ mutex_init(&sma1307->default_lock);
+
+ INIT_DELAYED_WORK(&sma1307->check_fault_work,
+ sma1307_check_fault_worker);
+
+ sma1307->dev = &client->dev;
+ sma1307->kobj = &client->dev.kobj;
+
+ i2c_set_clientdata(client, sma1307);
+
+ sma1307->pll_matches = sma1307_pll_matches;
+
+ regmap_read(sma1307->regmap,
+ SMA1307_FF_DEVICE_INDEX, &device_info);
+
+ if ((device_info & 0xF8) != SMA1307_DEVICE_ID) {
+ dev_err(&client->dev,
+ "%s: device initialization error (0x%02X)",
+ __func__, device_info);
+ return -ENODEV;
+ }
+ dev_dbg(&client->dev, "%s: chip version 0x%02X\n",
+ __func__, device_info);
+
+ i2c_set_clientdata(client, sma1307);
+
+ ret = devm_snd_soc_register_component(&client->dev,
+ &sma1307_component, sma1307_dai,
+ 1);
+
+ if (ret) {
+ dev_err(&client->dev, "%s: failed to register component\n",
+ __func__);
+
+ return ret;
+ }
+
+ return ret;
+}
+
+static void sma1307_i2c_remove(struct i2c_client *client)
+{
+ struct sma1307_priv *sma1307 =
+ (struct sma1307_priv *)i2c_get_clientdata(client);
+
+ cancel_delayed_work_sync(&sma1307->check_fault_work);
+}
+
+static const struct i2c_device_id sma1307_i2c_id[] = {
+ { "sma1307a", 0 },
+ { "sma1307aq", 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, sma1307_i2c_id);
+
+static const struct of_device_id sma1307_of_match[] = {
+ {
+ .compatible = "irondevice,sma1307a",
+ },
+ {
+ .compatible = "irondevice,sma1307aq",
+ .data = &sma1307aq_data //AEC-Q100 Qualificated
+ },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, sma1307_of_match);
+
+static struct i2c_driver sma1307_i2c_driver = {
+ .driver = {
+ .name = "sma1307",
+ .of_match_table = sma1307_of_match,
+ },
+ .probe = sma1307_i2c_probe,
+ .remove = sma1307_i2c_remove,
+ .id_table = sma1307_i2c_id,
+};
+
+module_i2c_driver(sma1307_i2c_driver);
+
+MODULE_DESCRIPTION("ALSA SoC SMA1307 driver");
+MODULE_AUTHOR("Gyuhwa Park, <gyuhwa.park@irondevice.com>");
+MODULE_AUTHOR("KS Jo, <kiseok.jo@irondevice.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sma1307.h b/sound/soc/codecs/sma1307.h
new file mode 100644
index 000000000000..44aab52a32f9
--- /dev/null
+++ b/sound/soc/codecs/sma1307.h
@@ -0,0 +1,444 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * sma1307.h -- sma1307 ALSA SoC Audio driver
+ *
+ * Copyright 2024 Iron Device Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _SMA1307_H
+#define _SMA1307_H
+
+#include <sound/soc.h>
+
+enum sma1307_fault {
+ SMA1307_FAULT_OT1,
+ SMA1307_FAULT_OT2,
+ SMA1307_FAULT_UVLO,
+ SMA1307_FAULT_OVP_BST,
+ SMA1307_FAULT_OCP_SPK,
+ SMA1307_FAULT_OCP_BST,
+ SMA1307_FAULT_CLK
+};
+
+enum sma1307_mode {
+ SMA1307_MONO_MODE,
+ SMA1307_LEFT_MODE,
+ SMA1307_RIGHT_MODE,
+};
+
+enum sma1307_sdo_mode {
+ SMA1307_OUT_DATA_ONE_48K,
+ SMA1307_OUT_DATA_TWO_48K,
+ SMA1307_OUT_DATA_TWO_24K,
+ SMA1307_OUT_CLK_PLL,
+ SMA1307_OUT_CLK_OSC
+};
+
+enum sma1307_sdo_source {
+ SMA1307_OUT_DISABLE,
+ SMA1307_OUT_FORMAT_C,
+ SMA1307_OUT_MIXER_OUT,
+ SMA1307_OUT_AFTER_DSP,
+ SMA1307_OUT_VRMS2_AVG,
+ SMA1307_OUT_BATTERY,
+ SMA1307_OUT_TEMP,
+ SMA1307_OUT_AFTER_DELAY
+};
+
+struct sma1307_setting_file {
+ bool status;
+ char *header;
+ int *def;
+ int *mode_set[5];
+ int checksum;
+ int num_mode;
+ size_t header_size;
+ size_t def_size;
+ size_t mode_size;
+};
+
+#define SMA1307_I2C_ADDR_00 0x1e
+#define SMA1307_I2C_ADDR_01 0x3e
+#define SMA1307_I2C_ADDR_10 0x5e
+#define SMA1307_I2C_ADDR_11 0x7e
+
+#define DEVICE_NAME_SMA1307A "sma1307a"
+#define DEVICE_NAME_SMA1307AQ "sma1307aq"
+
+#define SMA1307_EXTERNAL_CLOCK_19_2 0x00
+#define SMA1307_EXTERNAL_CLOCK_24_576 0x01
+#define SMA1307_PLL_CLKIN_MCLK 0x02
+#define SMA1307_PLL_CLKIN_BCLK 0x03
+
+#define SMA1307_OFFSET_DEFAULT_MODE 0x00
+#define SMA1307_OFFSET_BURNING_MODE 0x01
+
+#define SMA1307_SETTING_HEADER_SIZE 0x08
+#define SMA1307_SETTING_DEFAULT_SIZE 0xC0
+
+#define SMA1307_DEFAULT_SET 0x00
+#define SMA1307_BINARY_FILE_SET 0x01
+
+/* Controls Name */
+#define SMA1307_REG_CTRL_NAME "Register Byte Control"
+#define SMA1307_VOL_CTRL_NAME "Speaker Volume"
+#define SMA1307_FORCE_MUTE_CTRL_NAME "Force Mute Switch"
+#define SMA1307_TDM_RX0_POS_NAME "TDM RX Slot0 Position"
+#define SMA1307_TDM_RX1_POS_NAME "TDM RX Slot1 Position"
+#define SMA1307_TDM_TX0_POS_NAME "TDM TX Slot0 Position"
+#define SMA1307_TDM_TX1_POS_NAME "TDM TX Slot1 Position"
+#define SMA1307_OT1_SW_PROT_CTRL_NAME "OT1 SW Protection Switch"
+#define SMA1307_RESET_CTRL_NAME "Reset Switch"
+#define SMA1307_CHECK_FAULT_STATUS_NAME "Check Fault Status"
+#define SMA1307_CHECK_FAULT_PERIOD_NAME "Check Fault Period"
+
+/* DAPM Name */
+#define SMA1307_AIF_IN_NAME "AIF IN Source"
+#define SMA1307_AIF_OUT0_NAME "AIF OUT0 Source"
+#define SMA1307_AIF_OUT1_NAME "AIF OUT1 Source"
+
+/*
+ * SMA1307 Register Definition
+ */
+
+/* SMA1307 Register Addresses */
+#define SMA1307_00_SYSTEM_CTRL 0x00
+#define SMA1307_01_INPUT_CTRL1 0x01
+#define SMA1307_02_BROWN_OUT_PROT1 0x02
+#define SMA1307_03_BROWN_OUT_PROT2 0x03
+#define SMA1307_04_BROWN_OUT_PROT3 0x04
+#define SMA1307_05_BROWN_OUT_PROT8 0x05
+#define SMA1307_06_BROWN_OUT_PROT9 0x06
+#define SMA1307_07_BROWN_OUT_PROT10 0x07
+#define SMA1307_08_BROWN_OUT_PROT11 0x08
+#define SMA1307_09_OUTPUT_CTRL 0x09
+#define SMA1307_0A_SPK_VOL 0x0A
+#define SMA1307_0B_BST_TEST 0x0B
+#define SMA1307_0C_BOOST_CTRL8 0x0C
+#define SMA1307_0D_SPK_TEST 0x0D
+#define SMA1307_0E_MUTE_VOL_CTRL 0x0E
+#define SMA1307_0F_VBAT_TEMP_SENSING 0x0F
+
+#define SMA1307_10_SYSTEM_CTRL1 0x10
+#define SMA1307_11_SYSTEM_CTRL2 0x11
+#define SMA1307_12_SYSTEM_CTRL3 0x12
+#define SMA1307_13_DELAY 0x13
+#define SMA1307_14_MODULATOR 0x14
+#define SMA1307_15_BASS_SPK1 0x15
+#define SMA1307_16_BASS_SPK2 0x16
+#define SMA1307_17_BASS_SPK3 0x17
+#define SMA1307_18_BASS_SPK4 0x18
+#define SMA1307_19_BASS_SPK5 0x19
+#define SMA1307_1A_BASS_SPK6 0x1A
+#define SMA1307_1B_BASS_SPK7 0x1B
+#define SMA1307_1C_BROWN_OUT_PROT20 0x1C
+#define SMA1307_1D_BROWN_OUT_PROT0 0x1D
+#define SMA1307_1E_TONE_GENERATOR 0x1E
+#define SMA1307_1F_TONE_FINE_VOLUME 0x1F
+
+#define SMA1307_22_COMP_HYS_SEL 0x22
+#define SMA1307_23_COMPLIM1 0x23
+#define SMA1307_24_COMPLIM2 0x24
+#define SMA1307_25_COMPLIM3 0x25
+#define SMA1307_26_COMPLIM4 0x26
+#define SMA1307_27_BROWN_OUT_PROT4 0x27
+#define SMA1307_28_BROWN_OUT_PROT5 0x28
+#define SMA1307_29_BROWN_OUT_PROT12 0x29
+#define SMA1307_2A_BROWN_OUT_PROT13 0x2A
+#define SMA1307_2B_BROWN_OUT_PROT14 0x2B
+#define SMA1307_2C_BROWN_OUT_PROT15 0x2C
+#define SMA1307_2D_BROWN_OUT_PROT6 0x2D
+#define SMA1307_2E_BROWN_OUT_PROT7 0x2E
+#define SMA1307_2F_BROWN_OUT_PROT16 0x2F
+
+#define SMA1307_30_BROWN_OUT_PROT17 0x30
+#define SMA1307_31_BROWN_OUT_PROT18 0x31
+#define SMA1307_32_BROWN_OUT_PROT19 0x32
+#define SMA1307_34_OCP_SPK 0x34
+#define SMA1307_35_FDPEC_CTRL0 0x35
+#define SMA1307_36_PROTECTION 0x36
+#define SMA1307_37_SLOPECTRL 0x37
+#define SMA1307_38_POWER_METER 0x38
+#define SMA1307_39_PMT_NZ_VAL 0x39
+#define SMA1307_3B_TEST1 0x3B
+#define SMA1307_3C_TEST2 0x3C
+#define SMA1307_3D_TEST3 0x3D
+#define SMA1307_3E_IDLE_MODE_CTRL 0x3E
+#define SMA1307_3F_ATEST2 0x3F
+#define SMA1307_8B_PLL_POST_N 0x8B
+#define SMA1307_8C_PLL_N 0x8C
+#define SMA1307_8D_PLL_A_SETTING 0x8D
+#define SMA1307_8E_PLL_P_CP 0x8E
+#define SMA1307_8F_ANALOG_TEST 0x8F
+
+#define SMA1307_90_CRESTLIM1 0x90
+#define SMA1307_91_CRESTLIM2 0x91
+#define SMA1307_92_FDPEC_CTRL1 0x92
+#define SMA1307_93_INT_CTRL 0x93
+#define SMA1307_94_BOOST_CTRL9 0x94
+#define SMA1307_95_BOOST_CTRL10 0x95
+#define SMA1307_96_BOOST_CTRL11 0x96
+#define SMA1307_97_OTP_TRM0 0x97
+#define SMA1307_98_OTP_TRM1 0x98
+#define SMA1307_99_OTP_TRM2 0x99
+#define SMA1307_9A_OTP_TRM3 0x9A
+
+#define SMA1307_A0_PAD_CTRL0 0xA0
+#define SMA1307_A1_PAD_CTRL1 0xA1
+#define SMA1307_A2_TOP_MAN1 0xA2
+#define SMA1307_A3_TOP_MAN2 0xA3
+#define SMA1307_A4_TOP_MAN3 0xA4
+#define SMA1307_A5_TDM1 0xA5
+#define SMA1307_A6_TDM2 0xA6
+#define SMA1307_A7_CLK_MON 0xA7
+#define SMA1307_A8_BOOST_CTRL1 0xA8
+#define SMA1307_A9_BOOST_CTRL2 0xA9
+#define SMA1307_AA_BOOST_CTRL3 0xAA
+#define SMA1307_AB_BOOST_CTRL4 0xAB
+#define SMA1307_AC_BOOST_CTRL5 0xAC
+#define SMA1307_AD_BOOST_CTRL6 0xAD
+#define SMA1307_AE_BOOST_CTRL7 0xAE
+#define SMA1307_AF_LPF 0xAF
+
+#define SMA1307_B0_RMS_TC1 0xB0
+#define SMA1307_B1_RMS_TC2 0xB1
+#define SMA1307_B2_AVG_TC1 0xB2
+#define SMA1307_B3_AVG_TC2 0xB3
+#define SMA1307_B4_PRVALUE1 0xB4
+#define SMA1307_B5_PRVALUE2 0xB5
+#define SMA1307_B8_SPK_NG_CTRL1 0xB8
+#define SMA1307_B9_SPK_NG_CTRL2 0xB9
+#define SMA1307_BA_DGC1 0xBA
+#define SMA1307_BB_DGC2 0xBB
+#define SMA1307_BC_DGC3 0xBC
+#define SMA1307_BD_MCBS_CTRL1 0xBD
+#define SMA1307_BE_MCBS_CTRL2 0xBE
+
+/* Status Register Read Only */
+#define SMA1307_F5_READY_FOR_V_SAR 0xF5
+#define SMA1307_F7_READY_FOR_T_SAR 0xF7
+#define SMA1307_F8_STATUS_T1 0xF8
+#define SMA1307_F9_STATUS_T2 0xF9
+#define SMA1307_FA_STATUS1 0xFA
+#define SMA1307_FB_STATUS2 0xFB
+#define SMA1307_FC_STATUS3 0xFC
+#define SMA1307_FD_STATUS4 0xFD
+#define SMA1307_FE_STATUS5 0xFE
+#define SMA1307_FF_DEVICE_INDEX 0xFF
+
+/* SMA1307 Registers Bit Fields */
+/* Power On/Off */
+#define SMA1307_POWER_MASK BIT(0)
+#define SMA1307_POWER_OFF 0
+#define SMA1307_POWER_ON BIT(0)
+
+/* Reset */
+#define SMA1307_RESET_MASK BIT(1)
+#define SMA1307_RESET_ON BIT(1)
+
+/* Left Polarity */
+#define SMA1307_LEFTPOL_MASK BIT(3)
+#define SMA1307_LOW_FIRST_CH 0
+#define SMA1307_HIGH_FIRST_CH BIT(3)
+
+/* SCK Falling/Rising */
+#define SMA1307_SCK_RISING_MASK BIT(2)
+#define SMA1307_SCK_FALLING_EDGE 0
+#define SMA1307_SCK_RISING_EDGE BIT(2)
+
+/* SPK Mute */
+#define SMA1307_SPK_MUTE_MASK BIT(0)
+#define SMA1307_SPK_UNMUTE 0
+#define SMA1307_SPK_MUTE BIT(0)
+
+/* SPK Mode */
+#define SMA1307_SPK_MODE_MASK (BIT(2)|BIT(3)|BIT(4))
+#define SMA1307_SPK_OFF 0
+#define SMA1307_SPK_MONO BIT(2)
+#define SMA1307_SPK_STEREO BIT(4)
+
+/* Mono Mix */
+#define SMA1307_MONOMIX_MASK BIT(0)
+#define SMA1307_MONOMIX_OFF 0
+#define SMA1307_MONOMIX_ON BIT(0)
+
+/* LR Data Swap */
+#define SMA1307_LR_DATA_SW_MASK BIT(4)
+#define SMA1307_LR_DATA_SW_NORMAL 0
+#define SMA1307_LR_DATA_SW_SWAP BIT(4)
+
+/* PLL On/Off */
+#define SMA1307_PLL_MASK BIT(6)
+#define SMA1307_PLL_ON 0
+#define SMA1307_PLL_OFF BIT(6)
+
+/* Input Format */
+#define SMA1307_I2S_MODE_MASK (BIT(4)|BIT(5)|BIT(6))
+#define SMA1307_STANDARD_I2S 0
+#define SMA1307_LJ BIT(4)
+#define SMA1307_RJ_16BIT BIT(6)
+#define SMA1307_RJ_18BIT (BIT(4)|BIT(6))
+#define SMA1307_RJ_20BIT (BIT(5)|BIT(6))
+#define SMA1307_RJ_24BIT (BIT(4)|BIT(5)|BIT(6))
+
+/* Controller / Device Setting */
+#define SMA1307_CONTROLLER_DEVICE_MASK BIT(7)
+#define SMA1307_DEVICE_MODE 0
+#define SMA1307_CONTROLLER_MODE BIT(7)
+
+/* Port Config */
+#define SMA1307_PORT_CONFIG_MASK (BIT(6)|BIT(7))
+#define SMA1307_INPUT_PORT_ONLY 0
+#define SMA1307_OUTPUT_PORT_ENABLE BIT(7)
+
+/* SDO Output */
+#define SMA1307_SDO_OUTPUT_MASK BIT(3)
+#define SMA1307_LOGIC_OUTPUT 0
+#define SMA1307_HIGH_Z_OUTPUT BIT(3)
+
+#define SMA1307_DATA_CLK_SEL_MASK (BIT(6)|BIT(7))
+#define SMA1307_SDO_DATA 0
+#define SMA1307_SDO_CLK_PLL BIT(6)
+#define SMA1307_SDO_CLK_OSC (BIT(6)|BIT(7))
+
+/* SDO Output2 */
+#define SMA1307_SDO_OUTPUT2_MASK BIT(0)
+#define SMA1307_ONE_SDO_PER_CH 0
+#define SMA1307_TWO_SDO_PER_CH BIT(0)
+
+/* SDO Output3 */
+#define SMA1307_SDO_OUTPUT3_MASK BIT(2)
+#define SMA1307_SDO_OUTPUT3_DIS 0
+#define SMA1307_TWO_SDO_PER_CH_24K BIT(2)
+
+/* SDO OUT1 Select*/
+#define SMA1307_SDO_OUT1_SEL_MASK (BIT(3)|BIT(4)|BIT(5))
+#define SMA1307_SDO1_DISABLE 0
+#define SMA1307_SDO1_FORMAT_C BIT(3)
+#define SMA1307_SDO1_MONO_MIX BIT(4)
+#define SMA1307_SDO1_AFTER_DSP (BIT(3)|BIT(4))
+#define SMA1307_SDO1_VRMS2_AVG BIT(5)
+#define SMA1307_SDO1_VBAT_MON (BIT(3)|BIT(5))
+#define SMA1307_SDO1_TEMP_MON (BIT(4)|BIT(5))
+#define SMA1307_SDO1_AFTER_DELAY (BIT(3)|BIT(4)|BIT(5))
+
+/* SDO OUT0 Select*/
+#define SMA1307_SDO_OUT0_SEL_MASK (BIT(0)|BIT(1)|BIT(2))
+#define SMA1307_SDO0_DISABLE 0
+#define SMA1307_SDO0_FORMAT_C BIT(0)
+#define SMA1307_SDO0_MONO_MIX BIT(1)
+#define SMA1307_SDO0_AFTER_DSP (BIT(0)|BIT(1))
+#define SMA1307_SDO0_VRMS2_AVG BIT(2)
+#define SMA1307_SDO0_VBAT_MON (BIT(0)|BIT(2))
+#define SMA1307_SDO0_TEMP_MON (BIT(1)|BIT(2))
+#define SMA1307_SDO0_AFTER_DELAY (BIT(0)|BIT(1)|BIT(2))
+
+/* INTERRUPT Operation */
+#define SMA1307_SEL_INT_MASK BIT(2)
+#define SMA1307_INT_CLEAR_AUTO 0
+#define SMA1307_INT_CLEAR_MANUAL BIT(2)
+
+/* INTERRUPT CLEAR */
+#define SMA1307_CLR_INT_MASK BIT(1)
+#define SMA1307_INT_READY 0
+#define SMA1307_INT_CLEAR BIT(1)
+
+/* INTERRUPT Disable */
+#define SMA1307_DIS_INT_MASK BIT(0)
+#define SMA1307_NORMAL_INT 0
+#define SMA1307_HIGH_Z_INT BIT(0)
+
+/* Interface Control */
+#define SMA1307_INTERFACE_MASK (BIT(5)|BIT(6)|BIT(7))
+#define SMA1307_LJ_FORMAT BIT(5)
+#define SMA1307_I2S_FORMAT (BIT(5)|BIT(6))
+#define SMA1307_TDM_FORMAT BIT(7)
+
+#define SMA1307_SCK_RATE_MASK (BIT(3)|BIT(4))
+#define SMA1307_SCK_64FS 0
+#define SMA1307_SCK_32FS BIT(4)
+
+#define SMA1307_DATA_WIDTH_MASK (BIT(1)|BIT(2))
+#define SMA1307_DATA_24BIT 0
+#define SMA1307_DATA_16BIT (BIT(1)|BIT(2))
+
+#define SMA1307_TDM_TX_MODE_MASK BIT(6)
+#define SMA1307_TDM_TX_MONO 0
+#define SMA1307_TDM_TX_STEREO BIT(6)
+
+#define SMA1307_TDM_SLOT0_RX_POS_MASK (BIT(3)|BIT(4)|BIT(5))
+#define SMA1307_TDM_SLOT0_RX_POS_0 0
+#define SMA1307_TDM_SLOT0_RX_POS_1 BIT(3)
+#define SMA1307_TDM_SLOT0_RX_POS_2 BIT(4)
+#define SMA1307_TDM_SLOT0_RX_POS_3 (BIT(3)|BIT(4))
+#define SMA1307_TDM_SLOT0_RX_POS_4 BIT(5)
+#define SMA1307_TDM_SLOT0_RX_POS_5 (BIT(3)|BIT(5))
+#define SMA1307_TDM_SLOT0_RX_POS_6 (BIT(4)|BIT(5))
+#define SMA1307_TDM_SLOT0_RX_POS_7 (BIT(3)|BIT(4)|BIT(5))
+
+#define SMA1307_TDM_SLOT1_RX_POS_MASK (BIT(0)|BIT(1)|BIT(2))
+#define SMA1307_TDM_SLOT1_RX_POS_0 0
+#define SMA1307_TDM_SLOT1_RX_POS_1 BIT(0)
+#define SMA1307_TDM_SLOT1_RX_POS_2 BIT(1)
+#define SMA1307_TDM_SLOT1_RX_POS_3 (BIT(0)|BIT(1))
+#define SMA1307_TDM_SLOT1_RX_POS_4 BIT(2)
+#define SMA1307_TDM_SLOT1_RX_POS_5 (BIT(0)|BIT(2))
+#define SMA1307_TDM_SLOT1_RX_POS_6 (BIT(1)|BIT(2))
+#define SMA1307_TDM_SLOT1_RX_POS_7 (BIT(0)|BIT(1)|BIT(2))
+
+/* TDM2 FORMAT : 0xA6 */
+#define SMA1307_TDM_DL_MASK BIT(7)
+#define SMA1307_TDM_DL_16 0
+#define SMA1307_TDM_DL_32 BIT(7)
+
+#define SMA1307_TDM_N_SLOT_MASK BIT(6)
+#define SMA1307_TDM_N_SLOT_4 0
+#define SMA1307_TDM_N_SLOT_8 BIT(6)
+
+#define SMA1307_TDM_SLOT0_TX_POS_MASK (BIT(3)|BIT(4)|BIT(5))
+#define SMA1307_TDM_SLOT0_TX_POS_0 0
+#define SMA1307_TDM_SLOT0_TX_POS_1 BIT(3)
+#define SMA1307_TDM_SLOT0_TX_POS_2 BIT(4)
+#define SMA1307_TDM_SLOT0_TX_POS_3 (BIT(3)|BIT(4))
+#define SMA1307_TDM_SLOT0_TX_POS_4 BIT(5)
+#define SMA1307_TDM_SLOT0_TX_POS_5 (BIT(3)|BIT(5))
+#define SMA1307_TDM_SLOT0_TX_POS_6 (BIT(4)|BIT(5))
+#define SMA1307_TDM_SLOT0_TX_POS_7 (BIT(3)|BIT(4)|BIT(5))
+
+#define SMA1307_TDM_SLOT1_TX_POS_MASK (BIT(0)|BIT(1)|BIT(2))
+#define SMA1307_TDM_SLOT1_TX_POS_0 0
+#define SMA1307_TDM_SLOT1_TX_POS_1 BIT(0)
+#define SMA1307_TDM_SLOT1_TX_POS_2 BIT(1)
+#define SMA1307_TDM_SLOT1_TX_POS_3 (BIT(0)|BIT(1))
+#define SMA1307_TDM_SLOT1_TX_POS_4 BIT(2)
+#define SMA1307_TDM_SLOT1_TX_POS_5 (BIT(0)|BIT(2))
+#define SMA1307_TDM_SLOT1_TX_POS_6 (BIT(1)|BIT(2))
+#define SMA1307_TDM_SLOT1_TX_POS_7 (BIT(0)|BIT(1)|BIT(2))
+
+/* OTP STATUS */
+#define SMA1307_OTP_STAT_MASK BIT(6)
+#define SMA1307_OTP_STAT_0 0
+#define SMA1307_OTP_STAT_1 BIT(6)
+
+/* STATUS */
+#define SMA1307_OT1_OK_STATUS BIT(7)
+#define SMA1307_OT2_OK_STATUS BIT(6)
+#define SMA1307_UVLO_STATUS BIT(5)
+#define SMA1307_OVP_BST_STATUS BIT(4)
+#define SMA1307_POWER_FLAG BIT(3)
+
+#define SMA1307_SCAN_CHK BIT(7)
+#define SMA1307_OCP_SPK_STATUS BIT(5)
+#define SMA1307_OCP_BST_STATUS BIT(4)
+#define SMA1307_BOP_STATE (BIT(1)|BIT(2)|BIT(3))
+#define SMA1307_CLK_MON_STATUS BIT(0)
+
+#define SMA1307_DEVICE_ID (BIT(3)|BIT(4))
+#define SMA1307_REV_NUM_STATUS (BIT(0)|BIT(1))
+#define SMA1307_REV_NUM_REV0 0
+#define SMA1307_REV_NUM_REV1 BIT(0)
+
+#endif
diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c
index 310123d2bb5f..c9766979b1d7 100644
--- a/sound/soc/codecs/spdif_receiver.c
+++ b/sound/soc/codecs/spdif_receiver.c
@@ -36,7 +36,7 @@ static const struct snd_soc_dapm_route dir_routes[] = {
SNDRV_PCM_FMTBIT_S32_LE | \
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
-static struct snd_soc_component_driver soc_codec_spdif_dir = {
+static const struct snd_soc_component_driver soc_codec_spdif_dir = {
.dapm_widgets = dir_widgets,
.num_dapm_widgets = ARRAY_SIZE(dir_widgets),
.dapm_routes = dir_routes,
diff --git a/sound/soc/codecs/spdif_transmitter.c b/sound/soc/codecs/spdif_transmitter.c
index db51a46e689d..2409fd834f84 100644
--- a/sound/soc/codecs/spdif_transmitter.c
+++ b/sound/soc/codecs/spdif_transmitter.c
@@ -36,7 +36,7 @@ static const struct snd_soc_dapm_route dit_routes[] = {
{ "spdif-out", NULL, "Playback" },
};
-static struct snd_soc_component_driver soc_codec_spdif_dit = {
+static const struct snd_soc_component_driver soc_codec_spdif_dit = {
.dapm_widgets = dit_widgets,
.num_dapm_widgets = ARRAY_SIZE(dit_widgets),
.dapm_routes = dit_routes,
diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c
index 3de0132c345d..0aeb88abbf52 100644
--- a/sound/soc/codecs/tas2781-fmwlib.c
+++ b/sound/soc/codecs/tas2781-fmwlib.c
@@ -20,7 +20,7 @@
#include <sound/soc.h>
#include <sound/tlv.h>
#include <sound/tas2781.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#define ERROR_PRAM_CRCCHK 0x0000000
#define ERROR_YRAM_CRCCHK 0x0000001
@@ -1992,6 +1992,7 @@ static int tasdevice_dspfw_ready(const struct firmware *fmw,
break;
case 0x202:
case 0x400:
+ case 0x401:
tas_priv->fw_parse_variable_header =
fw_parse_variable_header_git;
tas_priv->fw_parse_program_data =
diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c
index d0ba7cbe03a8..e41f81eb8d16 100644
--- a/sound/soc/codecs/tas2781-i2c.c
+++ b/sound/soc/codecs/tas2781-i2c.c
@@ -31,7 +31,7 @@
#include <sound/tlv.h>
#include <sound/tas2563-tlv.h>
#include <sound/tas2781-tlv.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#define X2563_CL_STT_VAL(xreg, xval) \
{ .reg = xreg, \
@@ -650,7 +650,6 @@ static int tasdev_tf_data_get(struct snd_kcontrol *kcontrol,
(struct soc_bytes_ext *) kcontrol->private_value;
unsigned char *dst = ucontrol->value.bytes.data;
unsigned int reg;
- int rc = -1;
if (tas_priv->chip_id == TAS2781)
reg = TAS2781_RUNTIME_RE_REG_TF;
@@ -659,9 +658,7 @@ static int tasdev_tf_data_get(struct snd_kcontrol *kcontrol,
guard(mutex)(&tas_priv->codec_lock);
dst[0] = bytes_ext->max;
- rc = calib_data_get(tas_priv, reg, &dst[1]);
-
- return rc;
+ return calib_data_get(tas_priv, reg, &dst[1]);
}
static int tasdev_re_data_get(struct snd_kcontrol *kcontrol,
@@ -673,7 +670,6 @@ static int tasdev_re_data_get(struct snd_kcontrol *kcontrol,
(struct soc_bytes_ext *) kcontrol->private_value;
unsigned char *dst = ucontrol->value.bytes.data;
unsigned int reg;
- int rc = -1;
if (tas_priv->chip_id == TAS2781)
reg = TAS2781_RUNTIME_RE_REG;
@@ -681,9 +677,7 @@ static int tasdev_re_data_get(struct snd_kcontrol *kcontrol,
reg = TAS2563_RUNTIME_RE_REG;
guard(mutex)(&tas_priv->codec_lock);
dst[0] = bytes_ext->max;
- rc = calib_data_get(tas_priv, reg, &dst[1]);
-
- return rc;
+ return calib_data_get(tas_priv, reg, &dst[1]);
}
static int tasdev_r0_data_get(struct snd_kcontrol *kcontrol,
@@ -696,7 +690,6 @@ static int tasdev_r0_data_get(struct snd_kcontrol *kcontrol,
(struct soc_bytes_ext *) kcontrol->private_value;
unsigned char *dst = ucontrol->value.bytes.data;
unsigned int reg;
- int rc = -1;
guard(mutex)(&tas_priv->codec_lock);
@@ -707,9 +700,7 @@ static int tasdev_r0_data_get(struct snd_kcontrol *kcontrol,
else
return -1;
dst[0] = bytes_ext->max;
- rc = calib_data_get(tas_priv, reg, &dst[1]);
-
- return rc;
+ return calib_data_get(tas_priv, reg, &dst[1]);
}
static int tasdev_XMA1_data_get(struct snd_kcontrol *kcontrol,
@@ -721,13 +712,10 @@ static int tasdev_XMA1_data_get(struct snd_kcontrol *kcontrol,
(struct soc_bytes_ext *) kcontrol->private_value;
unsigned char *dst = ucontrol->value.bytes.data;
unsigned int reg = TASDEVICE_XM_A1_REG;
- int rc = -1;
guard(mutex)(&tas_priv->codec_lock);
dst[0] = bytes_ext->max;
- rc = calib_data_get(tas_priv, reg, &dst[1]);
-
- return rc;
+ return calib_data_get(tas_priv, reg, &dst[1]);
}
static int tasdev_XMA2_data_get(struct snd_kcontrol *kcontrol,
@@ -739,13 +727,10 @@ static int tasdev_XMA2_data_get(struct snd_kcontrol *kcontrol,
(struct soc_bytes_ext *) kcontrol->private_value;
unsigned char *dst = ucontrol->value.bytes.data;
unsigned int reg = TASDEVICE_XM_A2_REG;
- int rc = -1;
guard(mutex)(&tas_priv->codec_lock);
dst[0] = bytes_ext->max;
- rc = calib_data_get(tas_priv, reg, &dst[1]);
-
- return rc;
+ return calib_data_get(tas_priv, reg, &dst[1]);
}
static int tasdev_nop_get(
@@ -1115,14 +1100,12 @@ static int tasdevice_active_num_put(struct snd_kcontrol *kcontrol,
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec);
int dev_id = ucontrol->value.integer.value[0];
- int max = tas_priv->ndev - 1, rc;
+ int max = tas_priv->ndev - 1;
dev_id = clamp(dev_id, 0, max);
guard(mutex)(&tas_priv->codec_lock);
- rc = tasdev_chn_switch(tas_priv, dev_id);
-
- return rc;
+ return tasdev_chn_switch(tas_priv, dev_id);
}
static int tasdevice_dsp_create_ctrls(struct tasdevice_priv *tas_priv)
@@ -1339,10 +1322,8 @@ static int tasdevice_create_cali_ctrls(struct tasdevice_priv *priv)
i++;
}
- rc = snd_soc_add_component_controls(priv->codec, cali_ctrls,
+ return snd_soc_add_component_controls(priv->codec, cali_ctrls,
nctrls < i ? nctrls : i);
-
- return rc;
}
static void tasdevice_fw_ready(const struct firmware *fmw,
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c
index f249e93e2a4e..6c6e7ae07d80 100644
--- a/sound/soc/codecs/tas571x.c
+++ b/sound/soc/codecs/tas571x.c
@@ -27,7 +27,7 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include "tas571x.h"
diff --git a/sound/soc/codecs/tas5805m.c b/sound/soc/codecs/tas5805m.c
index 3b53eba38a0b..4c32500eef3e 100644
--- a/sound/soc/codecs/tas5805m.c
+++ b/sound/soc/codecs/tas5805m.c
@@ -474,7 +474,7 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c)
return ret;
}
- tas5805m = devm_kzalloc(dev, sizeof(struct tas5805m_priv), GFP_KERNEL);
+ tas5805m = devm_kzalloc(dev, sizeof(*tas5805m), GFP_KERNEL);
if (!tas5805m)
return -ENOMEM;
diff --git a/sound/soc/codecs/tas6424.c b/sound/soc/codecs/tas6424.c
index bb0500e9d3ea..9be054837f68 100644
--- a/sound/soc/codecs/tas6424.c
+++ b/sound/soc/codecs/tas6424.c
@@ -364,7 +364,7 @@ static int tas6424_set_bias_level(struct snd_soc_component *component,
return 0;
}
-static struct snd_soc_component_driver soc_codec_dev_tas6424 = {
+static const struct snd_soc_component_driver soc_codec_dev_tas6424 = {
.set_bias_level = tas6424_set_bias_level,
.controls = tas6424_snd_controls,
.num_controls = ARRAY_SIZE(tas6424_snd_controls),
diff --git a/sound/soc/codecs/tlv320adc3xxx.c b/sound/soc/codecs/tlv320adc3xxx.c
index 7073b9d1cda8..868e8a91e05b 100644
--- a/sound/soc/codecs/tlv320adc3xxx.c
+++ b/sound/soc/codecs/tlv320adc3xxx.c
@@ -961,7 +961,7 @@ static int adc3xxx_gpio_request(struct gpio_chip *chip, unsigned int offset)
if (offset >= ADC3XXX_GPIOS_MAX)
return -EINVAL;
- if (offset >= 0 && offset < ADC3XXX_GPIO_PINS) {
+ if (offset < ADC3XXX_GPIO_PINS) {
/* GPIO1 is offset 0, GPIO2 is offset 1 */
/* We check here that the GPIO pins are either not configured
* in the DT, or that they purposely are set as outputs.
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 187d68e8688c..d81ab9c25c29 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -12,7 +12,7 @@
* and mono/stereo Class-D speaker driver.
*/
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 9c50ac356c89..e3782762139f 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -555,7 +555,7 @@ static const struct snd_kcontrol_new twl4030_dapm_dbypassv_control =
* On unmute: restore the register content from the reg_cache
* Outputs handled in this way: Earpiece, PreDrivL/R, CarkitL/R
*/
-#define TWL4030_OUTPUT_PGA(pin_name, reg, mask) \
+#define TWL4030_OUTPUT_PGA(pin_name, reg) \
static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \
struct snd_kcontrol *kcontrol, int event) \
{ \
@@ -575,11 +575,11 @@ static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \
return 0; \
}
-TWL4030_OUTPUT_PGA(earpiece, TWL4030_REG_EAR_CTL, TWL4030_EAR_GAIN);
-TWL4030_OUTPUT_PGA(predrivel, TWL4030_REG_PREDL_CTL, TWL4030_PREDL_GAIN);
-TWL4030_OUTPUT_PGA(predriver, TWL4030_REG_PREDR_CTL, TWL4030_PREDR_GAIN);
-TWL4030_OUTPUT_PGA(carkitl, TWL4030_REG_PRECKL_CTL, TWL4030_PRECKL_GAIN);
-TWL4030_OUTPUT_PGA(carkitr, TWL4030_REG_PRECKR_CTL, TWL4030_PRECKR_GAIN);
+TWL4030_OUTPUT_PGA(earpiece, TWL4030_REG_EAR_CTL);
+TWL4030_OUTPUT_PGA(predrivel, TWL4030_REG_PREDL_CTL);
+TWL4030_OUTPUT_PGA(predriver, TWL4030_REG_PREDR_CTL);
+TWL4030_OUTPUT_PGA(carkitl, TWL4030_REG_PRECKL_CTL);
+TWL4030_OUTPUT_PGA(carkitr, TWL4030_REG_PRECKR_CTL);
static void handsfree_ramp(struct snd_soc_component *component, int reg, int ramp)
{
diff --git a/sound/soc/codecs/uda1342.c b/sound/soc/codecs/uda1342.c
new file mode 100644
index 000000000000..3d49a7869948
--- /dev/null
+++ b/sound/soc/codecs/uda1342.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// uda1342.c -- UDA1342 ALSA SoC Codec driver
+// Based on the WM87xx drivers by Liam Girdwood and Richard Purdie
+//
+// Copyright 2007 Dension Audio Systems Ltd.
+// Copyright 2024 Loongson Technology Co.,Ltd.
+//
+// Modifications by Christian Pellegrin <chripell@evolware.org>
+// Further cleanup and restructuring by:
+// Binbin Zhou <zhoubinbin@loongson.cn>
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <linux/pm_runtime.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+#include "uda1342.h"
+
+#define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)
+
+struct uda1342_priv {
+ int sysclk;
+ int dai_fmt;
+
+ struct snd_pcm_substream *provider_substream;
+ struct snd_pcm_substream *consumer_substream;
+
+ struct regmap *regmap;
+ struct i2c_client *i2c;
+};
+
+static const struct reg_default uda1342_reg_defaults[] = {
+ { 0x00, 0x1042 },
+ { 0x01, 0x0000 },
+ { 0x10, 0x0088 },
+ { 0x11, 0x0000 },
+ { 0x12, 0x0000 },
+ { 0x20, 0x0080 },
+ { 0x21, 0x0080 },
+};
+
+static int uda1342_mute(struct snd_soc_dai *dai, int mute, int direction)
+{
+ struct snd_soc_component *component = dai->component;
+ struct uda1342_priv *uda1342 = snd_soc_component_get_drvdata(component);
+ unsigned int mask;
+ unsigned int val = 0;
+
+ /* Master mute */
+ mask = BIT(5);
+ if (mute)
+ val = mask;
+
+ return regmap_update_bits(uda1342->regmap, 0x10, mask, val);
+}
+
+static int uda1342_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct uda1342_priv *uda1342 = snd_soc_component_get_drvdata(component);
+ struct snd_pcm_runtime *provider_runtime;
+
+ if (uda1342->provider_substream) {
+ provider_runtime = uda1342->provider_substream->runtime;
+
+ snd_pcm_hw_constraint_single(substream->runtime,
+ SNDRV_PCM_HW_PARAM_RATE, provider_runtime->rate);
+ snd_pcm_hw_constraint_single(substream->runtime,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+ provider_runtime->sample_bits);
+
+ uda1342->consumer_substream = substream;
+ } else {
+ uda1342->provider_substream = substream;
+ }
+
+ return 0;
+}
+
+static void uda1342_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct uda1342_priv *uda1342 = snd_soc_component_get_drvdata(component);
+
+ if (uda1342->provider_substream == substream)
+ uda1342->provider_substream = uda1342->consumer_substream;
+
+ uda1342->consumer_substream = NULL;
+}
+
+static int uda1342_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 uda1342_priv *uda1342 = snd_soc_component_get_drvdata(component);
+ struct device *dev = &uda1342->i2c->dev;
+ unsigned int hw_params = 0;
+
+ if (substream == uda1342->consumer_substream)
+ return 0;
+
+ /* set SYSCLK / fs ratio */
+ switch (uda1342->sysclk / params_rate(params)) {
+ case 512:
+ break;
+ case 384:
+ hw_params |= BIT(4);
+ break;
+ case 256:
+ hw_params |= BIT(5);
+ break;
+ default:
+ dev_err(dev, "unsupported frequency\n");
+ return -EINVAL;
+ }
+
+ /* set DAI format and word length */
+ switch (uda1342->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ switch (params_width(params)) {
+ case 16:
+ hw_params |= BIT(1);
+ break;
+ case 18:
+ hw_params |= BIT(2);
+ break;
+ case 20:
+ hw_params |= BIT(2) | BIT(1);
+ break;
+ default:
+ dev_err(dev, "unsupported format (right)\n");
+ return -EINVAL;
+ }
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ hw_params |= BIT(3);
+ break;
+ default:
+ dev_err(dev, "unsupported format\n");
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(uda1342->regmap, 0x0,
+ STATUS0_DAIFMT_MASK | STATUS0_SYSCLK_MASK, hw_params);
+}
+
+static int uda1342_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_component *component = codec_dai->component;
+ struct uda1342_priv *uda1342 = snd_soc_component_get_drvdata(component);
+ struct device *dev = &uda1342->i2c->dev;
+
+ /*
+ * Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
+ * because the codec is slave. Of course limitations of the clock
+ * master (the IIS controller) apply.
+ * We'll error out on set_hw_params if it's not OK
+ */
+ if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
+ uda1342->sysclk = freq;
+ return 0;
+ }
+
+ dev_err(dev, "unsupported sysclk\n");
+
+ return -EINVAL;
+}
+
+static int uda1342_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+ struct snd_soc_component *component = codec_dai->component;
+ struct uda1342_priv *uda1342 = snd_soc_component_get_drvdata(component);
+
+ /* codec supports only full consumer mode */
+ if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_BC_FC) {
+ dev_err(&uda1342->i2c->dev, "unsupported consumer mode.\n");
+ return -EINVAL;
+ }
+
+ /* We can't setup DAI format here as it depends on the word bit num */
+ /* so let's just store the value for later */
+ uda1342->dai_fmt = fmt;
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new uda1342_snd_controls[] = {
+ SOC_SINGLE("Master Playback Volume", 0x11, 0, 0x3F, 1),
+ SOC_SINGLE("Analog1 Volume", 0x12, 0, 0x1F, 1),
+};
+
+/* Common DAPM widgets */
+static const struct snd_soc_dapm_widget uda1342_dapm_widgets[] = {
+ SND_SOC_DAPM_INPUT("VINL1"),
+ SND_SOC_DAPM_INPUT("VINR1"),
+ SND_SOC_DAPM_INPUT("VINL2"),
+ SND_SOC_DAPM_INPUT("VINR2"),
+
+ SND_SOC_DAPM_DAC("DAC", "Playback", 0, 1, 0),
+ SND_SOC_DAPM_ADC("ADC", "Capture", 0, 9, 0),
+
+ SND_SOC_DAPM_OUTPUT("VOUTL"),
+ SND_SOC_DAPM_OUTPUT("VOUTR"),
+};
+
+static const struct snd_soc_dapm_route uda1342_dapm_routes[] = {
+ { "ADC", NULL, "VINL1" },
+ { "ADC", NULL, "VINR1" },
+ { "ADC", NULL, "VINL2" },
+ { "ADC", NULL, "VINR2" },
+ { "VOUTL", NULL, "DAC" },
+ { "VOUTR", NULL, "DAC" },
+};
+
+static const struct snd_soc_dai_ops uda1342_dai_ops = {
+ .startup = uda1342_startup,
+ .shutdown = uda1342_shutdown,
+ .hw_params = uda1342_hw_params,
+ .mute_stream = uda1342_mute,
+ .set_sysclk = uda1342_set_dai_sysclk,
+ .set_fmt = uda1342_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver uda1342_dai = {
+ .name = "uda1342-hifi",
+ /* playback capabilities */
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = UDA134X_FORMATS,
+ },
+ /* capture capabilities */
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = UDA134X_FORMATS,
+ },
+ /* pcm operations */
+ .ops = &uda1342_dai_ops,
+};
+
+static const struct snd_soc_component_driver soc_component_dev_uda1342 = {
+ .controls = uda1342_snd_controls,
+ .num_controls = ARRAY_SIZE(uda1342_snd_controls),
+ .dapm_widgets = uda1342_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(uda1342_dapm_widgets),
+ .dapm_routes = uda1342_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(uda1342_dapm_routes),
+ .suspend_bias_off = 1,
+ .idle_bias_on = 1,
+ .use_pmdown_time = 1,
+ .endianness = 1,
+};
+
+static const struct regmap_config uda1342_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = 0x21,
+ .reg_defaults = uda1342_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(uda1342_reg_defaults),
+ .cache_type = REGCACHE_MAPLE,
+};
+
+static int uda1342_i2c_probe(struct i2c_client *i2c)
+{
+ struct uda1342_priv *uda1342;
+
+ uda1342 = devm_kzalloc(&i2c->dev, sizeof(*uda1342), GFP_KERNEL);
+ if (!uda1342)
+ return -ENOMEM;
+
+ uda1342->regmap = devm_regmap_init_i2c(i2c, &uda1342_regmap);
+ if (IS_ERR(uda1342->regmap))
+ return PTR_ERR(uda1342->regmap);
+
+ i2c_set_clientdata(i2c, uda1342);
+ uda1342->i2c = i2c;
+
+ return devm_snd_soc_register_component(&i2c->dev,
+ &soc_component_dev_uda1342,
+ &uda1342_dai, 1);
+}
+
+static int uda1342_suspend(struct device *dev)
+{
+ struct uda1342_priv *uda1342 = dev_get_drvdata(dev);
+
+ regcache_cache_only(uda1342->regmap, true);
+
+ return 0;
+}
+
+static int uda1342_resume(struct device *dev)
+{
+ struct uda1342_priv *uda1342 = dev_get_drvdata(dev);
+
+ regcache_mark_dirty(uda1342->regmap);
+ regcache_sync(uda1342->regmap);
+
+ return 0;
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(uda1342_pm_ops,
+ uda1342_suspend, uda1342_resume, NULL);
+
+static const struct i2c_device_id uda1342_i2c_id[] = {
+ { "uda1342", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, uda1342_i2c_id);
+
+static const struct of_device_id uda1342_of_match[] = {
+ { .compatible = "nxp,uda1342" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, uda1342_of_match);
+
+static struct i2c_driver uda1342_i2c_driver = {
+ .driver = {
+ .name = "uda1342",
+ .of_match_table = uda1342_of_match,
+ .pm = pm_sleep_ptr(&uda1342_pm_ops),
+ },
+ .probe = uda1342_i2c_probe,
+ .id_table = uda1342_i2c_id,
+};
+module_i2c_driver(uda1342_i2c_driver);
+
+MODULE_DESCRIPTION("UDA1342 ALSA soc codec driver");
+MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
+MODULE_AUTHOR("Binbin Zhou <zhoubinbin@loongson.cn>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/uda1342.h b/sound/soc/codecs/uda1342.h
new file mode 100644
index 000000000000..ff6aea0a8b01
--- /dev/null
+++ b/sound/soc/codecs/uda1342.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Audio support for NXP UDA1342
+ *
+ * Copyright (c) 2005 Giorgio Padrin <giorgio@mandarinlogiq.org>
+ * Copyright (c) 2024 Binbin Zhou <zhoubinbin@loongson.cn>
+ */
+
+#ifndef _UDA1342_H
+#define _UDA1342_H
+
+#define UDA1342_CLK 0x00
+#define UDA1342_IFACE 0x01
+#define UDA1342_PM 0x02
+#define UDA1342_AMIX 0x03
+#define UDA1342_HP 0x04
+#define UDA1342_MVOL 0x11
+#define UDA1342_MIXVOL 0x12
+#define UDA1342_MODE 0x12
+#define UDA1342_DEEMP 0x13
+#define UDA1342_MIXER 0x14
+#define UDA1342_INTSTAT 0x18
+#define UDA1342_DEC 0x20
+#define UDA1342_PGA 0x21
+#define UDA1342_ADC 0x22
+#define UDA1342_AGC 0x23
+#define UDA1342_DECSTAT 0x28
+#define UDA1342_RESET 0x7f
+
+/* Register flags */
+#define R00_EN_ADC 0x0800
+#define R00_EN_DEC 0x0400
+#define R00_EN_DAC 0x0200
+#define R00_EN_INT 0x0100
+#define R00_DAC_CLK 0x0010
+#define R01_SFORI_I2S 0x0000
+#define R01_SFORI_LSB16 0x0100
+#define R01_SFORI_LSB18 0x0200
+#define R01_SFORI_LSB20 0x0300
+#define R01_SFORI_MSB 0x0500
+#define R01_SFORI_MASK 0x0700
+#define R01_SFORO_I2S 0x0000
+#define R01_SFORO_LSB16 0x0001
+#define R01_SFORO_LSB18 0x0002
+#define R01_SFORO_LSB20 0x0003
+#define R01_SFORO_LSB24 0x0004
+#define R01_SFORO_MSB 0x0005
+#define R01_SFORO_MASK 0x0007
+#define R01_SEL_SOURCE 0x0040
+#define R01_SIM 0x0010
+#define R02_PON_PLL 0x8000
+#define R02_PON_HP 0x2000
+#define R02_PON_DAC 0x0400
+#define R02_PON_BIAS 0x0100
+#define R02_EN_AVC 0x0080
+#define R02_PON_AVC 0x0040
+#define R02_PON_LNA 0x0010
+#define R02_PON_PGAL 0x0008
+#define R02_PON_ADCL 0x0004
+#define R02_PON_PGAR 0x0002
+#define R02_PON_ADCR 0x0001
+#define R13_MTM 0x4000
+#define R14_SILENCE 0x0080
+#define R14_SDET_ON 0x0040
+#define R21_MT_ADC 0x8000
+#define R22_SEL_LNA 0x0008
+#define R22_SEL_MIC 0x0004
+#define R22_SKIP_DCFIL 0x0002
+#define R23_AGC_EN 0x0001
+
+#define UDA1342_DAI_DUPLEX 0 /* playback and capture on single DAI */
+#define UDA1342_DAI_PLAYBACK 1 /* playback DAI */
+#define UDA1342_DAI_CAPTURE 2 /* capture DAI */
+
+#define STATUS0_DAIFMT_MASK (~(7 << 1))
+#define STATUS0_SYSCLK_MASK (~(3 << 4))
+
+#endif /* _UDA1342_H */
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 373a31ddccb2..a2521e16c099 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -5177,4 +5177,3 @@ static struct slim_driver wcd9335_slim_driver = {
module_slim_driver(wcd9335_slim_driver);
MODULE_DESCRIPTION("WCD9335 slim driver");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("slim:217:1a0:*");
diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c
index 45f32d281908..c9d5e67bf66e 100644
--- a/sound/soc/codecs/wcd937x.c
+++ b/sound/soc/codecs/wcd937x.c
@@ -7,7 +7,6 @@
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of_gpio.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -715,12 +714,17 @@ static int wcd937x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
int hph_mode = wcd937x->hph_mode;
+ u8 val;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ val = WCD937X_DIGITAL_PDM_WD_CTL2_EN |
+ WCD937X_DIGITAL_PDM_WD_CTL2_TIMEOUT_SEL |
+ WCD937X_DIGITAL_PDM_WD_CTL2_HOLD_OFF;
snd_soc_component_update_bits(component,
WCD937X_DIGITAL_PDM_WD_CTL2,
- BIT(0), BIT(0));
+ WCD937X_DIGITAL_PDM_WD_CTL2_MASK,
+ val);
break;
case SND_SOC_DAPM_POST_PMU:
usleep_range(1000, 1010);
@@ -741,7 +745,8 @@ static int wcd937x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
hph_mode);
snd_soc_component_update_bits(component,
WCD937X_DIGITAL_PDM_WD_CTL2,
- BIT(0), 0x00);
+ WCD937X_DIGITAL_PDM_WD_CTL2_MASK,
+ 0x00);
break;
}
@@ -2049,6 +2054,8 @@ static const struct snd_kcontrol_new wcd937x_snd_controls[] = {
wcd937x_get_swr_port, wcd937x_set_swr_port),
SOC_SINGLE_EXT("HPHR Switch", WCD937X_HPH_R, 0, 1, 0,
wcd937x_get_swr_port, wcd937x_set_swr_port),
+ SOC_SINGLE_EXT("LO Switch", WCD937X_LO, 0, 1, 0,
+ wcd937x_get_swr_port, wcd937x_set_swr_port),
SOC_SINGLE_EXT("ADC1 Switch", WCD937X_ADC1, 1, 1, 0,
wcd937x_get_swr_port, wcd937x_set_swr_port),
diff --git a/sound/soc/codecs/wcd937x.h b/sound/soc/codecs/wcd937x.h
index 35f3d48bd7dd..4afa48dcaf74 100644
--- a/sound/soc/codecs/wcd937x.h
+++ b/sound/soc/codecs/wcd937x.h
@@ -391,6 +391,10 @@
#define WCD937X_DIGITAL_PDM_WD_CTL0 0x3465
#define WCD937X_DIGITAL_PDM_WD_CTL1 0x3466
#define WCD937X_DIGITAL_PDM_WD_CTL2 0x3467
+#define WCD937X_DIGITAL_PDM_WD_CTL2_HOLD_OFF BIT(2)
+#define WCD937X_DIGITAL_PDM_WD_CTL2_TIMEOUT_SEL BIT(1)
+#define WCD937X_DIGITAL_PDM_WD_CTL2_EN BIT(0)
+#define WCD937X_DIGITAL_PDM_WD_CTL2_MASK GENMASK(2, 0)
#define WCD937X_DIGITAL_INTR_MODE 0x346A
#define WCD937X_DIGITAL_INTR_MASK_0 0x346B
#define WCD937X_DIGITAL_INTR_MASK_1 0x346C
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 651f1319204d..9fc7a8325724 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -25,7 +25,7 @@
#include <linux/mfd/arizona/core.h>
#include <linux/mfd/arizona/registers.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include "arizona.h"
#include "wm5102.h"
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index 7878c7a58ff1..d08419b108fe 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -25,7 +25,7 @@
#include <linux/mfd/wm8994/pdata.h>
#include <linux/mfd/wm8994/gpio.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include "wm8994.h"
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index e283751abfef..8e88830e8e57 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -30,6 +30,7 @@ config SND_SOC_FSL_MQS
tristate "Medium Quality Sound (MQS) module support"
depends on SND_SOC_FSL_SAI
select REGMAP_MMIO
+ select IMX_SCMI_MISC_DRV if IMX_SCMI_MISC_EXT !=n
help
Say Y if you want to add Medium Quality Sound (MQS)
support for the Freescale CPUs.
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index f6c3aeff0d8e..02e1594e8223 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -317,8 +317,6 @@ static const struct snd_soc_dai_link fsl_asoc_card_dai[] = {
{
.name = "HiFi-ASRC-FE",
.stream_name = "HiFi-ASRC-FE",
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.dynamic = 1,
},
{
@@ -326,8 +324,6 @@ static const struct snd_soc_dai_link fsl_asoc_card_dai[] = {
.stream_name = "HiFi-ASRC-BE",
.be_hw_params_fixup = be_hw_params_fixup,
.ops = &fsl_asoc_card_ops,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.no_pcm = 1,
},
};
@@ -504,13 +500,13 @@ static int fsl_asoc_card_spdif_init(struct device_node *codec_np[],
}
if (priv->dai_link[0].playback_only) {
- priv->dai_link[1].dpcm_capture = false;
- priv->dai_link[2].dpcm_capture = false;
+ priv->dai_link[1].playback_only = true;
+ priv->dai_link[2].playback_only = true;
priv->card.dapm_routes = audio_map_tx;
priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
} else if (priv->dai_link[0].capture_only) {
- priv->dai_link[1].dpcm_playback = false;
- priv->dai_link[2].dpcm_playback = false;
+ priv->dai_link[1].capture_only = true;
+ priv->dai_link[2].capture_only = true;
priv->card.dapm_routes = audio_map_rx;
priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_rx);
}
@@ -764,8 +760,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
} else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic31xx")) {
codec_dai_name[0] = "tlv320dac31xx-hifi";
priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
- priv->dai_link[1].dpcm_capture = 0;
- priv->dai_link[2].dpcm_capture = 0;
+ priv->dai_link[1].playback_only = 1;
+ priv->dai_link[2].playback_only = 1;
priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_OUT;
priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT;
priv->card.dapm_routes = audio_map_tx;
@@ -791,15 +787,15 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
priv->dai_fmt = SND_SOC_DAIFMT_LEFT_J |
SND_SOC_DAIFMT_CBC_CFC |
SND_SOC_DAIFMT_NB_NF;
- priv->dai_link[1].dpcm_capture = 0;
- priv->dai_link[2].dpcm_capture = 0;
+ priv->dai_link[1].playback_only = 1;
+ priv->dai_link[2].playback_only = 1;
priv->card.dapm_routes = audio_map_tx;
priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
} else if (of_device_is_compatible(np, "fsl,imx-audio-wm8524")) {
codec_dai_name[0] = "wm8524-hifi";
priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC;
- priv->dai_link[1].dpcm_capture = 0;
- priv->dai_link[2].dpcm_capture = 0;
+ priv->dai_link[1].playback_only = 1;
+ priv->dai_link[2].playback_only = 1;
priv->cpu_priv.slot_width = 32;
priv->card.dapm_routes = audio_map_tx;
priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
@@ -1033,14 +1029,15 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
}
/*
- * Properties "hp-det-gpio" and "mic-det-gpio" are optional, and
+ * Properties "hp-det-gpios" and "mic-det-gpios" are optional, and
* simple_util_init_jack() uses these properties for creating
* Headphone Jack and Microphone Jack.
*
* The notifier is initialized in snd_soc_card_jack_new(), then
* snd_soc_jack_notifier_register can be called.
*/
- if (of_property_read_bool(np, "hp-det-gpio")) {
+ if (of_property_read_bool(np, "hp-det-gpios") ||
+ of_property_read_bool(np, "hp-det-gpio") /* deprecated */) {
ret = simple_util_init_jack(&priv->card, &priv->hp_jack,
1, NULL, "Headphone Jack");
if (ret)
@@ -1049,7 +1046,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
snd_soc_jack_notifier_register(&priv->hp_jack.jack, &hp_jack_nb);
}
- if (of_property_read_bool(np, "mic-det-gpio")) {
+ if (of_property_read_bool(np, "mic-det-gpios") ||
+ of_property_read_bool(np, "mic-det-gpio") /* deprecated */) {
ret = simple_util_init_jack(&priv->card, &priv->mic_jack,
0, NULL, "Mic Jack");
if (ret)
diff --git a/sound/soc/fsl/fsl_aud2htx.c b/sound/soc/fsl/fsl_aud2htx.c
index 021d73e409aa..bde642318835 100644
--- a/sound/soc/fsl/fsl_aud2htx.c
+++ b/sound/soc/fsl/fsl_aud2htx.c
@@ -169,7 +169,7 @@ static const struct regmap_config fsl_aud2htx_regmap_config = {
.readable_reg = fsl_aud2htx_readable_reg,
.volatile_reg = fsl_aud2htx_volatile_reg,
.writeable_reg = fsl_aud2htx_writeable_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static const struct of_device_id fsl_aud2htx_dt_ids[] = {
diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index 82359edd6a8b..d22f0621c465 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -1748,7 +1748,7 @@ static const struct regmap_config fsl_easrc_regmap_config = {
.rd_table = &fsl_easrc_readable_table,
.wr_table = &fsl_easrc_writeable_table,
.volatile_table = &fsl_easrc_volatileable_table,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
#ifdef DEBUG
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index a65f5b9935a2..0b247f16a163 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -119,10 +119,10 @@ static irqreturn_t esai_isr(int irq, void *devid)
dev_dbg(&pdev->dev, "isr: Transmission Initialized\n");
if (esr & ESAI_ESR_RFF_MASK)
- dev_warn(&pdev->dev, "isr: Receiving overrun\n");
+ dev_dbg(&pdev->dev, "isr: Receiving overrun\n");
if (esr & ESAI_ESR_TFE_MASK)
- dev_warn(&pdev->dev, "isr: Transmission underrun\n");
+ dev_dbg(&pdev->dev, "isr: Transmission underrun\n");
if (esr & ESAI_ESR_TLS_MASK)
dev_dbg(&pdev->dev, "isr: Just transmitted the last slot\n");
diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c
index 193be098fa5e..8c15389c9a04 100644
--- a/sound/soc/fsl/fsl_micfil.c
+++ b/sound/soc/fsl/fsl_micfil.c
@@ -28,6 +28,13 @@
#define MICFIL_OSR_DEFAULT 16
+#define MICFIL_NUM_RATES 7
+#define MICFIL_CLK_SRC_NUM 3
+/* clock source ids */
+#define MICFIL_AUDIO_PLL1 0
+#define MICFIL_AUDIO_PLL2 1
+#define MICFIL_CLK_EXT3 2
+
enum quality {
QUALITY_HIGH,
QUALITY_MEDIUM,
@@ -45,9 +52,12 @@ struct fsl_micfil {
struct clk *mclk;
struct clk *pll8k_clk;
struct clk *pll11k_clk;
+ struct clk *clk_src[MICFIL_CLK_SRC_NUM];
struct snd_dmaengine_dai_dma_data dma_params_rx;
struct sdma_peripheral_config sdmacfg;
struct snd_soc_card *card;
+ struct snd_pcm_hw_constraint_list constraint_rates;
+ unsigned int constraint_rates_list[MICFIL_NUM_RATES];
unsigned int dataline;
char name[32];
int irq[MICFIL_IRQ_LINES];
@@ -58,6 +68,7 @@ struct fsl_micfil {
int vad_detected;
struct fsl_micfil_verid verid;
struct fsl_micfil_param param;
+ bool mclk_flag; /* mclk enable flag */
};
struct fsl_micfil_soc_data {
@@ -67,6 +78,7 @@ struct fsl_micfil_soc_data {
bool imx;
bool use_edma;
bool use_verid;
+ bool volume_sx;
u64 formats;
};
@@ -76,6 +88,7 @@ static struct fsl_micfil_soc_data fsl_micfil_imx8mm = {
.fifo_depth = 8,
.dataline = 0xf,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .volume_sx = true,
};
static struct fsl_micfil_soc_data fsl_micfil_imx8mp = {
@@ -84,6 +97,7 @@ static struct fsl_micfil_soc_data fsl_micfil_imx8mp = {
.fifo_depth = 32,
.dataline = 0xf,
.formats = SNDRV_PCM_FMTBIT_S32_LE,
+ .volume_sx = false,
};
static struct fsl_micfil_soc_data fsl_micfil_imx93 = {
@@ -94,6 +108,7 @@ static struct fsl_micfil_soc_data fsl_micfil_imx93 = {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.use_edma = true,
.use_verid = true,
+ .volume_sx = false,
};
static const struct of_device_id fsl_micfil_dt_ids[] = {
@@ -317,7 +332,26 @@ static int hwvad_detected(struct snd_kcontrol *kcontrol,
return 0;
}
-static const struct snd_kcontrol_new fsl_micfil_snd_controls[] = {
+static const struct snd_kcontrol_new fsl_micfil_volume_controls[] = {
+ SOC_SINGLE_TLV("CH0 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(0), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH1 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(1), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH2 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(2), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH3 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(3), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH4 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(4), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH5 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(5), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH6 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(6), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH7 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(7), 0xF, 0, gain_tlv),
+};
+
+static const struct snd_kcontrol_new fsl_micfil_volume_sx_controls[] = {
SOC_SINGLE_SX_TLV("CH0 Volume", REG_MICFIL_OUT_CTRL,
MICFIL_OUTGAIN_CHX_SHIFT(0), 0x8, 0xF, gain_tlv),
SOC_SINGLE_SX_TLV("CH1 Volume", REG_MICFIL_OUT_CTRL,
@@ -334,6 +368,9 @@ static const struct snd_kcontrol_new fsl_micfil_snd_controls[] = {
MICFIL_OUTGAIN_CHX_SHIFT(6), 0x8, 0xF, gain_tlv),
SOC_SINGLE_SX_TLV("CH7 Volume", REG_MICFIL_OUT_CTRL,
MICFIL_OUTGAIN_CHX_SHIFT(7), 0x8, 0xF, gain_tlv),
+};
+
+static const struct snd_kcontrol_new fsl_micfil_snd_controls[] = {
SOC_ENUM_EXT("MICFIL Quality Select",
fsl_micfil_quality_enum,
micfil_quality_get, micfil_quality_set),
@@ -449,12 +486,34 @@ static int fsl_micfil_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsl_micfil *micfil = snd_soc_dai_get_drvdata(dai);
+ unsigned int rates[MICFIL_NUM_RATES] = {8000, 11025, 16000, 22050, 32000, 44100, 48000};
+ int i, j, k = 0;
+ u64 clk_rate;
if (!micfil) {
dev_err(dai->dev, "micfil dai priv_data not set\n");
return -EINVAL;
}
+ micfil->constraint_rates.list = micfil->constraint_rates_list;
+ micfil->constraint_rates.count = 0;
+
+ for (j = 0; j < MICFIL_NUM_RATES; j++) {
+ for (i = 0; i < MICFIL_CLK_SRC_NUM; i++) {
+ clk_rate = clk_get_rate(micfil->clk_src[i]);
+ if (clk_rate != 0 && do_div(clk_rate, rates[j]) == 0) {
+ micfil->constraint_rates_list[k++] = rates[j];
+ micfil->constraint_rates.count++;
+ break;
+ }
+ }
+ }
+
+ if (micfil->constraint_rates.count > 0)
+ snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &micfil->constraint_rates);
+
return 0;
}
@@ -650,7 +709,7 @@ static int fsl_micfil_trigger(struct snd_pcm_substream *substream, int cmd,
/* Enable the module */
ret = regmap_set_bits(micfil->regmap, REG_MICFIL_CTRL1,
- MICFIL_CTRL1_PDMIEN);
+ MICFIL_CTRL1_PDMIEN | MICFIL_CTRL1_ERREN);
if (ret)
return ret;
@@ -666,7 +725,7 @@ static int fsl_micfil_trigger(struct snd_pcm_substream *substream, int cmd,
/* Disable the module */
ret = regmap_clear_bits(micfil->regmap, REG_MICFIL_CTRL1,
- MICFIL_CTRL1_PDMIEN);
+ MICFIL_CTRL1_PDMIEN | MICFIL_CTRL1_ERREN);
if (ret)
return ret;
@@ -693,7 +752,6 @@ static int fsl_micfil_reparent_rootclk(struct fsl_micfil *micfil, unsigned int s
clk = micfil->mclk;
/* Disable clock first, for it was enabled by pm_runtime */
- clk_disable_unprepare(clk);
fsl_asoc_reparent_pll_clocks(dev, clk, micfil->pll8k_clk,
micfil->pll11k_clk, ratio);
ret = clk_prepare_enable(clk);
@@ -730,6 +788,8 @@ static int fsl_micfil_hw_params(struct snd_pcm_substream *substream,
if (ret)
return ret;
+ micfil->mclk_flag = true;
+
ret = clk_set_rate(micfil->mclk, rate * clk_div * osr * 8);
if (ret)
return ret;
@@ -764,6 +824,17 @@ static int fsl_micfil_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+static int fsl_micfil_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct fsl_micfil *micfil = snd_soc_dai_get_drvdata(dai);
+
+ clk_disable_unprepare(micfil->mclk);
+ micfil->mclk_flag = false;
+
+ return 0;
+}
+
static int fsl_micfil_dai_probe(struct snd_soc_dai *cpu_dai)
{
struct fsl_micfil *micfil = dev_get_drvdata(cpu_dai->dev);
@@ -801,11 +872,26 @@ static int fsl_micfil_dai_probe(struct snd_soc_dai *cpu_dai)
return 0;
}
+static int fsl_micfil_component_probe(struct snd_soc_component *component)
+{
+ struct fsl_micfil *micfil = snd_soc_component_get_drvdata(component);
+
+ if (micfil->soc->volume_sx)
+ snd_soc_add_component_controls(component, fsl_micfil_volume_sx_controls,
+ ARRAY_SIZE(fsl_micfil_volume_sx_controls));
+ else
+ snd_soc_add_component_controls(component, fsl_micfil_volume_controls,
+ ARRAY_SIZE(fsl_micfil_volume_controls));
+
+ return 0;
+}
+
static const struct snd_soc_dai_ops fsl_micfil_dai_ops = {
.probe = fsl_micfil_dai_probe,
.startup = fsl_micfil_startup,
.trigger = fsl_micfil_trigger,
.hw_params = fsl_micfil_hw_params,
+ .hw_free = fsl_micfil_hw_free,
};
static struct snd_soc_dai_driver fsl_micfil_dai = {
@@ -821,6 +907,7 @@ static struct snd_soc_dai_driver fsl_micfil_dai = {
static const struct snd_soc_component_driver fsl_micfil_component = {
.name = "fsl-micfil-dai",
+ .probe = fsl_micfil_component_probe,
.controls = fsl_micfil_snd_controls,
.num_controls = ARRAY_SIZE(fsl_micfil_snd_controls),
.legacy_dai_naming = 1,
@@ -926,6 +1013,7 @@ static bool fsl_micfil_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case REG_MICFIL_STAT:
+ case REG_MICFIL_FIFO_STAT:
case REG_MICFIL_DATACH0:
case REG_MICFIL_DATACH1:
case REG_MICFIL_DATACH2:
@@ -934,6 +1022,7 @@ static bool fsl_micfil_volatile_reg(struct device *dev, unsigned int reg)
case REG_MICFIL_DATACH5:
case REG_MICFIL_DATACH6:
case REG_MICFIL_DATACH7:
+ case REG_MICFIL_OUT_STAT:
case REG_MICFIL_VERID:
case REG_MICFIL_PARAM:
case REG_MICFIL_VAD0_STAT:
@@ -955,7 +1044,7 @@ static const struct regmap_config fsl_micfil_regmap_config = {
.readable_reg = fsl_micfil_readable_reg,
.volatile_reg = fsl_micfil_volatile_reg,
.writeable_reg = fsl_micfil_writeable_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
/* END OF REGMAP */
@@ -988,7 +1077,7 @@ static irqreturn_t micfil_isr(int irq, void *devid)
regmap_write_bits(micfil->regmap,
REG_MICFIL_STAT,
MICFIL_STAT_CHXF(i),
- 1);
+ MICFIL_STAT_CHXF(i));
}
for (i = 0; i < MICFIL_FIFO_NUM; i++) {
@@ -1010,6 +1099,8 @@ static irqreturn_t micfil_err_isr(int irq, void *devid)
{
struct fsl_micfil *micfil = (struct fsl_micfil *)devid;
struct platform_device *pdev = micfil->pdev;
+ u32 fifo_stat_reg;
+ u32 out_stat_reg;
u32 stat_reg;
regmap_read(micfil->regmap, REG_MICFIL_STAT, &stat_reg);
@@ -1023,9 +1114,17 @@ static irqreturn_t micfil_err_isr(int irq, void *devid)
if (stat_reg & MICFIL_STAT_LOWFREQF) {
dev_dbg(&pdev->dev, "isr: ipg_clk_app is too low\n");
regmap_write_bits(micfil->regmap, REG_MICFIL_STAT,
- MICFIL_STAT_LOWFREQF, 1);
+ MICFIL_STAT_LOWFREQF, MICFIL_STAT_LOWFREQF);
}
+ regmap_read(micfil->regmap, REG_MICFIL_FIFO_STAT, &fifo_stat_reg);
+ regmap_write_bits(micfil->regmap, REG_MICFIL_FIFO_STAT,
+ fifo_stat_reg, fifo_stat_reg);
+
+ regmap_read(micfil->regmap, REG_MICFIL_OUT_STAT, &out_stat_reg);
+ regmap_write_bits(micfil->regmap, REG_MICFIL_OUT_STAT,
+ out_stat_reg, out_stat_reg);
+
return IRQ_HANDLED;
}
@@ -1134,6 +1233,12 @@ static int fsl_micfil_probe(struct platform_device *pdev)
fsl_asoc_get_pll_clocks(&pdev->dev, &micfil->pll8k_clk,
&micfil->pll11k_clk);
+ micfil->clk_src[MICFIL_AUDIO_PLL1] = micfil->pll8k_clk;
+ micfil->clk_src[MICFIL_AUDIO_PLL2] = micfil->pll11k_clk;
+ micfil->clk_src[MICFIL_CLK_EXT3] = devm_clk_get(&pdev->dev, "clkext3");
+ if (IS_ERR(micfil->clk_src[MICFIL_CLK_EXT3]))
+ micfil->clk_src[MICFIL_CLK_EXT3] = NULL;
+
/* init regmap */
regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(regs))
@@ -1279,7 +1384,8 @@ static int fsl_micfil_runtime_suspend(struct device *dev)
regcache_cache_only(micfil->regmap, true);
- clk_disable_unprepare(micfil->mclk);
+ if (micfil->mclk_flag)
+ clk_disable_unprepare(micfil->mclk);
clk_disable_unprepare(micfil->busclk);
return 0;
@@ -1294,10 +1400,12 @@ static int fsl_micfil_runtime_resume(struct device *dev)
if (ret < 0)
return ret;
- ret = clk_prepare_enable(micfil->mclk);
- if (ret < 0) {
- clk_disable_unprepare(micfil->busclk);
- return ret;
+ if (micfil->mclk_flag) {
+ ret = clk_prepare_enable(micfil->mclk);
+ if (ret < 0) {
+ clk_disable_unprepare(micfil->busclk);
+ return ret;
+ }
}
regcache_cache_only(micfil->regmap, false);
diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c
index 145f9ca15e43..0513e9e8402e 100644
--- a/sound/soc/fsl/fsl_mqs.c
+++ b/sound/soc/fsl/fsl_mqs.c
@@ -6,6 +6,7 @@
// Copyright 2019 NXP
#include <linux/clk.h>
+#include <linux/firmware/imx/sm.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mfd/syscon.h>
@@ -74,6 +75,29 @@ struct fsl_mqs {
#define FSL_MQS_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
#define FSL_MQS_FORMATS SNDRV_PCM_FMTBIT_S16_LE
+static int fsl_mqs_sm_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct fsl_mqs *mqs_priv = context;
+ int num = 1;
+
+ if (IS_ENABLED(CONFIG_IMX_SCMI_MISC_DRV) &&
+ mqs_priv->soc->ctrl_off == reg)
+ return scmi_imx_misc_ctrl_get(SCMI_IMX_CTRL_MQS1_SETTINGS, &num, val);
+
+ return -EINVAL;
+};
+
+static int fsl_mqs_sm_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct fsl_mqs *mqs_priv = context;
+
+ if (IS_ENABLED(CONFIG_IMX_SCMI_MISC_DRV) &&
+ mqs_priv->soc->ctrl_off == reg)
+ return scmi_imx_misc_ctrl_set(SCMI_IMX_CTRL_MQS1_SETTINGS, val);
+
+ return -EINVAL;
+};
+
static int fsl_mqs_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -188,6 +212,13 @@ static const struct regmap_config fsl_mqs_regmap_config = {
.cache_type = REGCACHE_NONE,
};
+static const struct regmap_config fsl_mqs_sm_regmap = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_read = fsl_mqs_sm_read,
+ .reg_write = fsl_mqs_sm_write,
+};
+
static int fsl_mqs_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -219,6 +250,16 @@ static int fsl_mqs_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to get gpr regmap\n");
return PTR_ERR(mqs_priv->regmap);
}
+ } else if (mqs_priv->soc->type == TYPE_REG_SM) {
+ mqs_priv->regmap = devm_regmap_init(&pdev->dev,
+ NULL,
+ mqs_priv,
+ &fsl_mqs_sm_regmap);
+ if (IS_ERR(mqs_priv->regmap)) {
+ dev_err(&pdev->dev, "failed to init regmap: %ld\n",
+ PTR_ERR(mqs_priv->regmap));
+ return PTR_ERR(mqs_priv->regmap);
+ }
} else {
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c
index 8668abd35208..e257b8adafe0 100644
--- a/sound/soc/fsl/fsl_qmc_audio.c
+++ b/sound/soc/fsl/fsl_qmc_audio.c
@@ -838,8 +838,6 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
qmc_dai->id, i, ret);
return ret;
}
- dev_info(qmc_audio->dev, "dai %d QMC channel %d mode %d, nb_tx_ts %u, nb_rx_ts %u\n",
- qmc_dai->id, i, info.mode, info.nb_tx_ts, info.nb_rx_ts);
if (info.mode != QMC_TRANSPARENT) {
dev_err(qmc_audio->dev, "dai %d QMC chan %d mode %d is not QMC_TRANSPARENT\n",
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index ab58a4461073..634168d2bb6e 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -613,6 +613,9 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
val_cr4 |= FSL_SAI_CR4_FRSZ(slots);
+ /* Set to avoid channel swap */
+ val_cr4 |= FSL_SAI_CR4_FCONT;
+
/* Set to output mode to avoid tri-stated data pins */
if (tx)
val_cr4 |= FSL_SAI_CR4_CHMOD;
@@ -699,7 +702,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK |
- FSL_SAI_CR4_CHMOD_MASK,
+ FSL_SAI_CR4_CHMOD_MASK | FSL_SAI_CR4_FCONT_MASK,
val_cr4);
regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs),
FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index dadbd16ee394..9c4d19fe22c6 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -137,6 +137,7 @@
/* SAI Transmit and Receive Configuration 4 Register */
+#define FSL_SAI_CR4_FCONT_MASK BIT(28)
#define FSL_SAI_CR4_FCONT BIT(28)
#define FSL_SAI_CR4_FCOMB_SHIFT BIT(26)
#define FSL_SAI_CR4_FCOMB_SOFT BIT(27)
diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
index beede7344efd..1e0bfd59d511 100644
--- a/sound/soc/fsl/fsl_xcvr.c
+++ b/sound/soc/fsl/fsl_xcvr.c
@@ -53,6 +53,8 @@ struct fsl_xcvr {
struct snd_aes_iec958 rx_iec958;
struct snd_aes_iec958 tx_iec958;
u8 cap_ds[FSL_XCVR_CAPDS_SIZE];
+ struct work_struct work_rst;
+ spinlock_t lock; /* Protect hw_reset and trigger */
};
static const struct fsl_xcvr_pll_conf {
@@ -663,7 +665,10 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
{
struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
- int ret;
+ unsigned long lock_flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&xcvr->lock, lock_flags);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -675,7 +680,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
FSL_XCVR_EXT_CTRL_DPTH_RESET(tx));
if (ret < 0) {
dev_err(dai->dev, "Failed to set DPATH RESET: %d\n", ret);
- return ret;
+ goto release_lock;
}
if (tx) {
@@ -687,7 +692,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
FSL_XCVR_ISR_CMDC_TX_EN);
if (ret < 0) {
dev_err(dai->dev, "err updating isr %d\n", ret);
- return ret;
+ goto release_lock;
}
fallthrough;
case FSL_XCVR_MODE_SPDIF:
@@ -696,7 +701,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);
if (ret < 0) {
dev_err(dai->dev, "Failed to start DATA_TX: %d\n", ret);
- return ret;
+ goto release_lock;
}
break;
}
@@ -707,14 +712,14 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
FSL_XCVR_EXT_CTRL_DMA_DIS(tx), 0);
if (ret < 0) {
dev_err(dai->dev, "Failed to enable DMA: %d\n", ret);
- return ret;
+ goto release_lock;
}
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0,
FSL_XCVR_IRQ_EARC_ALL, FSL_XCVR_IRQ_EARC_ALL);
if (ret < 0) {
dev_err(dai->dev, "Error while setting IER0: %d\n", ret);
- return ret;
+ goto release_lock;
}
/* clear DPATH RESET */
@@ -723,7 +728,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
0);
if (ret < 0) {
dev_err(dai->dev, "Failed to clear DPATH RESET: %d\n", ret);
- return ret;
+ goto release_lock;
}
break;
@@ -736,14 +741,14 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
FSL_XCVR_EXT_CTRL_DMA_DIS(tx));
if (ret < 0) {
dev_err(dai->dev, "Failed to disable DMA: %d\n", ret);
- return ret;
+ goto release_lock;
}
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0,
FSL_XCVR_IRQ_EARC_ALL, 0);
if (ret < 0) {
dev_err(dai->dev, "Failed to clear IER0: %d\n", ret);
- return ret;
+ goto release_lock;
}
if (tx) {
@@ -754,7 +759,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);
if (ret < 0) {
dev_err(dai->dev, "Failed to stop DATA_TX: %d\n", ret);
- return ret;
+ goto release_lock;
}
if (xcvr->soc_data->spdif_only)
break;
@@ -768,17 +773,20 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
if (ret < 0) {
dev_err(dai->dev,
"Err updating ISR %d\n", ret);
- return ret;
+ goto release_lock;
}
break;
}
}
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ break;
}
- return 0;
+release_lock:
+ spin_unlock_irqrestore(&xcvr->lock, lock_flags);
+ return ret;
}
static int fsl_xcvr_load_firmware(struct fsl_xcvr *xcvr)
@@ -1198,6 +1206,34 @@ static const struct regmap_config fsl_xcvr_regmap_cfg = {
.cache_type = REGCACHE_FLAT,
};
+static void reset_rx_work(struct work_struct *work)
+{
+ struct fsl_xcvr *xcvr = container_of(work, struct fsl_xcvr, work_rst);
+ struct device *dev = &xcvr->pdev->dev;
+ unsigned long lock_flags;
+ u32 ext_ctrl;
+
+ dev_dbg(dev, "reset rx path\n");
+ spin_lock_irqsave(&xcvr->lock, lock_flags);
+ regmap_read(xcvr->regmap, FSL_XCVR_EXT_CTRL, &ext_ctrl);
+
+ if (!(ext_ctrl & FSL_XCVR_EXT_CTRL_DMA_RD_DIS)) {
+ regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
+ FSL_XCVR_EXT_CTRL_DMA_RD_DIS,
+ FSL_XCVR_EXT_CTRL_DMA_RD_DIS);
+ regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
+ FSL_XCVR_EXT_CTRL_RX_DPTH_RESET,
+ FSL_XCVR_EXT_CTRL_RX_DPTH_RESET);
+ regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
+ FSL_XCVR_EXT_CTRL_DMA_RD_DIS,
+ 0);
+ regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
+ FSL_XCVR_EXT_CTRL_RX_DPTH_RESET,
+ 0);
+ }
+ spin_unlock_irqrestore(&xcvr->lock, lock_flags);
+}
+
static irqreturn_t irq0_isr(int irq, void *devid)
{
struct fsl_xcvr *xcvr = (struct fsl_xcvr *)devid;
@@ -1265,6 +1301,33 @@ static irqreturn_t irq0_isr(int irq, void *devid)
dev_dbg(dev, "DMA write request\n");
isr_clr |= FSL_XCVR_IRQ_DMA_WR_REQ;
}
+ if (isr & FSL_XCVR_IRQ_CMDC_STATUS_UPD) {
+ dev_dbg(dev, "CMDC status update\n");
+ isr_clr |= FSL_XCVR_IRQ_CMDC_STATUS_UPD;
+ }
+ if (isr & FSL_XCVR_IRQ_PREAMBLE_MISMATCH) {
+ dev_dbg(dev, "Preamble mismatch\n");
+ isr_clr |= FSL_XCVR_IRQ_PREAMBLE_MISMATCH;
+ }
+ if (isr & FSL_XCVR_IRQ_UNEXP_PRE_REC) {
+ dev_dbg(dev, "Unexpected preamble received\n");
+ isr_clr |= FSL_XCVR_IRQ_UNEXP_PRE_REC;
+ }
+ if (isr & FSL_XCVR_IRQ_M_W_PRE_MISMATCH) {
+ dev_dbg(dev, "M/W preamble mismatch\n");
+ isr_clr |= FSL_XCVR_IRQ_M_W_PRE_MISMATCH;
+ }
+ if (isr & FSL_XCVR_IRQ_B_PRE_MISMATCH) {
+ dev_dbg(dev, "B preamble mismatch\n");
+ isr_clr |= FSL_XCVR_IRQ_B_PRE_MISMATCH;
+ }
+
+ if (isr & (FSL_XCVR_IRQ_PREAMBLE_MISMATCH |
+ FSL_XCVR_IRQ_UNEXP_PRE_REC |
+ FSL_XCVR_IRQ_M_W_PRE_MISMATCH |
+ FSL_XCVR_IRQ_B_PRE_MISMATCH)) {
+ schedule_work(&xcvr->work_rst);
+ }
if (isr_clr) {
regmap_write(regmap, FSL_XCVR_EXT_ISR_CLR, isr_clr);
@@ -1411,11 +1474,16 @@ static int fsl_xcvr_probe(struct platform_device *pdev)
fsl_xcvr_comp.name);
}
+ INIT_WORK(&xcvr->work_rst, reset_rx_work);
+ spin_lock_init(&xcvr->lock);
return ret;
}
static void fsl_xcvr_remove(struct platform_device *pdev)
{
+ struct fsl_xcvr *xcvr = dev_get_drvdata(&pdev->dev);
+
+ cancel_work_sync(&xcvr->work_rst);
pm_runtime_disable(&pdev->dev);
}
diff --git a/sound/soc/fsl/fsl_xcvr.h b/sound/soc/fsl/fsl_xcvr.h
index 882428592e1a..c72cb05184df 100644
--- a/sound/soc/fsl/fsl_xcvr.h
+++ b/sound/soc/fsl/fsl_xcvr.h
@@ -165,6 +165,11 @@
FSL_XCVR_IRQ_MUTE | \
FSL_XCVR_IRQ_FIFO_UOFL_ERR | \
FSL_XCVR_IRQ_HOST_WAKEUP | \
+ FSL_XCVR_IRQ_CMDC_STATUS_UPD |\
+ FSL_XCVR_IRQ_B_PRE_MISMATCH |\
+ FSL_XCVR_IRQ_M_W_PRE_MISMATCH |\
+ FSL_XCVR_IRQ_PREAMBLE_MISMATCH |\
+ FSL_XCVR_IRQ_UNEXP_PRE_REC |\
FSL_XCVR_IRQ_ARC_MODE)
#define FSL_XCVR_ISR_CMDC_TX_EN BIT(3)
diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c
index 6fbcf33fd0de..dcf770b55c4b 100644
--- a/sound/soc/fsl/imx-audmix.c
+++ b/sound/soc/fsl/imx-audmix.c
@@ -264,11 +264,10 @@ static int imx_audmix_probe(struct platform_device *pdev)
priv->dai[i].cpus->dai_name = name[1][i];
priv->dai[i].dynamic = 1;
- priv->dai[i].dpcm_playback = 1;
- if (i == num_dai - 1) {
- priv->dai[i].dpcm_capture = 1;
- priv->dai[i].dpcm_playback = 0;
- }
+ if (i == num_dai - 1)
+ priv->dai[i].capture_only = 1;
+ else
+ priv->dai[i].playback_only = 1;
priv->dai[i].ignore_pmdown_time = 1;
priv->dai[i].ops = &imx_audmix_fe_ops;
@@ -285,11 +284,10 @@ static int imx_audmix_probe(struct platform_device *pdev)
priv->dai[num_dai + i].cpus->of_node = audmix_np;
priv->dai[num_dai + i].cpus->dai_name = be_name;
priv->dai[num_dai + i].no_pcm = 1;
- priv->dai[num_dai + i].dpcm_playback = 1;
- if (i == num_dai - 1) {
- priv->dai[num_dai + i].dpcm_capture = 1;
- priv->dai[num_dai + i].dpcm_playback = 0;
- }
+ if (i == num_dai - 1)
+ priv->dai[num_dai + i].capture_only = 1;
+ else
+ priv->dai[num_dai + i].playback_only = 1;
priv->dai[num_dai + i].ignore_pmdown_time = 1;
priv->dai[num_dai + i].ops = &imx_audmix_be_ops;
diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c
index 98b37dd2b901..95a57fda0250 100644
--- a/sound/soc/fsl/imx-card.c
+++ b/sound/soc/fsl/imx-card.c
@@ -25,6 +25,7 @@ enum codec_type {
CODEC_AK4458,
CODEC_AK4497,
CODEC_AK5552,
+ CODEC_CS42888,
};
/*
@@ -185,6 +186,16 @@ static struct imx_akcodec_tdm_fs_mul ak5558_tdm_fs_mul[] = {
{ .min = 512, .max = 512, .mul = 1024 },
};
+static struct imx_akcodec_fs_mul cs42888_fs_mul[] = {
+ { .rmin = 8000, .rmax = 48000, .wmin = 256, .wmax = 1024, },
+ { .rmin = 64000, .rmax = 96000, .wmin = 128, .wmax = 512, },
+ { .rmin = 176400, .rmax = 192000, .wmin = 64, .wmax = 256, },
+};
+
+static struct imx_akcodec_tdm_fs_mul cs42888_tdm_fs_mul[] = {
+ { .min = 256, .max = 256, .mul = 256 },
+};
+
static const u32 akcodec_rates[] = {
8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
96000, 176400, 192000, 352800, 384000, 705600, 768000,
@@ -210,6 +221,14 @@ static const u32 ak5558_tdm_channels[] = {
1, 2, 3, 4, 5, 6, 7, 8,
};
+static const u32 cs42888_channels[] = {
+ 1, 2, 4, 6, 8,
+};
+
+static const u32 cs42888_tdm_channels[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8,
+};
+
static bool format_is_dsd(struct snd_pcm_hw_params *params)
{
snd_pcm_format_t format = params_format(params);
@@ -241,6 +260,7 @@ static bool codec_is_akcodec(unsigned int type)
case CODEC_AK4497:
case CODEC_AK5558:
case CODEC_AK5552:
+ case CODEC_CS42888:
return true;
default:
break;
@@ -255,7 +275,7 @@ static unsigned long akcodec_get_mclk_rate(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct imx_card_data *data = snd_soc_card_get_drvdata(rtd->card);
const struct imx_card_plat_data *plat_data = data->plat_data;
- struct dai_link_data *link_data = &data->link_data[rtd->num];
+ struct dai_link_data *link_data = &data->link_data[rtd->id];
unsigned int width = slots * slot_width;
unsigned int rate = params_rate(params);
int i;
@@ -293,7 +313,7 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct snd_soc_card *card = rtd->card;
struct imx_card_data *data = snd_soc_card_get_drvdata(card);
- struct dai_link_data *link_data = &data->link_data[rtd->num];
+ struct dai_link_data *link_data = &data->link_data[rtd->id];
struct imx_card_plat_data *plat_data = data->plat_data;
struct device *dev = card->dev;
struct snd_soc_dai *codec_dai;
@@ -340,13 +360,15 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream,
return ret;
}
- ret = snd_soc_dai_set_tdm_slot(codec_dai,
- BIT(slots) - 1,
- BIT(slots) - 1,
- slots, slot_width);
- if (ret && ret != -ENOTSUPP) {
- dev_err(dev, "failed to set codec dai[%d] tdm slot: %d\n", i, ret);
- return ret;
+ if (format_is_tdm(link_data)) {
+ ret = snd_soc_dai_set_tdm_slot(codec_dai,
+ BIT(slots) - 1,
+ BIT(slots) - 1,
+ slots, slot_width);
+ if (ret && ret != -ENOTSUPP) {
+ dev_err(dev, "failed to set codec dai[%d] tdm slot: %d\n", i, ret);
+ return ret;
+ }
}
}
@@ -370,6 +392,11 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream,
dev_err(dev, "failed to set cpui dai mclk1 rate (%lu): %d\n", mclk_freq, ret);
return ret;
}
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_freq, SND_SOC_CLOCK_IN);
+ if (ret && ret != -ENOTSUPP) {
+ dev_err(dev, "failed to set codec dai mclk rate (%lu): %d\n", mclk_freq, ret);
+ return ret;
+ }
return 0;
}
@@ -408,7 +435,7 @@ static int imx_aif_startup(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct imx_card_data *data = snd_soc_card_get_drvdata(card);
- struct dai_link_data *link_data = &data->link_data[rtd->num];
+ struct dai_link_data *link_data = &data->link_data[rtd->id];
static struct snd_pcm_hw_constraint_list constraint_rates;
static struct snd_pcm_hw_constraint_list constraint_channels;
int ret = 0;
@@ -604,6 +631,8 @@ static int imx_card_parse_of(struct imx_card_data *data)
plat_data->type = CODEC_AK5558;
else if (!strcmp(link->codecs->dai_name, "ak5552-aif"))
plat_data->type = CODEC_AK5552;
+ else if (!strcmp(link->codecs->dai_name, "cs42888"))
+ plat_data->type = CODEC_CS42888;
} else {
link->codecs = &snd_soc_dummy_dlc;
@@ -710,6 +739,7 @@ static int imx_card_probe(struct platform_device *pdev)
data->plat_data = plat_data;
data->card.dev = &pdev->dev;
+ data->card.owner = THIS_MODULE;
dev_set_drvdata(&pdev->dev, &data->card);
snd_soc_card_set_drvdata(&data->card, data);
@@ -760,6 +790,12 @@ static int imx_card_probe(struct platform_device *pdev)
data->dapm_routes[i].sink = "ASRC-Capture";
data->dapm_routes[i].source = "CPU-Capture";
break;
+ case CODEC_CS42888:
+ data->dapm_routes[0].sink = "Playback";
+ data->dapm_routes[0].source = "CPU-Playback";
+ data->dapm_routes[1].sink = "CPU-Capture";
+ data->dapm_routes[1].source = "Capture";
+ break;
default:
break;
}
@@ -799,6 +835,16 @@ static int imx_card_probe(struct platform_device *pdev)
plat_data->support_tdm_channels = ak5558_tdm_channels;
plat_data->num_tdm_channels = ARRAY_SIZE(ak5558_tdm_channels);
break;
+ case CODEC_CS42888:
+ plat_data->fs_mul = cs42888_fs_mul;
+ plat_data->num_fs_mul = ARRAY_SIZE(cs42888_fs_mul);
+ plat_data->tdm_fs_mul = cs42888_tdm_fs_mul;
+ plat_data->num_tdm_fs_mul = ARRAY_SIZE(cs42888_tdm_fs_mul);
+ plat_data->support_channels = cs42888_channels;
+ plat_data->num_channels = ARRAY_SIZE(cs42888_channels);
+ plat_data->support_tdm_channels = cs42888_tdm_channels;
+ plat_data->num_tdm_channels = ARRAY_SIZE(cs42888_tdm_channels);
+ break;
default:
break;
}
@@ -814,8 +860,8 @@ static int imx_card_probe(struct platform_device *pdev)
}
for_each_card_prelinks(&data->card, i, link) {
if (link->dynamic == 1 && link_be) {
- link->dpcm_playback = link_be->dpcm_playback;
- link->dpcm_capture = link_be->dpcm_capture;
+ link->playback_only = link_be->playback_only;
+ link->capture_only = link_be->capture_only;
}
}
}
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c
index 4b384475b972..7655425a3deb 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -372,7 +372,7 @@ static int __graph_for_each_link(struct simple_util_priv *priv,
cpu_port = it.node;
/* loop for all CPU endpoint */
- for_each_child_of_node_scoped(cpu_port, cpu_ep) {
+ for_each_of_graph_port_endpoint(cpu_port, cpu_ep) {
/* get codec */
codec_ep = of_graph_get_remote_endpoint(cpu_ep);
codec_port = ep_to_port(codec_ep);
diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c
index 4ad3d1b0714f..5280c1b20d85 100644
--- a/sound/soc/generic/audio-graph-card2.c
+++ b/sound/soc/generic/audio-graph-card2.c
@@ -50,7 +50,7 @@
snd_soc_runtime_get_dai_fmt()
sample driver
- linux/sound/soc/sh/rcar/core.c
+ linux/sound/soc/renesas/rcar/core.c
linux/sound/soc/codecs/ak4613.c
linux/sound/soc/codecs/pcm3168a.c
linux/sound/soc/soc-utils.c
@@ -234,8 +234,6 @@ enum graph_type {
#define GRAPH_NODENAME_DPCM "dpcm"
#define GRAPH_NODENAME_C2C "codec2codec"
-#define port_to_endpoint(port) of_get_child_by_name(port, "endpoint")
-
#define ep_to_port(ep) of_get_parent(ep)
static struct device_node *port_to_ports(struct device_node *port)
{
@@ -270,16 +268,19 @@ static enum graph_type __graph_get_type(struct device_node *lnk)
if (of_node_name_eq(np, GRAPH_NODENAME_MULTI)) {
ret = GRAPH_MULTI;
+ fw_devlink_purge_absent_suppliers(&np->fwnode);
goto out_put;
}
if (of_node_name_eq(np, GRAPH_NODENAME_DPCM)) {
ret = GRAPH_DPCM;
+ fw_devlink_purge_absent_suppliers(&np->fwnode);
goto out_put;
}
if (of_node_name_eq(np, GRAPH_NODENAME_C2C)) {
ret = GRAPH_C2C;
+ fw_devlink_purge_absent_suppliers(&np->fwnode);
goto out_put;
}
@@ -351,14 +352,9 @@ static struct device_node *graph_get_next_multi_ep(struct device_node **port)
* port@1 { rep1 };
* };
*/
- do {
- *port = of_get_next_child(ports, *port);
- if (!*port)
- break;
- } while (!of_node_name_eq(*port, "port"));
-
+ *port = of_graph_get_next_port(ports, *port);
if (*port) {
- ep = port_to_endpoint(*port);
+ ep = of_graph_get_next_port_endpoint(*port, NULL);
rep = of_graph_get_remote_endpoint(ep);
}
@@ -530,67 +526,66 @@ static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link,
* };
* };
*/
- struct device_node *mcpu_ep = port_to_endpoint(mcpu_port);
- struct device_node *mcpu_ep_n = mcpu_ep;
- struct device_node *mcpu_port_top = of_get_next_child(port_to_ports(mcpu_port), NULL);
- struct device_node *mcpu_ep_top = port_to_endpoint(mcpu_port_top);
+ struct device_node *mcpu_ep = of_graph_get_next_port_endpoint(mcpu_port, NULL);
+ struct device_node *mcpu_ports = port_to_ports(mcpu_port);
+ struct device_node *mcpu_port_top = of_graph_get_next_port(mcpu_ports, NULL);
+ struct device_node *mcpu_ep_top = of_graph_get_next_port_endpoint(mcpu_port_top, NULL);
struct device_node *mcodec_ep_top = of_graph_get_remote_endpoint(mcpu_ep_top);
struct device_node *mcodec_port_top = ep_to_port(mcodec_ep_top);
struct device_node *mcodec_ports = port_to_ports(mcodec_port_top);
int nm_max = max(dai_link->num_cpus, dai_link->num_codecs);
- int ret = -EINVAL;
+ int ret = 0;
- if (cpu_idx > dai_link->num_cpus)
+ if (cpu_idx > dai_link->num_cpus) {
+ ret = -EINVAL;
goto mcpu_err;
+ }
- while (1) {
+ for_each_of_graph_port_endpoint(mcpu_port, mcpu_ep_n) {
struct device_node *mcodec_ep_n;
- struct device_node *mcodec_port_i;
struct device_node *mcodec_port;
int codec_idx;
+ /* ignore 1st ep which is for element */
+ if (mcpu_ep_n == mcpu_ep)
+ continue;
+
if (*nm_idx > nm_max)
break;
- mcpu_ep_n = of_get_next_child(mcpu_port, mcpu_ep_n);
- if (!mcpu_ep_n) {
- ret = 0;
- break;
- }
-
mcodec_ep_n = of_graph_get_remote_endpoint(mcpu_ep_n);
mcodec_port = ep_to_port(mcodec_ep_n);
- if (mcodec_ports != port_to_ports(mcodec_port))
+ if (mcodec_ports != port_to_ports(mcodec_port)) {
+ ret = -EINVAL;
goto mcpu_err;
+ }
codec_idx = 0;
- mcodec_port_i = of_get_next_child(mcodec_ports, NULL);
- while (1) {
- if (codec_idx > dai_link->num_codecs)
- goto mcodec_err;
-
- mcodec_port_i = of_get_next_child(mcodec_ports, mcodec_port_i);
+ ret = -EINVAL;
+ for_each_of_graph_port(mcodec_ports, mcodec_port_i) {
- if (!mcodec_port_i)
- goto mcodec_err;
+ /* ignore 1st port which is for pair connection */
+ if (mcodec_port_top == mcodec_port_i)
+ continue;
- if (mcodec_port_i == mcodec_port)
+ if (codec_idx > dai_link->num_codecs)
break;
+ if (mcodec_port_i == mcodec_port) {
+ dai_link->ch_maps[*nm_idx].cpu = cpu_idx;
+ dai_link->ch_maps[*nm_idx].codec = codec_idx;
+
+ (*nm_idx)++;
+ ret = 0;
+ break;
+ }
codec_idx++;
}
-
- dai_link->ch_maps[*nm_idx].cpu = cpu_idx;
- dai_link->ch_maps[*nm_idx].codec = codec_idx;
-
- (*nm_idx)++;
-
- of_node_put(mcodec_port_i);
-mcodec_err:
of_node_put(mcodec_port);
- of_node_put(mcpu_ep_n);
of_node_put(mcodec_ep_n);
+ if (ret < 0)
+ break;
}
mcpu_err:
of_node_put(mcpu_ep);
@@ -674,7 +669,7 @@ static int graph_parse_node_single(struct simple_util_priv *priv,
struct device_node *port,
struct link_info *li, int is_cpu)
{
- struct device_node *ep = port_to_endpoint(port);
+ struct device_node *ep = of_graph_get_next_port_endpoint(port, NULL);
int ret = __graph_parse_node(priv, gtype, ep, li, is_cpu, 0);
of_node_put(ep);
@@ -769,7 +764,7 @@ static void graph_link_init(struct simple_util_priv *priv,
of_node_put(port_cpu);
port_cpu = ep_to_port(ep_cpu);
} else {
- ep_cpu = port_to_endpoint(port_cpu);
+ ep_cpu = of_graph_get_next_port_endpoint(port_cpu, NULL);
}
ports_cpu = port_to_ports(port_cpu);
@@ -779,7 +774,7 @@ static void graph_link_init(struct simple_util_priv *priv,
of_node_put(port_cpu);
port_codec = ep_to_port(ep_codec);
} else {
- ep_codec = port_to_endpoint(port_codec);
+ ep_codec = of_graph_get_next_port_endpoint(port_codec, NULL);
}
ports_codec = port_to_ports(port_codec);
@@ -850,7 +845,7 @@ int audio_graph2_link_normal(struct simple_util_priv *priv,
struct link_info *li)
{
struct device_node *cpu_port = lnk;
- struct device_node *cpu_ep = port_to_endpoint(cpu_port);
+ struct device_node *cpu_ep = of_graph_get_next_port_endpoint(cpu_port, NULL);
struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
int ret;
@@ -883,7 +878,7 @@ int audio_graph2_link_dpcm(struct simple_util_priv *priv,
struct device_node *lnk,
struct link_info *li)
{
- struct device_node *ep = port_to_endpoint(lnk);
+ struct device_node *ep = of_graph_get_next_port_endpoint(lnk, NULL);
struct device_node *rep = of_graph_get_remote_endpoint(ep);
struct device_node *cpu_port = NULL;
struct device_node *codec_port = NULL;
@@ -1007,7 +1002,7 @@ int audio_graph2_link_c2c(struct simple_util_priv *priv,
of_node_get(lnk);
port0 = lnk;
ports = port_to_ports(port0);
- port1 = of_get_next_child(ports, lnk);
+ port1 = of_graph_get_next_port(ports, port0);
/*
* Card2 can use original Codec2Codec settings if DT has.
@@ -1037,8 +1032,8 @@ int audio_graph2_link_c2c(struct simple_util_priv *priv,
dai_link->num_c2c_params = 1;
}
- ep0 = port_to_endpoint(port0);
- ep1 = port_to_endpoint(port1);
+ ep0 = of_graph_get_next_port_endpoint(port0, NULL);
+ ep1 = of_graph_get_next_port_endpoint(port1, NULL);
codec0_port = of_graph_get_remote_port(ep0);
codec1_port = of_graph_get_remote_port(ep1);
@@ -1144,7 +1139,7 @@ static int graph_counter(struct device_node *lnk)
* CPU/Codec = N:M case has many endpoints.
* We can't use of_graph_get_endpoint_count() here
*/
- return of_get_child_count(ports) - 1;
+ return of_graph_get_port_count(ports) - 1;
}
/*
* Single CPU / Codec
@@ -1158,7 +1153,7 @@ static int graph_count_normal(struct simple_util_priv *priv,
struct link_info *li)
{
struct device_node *cpu_port = lnk;
- struct device_node *cpu_ep = port_to_endpoint(cpu_port);
+ struct device_node *cpu_ep = of_graph_get_next_port_endpoint(cpu_port, NULL);
struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
/*
@@ -1186,7 +1181,7 @@ static int graph_count_dpcm(struct simple_util_priv *priv,
struct device_node *lnk,
struct link_info *li)
{
- struct device_node *ep = port_to_endpoint(lnk);
+ struct device_node *ep = of_graph_get_next_port_endpoint(lnk, NULL);
struct device_node *rport = of_graph_get_remote_port(ep);
/*
@@ -1228,9 +1223,9 @@ static int graph_count_c2c(struct simple_util_priv *priv,
{
struct device_node *ports = port_to_ports(lnk);
struct device_node *port0 = lnk;
- struct device_node *port1 = of_get_next_child(ports, of_node_get(lnk));
- struct device_node *ep0 = port_to_endpoint(port0);
- struct device_node *ep1 = port_to_endpoint(port1);
+ struct device_node *port1 = of_graph_get_next_port(ports, of_node_get(port0));
+ struct device_node *ep0 = of_graph_get_next_port_endpoint(port0, NULL);
+ struct device_node *ep1 = of_graph_get_next_port_endpoint(port1, NULL);
struct device_node *codec0 = of_graph_get_remote_port(ep0);
struct device_node *codec1 = of_graph_get_remote_port(ep1);
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index fedae7f6f70c..24b371f32066 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -296,7 +296,7 @@ int simple_util_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
- struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num);
+ struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id);
struct simple_util_dai *dai;
unsigned int fixed_sysclk = 0;
int i1, i2, i;
@@ -357,7 +357,7 @@ void simple_util_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
- struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num);
+ struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id);
struct simple_util_dai *dai;
int i;
@@ -448,7 +448,7 @@ int simple_util_hw_params(struct snd_pcm_substream *substream,
struct simple_util_dai *pdai;
struct snd_soc_dai *sdai;
struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
- struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num);
+ struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id);
unsigned int mclk, mclk_fs = 0;
int i, ret;
@@ -517,7 +517,7 @@ int simple_util_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
- struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num);
+ struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->id);
struct simple_util_data *data = &dai_props->adata;
struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
@@ -628,7 +628,7 @@ static int simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd,
int simple_util_dai_init(struct snd_soc_pcm_runtime *rtd)
{
struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
- struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num);
+ struct simple_dai_props *props = simple_priv_to_props(priv, rtd->id);
struct simple_util_dai *dai;
int i, ret;
@@ -858,6 +858,10 @@ int simple_util_init_aux_jacks(struct simple_util_priv *priv, char *prefix)
}
EXPORT_SYMBOL_GPL(simple_util_init_aux_jacks);
+static struct simple_util_dai dummy_util_dais = {
+ .name = "dummy_util_dais",
+};
+
int simple_util_init_priv(struct simple_util_priv *priv,
struct link_info *li)
{
@@ -929,6 +933,7 @@ int simple_util_init_priv(struct simple_util_priv *priv,
dai_link[i].cpus = &snd_soc_dummy_dlc;
dai_props[i].num.cpus =
dai_link[i].num_cpus = 1;
+ dai_props[i].cpu_dai = &dummy_util_dais;
}
if (li->num[i].codecs) {
@@ -951,6 +956,7 @@ int simple_util_init_priv(struct simple_util_priv *priv,
dai_link[i].codecs = &snd_soc_dummy_dlc;
dai_props[i].num.codecs =
dai_link[i].num_codecs = 1;
+ dai_props[i].codec_dai = &dummy_util_dais;
}
if (li->num[i].platforms) {
diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c
index 407288055741..5430d25deaef 100644
--- a/sound/soc/generic/test-component.c
+++ b/sound/soc/generic/test-component.c
@@ -224,7 +224,7 @@ static const struct snd_soc_dai_ops test_verbose_ops = {
.num_auto_selectable_formats = 1,
};
-#define STUB_RATES SNDRV_PCM_RATE_8000_384000
+#define STUB_RATES SNDRV_PCM_RATE_CONTINUOUS
#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_U8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
@@ -521,7 +521,6 @@ static int test_driver_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
- struct device_node *ep;
const struct test_adata *adata = of_device_get_match_data(&pdev->dev);
struct snd_soc_component_driver *cdriv;
struct snd_soc_dai_driver *ddriv;
@@ -591,7 +590,7 @@ static int test_driver_probe(struct platform_device *pdev)
}
i = 0;
- for_each_endpoint_of_node(node, ep) {
+ for_each_of_graph_port(node, port) {
snprintf(dname[i].name, TEST_NAME_LEN, "%s.%d", node->name, i);
ddriv[i].name = dname[i].name;
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index a32fb0a8d7d7..2db494b0e3cf 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -15,9 +15,6 @@ config SND_SOC_INTEL_SST_TOPLEVEL
if SND_SOC_INTEL_SST_TOPLEVEL
-config SND_SOC_INTEL_SST
- tristate
-
config SND_SOC_INTEL_CATPT
tristate "Haswell and Broadwell"
depends on ACPI || COMPILE_TEST
@@ -74,9 +71,14 @@ if SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL
config SND_SOC_ACPI_INTEL_MATCH
tristate
select SND_SOC_ACPI if ACPI
+ select SND_SOC_ACPI_INTEL_SDCA_QUIRKS
# this option controls the compilation of ACPI matching tables and
# helpers and is not meant to be selected by the user.
+config SND_SOC_ACPI_INTEL_SDCA_QUIRKS
+ tristate
+ select SND_SOC_SDCA if ACPI
+
endif ## SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL
config SND_SOC_INTEL_KEEMBAY
diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c
index 9956dc63db74..257180630475 100644
--- a/sound/soc/intel/atom/sst/sst_acpi.c
+++ b/sound/soc/intel/atom/sst/sst_acpi.c
@@ -125,6 +125,28 @@ static const struct sst_res_info bytcr_res_info = {
.acpi_ipc_irq_index = 0
};
+/* For "LPE0F28" ACPI device found on some Android factory OS models */
+static const struct sst_res_info lpe8086_res_info = {
+ .shim_offset = 0x140000,
+ .shim_size = 0x000100,
+ .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
+ .ssp0_offset = 0xa0000,
+ .ssp0_size = 0x1000,
+ .dma0_offset = 0x98000,
+ .dma0_size = 0x4000,
+ .dma1_offset = 0x9c000,
+ .dma1_size = 0x4000,
+ .iram_offset = 0x0c0000,
+ .iram_size = 0x14000,
+ .dram_offset = 0x100000,
+ .dram_size = 0x28000,
+ .mbox_offset = 0x144000,
+ .mbox_size = 0x1000,
+ .acpi_lpe_res_index = 1,
+ .acpi_ddr_index = 0,
+ .acpi_ipc_irq_index = 0
+};
+
static struct sst_platform_info byt_rvp_platform_data = {
.probe_data = &byt_fwparse_info,
.ipc_info = &byt_ipc_info,
@@ -268,10 +290,38 @@ static int sst_acpi_probe(struct platform_device *pdev)
mach->pdata = &chv_platform_data;
pdata = mach->pdata;
- ret = kstrtouint(id->id, 16, &dev_id);
- if (ret < 0) {
- dev_err(dev, "Unique device id conversion error: %d\n", ret);
- return ret;
+ if (!strcmp(id->id, "LPE0F28")) {
+ struct resource *rsrc;
+
+ /* Use regular BYT SST PCI VID:PID */
+ dev_id = 0x80860F28;
+ byt_rvp_platform_data.res_info = &lpe8086_res_info;
+
+ /*
+ * The "LPE0F28" ACPI device has separate IO-mem resources for:
+ * DDR, SHIM, MBOX, IRAM, DRAM, CFG
+ * None of which covers the entire LPE base address range.
+ * lpe8086_res_info.acpi_lpe_res_index points to the SHIM.
+ * Patch this to cover the entire base address range as expected
+ * by sst_platform_get_resources().
+ */
+ rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
+ pdata->res_info->acpi_lpe_res_index);
+ if (!rsrc) {
+ dev_err(dev, "Invalid SHIM base\n");
+ return -EIO;
+ }
+ rsrc->start -= pdata->res_info->shim_offset;
+ rsrc->end = rsrc->start + 0x200000 - 1;
+ } else {
+ ret = kstrtouint(id->id, 16, &dev_id);
+ if (ret < 0) {
+ dev_err(dev, "Unique device id conversion error: %d\n", ret);
+ return ret;
+ }
+
+ if (soc_intel_is_byt_cr(pdev))
+ byt_rvp_platform_data.res_info = &bytcr_res_info;
}
dev_dbg(dev, "ACPI device id: %x\n", dev_id);
@@ -280,11 +330,6 @@ static int sst_acpi_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- if (soc_intel_is_byt_cr(pdev)) {
- /* override resource info */
- byt_rvp_platform_data.res_info = &bytcr_res_info;
- }
-
/* update machine parameters */
mach->mach_params.acpi_ipc_irq_index =
pdata->res_info->acpi_ipc_irq_index;
@@ -344,6 +389,7 @@ static void sst_acpi_remove(struct platform_device *pdev)
}
static const struct acpi_device_id sst_acpi_ids[] = {
+ { "LPE0F28", (unsigned long)&snd_soc_acpi_intel_baytrail_machines},
{ "80860F28", (unsigned long)&snd_soc_acpi_intel_baytrail_machines},
{ "808622A8", (unsigned long)&snd_soc_acpi_intel_cherrytrail_machines},
{ },
diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c
index 80c0a1a95654..93eba4fd2771 100644
--- a/sound/soc/intel/avs/boards/da7219.c
+++ b/sound/soc/intel/avs/boards/da7219.c
@@ -203,8 +203,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->exit = avs_da7219_codec_exit;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_capture = 1;
- dl->dpcm_playback = 1;
*dai_link = dl;
diff --git a/sound/soc/intel/avs/boards/dmic.c b/sound/soc/intel/avs/boards/dmic.c
index a31aa471a1c2..4dd9591ee98b 100644
--- a/sound/soc/intel/avs/boards/dmic.c
+++ b/sound/soc/intel/avs/boards/dmic.c
@@ -22,7 +22,7 @@ static struct snd_soc_dai_link card_dai_links[] = {
{
.name = "DMIC",
.id = 0,
- .dpcm_capture = 1,
+ .capture_only = 1,
.nonatomic = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform),
@@ -30,7 +30,7 @@ static struct snd_soc_dai_link card_dai_links[] = {
{
.name = "DMIC WoV",
.id = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.nonatomic = 1,
.no_pcm = 1,
.ignore_suspend = 1,
diff --git a/sound/soc/intel/avs/boards/es8336.c b/sound/soc/intel/avs/boards/es8336.c
index c8522e2430f8..426ce37105ae 100644
--- a/sound/soc/intel/avs/boards/es8336.c
+++ b/sound/soc/intel/avs/boards/es8336.c
@@ -233,8 +233,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->ops = &avs_es8336_ops;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_capture = 1;
- dl->dpcm_playback = 1;
*dai_link = dl;
diff --git a/sound/soc/intel/avs/boards/hdaudio.c b/sound/soc/intel/avs/boards/hdaudio.c
index 430c070a1a0e..cb6d54db7189 100644
--- a/sound/soc/intel/avs/boards/hdaudio.c
+++ b/sound/soc/intel/avs/boards/hdaudio.c
@@ -39,8 +39,6 @@ static int avs_create_dai_links(struct device *dev, struct hda_codec *codec, int
dl[i].id = i;
dl[i].nonatomic = 1;
dl[i].no_pcm = 1;
- dl[i].dpcm_playback = 1;
- dl[i].dpcm_capture = 1;
dl[i].platforms = platform;
dl[i].num_platforms = 1;
dl[i].ignore_pmdown_time = 1;
@@ -160,8 +158,6 @@ static const struct snd_soc_dai_link probing_link = {
.id = -1,
.nonatomic = 1,
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.cpus = &snd_soc_dummy_dlc,
.num_cpus = 1,
.init = avs_probing_link_init,
diff --git a/sound/soc/intel/avs/boards/i2s_test.c b/sound/soc/intel/avs/boards/i2s_test.c
index 7e6c8d9c900b..4556f105c793 100644
--- a/sound/soc/intel/avs/boards/i2s_test.c
+++ b/sound/soc/intel/avs/boards/i2s_test.c
@@ -46,8 +46,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->id = 0;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_capture = 1;
- dl->dpcm_playback = 1;
*dai_link = dl;
diff --git a/sound/soc/intel/avs/boards/max98357a.c b/sound/soc/intel/avs/boards/max98357a.c
index 8d550e82b46a..6570209c1a63 100644
--- a/sound/soc/intel/avs/boards/max98357a.c
+++ b/sound/soc/intel/avs/boards/max98357a.c
@@ -82,7 +82,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->be_hw_params_fixup = avs_max98357a_be_fixup;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_playback = 1;
+ dl->playback_only = 1;
*dai_link = dl;
diff --git a/sound/soc/intel/avs/boards/max98373.c b/sound/soc/intel/avs/boards/max98373.c
index fdef5a008daf..6f25e66344b7 100644
--- a/sound/soc/intel/avs/boards/max98373.c
+++ b/sound/soc/intel/avs/boards/max98373.c
@@ -134,8 +134,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->be_hw_params_fixup = avs_max98373_be_fixup;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_capture = 1;
- dl->dpcm_playback = 1;
dl->ignore_pmdown_time = 1;
dl->ops = &avs_max98373_ops;
diff --git a/sound/soc/intel/avs/boards/max98927.c b/sound/soc/intel/avs/boards/max98927.c
index 082f311d8b84..ad18c4e9a670 100644
--- a/sound/soc/intel/avs/boards/max98927.c
+++ b/sound/soc/intel/avs/boards/max98927.c
@@ -131,8 +131,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->be_hw_params_fixup = avs_max98927_be_fixup;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_capture = 1;
- dl->dpcm_playback = 1;
dl->ignore_pmdown_time = 1;
dl->ops = &avs_max98927_ops;
diff --git a/sound/soc/intel/avs/boards/nau8825.c b/sound/soc/intel/avs/boards/nau8825.c
index 6ea9058fdb2a..bf902540744c 100644
--- a/sound/soc/intel/avs/boards/nau8825.c
+++ b/sound/soc/intel/avs/boards/nau8825.c
@@ -210,8 +210,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->ops = &avs_nau8825_ops;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_capture = 1;
- dl->dpcm_playback = 1;
*dai_link = dl;
diff --git a/sound/soc/intel/avs/boards/rt274.c b/sound/soc/intel/avs/boards/rt274.c
index 9fcce86c6eb4..4b6c02a40204 100644
--- a/sound/soc/intel/avs/boards/rt274.c
+++ b/sound/soc/intel/avs/boards/rt274.c
@@ -184,8 +184,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->be_hw_params_fixup = avs_rt274_be_fixup;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_capture = 1;
- dl->dpcm_playback = 1;
*dai_link = dl;
diff --git a/sound/soc/intel/avs/boards/rt286.c b/sound/soc/intel/avs/boards/rt286.c
index f157f2d19efb..e40563ca99fd 100644
--- a/sound/soc/intel/avs/boards/rt286.c
+++ b/sound/soc/intel/avs/boards/rt286.c
@@ -153,8 +153,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->ops = &avs_rt286_ops;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_capture = 1;
- dl->dpcm_playback = 1;
*dai_link = dl;
diff --git a/sound/soc/intel/avs/boards/rt298.c b/sound/soc/intel/avs/boards/rt298.c
index 1e85242c8dd2..94fce07c83f9 100644
--- a/sound/soc/intel/avs/boards/rt298.c
+++ b/sound/soc/intel/avs/boards/rt298.c
@@ -173,8 +173,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->ops = &avs_rt298_ops;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_capture = 1;
- dl->dpcm_playback = 1;
*dai_link = dl;
diff --git a/sound/soc/intel/avs/boards/rt5514.c b/sound/soc/intel/avs/boards/rt5514.c
index cfa146b6cf08..30588d9e9ba3 100644
--- a/sound/soc/intel/avs/boards/rt5514.c
+++ b/sound/soc/intel/avs/boards/rt5514.c
@@ -121,7 +121,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->be_hw_params_fixup = avs_rt5514_be_fixup;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_capture = 1;
+ dl->capture_only = 1;
dl->ops = &avs_rt5514_ops;
*dai_link = dl;
diff --git a/sound/soc/intel/avs/boards/rt5663.c b/sound/soc/intel/avs/boards/rt5663.c
index 44f857e90969..b456b9d14665 100644
--- a/sound/soc/intel/avs/boards/rt5663.c
+++ b/sound/soc/intel/avs/boards/rt5663.c
@@ -171,8 +171,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->be_hw_params_fixup = avs_rt5663_be_fixup;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_capture = 1;
- dl->dpcm_playback = 1;
dl->ops = &avs_rt5663_ops;
*dai_link = dl;
diff --git a/sound/soc/intel/avs/boards/rt5682.c b/sound/soc/intel/avs/boards/rt5682.c
index 0dcc6392a0cc..335960cfd7ba 100644
--- a/sound/soc/intel/avs/boards/rt5682.c
+++ b/sound/soc/intel/avs/boards/rt5682.c
@@ -242,8 +242,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->ops = &avs_rt5682_ops;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_capture = 1;
- dl->dpcm_playback = 1;
*dai_link = dl;
diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c
index 63bbfc30f35e..cfef00462f66 100644
--- a/sound/soc/intel/avs/boards/ssm4567.c
+++ b/sound/soc/intel/avs/boards/ssm4567.c
@@ -121,8 +121,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
dl->be_hw_params_fixup = avs_ssm4567_be_fixup;
dl->nonatomic = 1;
dl->no_pcm = 1;
- dl->dpcm_capture = 1;
- dl->dpcm_playback = 1;
dl->ignore_pmdown_time = 1;
*dai_link = dl;
diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c
index da7bac09acb4..73d4bde9b2f7 100644
--- a/sound/soc/intel/avs/core.c
+++ b/sound/soc/intel/avs/core.c
@@ -28,6 +28,7 @@
#include "avs.h"
#include "cldma.h"
#include "messages.h"
+#include "pcm.h"
static u32 pgctl_mask = AZX_PGCTL_LSRMD_MASK;
module_param(pgctl_mask, uint, 0444);
@@ -247,7 +248,7 @@ static void hdac_stream_update_pos(struct hdac_stream *stream, u64 buffer_size)
static void hdac_update_stream(struct hdac_bus *bus, struct hdac_stream *stream)
{
if (stream->substream) {
- snd_pcm_period_elapsed(stream->substream);
+ avs_period_elapsed(stream->substream);
} else if (stream->cstream) {
u64 buffer_size = stream->cstream->runtime->buffer_size;
diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c
index afc0fc74cf94..945f9c0a6a54 100644
--- a/sound/soc/intel/avs/pcm.c
+++ b/sound/soc/intel/avs/pcm.c
@@ -16,6 +16,7 @@
#include <sound/soc-component.h>
#include "avs.h"
#include "path.h"
+#include "pcm.h"
#include "topology.h"
#include "../../codecs/hda.h"
@@ -30,6 +31,7 @@ struct avs_dma_data {
struct hdac_ext_stream *host_stream;
};
+ struct work_struct period_elapsed_work;
struct snd_pcm_substream *substream;
};
@@ -56,6 +58,22 @@ avs_dai_find_path_template(struct snd_soc_dai *dai, bool is_fe, int direction)
return dw->priv;
}
+static void avs_period_elapsed_work(struct work_struct *work)
+{
+ struct avs_dma_data *data = container_of(work, struct avs_dma_data, period_elapsed_work);
+
+ snd_pcm_period_elapsed(data->substream);
+}
+
+void avs_period_elapsed(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0);
+ struct avs_dma_data *data = snd_soc_dai_get_dma_data(dai, substream);
+
+ schedule_work(&data->period_elapsed_work);
+}
+
static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
@@ -77,6 +95,7 @@ static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_d
data->substream = substream;
data->template = template;
data->adev = adev;
+ INIT_WORK(&data->period_elapsed_work, avs_period_elapsed_work);
snd_soc_dai_set_dma_data(dai, substream, data);
if (rtd->dai_link->ignore_suspend)
@@ -490,7 +509,7 @@ static int avs_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_CHANNELS,
SNDRV_PCM_HW_PARAM_RATE, -1);
- return ret;
+ return 0;
}
static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
diff --git a/sound/soc/intel/avs/pcm.h b/sound/soc/intel/avs/pcm.h
new file mode 100644
index 000000000000..0f3615c90398
--- /dev/null
+++ b/sound/soc/intel/avs/pcm.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright(c) 2024 Intel Corporation
+ *
+ * Authors: Cezary Rojewski <cezary.rojewski@intel.com>
+ * Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
+ */
+
+#ifndef __SOUND_SOC_INTEL_AVS_PCM_H
+#define __SOUND_SOC_INTEL_AVS_PCM_H
+
+#include <sound/pcm.h>
+
+void avs_period_elapsed(struct snd_pcm_substream *substream);
+
+#endif
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index cc10ae58b0c7..9b80b19bb8d0 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -519,6 +519,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
select SND_SOC_RT712_SDCA_DMIC_SDW
select SND_SOC_RT715_SDW
select SND_SOC_RT715_SDCA_SDW
+ select SND_SOC_RT721_SDCA_SDW
select SND_SOC_RT722_SDCA_SDW
select SND_SOC_RT1308_SDW
select SND_SOC_RT1308
diff --git a/sound/soc/intel/boards/bdw-rt5650.c b/sound/soc/intel/boards/bdw-rt5650.c
index 3c7cee03a02e..d25a7188f603 100644
--- a/sound/soc/intel/boards/bdw-rt5650.c
+++ b/sound/soc/intel/boards/bdw-rt5650.c
@@ -239,8 +239,6 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = {
SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST
},
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(fe, dummy, platform),
},
@@ -256,8 +254,6 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = {
.ignore_pmdown_time = 1,
.be_hw_params_fixup = broadwell_ssp0_fixup,
.ops = &bdw_rt5650_ops,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.init = bdw_rt5650_init,
SND_SOC_DAILINK_REG(ssp0_port, be, platform),
},
diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c
index 304af3d06d01..9484f3410787 100644
--- a/sound/soc/intel/boards/bdw-rt5677.c
+++ b/sound/soc/intel/boards/bdw-rt5677.c
@@ -329,8 +329,6 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = {
SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST
},
- .dpcm_capture = 1,
- .dpcm_playback = 1,
.ops = &bdw_rt5677_fe_ops,
SND_SOC_DAILINK_REG(fe, dummy, platform),
},
@@ -356,8 +354,6 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = {
.ignore_pmdown_time = 1,
.be_hw_params_fixup = broadwell_ssp0_fixup,
.ops = &bdw_rt5677_ops,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.init = bdw_rt5677_init,
.exit = bdw_rt5677_exit,
SND_SOC_DAILINK_REG(ssp0_port, be, platform),
diff --git a/sound/soc/intel/boards/bdw_rt286.c b/sound/soc/intel/boards/bdw_rt286.c
index 58db09d9b6e1..523ade9f31ab 100644
--- a/sound/soc/intel/boards/bdw_rt286.c
+++ b/sound/soc/intel/boards/bdw_rt286.c
@@ -133,8 +133,6 @@ static struct snd_soc_dai_link card_dai_links[] = {
.nonatomic = 1,
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(system, dummy, platform),
},
{
@@ -143,7 +141,7 @@ static struct snd_soc_dai_link card_dai_links[] = {
.nonatomic = 1,
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(offload0, dummy, platform),
},
{
@@ -152,7 +150,7 @@ static struct snd_soc_dai_link card_dai_links[] = {
.nonatomic = 1,
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(offload1, dummy, platform),
},
{
@@ -161,7 +159,7 @@ static struct snd_soc_dai_link card_dai_links[] = {
.nonatomic = 1,
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(loopback, dummy, platform),
},
/* Back End DAI links */
@@ -177,8 +175,6 @@ static struct snd_soc_dai_link card_dai_links[] = {
.ignore_pmdown_time = 1,
.be_hw_params_fixup = codec_link_hw_params_fixup,
.ops = &codec_link_ops,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(ssp0_port, codec, platform),
},
};
diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c
index 8c2b4ab764bb..68a3d345dc25 100644
--- a/sound/soc/intel/boards/bytcht_cx2072x.c
+++ b/sound/soc/intel/boards/bytcht_cx2072x.c
@@ -175,8 +175,6 @@ static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = {
.stream_name = "Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &byt_cht_cx2072x_aif1_ops,
SND_SOC_DAILINK_REG(media, dummy, platform),
},
@@ -185,7 +183,7 @@ static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = {
.stream_name = "Deep-Buffer Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &byt_cht_cx2072x_aif1_ops,
SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
},
@@ -198,8 +196,6 @@ static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = {
| SND_SOC_DAIFMT_CBC_CFC,
.init = byt_cht_cx2072x_init,
.be_hw_params_fixup = byt_cht_cx2072x_fixup,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(ssp2, cx2072x, platform),
},
};
diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c
index 9178bbe8d995..31141d4b6b25 100644
--- a/sound/soc/intel/boards/bytcht_da7213.c
+++ b/sound/soc/intel/boards/bytcht_da7213.c
@@ -174,8 +174,6 @@ static struct snd_soc_dai_link dailink[] = {
.stream_name = "Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &aif1_ops,
SND_SOC_DAILINK_REG(media, dummy, platform),
},
@@ -184,7 +182,7 @@ static struct snd_soc_dai_link dailink[] = {
.stream_name = "Deep-Buffer Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &aif1_ops,
SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
},
@@ -197,8 +195,6 @@ static struct snd_soc_dai_link dailink[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBC_CFC,
.be_hw_params_fixup = codec_fixup,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &ssp2_ops,
SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
},
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
index d3327bc237b5..62594e7966ab 100644
--- a/sound/soc/intel/boards/bytcht_es8316.c
+++ b/sound/soc/intel/boards/bytcht_es8316.c
@@ -315,8 +315,6 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
.stream_name = "Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &byt_cht_es8316_aif1_ops,
SND_SOC_DAILINK_REG(media, dummy, platform),
},
@@ -326,7 +324,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
.stream_name = "Deep-Buffer Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &byt_cht_es8316_aif1_ops,
SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
},
@@ -339,8 +337,6 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBC_CFC,
.be_hw_params_fixup = byt_cht_es8316_codec_fixup,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.init = byt_cht_es8316_init,
SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
},
diff --git a/sound/soc/intel/boards/bytcht_nocodec.c b/sound/soc/intel/boards/bytcht_nocodec.c
index 4a957d1cece3..fec23bda9e64 100644
--- a/sound/soc/intel/boards/bytcht_nocodec.c
+++ b/sound/soc/intel/boards/bytcht_nocodec.c
@@ -119,8 +119,6 @@ static struct snd_soc_dai_link dais[] = {
.ignore_suspend = 1,
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &aif1_ops,
SND_SOC_DAILINK_REG(media, dummy, platform),
},
@@ -130,7 +128,7 @@ static struct snd_soc_dai_link dais[] = {
.ignore_suspend = 1,
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &aif1_ops,
SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
},
@@ -144,8 +142,6 @@ static struct snd_soc_dai_link dais[] = {
| SND_SOC_DAIFMT_CBC_CFC,
.be_hw_params_fixup = codec_fixup,
.ignore_suspend = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(ssp2_port, dummy, platform),
},
};
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 2ed49acb4e36..9caa4407c1ca 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -17,6 +17,7 @@
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/device.h>
+#include <linux/device/bus.h>
#include <linux/dmi.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h>
@@ -32,6 +33,8 @@
#include "../atom/sst-atom-controls.h"
#include "../common/soc-intel-quirks.h"
+#define BYT_RT5640_FALLBACK_CODEC_DEV_NAME "i2c-rt5640"
+
enum {
BYT_RT5640_DMIC1_MAP,
BYT_RT5640_DMIC2_MAP,
@@ -1129,6 +1132,21 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF2 |
BYT_RT5640_MCLK_EN),
},
+ { /* Vexia Edu Atla 10 tablet */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+ /* Above strings are too generic, also match on BIOS date */
+ DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"),
+ },
+ .driver_data = (void *)(BYT_RT5640_IN1_MAP |
+ BYT_RT5640_JD_SRC_JD2_IN4N |
+ BYT_RT5640_OVCD_TH_2000UA |
+ BYT_RT5640_OVCD_SF_0P75 |
+ BYT_RT5640_DIFF_MIC |
+ BYT_RT5640_SSP0_AIF2 |
+ BYT_RT5640_MCLK_EN),
+ },
{ /* Voyo Winpad A15 */
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
@@ -1546,8 +1564,6 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
.stream_name = "Baytrail Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &byt_rt5640_aif1_ops,
SND_SOC_DAILINK_REG(media, dummy, platform),
},
@@ -1556,7 +1572,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
.stream_name = "Deep-Buffer Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &byt_rt5640_aif1_ops,
SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
},
@@ -1568,8 +1584,6 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBC_CFC,
.be_hw_params_fixup = byt_rt5640_codec_fixup,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.init = byt_rt5640_init,
.exit = byt_rt5640_exit,
.ops = &byt_rt5640_be_ssp2_ops,
@@ -1698,9 +1712,33 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
codec_dev = acpi_get_first_physical_node(adev);
acpi_dev_put(adev);
- if (!codec_dev)
- return -EPROBE_DEFER;
- priv->codec_dev = get_device(codec_dev);
+
+ if (codec_dev) {
+ priv->codec_dev = get_device(codec_dev);
+ } else {
+ /*
+ * Special case for Android tablets where the codec i2c_client
+ * has been manually instantiated by x86_android_tablets.ko due
+ * to a broken DSDT.
+ */
+ codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,
+ BYT_RT5640_FALLBACK_CODEC_DEV_NAME);
+ if (!codec_dev)
+ return -EPROBE_DEFER;
+
+ if (!i2c_verify_client(codec_dev)) {
+ dev_err(dev, "Error '%s' is not an i2c_client\n",
+ BYT_RT5640_FALLBACK_CODEC_DEV_NAME);
+ put_device(codec_dev);
+ }
+
+ /* fixup codec name */
+ strscpy(byt_rt5640_codec_name, BYT_RT5640_FALLBACK_CODEC_DEV_NAME,
+ sizeof(byt_rt5640_codec_name));
+
+ /* bus_find_device() returns a reference no need to get() */
+ priv->codec_dev = codec_dev;
+ }
/*
* swap SSP0 if bytcr is detected
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 8e4b821efe92..67c62844ca2a 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -770,8 +770,6 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = {
.stream_name = "Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &byt_rt5651_aif1_ops,
SND_SOC_DAILINK_REG(media, dummy, platform),
},
@@ -780,7 +778,7 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = {
.stream_name = "Deep-Buffer Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &byt_rt5651_aif1_ops,
SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
},
@@ -793,8 +791,6 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBC_CFC,
.be_hw_params_fixup = byt_rt5651_codec_fixup,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.init = byt_rt5651_init,
.ops = &byt_rt5651_be_ssp2_ops,
SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c
index 0b10d89cb189..a6dfbcfdf74e 100644
--- a/sound/soc/intel/boards/bytcr_wm5102.c
+++ b/sound/soc/intel/boards/bytcr_wm5102.c
@@ -462,8 +462,6 @@ static struct snd_soc_dai_link byt_wm5102_dais[] = {
.stream_name = "Baytrail Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &byt_wm5102_aif1_ops,
SND_SOC_DAILINK_REG(media, dummy, platform),
@@ -473,7 +471,7 @@ static struct snd_soc_dai_link byt_wm5102_dais[] = {
.stream_name = "Deep-Buffer Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &byt_wm5102_aif1_ops,
SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
},
@@ -490,8 +488,6 @@ static struct snd_soc_dai_link byt_wm5102_dais[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBC_CFC,
.be_hw_params_fixup = byt_wm5102_codec_fixup,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.init = byt_wm5102_init,
SND_SOC_DAILINK_REG(ssp0_port, ssp0_codec, platform),
},
diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
index d7c114858833..36984de8a067 100644
--- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c
+++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
@@ -351,8 +351,6 @@ static struct snd_soc_dai_link cht_dailink[] = {
.stream_name = "Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &cht_aif1_ops,
SND_SOC_DAILINK_REG(media, dummy, platform),
},
@@ -361,7 +359,7 @@ static struct snd_soc_dai_link cht_dailink[] = {
.stream_name = "Deep-Buffer Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &cht_aif1_ops,
SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
},
@@ -374,8 +372,6 @@ static struct snd_soc_dai_link cht_dailink[] = {
| SND_SOC_DAIFMT_CBC_CFC,
.init = cht_codec_init,
.be_hw_params_fixup = cht_codec_fixup,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &cht_be_ssp2_ops,
SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
},
diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c
index 7651b83632fa..4afb292d4f13 100644
--- a/sound/soc/intel/boards/cht_bsw_nau8824.c
+++ b/sound/soc/intel/boards/cht_bsw_nau8824.c
@@ -193,8 +193,6 @@ static struct snd_soc_dai_link cht_dailink[] = {
.stream_name = "Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &cht_aif1_ops,
SND_SOC_DAILINK_REG(media, dummy, platform),
},
@@ -203,7 +201,7 @@ static struct snd_soc_dai_link cht_dailink[] = {
.stream_name = "Deep-Buffer Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &cht_aif1_ops,
SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
},
@@ -217,8 +215,6 @@ static struct snd_soc_dai_link cht_dailink[] = {
| SND_SOC_DAIFMT_CBC_CFC,
.init = cht_codec_init,
.be_hw_params_fixup = cht_codec_fixup,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &cht_be_ssp2_ops,
SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
},
diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c
index ac23a8b7cafc..b977a2db73a3 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5645.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5645.c
@@ -448,8 +448,6 @@ static struct snd_soc_dai_link cht_dailink[] = {
.stream_name = "Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &cht_aif1_ops,
SND_SOC_DAILINK_REG(media, dummy, platform),
},
@@ -458,7 +456,7 @@ static struct snd_soc_dai_link cht_dailink[] = {
.stream_name = "Deep-Buffer Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &cht_aif1_ops,
SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
},
@@ -470,8 +468,6 @@ static struct snd_soc_dai_link cht_dailink[] = {
.no_pcm = 1,
.init = cht_codec_init,
.be_hw_params_fixup = cht_codec_fixup,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &cht_be_ssp2_ops,
SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
},
diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c
index c6c469d51243..aaef212cf44e 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5672.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5672.c
@@ -358,8 +358,6 @@ static struct snd_soc_dai_link cht_dailink[] = {
.stream_name = "Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &cht_aif1_ops,
SND_SOC_DAILINK_REG(media, dummy, platform),
},
@@ -368,7 +366,7 @@ static struct snd_soc_dai_link cht_dailink[] = {
.stream_name = "Deep-Buffer Audio",
.nonatomic = true,
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &cht_aif1_ops,
SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
},
@@ -381,8 +379,6 @@ static struct snd_soc_dai_link cht_dailink[] = {
.no_pcm = 1,
.init = cht_codec_init,
.be_hw_params_fixup = cht_codec_fixup,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &cht_be_ssp2_ops,
SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
},
diff --git a/sound/soc/intel/boards/ehl_rt5660.c b/sound/soc/intel/boards/ehl_rt5660.c
index 90d93e667bd9..ebc417c04a50 100644
--- a/sound/soc/intel/boards/ehl_rt5660.c
+++ b/sound/soc/intel/boards/ehl_rt5660.c
@@ -178,8 +178,6 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = {
.name = "SSP0-Codec",
.id = 0,
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &rt5660_ops,
SND_SOC_DAILINK_REG(ssp0_pin, rt5660_codec, platform),
},
@@ -187,7 +185,7 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = {
.name = "dmic48k",
.id = 1,
.ignore_suspend = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform),
},
@@ -195,7 +193,7 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = {
.name = "dmic16k",
.id = 2,
.ignore_suspend = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform),
},
@@ -203,7 +201,7 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = {
.name = "iDisp1",
.id = 5,
.init = hdmi_init,
- .dpcm_playback = 1,
+ .playback_only = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
},
@@ -211,7 +209,7 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = {
.name = "iDisp2",
.id = 6,
.init = hdmi_init,
- .dpcm_playback = 1,
+ .playback_only = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
},
@@ -219,7 +217,7 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = {
.name = "iDisp3",
.id = 7,
.init = hdmi_init,
- .dpcm_playback = 1,
+ .playback_only = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
},
@@ -227,7 +225,7 @@ static struct snd_soc_dai_link ehl_rt5660_dailink[] = {
.name = "iDisp4",
.id = 8,
.init = hdmi_init,
- .dpcm_playback = 1,
+ .playback_only = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(idisp4_pin, idisp4_codec, platform),
},
diff --git a/sound/soc/intel/boards/hsw_rt5640.c b/sound/soc/intel/boards/hsw_rt5640.c
index 1826a4dfd0f3..9bb2822ba63e 100644
--- a/sound/soc/intel/boards/hsw_rt5640.c
+++ b/sound/soc/intel/boards/hsw_rt5640.c
@@ -85,8 +85,6 @@ static struct snd_soc_dai_link card_dai_links[] = {
.nonatomic = 1,
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(system, dummy, platform),
},
{
@@ -95,7 +93,7 @@ static struct snd_soc_dai_link card_dai_links[] = {
.nonatomic = 1,
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(offload0, dummy, platform),
},
{
@@ -104,7 +102,7 @@ static struct snd_soc_dai_link card_dai_links[] = {
.nonatomic = 1,
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(offload1, dummy, platform),
},
{
@@ -113,7 +111,7 @@ static struct snd_soc_dai_link card_dai_links[] = {
.nonatomic = 1,
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(loopback, dummy, platform),
},
/* Back End DAI links */
@@ -127,8 +125,6 @@ static struct snd_soc_dai_link card_dai_links[] = {
.ignore_pmdown_time = 1,
.be_hw_params_fixup = codec_link_hw_params_fixup,
.ops = &codec_link_ops,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(ssp0_port, codec, platform),
},
};
diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c
index 24f716e42d6a..50e846d67c19 100644
--- a/sound/soc/intel/boards/sof_board_helpers.c
+++ b/sound/soc/intel/boards/sof_board_helpers.c
@@ -217,8 +217,6 @@ static int set_ssp_codec_link(struct device *dev, struct snd_soc_dai_link *link,
link->id = be_id;
link->no_pcm = 1;
- link->dpcm_capture = 1;
- link->dpcm_playback = 1;
return 0;
}
@@ -268,7 +266,7 @@ static int set_dmic_link(struct device *dev, struct snd_soc_dai_link *link,
link->init = dmic_init;
link->ignore_suspend = 1;
link->no_pcm = 1;
- link->dpcm_capture = 1;
+ link->capture_only = 1;
return 0;
}
@@ -326,7 +324,7 @@ static int set_idisp_hdmi_link(struct device *dev, struct snd_soc_dai_link *link
link->id = be_id;
link->init = (hdmi_id == 1) ? hdmi_init : NULL;
link->no_pcm = 1;
- link->dpcm_playback = 1;
+ link->playback_only = 1;
return 0;
}
@@ -361,13 +359,12 @@ static int set_ssp_amp_link(struct device *dev, struct snd_soc_dai_link *link,
/* codecs - caller to handle */
/* platforms */
+ /* feedback stream or firmware-generated echo reference */
link->platforms = platform_component;
link->num_platforms = ARRAY_SIZE(platform_component);
link->id = be_id;
link->no_pcm = 1;
- link->dpcm_capture = 1; /* feedback stream or firmware-generated echo reference */
- link->dpcm_playback = 1;
return 0;
}
@@ -407,8 +404,6 @@ static int set_bt_offload_link(struct device *dev, struct snd_soc_dai_link *link
link->id = be_id;
link->no_pcm = 1;
- link->dpcm_capture = 1;
- link->dpcm_playback = 1;
return 0;
}
@@ -448,7 +443,7 @@ static int set_hdmi_in_link(struct device *dev, struct snd_soc_dai_link *link,
link->id = be_id;
link->no_pcm = 1;
- link->dpcm_capture = 1;
+ link->capture_only = 1;
return 0;
}
@@ -496,8 +491,6 @@ static int set_hda_codec_link(struct device *dev, struct snd_soc_dai_link *link,
if (be_type == SOF_HDA_ANALOG)
link->init = hda_init;
link->no_pcm = 1;
- link->dpcm_capture = 1;
- link->dpcm_playback = 1;
return 0;
}
diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
index fc998fe4b196..a92707876851 100644
--- a/sound/soc/intel/boards/sof_es8336.c
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -455,8 +455,6 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
links[id].exit = sof_es8316_exit;
links[id].ops = &sof_es8336_ops;
links[id].nonatomic = true;
- 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;
@@ -496,7 +494,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
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].capture_only = 1;
links[id].no_pcm = 1;
id++;
@@ -539,7 +537,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
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].playback_only = 1;
links[id].no_pcm = 1;
id++;
@@ -569,7 +567,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
links[id].num_codecs = 1;
links[id].platforms = platform_component;
links[id].num_platforms = ARRAY_SIZE(platform_component);
- links[id].dpcm_capture = 1;
+ links[id].capture_only = 1;
links[id].no_pcm = 1;
links[id].num_cpus = 1;
id++;
diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c
index 8d237f67bd06..68380b738d88 100644
--- a/sound/soc/intel/boards/sof_pcm512x.c
+++ b/sound/soc/intel/boards/sof_pcm512x.c
@@ -246,12 +246,11 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
links[id].num_platforms = ARRAY_SIZE(platform_component);
links[id].init = sof_pcm512x_codec_init;
links[id].ops = &sof_pcm512x_ops;
- links[id].dpcm_playback = 1;
/*
* capture only supported with specific versions of the Hifiberry DAC+
*/
- if (sof_pcm512x_quirk & SOF_PCM512X_ENABLE_SSP_CAPTURE)
- links[id].dpcm_capture = 1;
+ if (!(sof_pcm512x_quirk & SOF_PCM512X_ENABLE_SSP_CAPTURE))
+ links[id].playback_only = 1;
links[id].no_pcm = 1;
links[id].cpus = &cpus[id];
links[id].num_cpus = 1;
@@ -294,7 +293,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
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].capture_only = 1;
links[id].no_pcm = 1;
id++;
}
@@ -341,7 +340,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
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].playback_only = 1;
links[id].no_pcm = 1;
id++;
}
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c
index bc581fea0e3a..5ceb376d4924 100644
--- a/sound/soc/intel/boards/sof_rt5682.c
+++ b/sound/soc/intel/boards/sof_rt5682.c
@@ -871,12 +871,27 @@ static const struct platform_device_id board_ids[] = {
SOF_BT_OFFLOAD_PRESENT),
},
{
+ .name = "mtl_rt5682_c1_h02",
+ .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
+ SOF_SSP_PORT_CODEC(1) |
+ /* SSP 0 and SSP 2 are used for HDMI IN */
+ SOF_SSP_MASK_HDMI_CAPTURE(0x5)),
+ },
+ {
.name = "arl_rt5682_c1_h02",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_SSP_PORT_CODEC(1) |
/* SSP 0 and SSP 2 are used for HDMI IN */
SOF_SSP_MASK_HDMI_CAPTURE(0x5)),
},
+ {
+ .name = "ptl_rt5682_def",
+ .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
+ SOF_SSP_PORT_CODEC(0) |
+ SOF_SSP_PORT_AMP(1) |
+ SOF_SSP_PORT_BT_OFFLOAD(2) |
+ SOF_BT_OFFLOAD_PRESENT),
+ },
{ }
};
MODULE_DEVICE_TABLE(platform, board_ids);
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index 5196d96f5c0e..ea5249df8ac3 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -484,10 +484,26 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF6")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF9")
},
.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
},
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CFA")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
/* MeteorLake devices */
{
.callback = sof_sdw_quirk_cb,
@@ -576,10 +592,59 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D36")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF8")
},
.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
},
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "3838")
+ },
+ .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "3832")
+ },
+ .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "380E")
+ },
+ .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "233C")
+ },
+ /* Note this quirk excludes the CODEC mic */
+ .driver_data = (void *)(SOC_SDW_CODEC_MIC),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "233B")
+ },
+ .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
+ },
/* ArrowLake devices */
{
@@ -594,10 +659,58 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF1")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF7")
},
.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
},
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF0")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF3")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF4")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF5")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
+ /* Pantherlake devices*/
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_ptlrvp"),
+ },
+ .driver_data = (void *)(SOC_SDW_PCH_DMIC),
+ },
{}
};
@@ -733,7 +846,7 @@ static int create_sdw_dailink(struct snd_soc_card *card,
asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture,
cpus, num_cpus, platform_component,
ARRAY_SIZE(platform_component), codecs, num_codecs,
- asoc_sdw_rtd_init, &sdw_ops);
+ 1, asoc_sdw_rtd_init, &sdw_ops);
/*
* SoundWire DAILINKs use 'stream' functions and Bank Switch operations
@@ -800,6 +913,9 @@ static int create_ssp_dailinks(struct snd_soc_card *card,
char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i);
char *codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d",
ssp_info->acpi_id, j++);
+ if (!name || !cpu_dai_name || !codec_name)
+ return -ENOMEM;
+
int playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK];
int capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE];
@@ -807,7 +923,7 @@ static int create_ssp_dailinks(struct snd_soc_card *card,
playback, capture, cpu_dai_name,
platform_component->name,
ARRAY_SIZE(platform_component), codec_name,
- ssp_info->dais[0].dai_name, NULL,
+ ssp_info->dais[0].dai_name, 1, NULL,
ssp_info->ops);
if (ret)
return ret;
@@ -832,7 +948,7 @@ static int create_dmic_dailinks(struct snd_soc_card *card,
0, 1, // DMIC only supports capture
"DMIC01 Pin", platform_component->name,
ARRAY_SIZE(platform_component),
- "dmic-codec", "dmic-hifi",
+ "dmic-codec", "dmic-hifi", 1,
asoc_sdw_dmic_init, NULL);
if (ret)
return ret;
@@ -843,7 +959,7 @@ static int create_dmic_dailinks(struct snd_soc_card *card,
0, 1, // DMIC only supports capture
"DMIC16k Pin", platform_component->name,
ARRAY_SIZE(platform_component),
- "dmic-codec", "dmic-hifi",
+ "dmic-codec", "dmic-hifi", 1,
/* don't call asoc_sdw_dmic_init() twice */
NULL, NULL);
if (ret)
@@ -866,6 +982,9 @@ static int create_hdmi_dailinks(struct snd_soc_card *card,
for (i = 0; i < hdmi_num; i++) {
char *name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1);
char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1);
+ if (!name || !cpu_dai_name)
+ return -ENOMEM;
+
char *codec_name, *codec_dai_name;
if (intel_ctx->hdmi.idisp_codec) {
@@ -877,11 +996,14 @@ static int create_hdmi_dailinks(struct snd_soc_card *card,
codec_dai_name = "snd-soc-dummy-dai";
}
+ if (!codec_dai_name)
+ return -ENOMEM;
+
ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name,
1, 0, // HDMI only supports playback
cpu_dai_name, platform_component->name,
ARRAY_SIZE(platform_component),
- codec_name, codec_dai_name,
+ codec_name, codec_dai_name, 1,
i == 0 ? sof_sdw_hdmi_init : NULL, NULL);
if (ret)
return ret;
@@ -900,13 +1022,16 @@ static int create_bt_dailinks(struct snd_soc_card *card,
SOF_BT_OFFLOAD_SSP_SHIFT;
char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port);
+ if (!name || !cpu_dai_name)
+ return -ENOMEM;
+
int ret;
ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name,
1, 1, cpu_dai_name, platform_component->name,
ARRAY_SIZE(platform_component),
snd_soc_dummy_dlc.name, snd_soc_dummy_dlc.dai_name,
- NULL, NULL);
+ 1, NULL, NULL);
if (ret)
return ret;
diff --git a/sound/soc/intel/boards/sof_wm8804.c b/sound/soc/intel/boards/sof_wm8804.c
index facc6c32cbfe..51922347409f 100644
--- a/sound/soc/intel/boards/sof_wm8804.c
+++ b/sound/soc/intel/boards/sof_wm8804.c
@@ -167,8 +167,6 @@ static struct snd_soc_dai_link dailink[] = {
.name = "SSP5-Codec",
.id = 0,
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &sof_wm8804_ops,
SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform),
},
diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile
index 91e146e2487d..0afd114be9e5 100644
--- a/sound/soc/intel/common/Makefile
+++ b/sound/soc/intel/common/Makefile
@@ -1,6 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
-snd-soc-sst-dsp-y := sst-dsp.o
-snd-soc-sst-ipc-y := sst-ipc.o
snd-soc-acpi-intel-match-y := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-match.o \
soc-acpi-intel-hsw-bdw-match.o \
soc-acpi-intel-skl-match.o soc-acpi-intel-kbl-match.o \
@@ -18,5 +16,7 @@ snd-soc-acpi-intel-match-y := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-matc
snd-soc-acpi-intel-match-y += soc-acpi-intel-ssp-common.o
-obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o
+snd-soc-acpi-intel-sdca-quirks-y += soc-acpi-intel-sdca-quirks.o
+
obj-$(CONFIG_SND_SOC_ACPI_INTEL_MATCH) += snd-soc-acpi-intel-match.o
+obj-$(CONFIG_SND_SOC_ACPI_INTEL_SDCA_QUIRKS) += snd-soc-acpi-intel-sdca-quirks.o
diff --git a/sound/soc/intel/common/soc-acpi-intel-arl-match.c b/sound/soc/intel/common/soc-acpi-intel-arl-match.c
index c97c961187dd..24d850df77ca 100644
--- a/sound/soc/intel/common/soc-acpi-intel-arl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-arl-match.c
@@ -44,6 +44,31 @@ static const struct snd_soc_acpi_endpoint spk_3_endpoint = {
.group_id = 1,
};
+/*
+ * RT722 is a multi-function codec, three endpoints are created for
+ * its headset, amp and dmic functions.
+ */
+static const struct snd_soc_acpi_endpoint rt722_endpoints[] = {
+ {
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ {
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ {
+ .num = 2,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
static const struct snd_soc_acpi_adr_device cs35l56_2_lr_adr[] = {
{
.adr = 0x00023001FA355601ull,
@@ -185,12 +210,31 @@ static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = {
+ {
+ .adr = 0x000030025D072201ull,
+ .num_endpoints = ARRAY_SIZE(rt722_endpoints),
+ .endpoints = rt722_endpoints,
+ .name_prefix = "rt722"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device rt1320_2_single_adr[] = {
+ {
+ .adr = 0x000230025D132001ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt1320-1"
+ }
+};
+
static const struct snd_soc_acpi_link_adr arl_cs42l43_l0[] = {
{
.mask = BIT(0),
.num_adr = ARRAY_SIZE(cs42l43_0_adr),
.adr_d = cs42l43_0_adr,
},
+ {}
};
static const struct snd_soc_acpi_link_adr arl_cs42l43_l2[] = {
@@ -199,6 +243,7 @@ static const struct snd_soc_acpi_link_adr arl_cs42l43_l2[] = {
.num_adr = ARRAY_SIZE(cs42l43_2_adr),
.adr_d = cs42l43_2_adr,
},
+ {}
};
static const struct snd_soc_acpi_link_adr arl_cs42l43_l2_cs35l56_l3[] = {
@@ -285,6 +330,20 @@ static const struct snd_soc_acpi_link_adr arl_sdca_rvp[] = {
{}
};
+static const struct snd_soc_acpi_link_adr arl_rt722_l0_rt1320_l2[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt722_0_single_adr),
+ .adr_d = rt722_0_single_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(rt1320_2_single_adr),
+ .adr_d = rt1320_2_single_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_codecs arl_essx_83x6 = {
.num_codecs = 3,
.codecs = { "ESSX8316", "ESSX8326", "ESSX8336"},
@@ -383,6 +442,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-arl-rt711-l0.tplg",
},
+ {
+ .link_mask = BIT(0) | BIT(2),
+ .links = arl_rt722_l0_rt1320_l2,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-arl-rt722-l0_rt1320-l2.tplg",
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_arl_sdw_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
index 3c4e0c7ca8ee..98a9c36d7a4c 100644
--- a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
@@ -8,6 +8,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
+#include "soc-acpi-intel-sdca-quirks.h"
#include "soc-acpi-intel-sdw-mockup-match.h"
struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_machines[] = {
@@ -90,6 +91,30 @@ static const struct snd_soc_acpi_endpoint rt722_endpoints[] = {
},
};
+static const struct snd_soc_acpi_endpoint jack_amp_g1_dmic_endpoints_endpoints[] = {
+ /* Jack Endpoint */
+ {
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ /* Amp Endpoint, work as spk_l_endpoint */
+ {
+ .num = 1,
+ .aggregated = 1,
+ .group_position = 0,
+ .group_id = 1,
+ },
+ /* DMIC Endpoint */
+ {
+ .num = 2,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = {
{ /* Jack Playback Endpoint */
.num = 0,
@@ -198,6 +223,15 @@ static const struct snd_soc_acpi_adr_device rt1712_3_single_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt712_vb_2_group1_adr[] = {
+ {
+ .adr = 0x000230025D071201ull,
+ .num_endpoints = ARRAY_SIZE(jack_amp_g1_dmic_endpoints_endpoints),
+ .endpoints = jack_amp_g1_dmic_endpoints_endpoints,
+ .name_prefix = "rt712"
+ }
+};
+
static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = {
{
.adr = 0x000030025d072201ull,
@@ -225,6 +259,15 @@ static const struct snd_soc_acpi_adr_device rt1316_3_group1_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt1318_1_adr[] = {
+ {
+ .adr = 0x000133025D131801ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt1318-1"
+ }
+};
+
static const struct snd_soc_acpi_adr_device rt1318_1_group1_adr[] = {
{
.adr = 0x000130025D131801ull,
@@ -243,6 +286,24 @@ static const struct snd_soc_acpi_adr_device rt1318_2_group1_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt1320_1_group1_adr[] = {
+ {
+ .adr = 0x000130025D132001ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_r_endpoint,
+ .name_prefix = "rt1320-1"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device rt713_0_adr[] = {
+ {
+ .adr = 0x000031025D071301ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt713"
+ }
+};
+
static const struct snd_soc_acpi_adr_device rt714_0_adr[] = {
{
.adr = 0x000030025D071401ull,
@@ -378,6 +439,35 @@ static const struct snd_soc_acpi_link_adr lnl_sdw_rt1318_l12_rt714_l0[] = {
{}
};
+static const struct snd_soc_acpi_link_adr lnl_sdw_rt713_l0_rt1318_l1[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt713_0_adr),
+ .adr_d = rt713_0_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt1318_1_adr),
+ .adr_d = rt1318_1_adr,
+ },
+ {}
+};
+
+static const struct snd_soc_acpi_link_adr lnl_sdw_rt712_vb_l2_rt1320_l1[] = {
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(rt712_vb_2_group1_adr),
+ .adr_d = rt712_vb_2_group1_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt1320_1_group1_adr),
+ .adr_d = rt1320_1_group1_adr,
+ },
+ {}
+};
+
+/* this table is used when there is no I2S codec present */
/* this table is used when there is no I2S codec present */
struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = {
/* mockup tests need to be first */
@@ -447,6 +537,19 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-lnl-rt1318-l12-rt714-l0.tplg"
},
+ {
+ .link_mask = BIT(0) | BIT(1),
+ .links = lnl_sdw_rt713_l0_rt1318_l1,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-lnl-rt713-l0-rt1318-l1.tplg"
+ },
+ {
+ .link_mask = BIT(1) | BIT(2),
+ .links = lnl_sdw_rt712_vb_l2_rt1320_l1,
+ .drv_name = "sof_sdw",
+ .machine_check = snd_soc_acpi_intel_sdca_is_device_rt712_vb,
+ .sof_tplg_filename = "sof-lnl-rt712-l2-rt1320-l1.tplg"
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_lnl_sdw_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
index d4435a34a3a3..0b37465b6c53 100644
--- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
@@ -6,9 +6,12 @@
*
*/
+#include <linux/soundwire/sdw_intel.h>
+#include <sound/sdca.h>
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
#include <sound/soc-acpi-intel-ssp-common.h>
+#include "soc-acpi-intel-sdca-quirks.h"
#include "soc-acpi-intel-sdw-mockup-match.h"
static const struct snd_soc_acpi_codecs mtl_rt5682_rt5682s_hp = {
@@ -42,6 +45,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = {
SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |
SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
},
+ {
+ .comp_ids = &mtl_rt5682_rt5682s_hp,
+ .drv_name = "mtl_rt5682_c1_h02",
+ .machine_quirk = snd_soc_acpi_codec_list,
+ .quirk_data = &mtl_lt6911_hdmi,
+ .sof_tplg_filename = "sof-mtl-rt5682-ssp1-hdmi-ssp02.tplg",
+ },
/* place boards for each headphone codec: sof driver will complete the
* tplg name and machine driver will detect the amp type
*/
@@ -126,6 +136,27 @@ static const struct snd_soc_acpi_endpoint rt712_endpoints[] = {
},
};
+static const struct snd_soc_acpi_endpoint rt712_vb_endpoints[] = {
+ {
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ {
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ {
+ .num = 2,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
/*
* RT722 is a multi-function codec, three endpoints are created for
* its headset, amp and dmic functions.
@@ -183,6 +214,15 @@ static const struct snd_soc_acpi_adr_device rt712_0_single_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt712_vb_0_single_adr[] = {
+ {
+ .adr = 0x000030025D071201ull,
+ .num_endpoints = ARRAY_SIZE(rt712_vb_endpoints),
+ .endpoints = rt712_vb_endpoints,
+ .name_prefix = "rt712"
+ }
+};
+
static const struct snd_soc_acpi_adr_device rt1712_3_single_adr[] = {
{
.adr = 0x000330025D171201ull,
@@ -356,6 +396,15 @@ static const struct snd_soc_acpi_link_adr mtl_712_l0[] = {
{}
};
+static const struct snd_soc_acpi_link_adr mtl_712_vb_l0[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt712_vb_0_single_adr),
+ .adr_d = rt712_vb_0_single_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = {
{ /* Jack Playback Endpoint */
.num = 0,
@@ -769,6 +818,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
},
{
.link_mask = BIT(0),
+ .links = mtl_712_vb_l0,
+ .drv_name = "sof_sdw",
+ .machine_check = snd_soc_acpi_intel_sdca_is_device_rt712_vb,
+ .sof_tplg_filename = "sof-mtl-rt712-vb-l0.tplg",
+ },
+ {
+ .link_mask = BIT(0),
.links = mtl_712_l0,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-mtl-rt712-l0.tplg",
@@ -836,3 +892,5 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_sdw_machines);
+
+MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_SDCA_QUIRKS);
diff --git a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c
index 90f97a44b607..f1c0d7a02cda 100644
--- a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c
@@ -9,8 +9,21 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
#include "soc-acpi-intel-sdw-mockup-match.h"
+#include <sound/soc-acpi-intel-ssp-common.h>
+
+static const struct snd_soc_acpi_codecs ptl_rt5682_rt5682s_hp = {
+ .num_codecs = 2,
+ .codecs = {RT5682_ACPI_HID, RT5682S_ACPI_HID},
+};
struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_machines[] = {
+ {
+ .comp_ids = &ptl_rt5682_rt5682s_hp,
+ .drv_name = "ptl_rt5682_def",
+ .sof_tplg_filename = "sof-ptl", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME |
+ SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME,
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_ptl_machines);
@@ -23,10 +36,10 @@ static const struct snd_soc_acpi_endpoint single_endpoint = {
};
/*
- * RT722 is a multi-function codec, three endpoints are created for
- * its headset, amp and dmic functions.
+ * Multi-function codecs with three endpoints created for
+ * headset, amp and dmic functions.
*/
-static const struct snd_soc_acpi_endpoint rt722_endpoints[] = {
+static const struct snd_soc_acpi_endpoint rt_mf_endpoints[] = {
{
.num = 0,
.aggregated = 0,
@@ -56,11 +69,38 @@ static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt721_3_single_adr[] = {
+ {
+ .adr = 0x000330025d072101ull,
+ .num_endpoints = ARRAY_SIZE(rt_mf_endpoints),
+ .endpoints = rt_mf_endpoints,
+ .name_prefix = "rt721"
+ }
+};
+
+static const struct snd_soc_acpi_link_adr ptl_rt721_l3[] = {
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(rt721_3_single_adr),
+ .adr_d = rt721_3_single_adr,
+ },
+ {},
+};
+
static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = {
{
.adr = 0x000030025d072201ull,
- .num_endpoints = ARRAY_SIZE(rt722_endpoints),
- .endpoints = rt722_endpoints,
+ .num_endpoints = ARRAY_SIZE(rt_mf_endpoints),
+ .endpoints = rt_mf_endpoints,
+ .name_prefix = "rt722"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device rt722_1_single_adr[] = {
+ {
+ .adr = 0x000130025d072201ull,
+ .num_endpoints = ARRAY_SIZE(rt_mf_endpoints),
+ .endpoints = rt_mf_endpoints,
.name_prefix = "rt722"
}
};
@@ -68,8 +108,8 @@ static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = {
static const struct snd_soc_acpi_adr_device rt722_3_single_adr[] = {
{
.adr = 0x000330025d072201ull,
- .num_endpoints = ARRAY_SIZE(rt722_endpoints),
- .endpoints = rt722_endpoints,
+ .num_endpoints = ARRAY_SIZE(rt_mf_endpoints),
+ .endpoints = rt_mf_endpoints,
.name_prefix = "rt722"
}
};
@@ -83,6 +123,15 @@ static const struct snd_soc_acpi_link_adr ptl_rt722_only[] = {
{}
};
+static const struct snd_soc_acpi_link_adr ptl_rt722_l1[] = {
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt722_1_single_adr),
+ .adr_d = rt722_1_single_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_link_adr ptl_rt722_l3[] = {
{
.mask = BIT(3),
@@ -129,12 +178,24 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = {
.sof_tplg_filename = "sof-ptl-rt711.tplg",
},
{
+ .link_mask = BIT(3),
+ .links = ptl_rt721_l3,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-ptl-rt721.tplg",
+ },
+ {
.link_mask = BIT(0),
.links = ptl_rt722_only,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-ptl-rt722.tplg",
},
{
+ .link_mask = BIT(1),
+ .links = ptl_rt722_l1,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-ptl-rt722.tplg",
+ },
+ {
.link_mask = BIT(3),
.links = ptl_rt722_l3,
.drv_name = "sof_sdw",
diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c
index bc8817633b81..b83ac2e6337c 100644
--- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c
@@ -198,6 +198,7 @@ static const struct snd_soc_acpi_link_adr rpl_cs42l43_l0[] = {
.num_adr = ARRAY_SIZE(cs42l43_0_adr),
.adr_d = cs42l43_0_adr,
},
+ {}
};
static const struct snd_soc_acpi_link_adr rpl_sdca_3_in_1[] = {
diff --git a/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c
new file mode 100644
index 000000000000..0b7076606d66
--- /dev/null
+++ b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * soc-acpi-intel-sdca-quirks.c - tables and support for SDCA quirks
+ *
+ * Copyright (c) 2024, Intel Corporation.
+ *
+ */
+
+#include <linux/soundwire/sdw_intel.h>
+#include <sound/sdca.h>
+#include <sound/soc-acpi.h>
+#include "soc-acpi-intel-sdca-quirks.h"
+
+/*
+ * Pretend machine quirk. The argument type is not the traditional
+ * 'struct snd_soc_acpi_mach' pointer but instead the sdw_intel_ctx
+ * which contains the peripheral information required for the
+ * SoundWire/SDCA filter on the SMART_MIC setup and interface
+ * revision. When the return value is false, the entry in the
+ * 'snd_soc_acpi_mach' table needs to be skipped.
+ */
+bool snd_soc_acpi_intel_sdca_is_device_rt712_vb(void *arg)
+{
+ struct sdw_intel_ctx *ctx = arg;
+ int i;
+
+ if (!ctx)
+ return false;
+
+ for (i = 0; i < ctx->peripherals->num_peripherals; i++) {
+ if (sdca_device_quirk_match(ctx->peripherals->array[i],
+ SDCA_QUIRKS_RT712_VB))
+ return true;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_sdca_is_device_rt712_vb, SND_SOC_ACPI_INTEL_SDCA_QUIRKS);
+
+MODULE_DESCRIPTION("ASoC ACPI Intel SDCA quirks");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SND_SOC_SDCA);
diff --git a/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h
new file mode 100644
index 000000000000..bead5ec6243f
--- /dev/null
+++ b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * soc-acpi-intel-sdca-quirks.h - tables and support for SDCA quirks
+ *
+ * Copyright (c) 2024, Intel Corporation.
+ *
+ */
+
+#ifndef _SND_SOC_ACPI_INTEL_SDCA_QUIRKS
+#define _SND_SOC_ACPI_INTEL_SDCA_QUIRKS
+
+bool snd_soc_acpi_intel_sdca_is_device_rt712_vb(void *arg);
+
+#endif
diff --git a/sound/soc/intel/common/sst-dsp-priv.h b/sound/soc/intel/common/sst-dsp-priv.h
deleted file mode 100644
index de32bb9afccb..000000000000
--- a/sound/soc/intel/common/sst-dsp-priv.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel Smart Sound Technology
- *
- * Copyright (C) 2013, Intel Corporation
- */
-
-#ifndef __SOUND_SOC_SST_DSP_PRIV_H
-#define __SOUND_SOC_SST_DSP_PRIV_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/firmware.h>
-
-#include "../skylake/skl-sst-dsp.h"
-
-/*
- * DSP Operations exported by platform Audio DSP driver.
- */
-struct sst_ops {
- /* Shim IO */
- void (*write)(void __iomem *addr, u32 offset, u32 value);
- u32 (*read)(void __iomem *addr, u32 offset);
-
- /* IRQ handlers */
- irqreturn_t (*irq_handler)(int irq, void *context);
-
- /* SST init and free */
- int (*init)(struct sst_dsp *sst);
- void (*free)(struct sst_dsp *sst);
-};
-
-/*
- * Audio DSP memory offsets and addresses.
- */
-struct sst_addr {
- u32 sram0_base;
- u32 sram1_base;
- u32 w0_stat_sz;
- u32 w0_up_sz;
- void __iomem *lpe;
- void __iomem *shim;
-};
-
-/*
- * Audio DSP Mailbox configuration.
- */
-struct sst_mailbox {
- void __iomem *in_base;
- void __iomem *out_base;
- size_t in_size;
- size_t out_size;
-};
-
-/*
- * Generic SST Shim Interface.
- */
-struct sst_dsp {
-
- /* Shared for all platforms */
-
- /* runtime */
- struct sst_dsp_device *sst_dev;
- spinlock_t spinlock; /* IPC locking */
- struct mutex mutex; /* DSP FW lock */
- struct device *dev;
- void *thread_context;
- int irq;
- u32 id;
-
- /* operations */
- struct sst_ops *ops;
-
- /* debug FS */
- struct dentry *debugfs_root;
-
- /* base addresses */
- struct sst_addr addr;
-
- /* mailbox */
- struct sst_mailbox mailbox;
-
- /* SST FW files loaded and their modules */
- struct list_head module_list;
-
- /* SKL data */
-
- const char *fw_name;
-
- /* To allocate CL dma buffers */
- struct skl_dsp_loader_ops dsp_ops;
- struct skl_dsp_fw_ops fw_ops;
- int sst_state;
- struct skl_cl_dev cl_dev;
- u32 intr_status;
- const struct firmware *fw;
- struct snd_dma_buffer dmab;
-};
-
-#endif
diff --git a/sound/soc/intel/common/sst-dsp.c b/sound/soc/intel/common/sst-dsp.c
deleted file mode 100644
index cdd2f7cf50ae..000000000000
--- a/sound/soc/intel/common/sst-dsp.c
+++ /dev/null
@@ -1,250 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel Smart Sound Technology (SST) DSP Core Driver
- *
- * Copyright (C) 2013, Intel Corporation
- */
-
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io-64-nonatomic-lo-hi.h>
-#include <linux/delay.h>
-
-#include "sst-dsp.h"
-#include "sst-dsp-priv.h"
-
-#define CREATE_TRACE_POINTS
-#include <trace/events/intel-sst.h>
-
-/* Internal generic low-level SST IO functions - can be overidden */
-void sst_shim32_write(void __iomem *addr, u32 offset, u32 value)
-{
- writel(value, addr + offset);
-}
-EXPORT_SYMBOL_GPL(sst_shim32_write);
-
-u32 sst_shim32_read(void __iomem *addr, u32 offset)
-{
- return readl(addr + offset);
-}
-EXPORT_SYMBOL_GPL(sst_shim32_read);
-
-void sst_shim32_write64(void __iomem *addr, u32 offset, u64 value)
-{
- writeq(value, addr + offset);
-}
-EXPORT_SYMBOL_GPL(sst_shim32_write64);
-
-u64 sst_shim32_read64(void __iomem *addr, u32 offset)
-{
- return readq(addr + offset);
-}
-EXPORT_SYMBOL_GPL(sst_shim32_read64);
-
-/* Public API */
-void sst_dsp_shim_write(struct sst_dsp *sst, u32 offset, u32 value)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&sst->spinlock, flags);
- sst->ops->write(sst->addr.shim, offset, value);
- spin_unlock_irqrestore(&sst->spinlock, flags);
-}
-EXPORT_SYMBOL_GPL(sst_dsp_shim_write);
-
-u32 sst_dsp_shim_read(struct sst_dsp *sst, u32 offset)
-{
- unsigned long flags;
- u32 val;
-
- spin_lock_irqsave(&sst->spinlock, flags);
- val = sst->ops->read(sst->addr.shim, offset);
- spin_unlock_irqrestore(&sst->spinlock, flags);
-
- return val;
-}
-EXPORT_SYMBOL_GPL(sst_dsp_shim_read);
-
-void sst_dsp_shim_write_unlocked(struct sst_dsp *sst, u32 offset, u32 value)
-{
- sst->ops->write(sst->addr.shim, offset, value);
-}
-EXPORT_SYMBOL_GPL(sst_dsp_shim_write_unlocked);
-
-u32 sst_dsp_shim_read_unlocked(struct sst_dsp *sst, u32 offset)
-{
- return sst->ops->read(sst->addr.shim, offset);
-}
-EXPORT_SYMBOL_GPL(sst_dsp_shim_read_unlocked);
-
-int sst_dsp_shim_update_bits_unlocked(struct sst_dsp *sst, u32 offset,
- u32 mask, u32 value)
-{
- bool change;
- unsigned int old, new;
- u32 ret;
-
- ret = sst_dsp_shim_read_unlocked(sst, offset);
-
- old = ret;
- new = (old & (~mask)) | (value & mask);
-
- change = (old != new);
- if (change)
- sst_dsp_shim_write_unlocked(sst, offset, new);
-
- return change;
-}
-EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_unlocked);
-
-/* This is for registers bits with attribute RWC */
-void sst_dsp_shim_update_bits_forced_unlocked(struct sst_dsp *sst, u32 offset,
- u32 mask, u32 value)
-{
- unsigned int old, new;
- u32 ret;
-
- ret = sst_dsp_shim_read_unlocked(sst, offset);
-
- old = ret;
- new = (old & (~mask)) | (value & mask);
-
- sst_dsp_shim_write_unlocked(sst, offset, new);
-}
-EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced_unlocked);
-
-int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset,
- u32 mask, u32 value)
-{
- unsigned long flags;
- bool change;
-
- spin_lock_irqsave(&sst->spinlock, flags);
- change = sst_dsp_shim_update_bits_unlocked(sst, offset, mask, value);
- spin_unlock_irqrestore(&sst->spinlock, flags);
- return change;
-}
-EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits);
-
-/* This is for registers bits with attribute RWC */
-void sst_dsp_shim_update_bits_forced(struct sst_dsp *sst, u32 offset,
- u32 mask, u32 value)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&sst->spinlock, flags);
- sst_dsp_shim_update_bits_forced_unlocked(sst, offset, mask, value);
- spin_unlock_irqrestore(&sst->spinlock, flags);
-}
-EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced);
-
-int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask,
- u32 target, u32 time, char *operation)
-{
- u32 reg;
- unsigned long timeout;
- int k = 0, s = 500;
-
- /*
- * split the loop into sleeps of varying resolution. more accurately,
- * the range of wakeups are:
- * Phase 1(first 5ms): min sleep 0.5ms; max sleep 1ms.
- * Phase 2:( 5ms to 10ms) : min sleep 0.5ms; max sleep 10ms
- * (usleep_range (500, 1000) and usleep_range(5000, 10000) are
- * both possible in this phase depending on whether k > 10 or not).
- * Phase 3: (beyond 10 ms) min sleep 5ms; max sleep 10ms.
- */
-
- timeout = jiffies + msecs_to_jiffies(time);
- while ((((reg = sst_dsp_shim_read_unlocked(ctx, offset)) & mask) != target)
- && time_before(jiffies, timeout)) {
- k++;
- if (k > 10)
- s = 5000;
-
- usleep_range(s, 2*s);
- }
-
- if ((reg & mask) == target) {
- dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s successful\n",
- reg, operation);
-
- return 0;
- }
-
- dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s timedout\n",
- reg, operation);
- return -ETIME;
-}
-EXPORT_SYMBOL_GPL(sst_dsp_register_poll);
-
-int sst_dsp_mailbox_init(struct sst_dsp *sst, u32 inbox_offset, size_t inbox_size,
- u32 outbox_offset, size_t outbox_size)
-{
- sst->mailbox.in_base = sst->addr.lpe + inbox_offset;
- sst->mailbox.out_base = sst->addr.lpe + outbox_offset;
- sst->mailbox.in_size = inbox_size;
- sst->mailbox.out_size = outbox_size;
- return 0;
-}
-EXPORT_SYMBOL_GPL(sst_dsp_mailbox_init);
-
-void sst_dsp_outbox_write(struct sst_dsp *sst, void *message, size_t bytes)
-{
- u32 i;
-
- trace_sst_ipc_outbox_write(bytes);
-
- memcpy_toio(sst->mailbox.out_base, message, bytes);
-
- for (i = 0; i < bytes; i += 4)
- trace_sst_ipc_outbox_wdata(i, *(u32 *)(message + i));
-}
-EXPORT_SYMBOL_GPL(sst_dsp_outbox_write);
-
-void sst_dsp_outbox_read(struct sst_dsp *sst, void *message, size_t bytes)
-{
- u32 i;
-
- trace_sst_ipc_outbox_read(bytes);
-
- memcpy_fromio(message, sst->mailbox.out_base, bytes);
-
- for (i = 0; i < bytes; i += 4)
- trace_sst_ipc_outbox_rdata(i, *(u32 *)(message + i));
-}
-EXPORT_SYMBOL_GPL(sst_dsp_outbox_read);
-
-void sst_dsp_inbox_write(struct sst_dsp *sst, void *message, size_t bytes)
-{
- u32 i;
-
- trace_sst_ipc_inbox_write(bytes);
-
- memcpy_toio(sst->mailbox.in_base, message, bytes);
-
- for (i = 0; i < bytes; i += 4)
- trace_sst_ipc_inbox_wdata(i, *(u32 *)(message + i));
-}
-EXPORT_SYMBOL_GPL(sst_dsp_inbox_write);
-
-void sst_dsp_inbox_read(struct sst_dsp *sst, void *message, size_t bytes)
-{
- u32 i;
-
- trace_sst_ipc_inbox_read(bytes);
-
- memcpy_fromio(message, sst->mailbox.in_base, bytes);
-
- for (i = 0; i < bytes; i += 4)
- trace_sst_ipc_inbox_rdata(i, *(u32 *)(message + i));
-}
-EXPORT_SYMBOL_GPL(sst_dsp_inbox_read);
-
-/* Module information */
-MODULE_AUTHOR("Liam Girdwood");
-MODULE_DESCRIPTION("Intel SST Core");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/intel/common/sst-dsp.h b/sound/soc/intel/common/sst-dsp.h
deleted file mode 100644
index 998b1a052281..000000000000
--- a/sound/soc/intel/common/sst-dsp.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel Smart Sound Technology (SST) Core
- *
- * Copyright (C) 2013, Intel Corporation
- */
-
-#ifndef __SOUND_SOC_SST_DSP_H
-#define __SOUND_SOC_SST_DSP_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-
-struct sst_dsp;
-
-/*
- * SST Device.
- *
- * This structure is populated by the SST core driver.
- */
-struct sst_dsp_device {
- /* Mandatory fields */
- struct sst_ops *ops;
- irqreturn_t (*thread)(int irq, void *context);
- void *thread_context;
-};
-
-/* SHIM Read / Write */
-void sst_dsp_shim_write(struct sst_dsp *sst, u32 offset, u32 value);
-u32 sst_dsp_shim_read(struct sst_dsp *sst, u32 offset);
-int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset,
- u32 mask, u32 value);
-void sst_dsp_shim_update_bits_forced(struct sst_dsp *sst, u32 offset,
- u32 mask, u32 value);
-
-/* SHIM Read / Write Unlocked for callers already holding sst lock */
-void sst_dsp_shim_write_unlocked(struct sst_dsp *sst, u32 offset, u32 value);
-u32 sst_dsp_shim_read_unlocked(struct sst_dsp *sst, u32 offset);
-int sst_dsp_shim_update_bits_unlocked(struct sst_dsp *sst, u32 offset,
- u32 mask, u32 value);
-void sst_dsp_shim_update_bits_forced_unlocked(struct sst_dsp *sst, u32 offset,
- u32 mask, u32 value);
-
-/* Internal generic low-level SST IO functions - can be overidden */
-void sst_shim32_write(void __iomem *addr, u32 offset, u32 value);
-u32 sst_shim32_read(void __iomem *addr, u32 offset);
-void sst_shim32_write64(void __iomem *addr, u32 offset, u64 value);
-u64 sst_shim32_read64(void __iomem *addr, u32 offset);
-
-/* Mailbox management */
-int sst_dsp_mailbox_init(struct sst_dsp *sst, u32 inbox_offset,
- size_t inbox_size, u32 outbox_offset, size_t outbox_size);
-void sst_dsp_inbox_write(struct sst_dsp *sst, void *message, size_t bytes);
-void sst_dsp_inbox_read(struct sst_dsp *sst, void *message, size_t bytes);
-void sst_dsp_outbox_write(struct sst_dsp *sst, void *message, size_t bytes);
-void sst_dsp_outbox_read(struct sst_dsp *sst, void *message, size_t bytes);
-int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask,
- u32 target, u32 time, char *operation);
-
-#endif
diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c
deleted file mode 100644
index 6b2c83f9f010..000000000000
--- a/sound/soc/intel/common/sst-ipc.c
+++ /dev/null
@@ -1,294 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel SST generic IPC Support
- *
- * Copyright (C) 2015, Intel Corporation
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/wait.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <sound/asound.h>
-
-#include "sst-dsp.h"
-#include "sst-dsp-priv.h"
-#include "sst-ipc.h"
-
-/* IPC message timeout (msecs) */
-#define IPC_TIMEOUT_MSECS 300
-
-#define IPC_EMPTY_LIST_SIZE 8
-
-/* locks held by caller */
-static struct ipc_message *msg_get_empty(struct sst_generic_ipc *ipc)
-{
- struct ipc_message *msg = NULL;
-
- if (!list_empty(&ipc->empty_list)) {
- msg = list_first_entry(&ipc->empty_list, struct ipc_message,
- list);
- list_del(&msg->list);
- }
-
- return msg;
-}
-
-static int tx_wait_done(struct sst_generic_ipc *ipc,
- struct ipc_message *msg, struct sst_ipc_message *reply)
-{
- unsigned long flags;
- int ret;
-
- /* wait for DSP completion (in all cases atm inc pending) */
- ret = wait_event_timeout(msg->waitq, msg->complete,
- msecs_to_jiffies(IPC_TIMEOUT_MSECS));
-
- spin_lock_irqsave(&ipc->dsp->spinlock, flags);
- if (ret == 0) {
- if (ipc->ops.shim_dbg != NULL)
- ipc->ops.shim_dbg(ipc, "message timeout");
-
- list_del(&msg->list);
- ret = -ETIMEDOUT;
- } else {
-
- /* copy the data returned from DSP */
- if (reply) {
- reply->header = msg->rx.header;
- if (reply->data)
- memcpy(reply->data, msg->rx.data, msg->rx.size);
- }
- ret = msg->errno;
- }
-
- list_add_tail(&msg->list, &ipc->empty_list);
- spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
- return ret;
-}
-
-static int ipc_tx_message(struct sst_generic_ipc *ipc,
- struct sst_ipc_message request,
- struct sst_ipc_message *reply, int wait)
-{
- struct ipc_message *msg;
- unsigned long flags;
-
- spin_lock_irqsave(&ipc->dsp->spinlock, flags);
-
- msg = msg_get_empty(ipc);
- if (msg == NULL) {
- spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
- return -EBUSY;
- }
-
- msg->tx.header = request.header;
- msg->tx.size = request.size;
- msg->rx.header = 0;
- msg->rx.size = reply ? reply->size : 0;
- msg->wait = wait;
- msg->errno = 0;
- msg->pending = false;
- msg->complete = false;
-
- if ((request.size) && (ipc->ops.tx_data_copy != NULL))
- ipc->ops.tx_data_copy(msg, request.data, request.size);
-
- list_add_tail(&msg->list, &ipc->tx_list);
- schedule_work(&ipc->kwork);
- spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
-
- if (wait)
- return tx_wait_done(ipc, msg, reply);
- else
- return 0;
-}
-
-static int msg_empty_list_init(struct sst_generic_ipc *ipc)
-{
- int i;
-
- ipc->msg = kcalloc(IPC_EMPTY_LIST_SIZE, sizeof(struct ipc_message),
- GFP_KERNEL);
- if (ipc->msg == NULL)
- return -ENOMEM;
-
- for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
- ipc->msg[i].tx.data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL);
- if (ipc->msg[i].tx.data == NULL)
- goto free_mem;
-
- ipc->msg[i].rx.data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL);
- if (ipc->msg[i].rx.data == NULL) {
- kfree(ipc->msg[i].tx.data);
- goto free_mem;
- }
-
- init_waitqueue_head(&ipc->msg[i].waitq);
- list_add(&ipc->msg[i].list, &ipc->empty_list);
- }
-
- return 0;
-
-free_mem:
- while (i > 0) {
- kfree(ipc->msg[i-1].tx.data);
- kfree(ipc->msg[i-1].rx.data);
- --i;
- }
- kfree(ipc->msg);
-
- return -ENOMEM;
-}
-
-static void ipc_tx_msgs(struct work_struct *work)
-{
- struct sst_generic_ipc *ipc =
- container_of(work, struct sst_generic_ipc, kwork);
- struct ipc_message *msg;
-
- spin_lock_irq(&ipc->dsp->spinlock);
-
- while (!list_empty(&ipc->tx_list) && !ipc->pending) {
- /* if the DSP is busy, we will TX messages after IRQ.
- * also postpone if we are in the middle of processing
- * completion irq
- */
- if (ipc->ops.is_dsp_busy && ipc->ops.is_dsp_busy(ipc->dsp)) {
- dev_dbg(ipc->dev, "ipc_tx_msgs dsp busy\n");
- break;
- }
-
- msg = list_first_entry(&ipc->tx_list, struct ipc_message, list);
- list_move(&msg->list, &ipc->rx_list);
-
- if (ipc->ops.tx_msg != NULL)
- ipc->ops.tx_msg(ipc, msg);
- }
-
- spin_unlock_irq(&ipc->dsp->spinlock);
-}
-
-int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc,
- struct sst_ipc_message request, struct sst_ipc_message *reply)
-{
- int ret;
-
- /*
- * DSP maybe in lower power active state, so
- * check if the DSP supports DSP lp On method
- * if so invoke that before sending IPC
- */
- if (ipc->ops.check_dsp_lp_on)
- if (ipc->ops.check_dsp_lp_on(ipc->dsp, true))
- return -EIO;
-
- ret = ipc_tx_message(ipc, request, reply, 1);
-
- if (ipc->ops.check_dsp_lp_on)
- if (ipc->ops.check_dsp_lp_on(ipc->dsp, false))
- return -EIO;
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(sst_ipc_tx_message_wait);
-
-int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc,
- struct sst_ipc_message request)
-{
- return ipc_tx_message(ipc, request, NULL, 0);
-}
-EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nowait);
-
-int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc,
- struct sst_ipc_message request, struct sst_ipc_message *reply)
-{
- return ipc_tx_message(ipc, request, reply, 1);
-}
-EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nopm);
-
-struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc,
- u64 header)
-{
- struct ipc_message *msg;
- u64 mask;
-
- if (ipc->ops.reply_msg_match != NULL)
- header = ipc->ops.reply_msg_match(header, &mask);
- else
- mask = (u64)-1;
-
- if (list_empty(&ipc->rx_list)) {
- dev_err(ipc->dev, "error: rx list empty but received 0x%llx\n",
- header);
- return NULL;
- }
-
- list_for_each_entry(msg, &ipc->rx_list, list) {
- if ((msg->tx.header & mask) == header)
- return msg;
- }
-
- return NULL;
-}
-EXPORT_SYMBOL_GPL(sst_ipc_reply_find_msg);
-
-/* locks held by caller */
-void sst_ipc_tx_msg_reply_complete(struct sst_generic_ipc *ipc,
- struct ipc_message *msg)
-{
- msg->complete = true;
-
- if (!msg->wait)
- list_add_tail(&msg->list, &ipc->empty_list);
- else
- wake_up(&msg->waitq);
-}
-EXPORT_SYMBOL_GPL(sst_ipc_tx_msg_reply_complete);
-
-int sst_ipc_init(struct sst_generic_ipc *ipc)
-{
- int ret;
-
- INIT_LIST_HEAD(&ipc->tx_list);
- INIT_LIST_HEAD(&ipc->rx_list);
- INIT_LIST_HEAD(&ipc->empty_list);
- init_waitqueue_head(&ipc->wait_txq);
-
- ret = msg_empty_list_init(ipc);
- if (ret < 0)
- return -ENOMEM;
-
- INIT_WORK(&ipc->kwork, ipc_tx_msgs);
- return 0;
-}
-EXPORT_SYMBOL_GPL(sst_ipc_init);
-
-void sst_ipc_fini(struct sst_generic_ipc *ipc)
-{
- int i;
-
- cancel_work_sync(&ipc->kwork);
-
- if (ipc->msg) {
- for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
- kfree(ipc->msg[i].tx.data);
- kfree(ipc->msg[i].rx.data);
- }
- kfree(ipc->msg);
- }
-}
-EXPORT_SYMBOL_GPL(sst_ipc_fini);
-
-/* Module information */
-MODULE_AUTHOR("Jin Yao");
-MODULE_DESCRIPTION("Intel SST IPC generic");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/intel/common/sst-ipc.h b/sound/soc/intel/common/sst-ipc.h
deleted file mode 100644
index 86d44ceadc92..000000000000
--- a/sound/soc/intel/common/sst-ipc.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel SST generic IPC Support
- *
- * Copyright (C) 2015, Intel Corporation
- */
-
-#ifndef __SST_GENERIC_IPC_H
-#define __SST_GENERIC_IPC_H
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/wait.h>
-#include <linux/list.h>
-#include <linux/workqueue.h>
-#include <linux/sched.h>
-
-struct sst_ipc_message {
- u64 header;
- void *data;
- size_t size;
-};
-
-struct ipc_message {
- struct list_head list;
- struct sst_ipc_message tx;
- struct sst_ipc_message rx;
-
- wait_queue_head_t waitq;
- bool pending;
- bool complete;
- bool wait;
- int errno;
-};
-
-struct sst_generic_ipc;
-struct sst_dsp;
-
-struct sst_plat_ipc_ops {
- void (*tx_msg)(struct sst_generic_ipc *, struct ipc_message *);
- void (*shim_dbg)(struct sst_generic_ipc *, const char *);
- void (*tx_data_copy)(struct ipc_message *, char *, size_t);
- u64 (*reply_msg_match)(u64 header, u64 *mask);
- bool (*is_dsp_busy)(struct sst_dsp *dsp);
- int (*check_dsp_lp_on)(struct sst_dsp *dsp, bool state);
-};
-
-/* SST generic IPC data */
-struct sst_generic_ipc {
- struct device *dev;
- struct sst_dsp *dsp;
-
- /* IPC messaging */
- struct list_head tx_list;
- struct list_head rx_list;
- struct list_head empty_list;
- wait_queue_head_t wait_txq;
- struct task_struct *tx_thread;
- struct work_struct kwork;
- bool pending;
- struct ipc_message *msg;
- int tx_data_max_size;
- int rx_data_max_size;
-
- struct sst_plat_ipc_ops ops;
-};
-
-int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc,
- struct sst_ipc_message request, struct sst_ipc_message *reply);
-
-int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc,
- struct sst_ipc_message request);
-
-int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc,
- struct sst_ipc_message request, struct sst_ipc_message *reply);
-
-struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc,
- u64 header);
-
-void sst_ipc_tx_msg_reply_complete(struct sst_generic_ipc *ipc,
- struct ipc_message *msg);
-
-int sst_ipc_init(struct sst_generic_ipc *ipc);
-void sst_ipc_fini(struct sst_generic_ipc *ipc);
-
-#endif
diff --git a/sound/soc/loongson/Kconfig b/sound/soc/loongson/Kconfig
index b8d7e2bade24..2d8291c1443c 100644
--- a/sound/soc/loongson/Kconfig
+++ b/sound/soc/loongson/Kconfig
@@ -1,11 +1,23 @@
# SPDX-License-Identifier: GPL-2.0
menu "SoC Audio for Loongson CPUs"
+
+config SND_SOC_LOONGSON_CARD
+ tristate "Loongson Sound Card Driver"
depends on LOONGARCH || COMPILE_TEST
+ select SND_SOC_LOONGSON_I2S_PCI if PCI
+ select SND_SOC_LOONGSON_I2S_PLATFORM if OF
+ help
+ Say Y or M if you want to add support for SoC audio using
+ loongson I2S controller.
+
+ The driver add support for ALSA SoC Audio support using
+ loongson I2S controller.
config SND_SOC_LOONGSON_I2S_PCI
tristate "Loongson I2S-PCI Device Driver"
- select REGMAP_MMIO
+ depends on LOONGARCH || COMPILE_TEST
depends on PCI
+ select REGMAP_MMIO
help
Say Y or M if you want to add support for I2S driver for
Loongson I2S controller.
@@ -13,15 +25,15 @@ config SND_SOC_LOONGSON_I2S_PCI
The controller is found in loongson bridge chips or SoCs,
and work as a PCI device.
-config SND_SOC_LOONGSON_CARD
- tristate "Loongson Sound Card Driver"
- select SND_SOC_LOONGSON_I2S_PCI
- depends on PCI
+config SND_SOC_LOONGSON_I2S_PLATFORM
+ tristate "Loongson I2S-PLAT Device Driver"
+ depends on LOONGARCH || COMPILE_TEST
+ select REGMAP_MMIO
+ select SND_SOC_GENERIC_DMAENGINE_PCM
help
- Say Y or M if you want to add support for SoC audio using
- loongson I2S controller.
-
- The driver add support for ALSA SoC Audio support using
- loongson I2S controller.
+ Say Y or M if you want to add support for I2S driver for
+ Loongson I2S controller.
+ The controller work as a platform device, we can found it in
+ Loongson-2K1000 SoCs.
endmenu
diff --git a/sound/soc/loongson/Makefile b/sound/soc/loongson/Makefile
index 578030ad6563..c0cb1acb36e3 100644
--- a/sound/soc/loongson/Makefile
+++ b/sound/soc/loongson/Makefile
@@ -1,7 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
#Platform Support
-snd-soc-loongson-i2s-pci-y := loongson_i2s_pci.o loongson_i2s.o loongson_dma.o
-obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PCI) += snd-soc-loongson-i2s-pci.o
+snd-soc-loongson-i2s-pci-y := loongson_i2s_pci.o loongson_dma.o
+obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PCI) += snd-soc-loongson-i2s-pci.o snd-soc-loongson-i2s.o
+
+snd-soc-loongson-i2s-plat-y := loongson_i2s_plat.o
+obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PLATFORM) += snd-soc-loongson-i2s-plat.o snd-soc-loongson-i2s.o
+
+snd-soc-loongson-i2s-y := loongson_i2s.o
#Machine Support
snd-soc-loongson-card-y := loongson_card.o
diff --git a/sound/soc/loongson/loongson_card.c b/sound/soc/loongson/loongson_card.c
index 7379f24d385c..7910d5d9ac4f 100644
--- a/sound/soc/loongson/loongson_card.c
+++ b/sound/soc/loongson/loongson_card.c
@@ -144,6 +144,7 @@ static int loongson_card_parse_of(struct loongson_card_data *data)
dev_err(dev, "getting cpu dlc error (%d)\n", ret);
goto err;
}
+ loongson_dai_links[i].platforms->of_node = loongson_dai_links[i].cpus->of_node;
ret = snd_soc_of_get_dlc(codec, NULL, loongson_dai_links[i].codecs, 0);
if (ret < 0) {
diff --git a/sound/soc/loongson/loongson_i2s.c b/sound/soc/loongson/loongson_i2s.c
index 40bbf3205391..e8852a30f213 100644
--- a/sound/soc/loongson/loongson_i2s.c
+++ b/sound/soc/loongson/loongson_i2s.c
@@ -246,6 +246,7 @@ struct snd_soc_dai_driver loongson_i2s_dai = {
.ops = &loongson_i2s_dai_ops,
.symmetric_rate = 1,
};
+EXPORT_SYMBOL_GPL(loongson_i2s_dai);
static int i2s_suspend(struct device *dev)
{
@@ -268,3 +269,7 @@ static int i2s_resume(struct device *dev)
const struct dev_pm_ops loongson_i2s_pm = {
SYSTEM_SLEEP_PM_OPS(i2s_suspend, i2s_resume)
};
+EXPORT_SYMBOL_GPL(loongson_i2s_pm);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Common functions for loongson I2S controller driver");
diff --git a/sound/soc/loongson/loongson_i2s_plat.c b/sound/soc/loongson/loongson_i2s_plat.c
new file mode 100644
index 000000000000..fa2e450ff618
--- /dev/null
+++ b/sound/soc/loongson/loongson_i2s_plat.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Loongson I2S controller master mode dirver(platform device)
+//
+// Copyright (C) 2023-2024 Loongson Technology Corporation Limited
+//
+// Author: Yingkun Meng <mengyingkun@loongson.cn>
+// Binbin Zhou <zhoubinbin@loongson.cn>
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "loongson_i2s.h"
+
+#define LOONGSON_I2S_RX_DMA_OFFSET 21
+#define LOONGSON_I2S_TX_DMA_OFFSET 18
+
+#define LOONGSON_DMA0_CONF 0x0
+#define LOONGSON_DMA1_CONF 0x1
+#define LOONGSON_DMA2_CONF 0x2
+#define LOONGSON_DMA3_CONF 0x3
+#define LOONGSON_DMA4_CONF 0x4
+
+/* periods_max = PAGE_SIZE / sizeof(struct ls_dma_chan_reg) */
+static const struct snd_pcm_hardware loongson_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_RESUME |
+ SNDRV_PCM_INFO_PAUSE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S20_3LE |
+ SNDRV_PCM_FMTBIT_S24_LE,
+ .period_bytes_min = 128,
+ .period_bytes_max = 128 * 1024,
+ .periods_min = 1,
+ .periods_max = 64,
+ .buffer_bytes_max = 1024 * 1024,
+};
+
+static const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config = {
+ .pcm_hardware = &loongson_pcm_hardware,
+ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+ .prealloc_buffer_size = 128 * 1024,
+};
+
+static int loongson_pcm_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ if (substream->pcm->device & 1) {
+ runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
+ runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
+ }
+
+ if (substream->pcm->device & 2)
+ runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID);
+ /*
+ * For mysterious reasons (and despite what the manual says)
+ * playback samples are lost if the DMA count is not a multiple
+ * of the DMA burst size. Let's add a rule to enforce that.
+ */
+ snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
+ snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128);
+ snd_pcm_hw_constraint_integer(substream->runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver loongson_i2s_component_driver = {
+ .name = LS_I2S_DRVNAME,
+ .open = loongson_pcm_open,
+};
+
+static const struct regmap_config loongson_i2s_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x14,
+ .cache_type = REGCACHE_FLAT,
+};
+
+static int loongson_i2s_apbdma_config(struct platform_device *pdev)
+{
+ int val;
+ void __iomem *regs;
+
+ regs = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ val = readl(regs);
+ val |= LOONGSON_DMA2_CONF << LOONGSON_I2S_TX_DMA_OFFSET;
+ val |= LOONGSON_DMA3_CONF << LOONGSON_I2S_RX_DMA_OFFSET;
+ writel(val, regs);
+
+ return 0;
+}
+
+static int loongson_i2s_plat_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct loongson_i2s *i2s;
+ struct resource *res;
+ struct clk *i2s_clk;
+ int ret;
+
+ i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL);
+ if (!i2s)
+ return -ENOMEM;
+
+ ret = loongson_i2s_apbdma_config(pdev);
+ if (ret)
+ return ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ i2s->reg_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(i2s->reg_base))
+ return dev_err_probe(dev, PTR_ERR(i2s->reg_base),
+ "devm_ioremap_resource failed\n");
+
+ i2s->regmap = devm_regmap_init_mmio(dev, i2s->reg_base,
+ &loongson_i2s_regmap_config);
+ if (IS_ERR(i2s->regmap))
+ return dev_err_probe(dev, PTR_ERR(i2s->regmap),
+ "devm_regmap_init_mmio failed\n");
+
+ i2s->playback_dma_data.addr = res->start + LS_I2S_TX_DATA;
+ i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ i2s->playback_dma_data.maxburst = 4;
+
+ i2s->capture_dma_data.addr = res->start + LS_I2S_RX_DATA;
+ i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ i2s->capture_dma_data.maxburst = 4;
+
+ i2s_clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(i2s_clk))
+ return dev_err_probe(dev, PTR_ERR(i2s_clk), "clock property invalid\n");
+ i2s->clk_rate = clk_get_rate(i2s_clk);
+
+ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+ dev_set_name(dev, LS_I2S_DRVNAME);
+ dev_set_drvdata(dev, i2s);
+
+ ret = devm_snd_soc_register_component(dev, &loongson_i2s_component_driver,
+ &loongson_i2s_dai, 1);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register DAI\n");
+
+ return devm_snd_dmaengine_pcm_register(dev, &loongson_dmaengine_pcm_config,
+ SND_DMAENGINE_PCM_FLAG_COMPAT);
+}
+
+static const struct of_device_id loongson_i2s_ids[] = {
+ { .compatible = "loongson,ls2k1000-i2s" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, loongson_i2s_ids);
+
+static struct platform_driver loongson_i2s_driver = {
+ .probe = loongson_i2s_plat_probe,
+ .driver = {
+ .name = "loongson-i2s-plat",
+ .pm = pm_sleep_ptr(&loongson_i2s_pm),
+ .of_match_table = loongson_i2s_ids,
+ },
+};
+module_platform_driver(loongson_i2s_driver);
+
+MODULE_DESCRIPTION("Loongson I2S Master Mode ASoC Driver");
+MODULE_AUTHOR("Loongson Technology Corporation Limited");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/mediatek/mt2701/mt2701-cs42448.c b/sound/soc/mediatek/mt2701/mt2701-cs42448.c
index 4974b0536b7b..00a79867235d 100644
--- a/sound/soc/mediatek/mt2701/mt2701-cs42448.c
+++ b/sound/soc/mediatek/mt2701/mt2701-cs42448.c
@@ -221,7 +221,7 @@ static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST},
.ops = &mt2701_cs42448_48k_fe_ops,
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(fe_multi_ch_out),
},
[DAI_LINK_FE_PCM0_IN] = {
@@ -231,7 +231,7 @@ static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST},
.ops = &mt2701_cs42448_48k_fe_ops,
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(fe_pcm0_in),
},
[DAI_LINK_FE_PCM1_IN] = {
@@ -241,7 +241,7 @@ static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST},
.ops = &mt2701_cs42448_48k_fe_ops,
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(fe_pcm1_in),
},
[DAI_LINK_FE_BT_OUT] = {
@@ -250,7 +250,7 @@ static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(fe_bt_out),
},
[DAI_LINK_FE_BT_IN] = {
@@ -259,7 +259,7 @@ static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(fe_bt_in),
},
/* BE */
@@ -269,8 +269,6 @@ static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
| SND_SOC_DAIFMT_GATED,
.ops = &mt2701_cs42448_be_ops,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(be_i2s0),
},
[DAI_LINK_BE_I2S1] = {
@@ -279,8 +277,6 @@ static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
| SND_SOC_DAIFMT_GATED,
.ops = &mt2701_cs42448_be_ops,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(be_i2s1),
},
[DAI_LINK_BE_I2S2] = {
@@ -289,8 +285,6 @@ static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
| SND_SOC_DAIFMT_GATED,
.ops = &mt2701_cs42448_be_ops,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(be_i2s2),
},
[DAI_LINK_BE_I2S3] = {
@@ -299,15 +293,11 @@ static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
| SND_SOC_DAIFMT_GATED,
.ops = &mt2701_cs42448_be_ops,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(be_i2s3),
},
[DAI_LINK_BE_MRG_BT] = {
.name = "mt2701-cs42448-MRG-BT",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(be_mrg_bt),
},
};
diff --git a/sound/soc/mediatek/mt2701/mt2701-wm8960.c b/sound/soc/mediatek/mt2701/mt2701-wm8960.c
index 8a6643bfe830..2814f0570928 100644
--- a/sound/soc/mediatek/mt2701/mt2701-wm8960.c
+++ b/sound/soc/mediatek/mt2701/mt2701-wm8960.c
@@ -67,7 +67,7 @@ static struct snd_soc_dai_link mt2701_wm8960_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback),
},
{
@@ -76,7 +76,7 @@ static struct snd_soc_dai_link mt2701_wm8960_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture),
},
/* BE */
@@ -86,8 +86,6 @@ static struct snd_soc_dai_link mt2701_wm8960_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS
| SND_SOC_DAIFMT_GATED,
.ops = &mt2701_wm8960_be_ops,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(codec),
},
};
diff --git a/sound/soc/mediatek/mt6797/mt6797-mt6351.c b/sound/soc/mediatek/mt6797/mt6797-mt6351.c
index 784c201b8fd4..daad9544a8d4 100644
--- a/sound/soc/mediatek/mt6797/mt6797-mt6351.c
+++ b/sound/soc/mediatek/mt6797/mt6797-mt6351.c
@@ -78,7 +78,7 @@ static struct snd_soc_dai_link mt6797_mt6351_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback_1),
},
{
@@ -87,7 +87,7 @@ static struct snd_soc_dai_link mt6797_mt6351_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback_2),
},
{
@@ -96,7 +96,7 @@ static struct snd_soc_dai_link mt6797_mt6351_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback_3),
},
{
@@ -105,7 +105,7 @@ static struct snd_soc_dai_link mt6797_mt6351_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture_1),
},
{
@@ -114,7 +114,7 @@ static struct snd_soc_dai_link mt6797_mt6351_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture_2),
},
{
@@ -123,7 +123,7 @@ static struct snd_soc_dai_link mt6797_mt6351_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture_3),
},
{
@@ -132,7 +132,7 @@ static struct snd_soc_dai_link mt6797_mt6351_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture_mono_1),
},
{
@@ -141,8 +141,6 @@ static struct snd_soc_dai_link mt6797_mt6351_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_lpbk),
},
@@ -152,8 +150,6 @@ static struct snd_soc_dai_link mt6797_mt6351_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_speech),
},
@@ -161,24 +157,18 @@ static struct snd_soc_dai_link mt6797_mt6351_dai_links[] = {
{
.name = "Primary Codec",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(primary_codec),
},
{
.name = "PCM 1",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(pcm1),
},
{
.name = "PCM 2",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(pcm2),
},
diff --git a/sound/soc/mediatek/mt7986/mt7986-wm8960.c b/sound/soc/mediatek/mt7986/mt7986-wm8960.c
index 6982e833421d..c3d1e2eeb0e5 100644
--- a/sound/soc/mediatek/mt7986/mt7986-wm8960.c
+++ b/sound/soc/mediatek/mt7986/mt7986-wm8960.c
@@ -45,7 +45,7 @@ static struct snd_soc_dai_link mt7986_wm8960_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback),
},
{
@@ -54,7 +54,7 @@ static struct snd_soc_dai_link mt7986_wm8960_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture),
},
/* BE */
@@ -65,8 +65,6 @@ static struct snd_soc_dai_link mt7986_wm8960_dai_links[] = {
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS |
SND_SOC_DAIFMT_GATED,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(codec),
},
};
diff --git a/sound/soc/mediatek/mt8173/mt8173-max98090.c b/sound/soc/mediatek/mt8173/mt8173-max98090.c
index 0557a287c641..0724564cee6a 100644
--- a/sound/soc/mediatek/mt8173/mt8173-max98090.c
+++ b/sound/soc/mediatek/mt8173/mt8173-max98090.c
@@ -104,7 +104,7 @@ static struct snd_soc_dai_link mt8173_max98090_dais[] = {
.stream_name = "MAX98090 Playback",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback),
},
{
@@ -112,7 +112,7 @@ static struct snd_soc_dai_link mt8173_max98090_dais[] = {
.stream_name = "MAX98090 Capture",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture),
},
/* Back End DAI links */
@@ -123,8 +123,6 @@ static struct snd_soc_dai_link mt8173_max98090_dais[] = {
.ops = &mt8173_max98090_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(hifi),
},
};
diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c
index 4ed06c269065..d8e4e70d834c 100644
--- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c
+++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c
@@ -139,7 +139,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5514_dais[] = {
.stream_name = "rt5650_rt5514 Playback",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback),
},
[DAI_LINK_CAPTURE] = {
@@ -147,7 +147,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5514_dais[] = {
.stream_name = "rt5650_rt5514 Capture",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture),
},
/* Back End DAI links */
@@ -159,8 +159,6 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5514_dais[] = {
SND_SOC_DAIFMT_CBS_CFS,
.ops = &mt8173_rt5650_rt5514_ops,
.ignore_pmdown_time = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(codec),
},
};
diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c
index 763067c21153..488f2314dbf7 100644
--- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c
+++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c
@@ -171,7 +171,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
.stream_name = "rt5650_rt5676 Playback",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback),
},
[DAI_LINK_CAPTURE] = {
@@ -179,7 +179,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
.stream_name = "rt5650_rt5676 Capture",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture),
},
[DAI_LINK_HDMI] = {
@@ -187,7 +187,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
.stream_name = "HDMI PCM",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(hdmi_pcm),
},
@@ -200,14 +200,12 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
SND_SOC_DAIFMT_CBS_CFS,
.ops = &mt8173_rt5650_rt5676_ops,
.ignore_pmdown_time = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(codec),
},
[DAI_LINK_HDMI_I2S] = {
.name = "HDMI BE",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(hdmi_be),
},
/* rt5676 <-> rt5650 intercodec link: Sets rt5676 I2S2 as master */
diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c
index 466f176f8e94..59c19fdd8675 100644
--- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c
+++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c
@@ -210,7 +210,7 @@ static struct snd_soc_dai_link mt8173_rt5650_dais[] = {
.stream_name = "rt5650 Playback",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback),
},
[DAI_LINK_CAPTURE] = {
@@ -218,7 +218,7 @@ static struct snd_soc_dai_link mt8173_rt5650_dais[] = {
.stream_name = "rt5650 Capture",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture),
},
[DAI_LINK_HDMI] = {
@@ -226,7 +226,7 @@ static struct snd_soc_dai_link mt8173_rt5650_dais[] = {
.stream_name = "HDMI PCM",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(hdmi_pcm),
},
/* Back End DAI links */
@@ -238,14 +238,12 @@ static struct snd_soc_dai_link mt8173_rt5650_dais[] = {
SND_SOC_DAIFMT_CBS_CFS,
.ops = &mt8173_rt5650_ops,
.ignore_pmdown_time = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(codec),
},
[DAI_LINK_HDMI_I2S] = {
.name = "HDMI BE",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.init = mt8173_rt5650_hdmi_init,
SND_SOC_DAILINK_REG(hdmi_be),
},
diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
index f848e14b091a..1d8881e0a361 100644
--- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
+++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
@@ -425,7 +425,7 @@ static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mt8183_da7219_max98357_ops,
SND_SOC_DAILINK_REG(playback1),
},
@@ -435,7 +435,7 @@ static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mt8183_da7219_max98357_bt_sco_ops,
SND_SOC_DAILINK_REG(playback2),
},
@@ -445,7 +445,7 @@ static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback3),
},
{
@@ -454,7 +454,7 @@ static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mt8183_da7219_max98357_bt_sco_ops,
SND_SOC_DAILINK_REG(capture1),
},
@@ -464,7 +464,7 @@ static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture2),
},
{
@@ -473,7 +473,7 @@ static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mt8183_da7219_max98357_ops,
SND_SOC_DAILINK_REG(capture3),
},
@@ -483,7 +483,7 @@ static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture_mono),
},
{
@@ -492,38 +492,32 @@ static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback_hdmi),
},
/* BE */
{
.name = "Primary Codec",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(primary_codec),
},
{
.name = "PCM 1",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(pcm1),
},
{
.name = "PCM 2",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(pcm2),
},
{
.name = "I2S0",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
.ops = &mt8183_mt6358_i2s_ops,
@@ -532,7 +526,7 @@ static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
{
.name = "I2S1",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
.ops = &mt8183_mt6358_i2s_ops,
@@ -541,7 +535,7 @@ static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
{
.name = "I2S2",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
.ops = &mt8183_da7219_i2s_ops,
@@ -551,13 +545,13 @@ static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
{
.name = "I2S3",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
},
{
.name = "I2S5",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
.ops = &mt8183_mt6358_i2s_ops,
@@ -570,7 +564,7 @@ static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_IB_IF |
SND_SOC_DAIFMT_CBM_CFM,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
.ignore = 1,
diff --git a/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c b/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c
index 65e46ebe7be6..5cf5592336d3 100644
--- a/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c
+++ b/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c
@@ -1036,7 +1036,6 @@ static int mt8183_dai_i2s_set_priv(struct mtk_base_afe *afe)
int mt8183_dai_i2s_register(struct mtk_base_afe *afe)
{
struct mtk_base_afe_dai *dai;
- int ret;
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
if (!dai)
@@ -1055,9 +1054,5 @@ int mt8183_dai_i2s_register(struct mtk_base_afe *afe)
dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);
/* set all dai i2s private data */
- ret = mt8183_dai_i2s_set_priv(afe);
- if (ret)
- return ret;
-
- return 0;
+ return mt8183_dai_i2s_set_priv(afe);
}
diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
index bb6df056a878..6267c8554c15 100644
--- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
+++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
@@ -430,7 +430,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mt8183_mt6358_ops,
SND_SOC_DAILINK_REG(playback1),
},
@@ -440,7 +440,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mt8183_mt6358_ts3a227_max98357_bt_sco_ops,
SND_SOC_DAILINK_REG(playback2),
},
@@ -450,7 +450,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback3),
},
{
@@ -459,7 +459,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mt8183_mt6358_ts3a227_max98357_bt_sco_ops,
SND_SOC_DAILINK_REG(capture1),
},
@@ -469,7 +469,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture2),
},
{
@@ -478,7 +478,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mt8183_mt6358_ops,
SND_SOC_DAILINK_REG(capture3),
},
@@ -488,7 +488,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture_mono),
},
{
@@ -497,7 +497,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback_hdmi),
},
{
@@ -513,31 +513,25 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
{
.name = "Primary Codec",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(primary_codec),
},
{
.name = "PCM 1",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(pcm1),
},
{
.name = "PCM 2",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(pcm2),
},
{
.name = "I2S0",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
.ops = &mt8183_mt6358_i2s_ops,
SND_SOC_DAILINK_REG(i2s0),
@@ -545,7 +539,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
{
.name = "I2S1",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
.ops = &mt8183_mt6358_i2s_ops,
@@ -554,7 +548,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
{
.name = "I2S2",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
.ops = &mt8183_mt6358_i2s_ops,
@@ -564,13 +558,13 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
{
.name = "I2S3",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
},
{
.name = "I2S5",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.ops = &mt8183_mt6358_i2s_ops,
.init = &mt8183_bt_init,
@@ -582,7 +576,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_IB_IF |
SND_SOC_DAIFMT_CBM_CFM,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
.ops = &mt8183_mt6358_tdm_ops,
diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366.c b/sound/soc/mediatek/mt8186/mt8186-mt6366.c
index 771d53611c2a..a5ef913743d4 100644
--- a/sound/soc/mediatek/mt8186/mt8186-mt6366.c
+++ b/sound/soc/mediatek/mt8186/mt8186-mt6366.c
@@ -647,7 +647,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
@@ -660,7 +660,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback12),
},
{
@@ -669,7 +669,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
@@ -681,7 +681,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
@@ -694,7 +694,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback4),
},
{
@@ -703,7 +703,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback5),
},
{
@@ -712,7 +712,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback6),
},
{
@@ -721,7 +721,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback7),
},
{
@@ -730,7 +730,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback8),
},
{
@@ -739,7 +739,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture1),
},
{
@@ -748,7 +748,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
@@ -761,7 +761,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture3),
},
{
@@ -770,7 +770,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
@@ -783,7 +783,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture5),
},
{
@@ -792,7 +792,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
@@ -804,7 +804,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture7),
},
{
@@ -813,8 +813,6 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_lpbk),
},
@@ -824,8 +822,6 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_fm),
},
@@ -835,8 +831,6 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_src1),
},
@@ -846,8 +840,6 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_src_bargein),
},
@@ -857,7 +849,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_hw_gain_aaudio),
},
@@ -867,8 +859,6 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_src_aaudio),
},
@@ -876,8 +866,6 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
{
.name = "Primary Codec",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
.init = primary_codec_init,
SND_SOC_DAILINK_REG(adda),
@@ -888,7 +876,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_IB_IF |
SND_SOC_DAIFMT_CBM_CFM,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.init = mt8186_mt6366_rt1019_rt5682s_hdmi_init,
SND_SOC_DAILINK_REG(i2s3),
@@ -896,7 +884,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
{
.name = "I2S0",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
.ops = &mt8186_rt5682s_i2s_ops,
SND_SOC_DAILINK_REG(i2s0),
@@ -904,7 +892,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
{
.name = "I2S1",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.init = mt8186_headset_codec_init,
SND_SOC_DAILINK_REG(i2s1),
@@ -912,46 +900,38 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
{
.name = "I2S2",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(i2s2),
},
{
.name = "HW Gain 1",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hw_gain1),
},
{
.name = "HW Gain 2",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hw_gain2),
},
{
.name = "HW_SRC_1",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hw_src1),
},
{
.name = "HW_SRC_2",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hw_src2),
},
{
.name = "CONNSYS_I2S",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(connsys_i2s),
},
@@ -960,15 +940,13 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_IF,
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(pcm1),
},
{
.name = "TDM IN",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(tdm_in),
},
@@ -976,35 +954,35 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
{
.name = "Hostless_UL1",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_ul1),
},
{
.name = "Hostless_UL2",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_ul2),
},
{
.name = "Hostless_UL3",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_ul3),
},
{
.name = "Hostless_UL5",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_ul5),
},
{
.name = "Hostless_UL6",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_ul6),
},
@@ -1012,25 +990,25 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
{
.name = "AFE_SOF_DL1",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(AFE_SOF_DL1),
},
{
.name = "AFE_SOF_DL2",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(AFE_SOF_DL2),
},
{
.name = "AFE_SOF_UL1",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(AFE_SOF_UL1),
},
{
.name = "AFE_SOF_UL2",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(AFE_SOF_UL2),
},
};
diff --git a/sound/soc/mediatek/mt8188/mt8188-dai-adda.c b/sound/soc/mediatek/mt8188/mt8188-dai-adda.c
index 8a17d1935c48..43670316611e 100644
--- a/sound/soc/mediatek/mt8188/mt8188-dai-adda.c
+++ b/sound/soc/mediatek/mt8188/mt8188-dai-adda.c
@@ -63,7 +63,6 @@ static int mt8188_adda_mtkaif_init(struct mtk_base_afe *afe)
param->mtkaif_phase_cycle[MT8188_MTKAIF_MISO_0];
}
- val = 0;
mask = (MTKAIF_RXIF_DELAY_DATA | MTKAIF_RXIF_DELAY_CYCLE_MASK);
val |= FIELD_PREP(MTKAIF_RXIF_DELAY_CYCLE_MASK, delay_cycle);
val |= FIELD_PREP(MTKAIF_RXIF_DELAY_DATA, delay_data);
diff --git a/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c b/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c
index 2a48f5fd6826..69a091dad88d 100644
--- a/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c
+++ b/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c
@@ -2422,7 +2422,6 @@ static int mtk_dai_hdmitx_dptx_hw_params(struct snd_pcm_substream *substream,
unsigned int channels = params_channels(params);
snd_pcm_format_t format = params_format(params);
int width = snd_pcm_format_physical_width(format);
- int ret;
if (!is_valid_etdm_dai(dai->id))
return -EINVAL;
@@ -2450,9 +2449,7 @@ static int mtk_dai_hdmitx_dptx_hw_params(struct snd_pcm_substream *substream,
etdm_data->data_mode = MTK_DAI_ETDM_DATA_MULTI_PIN;
}
- ret = mtk_dai_etdm_configure(afe, rate, channels, width, dai->id);
-
- return ret;
+ return mtk_dai_etdm_configure(afe, rate, channels, width, dai->id);
}
static int mtk_dai_hdmitx_dptx_set_sysclk(struct snd_soc_dai *dai,
diff --git a/sound/soc/mediatek/mt8188/mt8188-dai-pcm.c b/sound/soc/mediatek/mt8188/mt8188-dai-pcm.c
index 5bc854a8f3df..8ca7cc75e21d 100644
--- a/sound/soc/mediatek/mt8188/mt8188-dai-pcm.c
+++ b/sound/soc/mediatek/mt8188/mt8188-dai-pcm.c
@@ -128,7 +128,7 @@ static int mtk_dai_pcm_configure(struct snd_pcm_substream *substream,
unsigned int lrck_inv;
unsigned int bck_inv;
unsigned int fmt;
- unsigned int bit_width = dai->sample_bits;
+ unsigned int bit_width = dai->symmetric_sample_bits;
unsigned int val = 0;
unsigned int mask = 0;
int fs = 0;
diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
index 08ae962afeb9..84abdba9ddb6 100644
--- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c
+++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
@@ -932,7 +932,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
.dpcm_merged_format = 1,
@@ -946,7 +946,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
.dpcm_merged_format = 1,
@@ -960,7 +960,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
.dpcm_merged_format = 1,
@@ -974,7 +974,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_PRE,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback7),
},
[DAI_LINK_DL8_FE] = {
@@ -985,7 +985,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback8),
},
[DAI_LINK_DL10_FE] = {
@@ -996,7 +996,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback10),
},
[DAI_LINK_DL11_FE] = {
@@ -1007,7 +1007,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback11),
},
[DAI_LINK_UL1_FE] = {
@@ -1018,7 +1018,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_PRE,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture1),
},
[DAI_LINK_UL2_FE] = {
@@ -1029,7 +1029,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture2),
},
[DAI_LINK_UL3_FE] = {
@@ -1040,7 +1040,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture3),
},
[DAI_LINK_UL4_FE] = {
@@ -1051,7 +1051,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
.dpcm_merged_format = 1,
@@ -1065,7 +1065,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
.dpcm_merged_format = 1,
@@ -1079,7 +1079,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_PRE,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture6),
},
[DAI_LINK_UL8_FE] = {
@@ -1090,7 +1090,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture8),
},
[DAI_LINK_UL9_FE] = {
@@ -1101,7 +1101,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture9),
},
[DAI_LINK_UL10_FE] = {
@@ -1112,14 +1112,14 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture10),
},
/* BE */
[DAI_LINK_DL_SRC_BE] = {
.name = "DL_SRC_BE",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(dl_src),
},
[DAI_LINK_DPTX_BE] = {
@@ -1127,7 +1127,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
.ops = &mt8188_dptx_ops,
.be_hw_params_fixup = mt8188_dptx_hw_params_fixup,
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(dptx),
},
[DAI_LINK_ETDM1_IN_BE] = {
@@ -1136,7 +1136,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(etdm1_in),
},
@@ -1146,7 +1146,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBP_CFP,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(etdm2_in),
},
[DAI_LINK_ETDM1_OUT_BE] = {
@@ -1155,7 +1155,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(etdm1_out),
},
[DAI_LINK_ETDM2_OUT_BE] = {
@@ -1164,7 +1164,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(etdm2_out),
},
[DAI_LINK_ETDM3_OUT_BE] = {
@@ -1173,7 +1173,7 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(etdm3_out),
},
[DAI_LINK_PCM1_BE] = {
@@ -1182,14 +1182,12 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(pcm1),
},
[DAI_LINK_UL_SRC_BE] = {
.name = "UL_SRC_BE",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(ul_src),
},
@@ -1197,28 +1195,28 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
[DAI_LINK_SOF_DL2_BE] = {
.name = "AFE_SOF_DL2",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mt8188_sof_be_ops,
SND_SOC_DAILINK_REG(AFE_SOF_DL2),
},
[DAI_LINK_SOF_DL3_BE] = {
.name = "AFE_SOF_DL3",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mt8188_sof_be_ops,
SND_SOC_DAILINK_REG(AFE_SOF_DL3),
},
[DAI_LINK_SOF_UL4_BE] = {
.name = "AFE_SOF_UL4",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mt8188_sof_be_ops,
SND_SOC_DAILINK_REG(AFE_SOF_UL4),
},
[DAI_LINK_SOF_UL5_BE] = {
.name = "AFE_SOF_UL5",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mt8188_sof_be_ops,
SND_SOC_DAILINK_REG(AFE_SOF_UL5),
},
diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
index db00704e206d..1aba9c75594e 100644
--- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
+++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
@@ -598,7 +598,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback1),
},
{
@@ -607,7 +607,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback12),
},
{
@@ -616,7 +616,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback2),
},
{
@@ -625,7 +625,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(playback3),
},
@@ -635,7 +635,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback4),
},
{
@@ -644,7 +644,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback5),
},
{
@@ -653,7 +653,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback6),
},
{
@@ -662,7 +662,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback7),
},
{
@@ -671,7 +671,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback8),
},
{
@@ -680,7 +680,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback9),
},
{
@@ -689,7 +689,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(capture1),
},
@@ -699,7 +699,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(capture2),
},
@@ -709,7 +709,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture3),
},
{
@@ -718,7 +718,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture4),
},
{
@@ -727,7 +727,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture5),
},
{
@@ -736,7 +736,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture6),
},
{
@@ -745,7 +745,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture7),
},
{
@@ -754,7 +754,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture8),
},
{
@@ -763,7 +763,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture_mono1),
},
{
@@ -772,7 +772,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture_mono2),
},
{
@@ -781,7 +781,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(capture_mono3),
},
{
@@ -790,15 +790,13 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(playback_hdmi),
},
/* Back End DAI links */
{
.name = "Primary Codec",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
.init = mt8192_mt6359_init,
SND_SOC_DAILINK_REG(primary_codec),
@@ -806,29 +804,27 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
{
.name = "Primary Codec CH34",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(primary_codec_ch34),
},
{
.name = "AP_DMIC",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(ap_dmic),
},
{
.name = "AP_DMIC_CH34",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(ap_dmic_ch34),
},
{
.name = "I2S0",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s0),
@@ -836,7 +832,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
{
.name = "I2S1",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s1),
@@ -844,7 +840,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
{
.name = "I2S2",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s2),
@@ -852,7 +848,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
{
.name = "I2S3",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s3),
@@ -860,7 +856,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
{
.name = "I2S5",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s5),
@@ -868,7 +864,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
{
.name = "I2S6",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s6),
@@ -876,7 +872,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
{
.name = "I2S7",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s7),
@@ -884,7 +880,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
{
.name = "I2S8",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
.init = mt8192_rt5682_init,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
@@ -894,7 +890,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
{
.name = "I2S9",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s9),
@@ -903,23 +899,19 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
{
.name = "CONNSYS_I2S",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(connsys_i2s),
},
{
.name = "PCM 1",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(pcm1),
},
{
.name = "PCM 2",
.no_pcm = 1,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(pcm2),
},
@@ -929,7 +921,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_DSP_A |
SND_SOC_DAIFMT_IB_NF |
SND_SOC_DAIFMT_CBM_CFM,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
.ignore = 1,
diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c
index 6d6d79300d51..cdc16057d50e 100644
--- a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c
+++ b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c
@@ -127,7 +127,7 @@ static int mtk_dai_pcm_configure(struct snd_pcm_substream *substream,
unsigned int lrck_inv;
unsigned int bck_inv;
unsigned int fmt;
- unsigned int bit_width = dai->sample_bits;
+ unsigned int bit_width = dai->symmetric_sample_bits;
unsigned int val = 0;
unsigned int mask = 0;
int fs = 0;
diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359.c b/sound/soc/mediatek/mt8195/mt8195-mt6359.c
index 2832ef78eaed..56b9d2433a1e 100644
--- a/sound/soc/mediatek/mt8195/mt8195-mt6359.c
+++ b/sound/soc/mediatek/mt8195/mt8195-mt6359.c
@@ -913,7 +913,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(DL2_FE),
},
@@ -925,7 +925,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(DL3_FE),
},
@@ -937,7 +937,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(DL6_FE),
},
@@ -949,7 +949,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_PRE,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(DL7_FE),
},
[DAI_LINK_DL8_FE] = {
@@ -960,7 +960,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(DL8_FE),
},
@@ -972,7 +972,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mt8195_hdmitx_dptx_playback_ops,
SND_SOC_DAILINK_REG(DL10_FE),
},
@@ -984,7 +984,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(DL11_FE),
},
@@ -996,7 +996,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_PRE,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(UL1_FE),
},
[DAI_LINK_UL2_FE] = {
@@ -1007,7 +1007,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL2_FE),
},
@@ -1019,7 +1019,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL3_FE),
},
@@ -1031,7 +1031,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL4_FE),
},
@@ -1043,7 +1043,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL5_FE),
},
@@ -1055,7 +1055,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_PRE,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(UL6_FE),
},
[DAI_LINK_UL8_FE] = {
@@ -1066,7 +1066,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL8_FE),
},
@@ -1078,7 +1078,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL9_FE),
},
@@ -1090,7 +1090,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_POST,
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL10_FE),
},
@@ -1098,13 +1098,13 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
[DAI_LINK_DL_SRC_BE] = {
.name = "DL_SRC_BE",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(DL_SRC_BE),
},
[DAI_LINK_DPTX_BE] = {
.name = "DPTX_BE",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mt8195_dptx_ops,
.be_hw_params_fixup = mt8195_dptx_hw_params_fixup,
SND_SOC_DAILINK_REG(DPTX_BE),
@@ -1115,7 +1115,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(ETDM1_IN_BE),
},
[DAI_LINK_ETDM2_IN_BE] = {
@@ -1124,7 +1124,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
- .dpcm_capture = 1,
+ .capture_only = 1,
.be_hw_params_fixup = mt8195_etdm_hw_params_fixup,
SND_SOC_DAILINK_REG(ETDM2_IN_BE),
},
@@ -1134,7 +1134,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
- .dpcm_playback = 1,
+ .playback_only = 1,
.be_hw_params_fixup = mt8195_etdm_hw_params_fixup,
SND_SOC_DAILINK_REG(ETDM1_OUT_BE),
},
@@ -1144,7 +1144,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(ETDM2_OUT_BE),
},
[DAI_LINK_ETDM3_OUT_BE] = {
@@ -1153,7 +1153,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(ETDM3_OUT_BE),
},
[DAI_LINK_PCM1_BE] = {
@@ -1162,48 +1162,46 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(PCM1_BE),
},
[DAI_LINK_UL_SRC1_BE] = {
.name = "UL_SRC1_BE",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(UL_SRC1_BE),
},
[DAI_LINK_UL_SRC2_BE] = {
.name = "UL_SRC2_BE",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(UL_SRC2_BE),
},
/* SOF BE */
[DAI_LINK_SOF_DL2_BE] = {
.name = "AFE_SOF_DL2",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mt8195_sof_be_ops,
SND_SOC_DAILINK_REG(AFE_SOF_DL2),
},
[DAI_LINK_SOF_DL3_BE] = {
.name = "AFE_SOF_DL3",
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.ops = &mt8195_sof_be_ops,
SND_SOC_DAILINK_REG(AFE_SOF_DL3),
},
[DAI_LINK_SOF_UL4_BE] = {
.name = "AFE_SOF_UL4",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mt8195_sof_be_ops,
SND_SOC_DAILINK_REG(AFE_SOF_UL4),
},
[DAI_LINK_SOF_UL5_BE] = {
.name = "AFE_SOF_UL5",
.no_pcm = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.ops = &mt8195_sof_be_ops,
SND_SOC_DAILINK_REG(AFE_SOF_UL5),
},
diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c b/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c
index f9945c2a2cd1..0bac143b48bf 100644
--- a/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c
+++ b/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c
@@ -118,13 +118,13 @@ static int mt8365_dai_configure_dmic(struct mtk_base_afe *afe,
unsigned int clk_phase_sel_ch1 = dmic_data->clk_phase_sel_ch1;
unsigned int clk_phase_sel_ch2 = dmic_data->clk_phase_sel_ch2;
unsigned int val = 0;
- unsigned int rate = dai->rate;
- int reg = get_chan_reg(dai->channels);
+ unsigned int rate = dai->symmetric_rate;
+ int reg = get_chan_reg(dai->symmetric_channels);
if (reg < 0)
return -EINVAL;
- dmic_data->dmic_channel = dai->channels;
+ dmic_data->dmic_channel = dai->symmetric_channels;
val |= DMIC_TOP_CON_SDM3_LEVEL_MODE;
diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-pcm.c b/sound/soc/mediatek/mt8365/mt8365-dai-pcm.c
index f85ec07249c3..3373b88da28e 100644
--- a/sound/soc/mediatek/mt8365/mt8365-dai-pcm.c
+++ b/sound/soc/mediatek/mt8365/mt8365-dai-pcm.c
@@ -44,7 +44,7 @@ static int mt8365_dai_configure_pcm1(struct snd_pcm_substream *substream,
bool lrck_inv = pcm_priv->lrck_inv;
bool bck_inv = pcm_priv->bck_inv;
unsigned int fmt = pcm_priv->format;
- unsigned int bit_width = dai->sample_bits;
+ unsigned int bit_width = dai->symmetric_sample_bits;
unsigned int val = 0;
if (!slave_mode) {
diff --git a/sound/soc/mediatek/mt8365/mt8365-mt6357.c b/sound/soc/mediatek/mt8365/mt8365-mt6357.c
index 42cbdfdfadb5..d398e83ea052 100644
--- a/sound/soc/mediatek/mt8365/mt8365-mt6357.c
+++ b/sound/soc/mediatek/mt8365/mt8365-mt6357.c
@@ -168,7 +168,7 @@ static struct snd_soc_dai_link mt8365_mt6357_dais[] = {
SND_SOC_DPCM_TRIGGER_POST
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.dpcm_merged_rate = 1,
SND_SOC_DAILINK_REG(playback1),
},
@@ -181,7 +181,7 @@ static struct snd_soc_dai_link mt8365_mt6357_dais[] = {
SND_SOC_DPCM_TRIGGER_POST
},
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.dpcm_merged_rate = 1,
SND_SOC_DAILINK_REG(playback2),
},
@@ -194,7 +194,7 @@ static struct snd_soc_dai_link mt8365_mt6357_dais[] = {
SND_SOC_DPCM_TRIGGER_POST
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.dpcm_merged_rate = 1,
SND_SOC_DAILINK_REG(awb_capture),
},
@@ -207,7 +207,7 @@ static struct snd_soc_dai_link mt8365_mt6357_dais[] = {
SND_SOC_DPCM_TRIGGER_POST
},
.dynamic = 1,
- .dpcm_capture = 1,
+ .capture_only = 1,
.dpcm_merged_rate = 1,
SND_SOC_DAILINK_REG(vul),
},
@@ -219,23 +219,19 @@ static struct snd_soc_dai_link mt8365_mt6357_dais[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(i2s3),
},
[DAI_LINK_DMIC] = {
.name = "DMIC_BE",
.no_pcm = 1,
.id = DAI_LINK_DMIC,
- .dpcm_capture = 1,
+ .capture_only = 1,
SND_SOC_DAILINK_REG(dmic),
},
[DAI_LINK_INT_ADDA] = {
.name = "MTK_Codec",
.no_pcm = 1,
.id = DAI_LINK_INT_ADDA,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
.ops = &mt8365_mt6357_int_adda_ops,
SND_SOC_DAILINK_REG(primary_codec),
},
diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c
index 5ebf287fe700..a2dfccb7990f 100644
--- a/sound/soc/meson/axg-card.c
+++ b/sound/soc/meson/axg-card.c
@@ -43,7 +43,7 @@ static int axg_card_tdm_be_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card);
struct axg_dai_link_tdm_data *be =
- (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num];
+ (struct axg_dai_link_tdm_data *)priv->link_data[rtd->id];
return meson_card_i2s_set_sysclk(substream, params, be->mclk_fs);
}
@@ -56,7 +56,7 @@ static int axg_card_tdm_dai_init(struct snd_soc_pcm_runtime *rtd)
{
struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card);
struct axg_dai_link_tdm_data *be =
- (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num];
+ (struct axg_dai_link_tdm_data *)priv->link_data[rtd->id];
struct snd_soc_dai *codec_dai;
int ret, i;
@@ -86,7 +86,7 @@ static int axg_card_tdm_dai_lb_init(struct snd_soc_pcm_runtime *rtd)
{
struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card);
struct axg_dai_link_tdm_data *be =
- (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num];
+ (struct axg_dai_link_tdm_data *)priv->link_data[rtd->id];
int ret;
/* The loopback rx_mask is the pad tx_mask */
diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c
index 62057c71f742..09103eef2a97 100644
--- a/sound/soc/meson/axg-tdm-interface.c
+++ b/sound/soc/meson/axg-tdm-interface.c
@@ -442,14 +442,18 @@ static const struct snd_soc_dai_driver axg_tdm_iface_dai_drv[] = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = AXG_TDM_CHANNEL_MAX,
- .rates = AXG_TDM_RATES,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 5512,
+ .rate_max = 768000,
.formats = AXG_TDM_FORMATS,
},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = AXG_TDM_CHANNEL_MAX,
- .rates = AXG_TDM_RATES,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 5512,
+ .rate_max = 768000,
.formats = AXG_TDM_FORMATS,
},
.id = TDM_IFACE_PAD,
@@ -461,7 +465,9 @@ static const struct snd_soc_dai_driver axg_tdm_iface_dai_drv[] = {
.stream_name = "Loopback",
.channels_min = 1,
.channels_max = AXG_TDM_CHANNEL_MAX,
- .rates = AXG_TDM_RATES,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 5512,
+ .rate_max = 768000,
.formats = AXG_TDM_FORMATS,
},
.id = TDM_IFACE_LOOPBACK,
diff --git a/sound/soc/meson/axg-tdm.h b/sound/soc/meson/axg-tdm.h
index 1a17f546ce6e..acfcd48f8a00 100644
--- a/sound/soc/meson/axg-tdm.h
+++ b/sound/soc/meson/axg-tdm.h
@@ -15,8 +15,6 @@
#define AXG_TDM_NUM_LANES 4
#define AXG_TDM_CHANNEL_MAX 128
-#define AXG_TDM_RATES (SNDRV_PCM_RATE_5512 | \
- SNDRV_PCM_RATE_8000_768000)
#define AXG_TDM_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S20_LE | \
diff --git a/sound/soc/meson/gx-card.c b/sound/soc/meson/gx-card.c
index 455f6bfc9f8f..b408cc2bbc91 100644
--- a/sound/soc/meson/gx-card.c
+++ b/sound/soc/meson/gx-card.c
@@ -32,7 +32,7 @@ static int gx_card_i2s_be_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card);
struct gx_dai_link_i2s_data *be =
- (struct gx_dai_link_i2s_data *)priv->link_data[rtd->num];
+ (struct gx_dai_link_i2s_data *)priv->link_data[rtd->id];
return meson_card_i2s_set_sysclk(substream, params, be->mclk_fs);
}
diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig
index 762491d6f2f2..ca7a30ebd26a 100644
--- a/sound/soc/qcom/Kconfig
+++ b/sound/soc/qcom/Kconfig
@@ -157,6 +157,7 @@ config SND_SOC_SDM845
depends on COMMON_CLK
select SND_SOC_QDSP6
select SND_SOC_QCOM_COMMON
+ select SND_SOC_QCOM_SDW
select SND_SOC_RT5663
select SND_SOC_MAX98927
imply SND_SOC_CROS_EC_CODEC
@@ -208,6 +209,7 @@ config SND_SOC_SC7280
tristate "SoC Machine driver for SC7280 boards"
depends on I2C && SOUNDWIRE
select SND_SOC_QCOM_COMMON
+ select SND_SOC_QCOM_SDW
select SND_SOC_LPASS_SC7280
select SND_SOC_MAX98357A
select SND_SOC_WCD938X_SDW
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c
index 5a47f661e0c6..242bc16da36d 100644
--- a/sound/soc/qcom/lpass-cpu.c
+++ b/sound/soc/qcom/lpass-cpu.c
@@ -1242,6 +1242,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
/* Allocation for i2sctl regmap fields */
drvdata->i2sctl = devm_kzalloc(&pdev->dev, sizeof(struct lpaif_i2sctl),
GFP_KERNEL);
+ if (!drvdata->i2sctl)
+ return -ENOMEM;
/* Initialize bitfields for dai I2SCTL register */
ret = lpass_cpu_init_i2sctl_bitfields(dev, drvdata->i2sctl,
diff --git a/sound/soc/qcom/sc7280.c b/sound/soc/qcom/sc7280.c
index 207ac5da4dd4..230af8d7b205 100644
--- a/sound/soc/qcom/sc7280.c
+++ b/sound/soc/qcom/sc7280.c
@@ -23,6 +23,7 @@
#include "common.h"
#include "lpass.h"
#include "qdsp6/q6afe.h"
+#include "sdw.h"
#define DEFAULT_MCLK_RATE 19200000
#define RT5682_PLL_FREQ (48000 * 512)
@@ -316,6 +317,7 @@ static void sc7280_snd_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_card *card = rtd->card;
struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
switch (cpu_dai->id) {
case MI2S_PRIMARY:
@@ -333,6 +335,9 @@ static void sc7280_snd_shutdown(struct snd_pcm_substream *substream)
default:
break;
}
+
+ data->sruntime[cpu_dai->id] = NULL;
+ sdw_release_stream(sruntime);
}
static int sc7280_snd_startup(struct snd_pcm_substream *substream)
@@ -347,6 +352,8 @@ static int sc7280_snd_startup(struct snd_pcm_substream *substream)
switch (cpu_dai->id) {
case MI2S_PRIMARY:
ret = sc7280_rt5682_init(rtd);
+ if (ret)
+ return ret;
break;
case SECONDARY_MI2S_RX:
codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
@@ -360,7 +367,8 @@ static int sc7280_snd_startup(struct snd_pcm_substream *substream)
default:
break;
}
- return ret;
+
+ return qcom_snd_sdw_startup(substream);
}
static const struct snd_soc_ops sc7280_ops = {
diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c
index 922ecada1cd8..311377317176 100644
--- a/sound/soc/qcom/sc8280xp.c
+++ b/sound/soc/qcom/sc8280xp.c
@@ -190,6 +190,7 @@ static const struct of_device_id snd_sc8280xp_dt_match[] = {
{.compatible = "qcom,sm8450-sndcard", "sm8450"},
{.compatible = "qcom,sm8550-sndcard", "sm8550"},
{.compatible = "qcom,sm8650-sndcard", "sm8650"},
+ {.compatible = "qcom,sm8750-sndcard", "sm8750"},
{}
};
diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
index 75701546b6ea..a479d7e5b7fb 100644
--- a/sound/soc/qcom/sdm845.c
+++ b/sound/soc/qcom/sdm845.c
@@ -15,6 +15,7 @@
#include <uapi/linux/input-event-codes.h>
#include "common.h"
#include "qdsp6/q6afe.h"
+#include "sdw.h"
#include "../codecs/rt5663.h"
#define DRIVER_NAME "sdm845"
@@ -416,7 +417,7 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream)
pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
break;
}
- return 0;
+ return qcom_snd_sdw_startup(substream);
}
static void sdm845_snd_shutdown(struct snd_pcm_substream *substream)
@@ -425,6 +426,7 @@ static void sdm845_snd_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_card *card = rtd->card;
struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
switch (cpu_dai->id) {
case PRIMARY_MI2S_RX:
@@ -463,6 +465,9 @@ static void sdm845_snd_shutdown(struct snd_pcm_substream *substream)
pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
break;
}
+
+ data->sruntime[cpu_dai->id] = NULL;
+ sdw_release_stream(sruntime);
}
static int sdm845_snd_prepare(struct snd_pcm_substream *substream)
diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c
index 274bab28209a..45e0c33fc3f3 100644
--- a/sound/soc/qcom/sm8250.c
+++ b/sound/soc/qcom/sm8250.c
@@ -63,6 +63,14 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream)
snd_soc_dai_set_fmt(cpu_dai, fmt);
snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
break;
+ case SECONDARY_MI2S_RX:
+ codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
+ snd_soc_dai_set_sysclk(cpu_dai,
+ Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
+ MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
+ snd_soc_dai_set_fmt(cpu_dai, fmt);
+ snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
+ break;
case TERTIARY_MI2S_RX:
codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
snd_soc_dai_set_sysclk(cpu_dai,
@@ -78,7 +86,7 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream)
return qcom_snd_sdw_startup(substream);
}
-static void sm2450_snd_shutdown(struct snd_pcm_substream *substream)
+static void sm8250_snd_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
@@ -123,7 +131,7 @@ static int sm8250_snd_hw_free(struct snd_pcm_substream *substream)
static const struct snd_soc_ops sm8250_be_ops = {
.startup = sm8250_snd_startup,
- .shutdown = sm2450_snd_shutdown,
+ .shutdown = sm8250_snd_shutdown,
.hw_params = sm8250_snd_hw_params,
.hw_free = sm8250_snd_hw_free,
.prepare = sm8250_snd_prepare,
@@ -174,6 +182,7 @@ static int sm8250_platform_probe(struct platform_device *pdev)
static const struct of_device_id snd_sm8250_dt_match[] = {
{.compatible = "qcom,sm8250-sndcard"},
+ {.compatible = "qcom,qrb4210-rb2-sndcard"},
{.compatible = "qcom,qrb5165-rb5-sndcard"},
{}
};
diff --git a/sound/soc/qcom/x1e80100.c b/sound/soc/qcom/x1e80100.c
index 898b5c26bf1e..8eb57fc12f0d 100644
--- a/sound/soc/qcom/x1e80100.c
+++ b/sound/soc/qcom/x1e80100.c
@@ -95,23 +95,53 @@ static int x1e80100_snd_hw_params(struct snd_pcm_substream *substream,
return qcom_snd_sdw_hw_params(substream, params, &data->sruntime[cpu_dai->id]);
}
+static int x1e80100_snd_hw_map_channels(unsigned int *ch_map, int num)
+{
+ switch (num) {
+ case 1:
+ ch_map[0] = PCM_CHANNEL_FC;
+ break;
+ case 2:
+ ch_map[0] = PCM_CHANNEL_FL;
+ ch_map[1] = PCM_CHANNEL_FR;
+ break;
+ case 3:
+ ch_map[0] = PCM_CHANNEL_FL;
+ ch_map[1] = PCM_CHANNEL_FR;
+ ch_map[2] = PCM_CHANNEL_FC;
+ break;
+ case 4:
+ ch_map[0] = PCM_CHANNEL_FL;
+ ch_map[1] = PCM_CHANNEL_LB;
+ ch_map[2] = PCM_CHANNEL_FR;
+ ch_map[3] = PCM_CHANNEL_RB;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int x1e80100_snd_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
- const unsigned int rx_slot[4] = { PCM_CHANNEL_FL,
- PCM_CHANNEL_LB,
- PCM_CHANNEL_FR,
- PCM_CHANNEL_RB };
+ unsigned int channels = substream->runtime->channels;
+ unsigned int rx_slot[4];
int ret;
switch (cpu_dai->id) {
case WSA_CODEC_DMA_RX_0:
case WSA_CODEC_DMA_RX_1:
+ ret = x1e80100_snd_hw_map_channels(rx_slot, channels);
+ if (ret)
+ return ret;
+
ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
- ARRAY_SIZE(rx_slot), rx_slot);
+ channels, rx_slot);
if (ret)
return ret;
break;
diff --git a/sound/soc/sh/Kconfig b/sound/soc/renesas/Kconfig
index 426632996a0a..426632996a0a 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/renesas/Kconfig
diff --git a/sound/soc/sh/Makefile b/sound/soc/renesas/Makefile
index f0e19cbd1581..f0e19cbd1581 100644
--- a/sound/soc/sh/Makefile
+++ b/sound/soc/renesas/Makefile
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/renesas/dma-sh7760.c
index c53539482c20..c53539482c20 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/renesas/dma-sh7760.c
diff --git a/sound/soc/sh/fsi.c b/sound/soc/renesas/fsi.c
index 221ce91f1950..221ce91f1950 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/renesas/fsi.c
diff --git a/sound/soc/sh/hac.c b/sound/soc/renesas/hac.c
index db618c09d1e0..db618c09d1e0 100644
--- a/sound/soc/sh/hac.c
+++ b/sound/soc/renesas/hac.c
diff --git a/sound/soc/sh/migor.c b/sound/soc/renesas/migor.c
index 5a0bc6edac0a..5a0bc6edac0a 100644
--- a/sound/soc/sh/migor.c
+++ b/sound/soc/renesas/migor.c
diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/renesas/rcar/Makefile
index 45eb875a912a..45eb875a912a 100644
--- a/sound/soc/sh/rcar/Makefile
+++ b/sound/soc/renesas/rcar/Makefile
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/renesas/rcar/adg.c
index 0f190abf00e7..0f190abf00e7 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/renesas/rcar/adg.c
diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/renesas/rcar/cmd.c
index 8d9a1e345a22..8d9a1e345a22 100644
--- a/sound/soc/sh/rcar/cmd.c
+++ b/sound/soc/renesas/rcar/cmd.c
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/renesas/rcar/core.c
index 9784718a2b6f..e2234928c9e8 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/renesas/rcar/core.c
@@ -1233,6 +1233,19 @@ int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name
return i;
}
+static struct device_node*
+ rsnd_pick_endpoint_node_for_ports(struct device_node *e_ports,
+ struct device_node *e_port)
+{
+ if (of_node_name_eq(e_ports, "ports"))
+ return e_ports;
+
+ if (of_node_name_eq(e_ports, "port"))
+ return e_port;
+
+ return NULL;
+}
+
static int rsnd_dai_of_node(struct rsnd_priv *priv, int *is_graph)
{
struct device *dev = rsnd_priv_to_dev(priv);
@@ -1278,10 +1291,10 @@ audio_graph:
* Audio-Graph-Card
*/
for_each_child_of_node(np, ports) {
- if (!of_node_name_eq(ports, "ports") &&
- !of_node_name_eq(ports, "port"))
+ node = rsnd_pick_endpoint_node_for_ports(ports, np);
+ if (!node)
continue;
- priv->component_dais[i] = of_graph_get_endpoint_count(ports);
+ priv->component_dais[i] = of_graph_get_endpoint_count(node);
nr += priv->component_dais[i];
i++;
if (i >= RSND_MAX_COMPONENT) {
@@ -1486,14 +1499,16 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
*/
dai_i = 0;
if (is_graph) {
+ struct device_node *dai_np_port;
struct device_node *ports;
struct device_node *dai_np;
for_each_child_of_node(np, ports) {
- if (!of_node_name_eq(ports, "ports") &&
- !of_node_name_eq(ports, "port"))
+ dai_np_port = rsnd_pick_endpoint_node_for_ports(ports, np);
+ if (!dai_np_port)
continue;
- for_each_endpoint_of_node(ports, dai_np) {
+
+ for_each_endpoint_of_node(dai_np_port, dai_np) {
__rsnd_dai_probe(priv, dai_np, dai_np, 0, dai_i);
if (!rsnd_is_gen1(priv) && !rsnd_is_gen2(priv)) {
rdai = rsnd_rdai_get(priv, dai_i);
@@ -1828,7 +1843,7 @@ int rsnd_kctrl_new(struct rsnd_mod *mod,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = name,
.info = rsnd_kctrl_info,
- .index = rtd->num,
+ .index = rtd->id,
.get = rsnd_kctrl_get,
.put = rsnd_kctrl_put,
};
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/renesas/rcar/ctu.c
index a26ec7b780cd..a26ec7b780cd 100644
--- a/sound/soc/sh/rcar/ctu.c
+++ b/sound/soc/renesas/rcar/ctu.c
diff --git a/sound/soc/sh/rcar/debugfs.c b/sound/soc/renesas/rcar/debugfs.c
index 26d3b310b9db..26d3b310b9db 100644
--- a/sound/soc/sh/rcar/debugfs.c
+++ b/sound/soc/renesas/rcar/debugfs.c
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/renesas/rcar/dma.c
index 2342bbb6fe92..2342bbb6fe92 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/renesas/rcar/dma.c
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/renesas/rcar/dvc.c
index da91dd301aab..da91dd301aab 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/renesas/rcar/dvc.c
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/renesas/rcar/gen.c
index d1f20cde66be..d1f20cde66be 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/renesas/rcar/gen.c
diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/renesas/rcar/mix.c
index 024d91cc8748..024d91cc8748 100644
--- a/sound/soc/sh/rcar/mix.c
+++ b/sound/soc/renesas/rcar/mix.c
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/renesas/rcar/rsnd.h
index 3c164d8e3b16..3c164d8e3b16 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/renesas/rcar/rsnd.h
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/renesas/rcar/src.c
index e7f86db0d94c..e7f86db0d94c 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/renesas/rcar/src.c
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/renesas/rcar/ssi.c
index b3d4e8ae07ef..b3d4e8ae07ef 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/renesas/rcar/ssi.c
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/renesas/rcar/ssiu.c
index 665e8b2db579..665e8b2db579 100644
--- a/sound/soc/sh/rcar/ssiu.c
+++ b/sound/soc/renesas/rcar/ssiu.c
diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/renesas/rz-ssi.c
index 040ce0431fd2..6efd017aaa7f 100644
--- a/sound/soc/sh/rz-ssi.c
+++ b/sound/soc/renesas/rz-ssi.c
@@ -311,8 +311,7 @@ static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate,
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));
+ rz_ssi_reg_writel(ssi, SSIFCR, SSIFCR_AUCKE | SSIFCR_FIFO_RST);
return 0;
}
@@ -343,8 +342,7 @@ static void rz_ssi_set_idle(struct rz_ssi_priv *ssi)
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);
+ rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_FIFO_RST);
}
static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/renesas/sh7760-ac97.c
index d267243a159b..d267243a159b 100644
--- a/sound/soc/sh/sh7760-ac97.c
+++ b/sound/soc/renesas/sh7760-ac97.c
diff --git a/sound/soc/sh/siu.h b/sound/soc/renesas/siu.h
index a675c36fc9d9..a675c36fc9d9 100644
--- a/sound/soc/sh/siu.h
+++ b/sound/soc/renesas/siu.h
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/renesas/siu_dai.c
index 7e771a164a80..7e771a164a80 100644
--- a/sound/soc/sh/siu_dai.c
+++ b/sound/soc/renesas/siu_dai.c
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/renesas/siu_pcm.c
index f15ff36e7934..f15ff36e7934 100644
--- a/sound/soc/sh/siu_pcm.c
+++ b/sound/soc/renesas/siu_pcm.c
diff --git a/sound/soc/sh/ssi.c b/sound/soc/renesas/ssi.c
index 96cf523c2273..96cf523c2273 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/renesas/ssi.c
diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c
index ed865cc07e2e..40ac12c07145 100644
--- a/sound/soc/samsung/odroid.c
+++ b/sound/soc/samsung/odroid.c
@@ -171,25 +171,24 @@ static struct snd_soc_dai_link odroid_card_dais[] = {
.name = "Primary",
.stream_name = "Primary",
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(primary),
}, {
/* BE <-> CODECs link */
.name = "I2S Mixer",
.ops = &odroid_card_be_ops,
.no_pcm = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
SND_SOC_DAILINK_REG(mixer),
}, {
/* Secondary FE <-> BE link */
- .playback_only = 1,
.ops = &odroid_card_fe_ops,
.name = "Secondary",
.stream_name = "Secondary",
.dynamic = 1,
- .dpcm_playback = 1,
+ .playback_only = 1,
SND_SOC_DAILINK_REG(secondary),
}
};
@@ -278,8 +277,8 @@ static int odroid_audio_probe(struct platform_device *pdev)
/* Set capture capability only for boards with the MAX98090 CODEC */
if (codec_link->num_codecs > 1) {
- card->dai_link[0].dpcm_capture = 1;
- card->dai_link[1].dpcm_capture = 1;
+ card->dai_link[0].playback_only = 0;
+ card->dai_link[1].playback_only = 0;
}
priv->sclk_i2s = of_clk_get_by_name(cpu_dai, "i2s_opclk1");
diff --git a/sound/soc/sdca/Kconfig b/sound/soc/sdca/Kconfig
new file mode 100644
index 000000000000..ee20b9914aa1
--- /dev/null
+++ b/sound/soc/sdca/Kconfig
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config SND_SOC_SDCA
+ tristate
+ depends on ACPI
+ help
+ This option enables support for the MIPI SoundWire Device
+ Class for Audio (SDCA).
+
+config SND_SOC_SDCA_OPTIONAL
+ def_tristate SND_SOC_SDCA || !SND_SOC_SDCA
diff --git a/sound/soc/sdca/Makefile b/sound/soc/sdca/Makefile
new file mode 100644
index 000000000000..c296bd5a0a7c
--- /dev/null
+++ b/sound/soc/sdca/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+snd-soc-sdca-objs := sdca_functions.o sdca_device.o
+
+obj-$(CONFIG_SND_SOC_SDCA) += snd-soc-sdca.o
diff --git a/sound/soc/sdca/sdca_device.c b/sound/soc/sdca/sdca_device.c
new file mode 100644
index 000000000000..c44dc21cb634
--- /dev/null
+++ b/sound/soc/sdca/sdca_device.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2024 Intel Corporation
+
+/*
+ * The MIPI SDCA specification is available for public downloads at
+ * https://www.mipi.org/mipi-sdca-v1-0-download
+ */
+
+#include <linux/acpi.h>
+#include <linux/soundwire/sdw.h>
+#include <sound/sdca.h>
+#include <sound/sdca_function.h>
+
+void sdca_lookup_interface_revision(struct sdw_slave *slave)
+{
+ struct fwnode_handle *fwnode = slave->dev.fwnode;
+
+ /*
+ * if this property is not present, then the sdca_interface_revision will
+ * remain zero, which will be considered as 'not defined' or 'invalid'.
+ */
+ fwnode_property_read_u32(fwnode, "mipi-sdw-sdca-interface-revision",
+ &slave->sdca_data.interface_revision);
+}
+EXPORT_SYMBOL_NS(sdca_lookup_interface_revision, SND_SOC_SDCA);
+
+static bool sdca_device_quirk_rt712_vb(struct sdw_slave *slave)
+{
+ struct sdw_slave_id *id = &slave->id;
+ int i;
+
+ /*
+ * The RT712_VA relies on the v06r04 draft, and the
+ * RT712_VB on a more recent v08r01 draft.
+ */
+ if (slave->sdca_data.interface_revision < 0x0801)
+ return false;
+
+ if (id->mfg_id != 0x025d)
+ return false;
+
+ if (id->part_id != 0x712 &&
+ id->part_id != 0x713 &&
+ id->part_id != 0x716 &&
+ id->part_id != 0x717)
+ return false;
+
+ for (i = 0; i < slave->sdca_data.num_functions; i++) {
+ if (slave->sdca_data.sdca_func[i].type ==
+ SDCA_FUNCTION_TYPE_SMART_MIC)
+ return true;
+ }
+
+ return false;
+}
+
+bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk)
+{
+ switch (quirk) {
+ case SDCA_QUIRKS_RT712_VB:
+ return sdca_device_quirk_rt712_vb(slave);
+ default:
+ break;
+ }
+ return false;
+}
+EXPORT_SYMBOL_NS(sdca_device_quirk_match, SND_SOC_SDCA);
diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c
new file mode 100644
index 000000000000..e6e5629c7054
--- /dev/null
+++ b/sound/soc/sdca/sdca_functions.c
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2024 Intel Corporation
+
+/*
+ * The MIPI SDCA specification is available for public downloads at
+ * https://www.mipi.org/mipi-sdca-v1-0-download
+ */
+
+#include <linux/acpi.h>
+#include <linux/soundwire/sdw.h>
+#include <sound/sdca.h>
+#include <sound/sdca_function.h>
+
+static int patch_sdca_function_type(struct device *dev,
+ u32 interface_revision,
+ u32 *function_type,
+ const char **function_name)
+{
+ unsigned long function_type_patch = 0;
+
+ /*
+ * Unfortunately early SDCA specifications used different indices for Functions,
+ * for backwards compatibility we have to reorder the values found
+ */
+ if (interface_revision >= 0x0801)
+ goto skip_early_draft_order;
+
+ switch (*function_type) {
+ case 1:
+ function_type_patch = SDCA_FUNCTION_TYPE_SMART_AMP;
+ break;
+ case 2:
+ function_type_patch = SDCA_FUNCTION_TYPE_SMART_MIC;
+ break;
+ case 3:
+ function_type_patch = SDCA_FUNCTION_TYPE_SPEAKER_MIC;
+ break;
+ case 4:
+ function_type_patch = SDCA_FUNCTION_TYPE_UAJ;
+ break;
+ case 5:
+ function_type_patch = SDCA_FUNCTION_TYPE_RJ;
+ break;
+ case 6:
+ function_type_patch = SDCA_FUNCTION_TYPE_HID;
+ break;
+ default:
+ dev_warn(dev, "%s: SDCA version %#x unsupported function type %d, skipped\n",
+ __func__, interface_revision, *function_type);
+ return -EINVAL;
+ }
+
+skip_early_draft_order:
+ if (function_type_patch)
+ *function_type = function_type_patch;
+
+ /* now double-check the values */
+ switch (*function_type) {
+ case SDCA_FUNCTION_TYPE_SMART_AMP:
+ *function_name = SDCA_FUNCTION_TYPE_SMART_AMP_NAME;
+ break;
+ case SDCA_FUNCTION_TYPE_SMART_MIC:
+ *function_name = SDCA_FUNCTION_TYPE_SMART_MIC_NAME;
+ break;
+ case SDCA_FUNCTION_TYPE_UAJ:
+ *function_name = SDCA_FUNCTION_TYPE_UAJ_NAME;
+ break;
+ case SDCA_FUNCTION_TYPE_HID:
+ *function_name = SDCA_FUNCTION_TYPE_HID_NAME;
+ break;
+ case SDCA_FUNCTION_TYPE_SIMPLE_AMP:
+ case SDCA_FUNCTION_TYPE_SIMPLE_MIC:
+ case SDCA_FUNCTION_TYPE_SPEAKER_MIC:
+ case SDCA_FUNCTION_TYPE_RJ:
+ case SDCA_FUNCTION_TYPE_IMP_DEF:
+ dev_warn(dev, "%s: found unsupported SDCA function type %d, skipped\n",
+ __func__, *function_type);
+ return -EINVAL;
+ default:
+ dev_err(dev, "%s: found invalid SDCA function type %d, skipped\n",
+ __func__, *function_type);
+ return -EINVAL;
+ }
+
+ dev_info(dev, "%s: found SDCA function %s (type %d)\n",
+ __func__, *function_name, *function_type);
+
+ return 0;
+}
+
+static int find_sdca_function(struct acpi_device *adev, void *data)
+{
+ struct fwnode_handle *function_node = acpi_fwnode_handle(adev);
+ struct sdca_device_data *sdca_data = data;
+ struct device *dev = &adev->dev;
+ struct fwnode_handle *control5; /* used to identify function type */
+ const char *function_name;
+ u32 function_type;
+ int func_index;
+ u64 addr;
+ int ret;
+
+ if (sdca_data->num_functions >= SDCA_MAX_FUNCTION_COUNT) {
+ dev_err(dev, "%s: maximum number of functions exceeded\n", __func__);
+ return -EINVAL;
+ }
+
+ /*
+ * The number of functions cannot exceed 8, we could use
+ * acpi_get_local_address() but the value is stored as u64 so
+ * we might as well avoid casts and intermediate levels
+ */
+ ret = acpi_get_local_u64_address(adev->handle, &addr);
+ if (ret < 0)
+ return ret;
+
+ if (!addr) {
+ dev_err(dev, "%s: no addr\n", __func__);
+ return -ENODEV;
+ }
+
+ /*
+ * Extracting the topology type for an SDCA function is a
+ * convoluted process.
+ * The Function type is only visible as a result of a read
+ * from a control. In theory this would mean reading from the hardware,
+ * but the SDCA/DisCo specs defined the notion of "DC value" - a constant
+ * represented with a DSD subproperty.
+ * Drivers have to query the properties for the control
+ * SDCA_CONTROL_ENTITY_0_FUNCTION_TOPOLOGY (0x05)
+ */
+ control5 = fwnode_get_named_child_node(function_node,
+ "mipi-sdca-control-0x5-subproperties");
+ if (!control5)
+ return -ENODEV;
+
+ ret = fwnode_property_read_u32(control5, "mipi-sdca-control-dc-value",
+ &function_type);
+
+ fwnode_handle_put(control5);
+
+ if (ret < 0) {
+ dev_err(dev, "%s: the function type can only be determined from ACPI information\n",
+ __func__);
+ return ret;
+ }
+
+ ret = patch_sdca_function_type(dev, sdca_data->interface_revision,
+ &function_type, &function_name);
+ if (ret < 0)
+ return ret;
+
+ /* store results */
+ func_index = sdca_data->num_functions;
+ sdca_data->sdca_func[func_index].adr = addr;
+ sdca_data->sdca_func[func_index].type = function_type;
+ sdca_data->sdca_func[func_index].name = function_name;
+ sdca_data->num_functions++;
+
+ return 0;
+}
+
+void sdca_lookup_functions(struct sdw_slave *slave)
+{
+ struct device *dev = &slave->dev;
+ struct acpi_device *adev = to_acpi_device_node(dev->fwnode);
+
+ if (!adev) {
+ dev_info(dev, "No matching ACPI device found, ignoring peripheral\n");
+ return;
+ }
+ acpi_dev_for_each_child(adev, find_sdca_function, &slave->sdca_data);
+}
+EXPORT_SYMBOL_NS(sdca_lookup_functions, SND_SOC_SDCA);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("SDCA library");
diff --git a/sound/soc/sdw_utils/Makefile b/sound/soc/sdw_utils/Makefile
index 28229ed96ffb..daf019113553 100644
--- a/sound/soc/sdw_utils/Makefile
+++ b/sound/soc/sdw_utils/Makefile
@@ -1,9 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-only
snd-soc-sdw-utils-y := soc_sdw_utils.o soc_sdw_dmic.o soc_sdw_rt_dmic.o \
soc_sdw_rt700.o soc_sdw_rt711.o \
- soc_sdw_rt712_sdca.o soc_sdw_rt722_sdca.o \
soc_sdw_rt5682.o soc_sdw_rt_sdca_jack_common.o \
- soc_sdw_rt_amp.o \
+ soc_sdw_rt_amp.o soc_sdw_rt_mf_sdca.o \
soc_sdw_bridge_cs35l56.o \
soc_sdw_cs42l42.o soc_sdw_cs42l43.o \
soc_sdw_cs_amp.o \
diff --git a/sound/soc/sdw_utils/soc_sdw_rt712_sdca.c b/sound/soc/sdw_utils/soc_sdw_rt712_sdca.c
deleted file mode 100644
index 5127210b9a03..000000000000
--- a/sound/soc/sdw_utils/soc_sdw_rt712_sdca.c
+++ /dev/null
@@ -1,48 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-// This file incorporates work covered by the following copyright notice:
-// Copyright (c) 2023 Intel Corporation
-// Copyright (c) 2024 Advanced Micro Devices, Inc.
-
-/*
- * soc_sdw_rt712_sdca - Helpers to handle RT712-SDCA from generic machine driver
- */
-
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/soundwire/sdw.h>
-#include <linux/soundwire/sdw_type.h>
-#include <sound/control.h>
-#include <sound/soc.h>
-#include <sound/soc-acpi.h>
-#include <sound/soc-dapm.h>
-#include <sound/soc_sdw_utils.h>
-
-/*
- * dapm routes for rt712 spk will be registered dynamically according
- * to the number of rt712 spk used. The first two entries will be registered
- * for one codec case, and the last two entries are also registered
- * if two rt712s are used.
- */
-static const struct snd_soc_dapm_route rt712_spk_map[] = {
- { "Speaker", NULL, "rt712 SPOL" },
- { "Speaker", NULL, "rt712 SPOR" },
-};
-
-int asoc_sdw_rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
-{
- struct snd_soc_card *card = rtd->card;
- int ret;
-
- card->components = devm_kasprintf(card->dev, GFP_KERNEL,
- "%s spk:rt712",
- card->components);
- if (!card->components)
- return -ENOMEM;
-
- ret = snd_soc_dapm_add_routes(&card->dapm, rt712_spk_map, ARRAY_SIZE(rt712_spk_map));
- if (ret)
- dev_err(rtd->dev, "failed to add SPK map: %d\n", ret);
-
- return ret;
-}
-EXPORT_SYMBOL_NS(asoc_sdw_rt712_spk_rtd_init, SND_SOC_SDW_UTILS);
diff --git a/sound/soc/sdw_utils/soc_sdw_rt722_sdca.c b/sound/soc/sdw_utils/soc_sdw_rt722_sdca.c
deleted file mode 100644
index 6a402172289f..000000000000
--- a/sound/soc/sdw_utils/soc_sdw_rt722_sdca.c
+++ /dev/null
@@ -1,41 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-// This file incorporates work covered by the following copyright notice:
-// Copyright (c) 2023 Intel Corporation
-// Copyright (c) 2024 Advanced Micro Devices, Inc.
-
-/*
- * soc_sdw_rt722_sdca - Helpers to handle RT722-SDCA from generic machine driver
- */
-
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/soundwire/sdw.h>
-#include <linux/soundwire/sdw_type.h>
-#include <sound/control.h>
-#include <sound/soc.h>
-#include <sound/soc-acpi.h>
-#include <sound/soc-dapm.h>
-#include <sound/soc_sdw_utils.h>
-
-static const struct snd_soc_dapm_route rt722_spk_map[] = {
- { "Speaker", NULL, "rt722 SPK" },
-};
-
-int asoc_sdw_rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
-{
- struct snd_soc_card *card = rtd->card;
- int ret;
-
- card->components = devm_kasprintf(card->dev, GFP_KERNEL,
- "%s spk:rt722",
- card->components);
- if (!card->components)
- return -ENOMEM;
-
- ret = snd_soc_dapm_add_routes(&card->dapm, rt722_spk_map, ARRAY_SIZE(rt722_spk_map));
- if (ret)
- dev_err(rtd->dev, "failed to add rt722 spk map: %d\n", ret);
-
- return ret;
-}
-EXPORT_SYMBOL_NS(asoc_sdw_rt722_spk_rtd_init, SND_SOC_SDW_UTILS);
diff --git a/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c b/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c
new file mode 100644
index 000000000000..81e43319876e
--- /dev/null
+++ b/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// This file incorporates work covered by the following copyright notice:
+// Copyright (c) 2024 Intel Corporation.
+
+/*
+ * soc_sdw_rt_mf_sdca
+ * - Helpers to handle RT Multifunction Codec from generic machine driver
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_type.h>
+#include <sound/control.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+#include <sound/soc-dapm.h>
+#include <sound/soc_sdw_utils.h>
+
+#define CODEC_NAME_SIZE 6
+
+/* dapm routes for RT-SPK will be registered dynamically */
+static const struct snd_soc_dapm_route rt712_spk_map[] = {
+ { "Speaker", NULL, "rt712 SPOL" },
+ { "Speaker", NULL, "rt712 SPOR" },
+};
+
+static const struct snd_soc_dapm_route rt721_spk_map[] = {
+ { "Speaker", NULL, "rt721 SPK" },
+};
+
+static const struct snd_soc_dapm_route rt722_spk_map[] = {
+ { "Speaker", NULL, "rt722 SPK" },
+};
+
+/* Structure to map codec names to respective route arrays and sizes */
+struct codec_route_map {
+ const char *codec_name;
+ const struct snd_soc_dapm_route *route_map;
+ size_t route_size;
+};
+
+/* Codec route maps array */
+static const struct codec_route_map codec_routes[] = {
+ { "rt712", rt712_spk_map, ARRAY_SIZE(rt712_spk_map) },
+ { "rt721", rt721_spk_map, ARRAY_SIZE(rt721_spk_map) },
+ { "rt722", rt722_spk_map, ARRAY_SIZE(rt722_spk_map) },
+};
+
+static const struct codec_route_map *get_codec_route_map(const char *codec_name)
+{
+ for (size_t i = 0; i < ARRAY_SIZE(codec_routes); i++) {
+ if (strcmp(codec_routes[i].codec_name, codec_name) == 0)
+ return &codec_routes[i];
+ }
+ return NULL;
+}
+
+int asoc_sdw_rt_mf_sdca_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = rtd->card;
+ char codec_name[CODEC_NAME_SIZE];
+ int ret;
+
+ /* acquire codec name */
+ snprintf(codec_name, CODEC_NAME_SIZE, "%s", dai->name);
+
+ /* acquire corresponding route map and size */
+ const struct codec_route_map *route_map = get_codec_route_map(codec_name);
+
+ if (!route_map) {
+ dev_err(rtd->dev, "failed to get codec name and route map\n");
+ return -EINVAL;
+ }
+
+ /* Update card components */
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+ "%s spk:%s",
+ card->components, codec_name);
+ if (!card->components)
+ return -ENOMEM;
+
+ /* Add routes */
+ ret = snd_soc_dapm_add_routes(&card->dapm, route_map->route_map, route_map->route_size);
+ if (ret)
+ dev_err(rtd->dev, "failed to add rt sdca spk map: %d\n", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_rt_mf_sdca_spk_rtd_init, SND_SOC_SDW_UTILS);
diff --git a/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c b/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c
index 3e6211dc1599..af43efbb8f79 100644
--- a/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c
+++ b/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c
@@ -60,6 +60,11 @@ static const struct snd_soc_dapm_route rt713_sdca_map[] = {
{ "rt713 MIC2", NULL, "Headset Mic" },
};
+static const struct snd_soc_dapm_route rt721_sdca_map[] = {
+ { "Headphone", NULL, "rt721 HP" },
+ { "rt721 MIC2", NULL, "Headset Mic" },
+};
+
static const struct snd_soc_dapm_route rt722_sdca_map[] = {
{ "Headphone", NULL, "rt722 HP" },
{ "rt722 MIC2", NULL, "Headset Mic" },
@@ -121,6 +126,9 @@ int asoc_sdw_rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_s
} else if (strstr(component->name_prefix, "rt713")) {
ret = snd_soc_dapm_add_routes(&card->dapm, rt713_sdca_map,
ARRAY_SIZE(rt713_sdca_map));
+ } else if (strstr(component->name_prefix, "rt721")) {
+ ret = snd_soc_dapm_add_routes(&card->dapm, rt721_sdca_map,
+ ARRAY_SIZE(rt721_sdca_map));
} else if (strstr(component->name_prefix, "rt722")) {
ret = snd_soc_dapm_add_routes(&card->dapm, rt722_sdca_map,
ARRAY_SIZE(rt722_sdca_map));
diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index a6070f822eb9..19bd02e2cd6d 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -138,14 +138,21 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
.init = asoc_sdw_rt_amp_init,
.exit = asoc_sdw_rt_amp_exit,
- .rtd_init = asoc_sdw_rt712_spk_rtd_init,
+ .rtd_init = asoc_sdw_rt_mf_sdca_spk_rtd_init,
.controls = generic_spk_controls,
.num_controls = ARRAY_SIZE(generic_spk_controls),
.widgets = generic_spk_widgets,
.num_widgets = ARRAY_SIZE(generic_spk_widgets),
},
+ {
+ .direction = {false, true},
+ .dai_name = "rt712-sdca-aif3",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_rt_dmic_rtd_init,
+ },
},
- .dai_num = 2,
+ .dai_num = 3,
},
{
.part_id = 0x1712,
@@ -178,8 +185,15 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.widgets = generic_jack_widgets,
.num_widgets = ARRAY_SIZE(generic_jack_widgets),
},
+ {
+ .direction = {false, true},
+ .dai_name = "rt712-sdca-aif3",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_rt_dmic_rtd_init,
+ },
},
- .dai_num = 1,
+ .dai_num = 2,
},
{
.part_id = 0x1713,
@@ -334,6 +348,47 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
{
+ .part_id = 0x721,
+ .version_id = 3,
+ .dais = {
+ {
+ .direction = {true, true},
+ .dai_name = "rt721-sdca-aif1",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
+ .init = asoc_sdw_rt_sdca_jack_init,
+ .exit = asoc_sdw_rt_sdca_jack_exit,
+ .rtd_init = asoc_sdw_rt_sdca_jack_rtd_init,
+ .controls = generic_jack_controls,
+ .num_controls = ARRAY_SIZE(generic_jack_controls),
+ .widgets = generic_jack_widgets,
+ .num_widgets = ARRAY_SIZE(generic_jack_widgets),
+ },
+ {
+ .direction = {true, false},
+ .dai_name = "rt721-sdca-aif2",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ /* No feedback capability is provided by rt721-sdca codec driver*/
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .init = asoc_sdw_rt_amp_init,
+ .exit = asoc_sdw_rt_amp_exit,
+ .rtd_init = asoc_sdw_rt_mf_sdca_spk_rtd_init,
+ .controls = generic_spk_controls,
+ .num_controls = ARRAY_SIZE(generic_spk_controls),
+ .widgets = generic_spk_widgets,
+ .num_widgets = ARRAY_SIZE(generic_spk_widgets),
+ },
+ {
+ .direction = {false, true},
+ .dai_name = "rt721-sdca-aif3",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_rt_dmic_rtd_init,
+ },
+ },
+ .dai_num = 3,
+ },
+ {
.part_id = 0x722,
.version_id = 3,
.dais = {
@@ -358,11 +413,13 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
.init = asoc_sdw_rt_amp_init,
.exit = asoc_sdw_rt_amp_exit,
- .rtd_init = asoc_sdw_rt722_spk_rtd_init,
+ .rtd_init = asoc_sdw_rt_mf_sdca_spk_rtd_init,
.controls = generic_spk_controls,
.num_controls = ARRAY_SIZE(generic_spk_controls),
.widgets = generic_spk_widgets,
.num_widgets = ARRAY_SIZE(generic_spk_widgets),
+ .quirk = SOC_SDW_CODEC_SPKR,
+ .quirk_exclude = true,
},
{
.direction = {false, true},
@@ -487,6 +544,8 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.rtd_init = asoc_sdw_cs42l43_dmic_rtd_init,
.widgets = generic_dmic_widgets,
.num_widgets = ARRAY_SIZE(generic_dmic_widgets),
+ .quirk = SOC_SDW_CODEC_MIC,
+ .quirk_exclude = true,
},
{
.direction = {false, true},
@@ -956,15 +1015,17 @@ void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_lin
struct snd_soc_dai_link_component *cpus, int cpus_num,
struct snd_soc_dai_link_component *platform_component,
int num_platforms, struct snd_soc_dai_link_component *codecs,
- int codecs_num, int (*init)(struct snd_soc_pcm_runtime *rtd),
+ int codecs_num, int no_pcm,
+ int (*init)(struct snd_soc_pcm_runtime *rtd),
const struct snd_soc_ops *ops)
{
dev_dbg(dev, "create dai link %s, id %d\n", name, *be_id);
dai_links->id = (*be_id)++;
dai_links->name = name;
+ dai_links->stream_name = name;
dai_links->platforms = platform_component;
dai_links->num_platforms = num_platforms;
- dai_links->no_pcm = 1;
+ dai_links->no_pcm = no_pcm;
dai_links->cpus = cpus;
dai_links->num_cpus = cpus_num;
dai_links->codecs = codecs;
@@ -980,7 +1041,7 @@ int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *d
int *be_id, char *name, int playback, int capture,
const char *cpu_dai_name, const char *platform_comp_name,
int num_platforms, const char *codec_name,
- const char *codec_dai_name,
+ const char *codec_dai_name, int no_pcm,
int (*init)(struct snd_soc_pcm_runtime *rtd),
const struct snd_soc_ops *ops)
{
@@ -999,7 +1060,7 @@ int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *d
asoc_sdw_init_dai_link(dev, dai_links, be_id, name, playback, capture,
&dlc[0], 1, &dlc[1], num_platforms,
- &dlc[2], 1, init, ops);
+ &dlc[2], 1, no_pcm, init, ops);
return 0;
}
@@ -1112,7 +1173,8 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
dai_info = &codec_info->dais[adr_end->num];
soc_dai = asoc_sdw_find_dailink(soc_dais, adr_end);
- if (dai_info->quirk && !(dai_info->quirk & ctx->mc_quirk))
+ if (dai_info->quirk &&
+ !(dai_info->quirk_exclude ^ !!(dai_info->quirk & ctx->mc_quirk)))
continue;
dev_dbg(dev,
diff --git a/sound/soc/soc-acpi.c b/sound/soc/soc-acpi.c
index 6d693b2ad5a3..270f9777942f 100644
--- a/sound/soc/soc-acpi.c
+++ b/sound/soc/soc-acpi.c
@@ -131,8 +131,7 @@ EXPORT_SYMBOL_GPL(snd_soc_acpi_codec_list);
/* Check if all Slaves defined on the link can be found */
bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev,
const struct snd_soc_acpi_link_adr *link,
- struct sdw_extended_slave_id *ids,
- int num_slaves)
+ struct sdw_peripherals *peripherals)
{
unsigned int part_id, link_id, unique_id, mfg_id, version;
int i, j, k;
@@ -146,22 +145,25 @@ bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev,
link_id = SDW_DISCO_LINK_ID(adr);
version = SDW_VERSION(adr);
- for (j = 0; j < num_slaves; j++) {
+ for (j = 0; j < peripherals->num_peripherals; j++) {
+ struct sdw_slave *peripheral = peripherals->array[j];
+
/* find out how many identical parts were reported on that link */
- if (ids[j].link_id == link_id &&
- ids[j].id.part_id == part_id &&
- ids[j].id.mfg_id == mfg_id &&
- ids[j].id.sdw_version == version)
+ if (peripheral->bus->link_id == link_id &&
+ peripheral->id.part_id == part_id &&
+ peripheral->id.mfg_id == mfg_id &&
+ peripheral->id.sdw_version == version)
reported_part_count++;
}
- for (j = 0; j < num_slaves; j++) {
+ for (j = 0; j < peripherals->num_peripherals; j++) {
+ struct sdw_slave *peripheral = peripherals->array[j];
int expected_part_count = 0;
- if (ids[j].link_id != link_id ||
- ids[j].id.part_id != part_id ||
- ids[j].id.mfg_id != mfg_id ||
- ids[j].id.sdw_version != version)
+ if (peripheral->bus->link_id != link_id ||
+ peripheral->id.part_id != part_id ||
+ peripheral->id.mfg_id != mfg_id ||
+ peripheral->id.sdw_version != version)
continue;
/* find out how many identical parts are expected */
@@ -180,7 +182,7 @@ bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev,
*/
unique_id = SDW_UNIQUE_ID(adr);
if (reported_part_count == 1 ||
- ids[j].id.unique_id == unique_id) {
+ peripheral->id.unique_id == unique_id) {
dev_dbg(dev, "found part_id %#x at link %d\n", part_id, link_id);
break;
}
@@ -189,7 +191,7 @@ bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev,
part_id, reported_part_count, expected_part_count, link_id);
}
}
- if (j == num_slaves) {
+ if (j == peripherals->num_peripherals) {
dev_dbg(dev, "Slave part_id %#x not found\n", part_id);
return false;
}
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index b3d7bb91e294..b67ef78f405c 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -58,7 +58,7 @@ static inline int soc_component_field_shift(struct snd_soc_component *component,
* In such case, we can update these macros.
*/
#define soc_component_mark_push(component, substream, tgt) ((component)->mark_##tgt = substream)
-#define soc_component_mark_pop(component, substream, tgt) ((component)->mark_##tgt = NULL)
+#define soc_component_mark_pop(component, tgt) ((component)->mark_##tgt = NULL)
#define soc_component_mark_match(component, substream, tgt) ((component)->mark_##tgt == substream)
void snd_soc_component_set_aux(struct snd_soc_component *component,
@@ -339,7 +339,7 @@ void snd_soc_component_module_put(struct snd_soc_component *component,
module_put(component->dev->driver->owner);
/* remove the mark from module */
- soc_component_mark_pop(component, mark, module);
+ soc_component_mark_pop(component, module);
}
int snd_soc_component_open(struct snd_soc_component *component,
@@ -370,7 +370,7 @@ int snd_soc_component_close(struct snd_soc_component *component,
ret = component->driver->close(component, substream);
/* remove marked substream */
- soc_component_mark_pop(component, substream, open);
+ soc_component_mark_pop(component, open);
return soc_component_ret(component, ret);
}
@@ -515,7 +515,7 @@ void snd_soc_component_compr_free(struct snd_soc_component *component,
component->driver->compress_ops->free(component, cstream);
/* remove marked substream */
- soc_component_mark_pop(component, cstream, compr_open);
+ soc_component_mark_pop(component, compr_open);
}
EXPORT_SYMBOL_GPL(snd_soc_component_compr_free);
@@ -1210,7 +1210,7 @@ void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream,
}
/* remove marked substream */
- soc_component_mark_pop(component, substream, hw_params);
+ soc_component_mark_pop(component, hw_params);
}
}
@@ -1254,7 +1254,7 @@ int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream,
r = soc_component_trigger(component, substream, cmd);
if (r < 0)
ret = r; /* use last ret */
- soc_component_mark_pop(component, substream, trigger);
+ soc_component_mark_pop(component, trigger);
}
}
@@ -1294,7 +1294,7 @@ void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
pm_runtime_put_autosuspend(component->dev);
/* remove marked stream */
- soc_component_mark_pop(component, stream, pm);
+ soc_component_mark_pop(component, pm);
}
}
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index e692aa3b8b22..563dc0767c17 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -69,10 +69,10 @@ static int soc_compr_clean(struct snd_compr_stream *cstream, int rollback)
snd_soc_dai_digital_mute(codec_dai, 1, stream);
if (!snd_soc_dai_active(cpu_dai))
- cpu_dai->rate = 0;
+ cpu_dai->symmetric_rate = 0;
if (!snd_soc_dai_active(codec_dai))
- codec_dai->rate = 0;
+ codec_dai->symmetric_rate = 0;
snd_soc_link_compr_shutdown(cstream, rollback);
@@ -537,11 +537,10 @@ static struct snd_compr_ops soc_compr_dyn_ops = {
* snd_soc_new_compress - create a new compress.
*
* @rtd: The runtime for which we will create compress
- * @num: the device index number (zero based - shared with normal PCMs)
*
* Return: 0 for success, else error.
*/
-int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
+int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *component;
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
@@ -606,12 +605,19 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
return -ENOMEM;
if (rtd->dai_link->dynamic) {
+ int playback = 1;
+ int capture = 1;
+
+ if (rtd->dai_link->capture_only)
+ playback = 0;
+ if (rtd->dai_link->playback_only)
+ capture = 0;
+
snprintf(new_name, sizeof(new_name), "(%s)",
rtd->dai_link->stream_name);
- ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
- rtd->dai_link->dpcm_playback,
- rtd->dai_link->dpcm_capture, &be_pcm);
+ ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, rtd->id,
+ playback, capture, &be_pcm);
if (ret < 0) {
dev_err(rtd->card->dev,
"Compress ASoC: can't create compressed for %s: %d\n",
@@ -624,14 +630,14 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
rtd->pcm = be_pcm;
rtd->fe_compr = 1;
- if (rtd->dai_link->dpcm_playback)
+ if (playback)
be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
- if (rtd->dai_link->dpcm_capture)
+ if (capture)
be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
} else {
snprintf(new_name, sizeof(new_name), "%s %s-%d",
- rtd->dai_link->stream_name, codec_dai->name, num);
+ rtd->dai_link->stream_name, codec_dai->name, rtd->id);
memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
}
@@ -645,7 +651,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
break;
}
- ret = snd_compress_new(rtd->card->snd_card, num, direction,
+ ret = snd_compress_new(rtd->card->snd_card, rtd->id, direction,
new_name, compr);
if (ret < 0) {
component = snd_soc_rtd_to_codec(rtd, 0)->component;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 20248a29d167..a1dace4bb616 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -558,7 +558,7 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
*/
rtd->card = card;
rtd->dai_link = dai_link;
- rtd->num = card->num_rtd++;
+ rtd->id = card->num_rtd++;
rtd->pmdown_time = pmdown_time; /* default power off timeout */
/* see for_each_card_rtds */
@@ -1166,7 +1166,7 @@ static int snd_soc_add_pcm_runtime(struct snd_soc_card *card,
struct snd_soc_pcm_runtime *rtd;
struct snd_soc_dai_link_component *codec, *platform, *cpu;
struct snd_soc_component *component;
- int i, ret;
+ int i, id, ret;
lockdep_assert_held(&client_mutex);
@@ -1225,6 +1225,28 @@ static int snd_soc_add_pcm_runtime(struct snd_soc_card *card,
}
}
+ /*
+ * Most drivers will register their PCMs using DAI link ordering but
+ * topology based drivers can use the DAI link id field to set PCM
+ * device number and then use rtd + a base offset of the BEs.
+ *
+ * FIXME
+ *
+ * This should be implemented by using "dai_link" feature instead of
+ * "component" feature.
+ */
+ id = rtd->id;
+ for_each_rtd_components(rtd, i, component) {
+ if (!component->driver->use_dai_pcm_id)
+ continue;
+
+ if (rtd->dai_link->no_pcm)
+ id += component->driver->be_pcm_base;
+ else
+ id = rtd->dai_link->id;
+ }
+ rtd->id = id;
+
return 0;
_err_defer:
@@ -1457,8 +1479,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card,
{
struct snd_soc_dai_link *dai_link = rtd->dai_link;
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct snd_soc_component *component;
- int ret, num, i;
+ int ret;
/* do machine specific initialization */
ret = snd_soc_link_init(rtd);
@@ -1473,30 +1494,13 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card,
/* add DPCM sysfs entries */
soc_dpcm_debugfs_add(rtd);
- num = rtd->num;
-
- /*
- * most drivers will register their PCMs using DAI link ordering but
- * topology based drivers can use the DAI link id field to set PCM
- * device number and then use rtd + a base offset of the BEs.
- */
- for_each_rtd_components(rtd, i, component) {
- if (!component->driver->use_dai_pcm_id)
- continue;
-
- if (rtd->dai_link->no_pcm)
- num += component->driver->be_pcm_base;
- else
- num = rtd->dai_link->id;
- }
-
/* create compress_device if possible */
- ret = snd_soc_dai_compress_new(cpu_dai, rtd, num);
+ ret = snd_soc_dai_compress_new(cpu_dai, rtd);
if (ret != -ENOTSUPP)
goto err;
/* create the pcm */
- ret = soc_new_pcm(rtd, num);
+ ret = soc_new_pcm(rtd);
if (ret < 0) {
dev_err(card->dev, "ASoC: can't create pcm %s :%d\n",
dai_link->stream_name, ret);
@@ -1999,25 +2003,7 @@ match:
dai_link->platforms->name = component->name;
/* convert non BE into BE */
- if (!dai_link->no_pcm) {
- dai_link->no_pcm = 1;
-
- if (dai_link->dpcm_playback)
- dev_warn(card->dev,
- "invalid configuration, dailink %s has flags no_pcm=0 and dpcm_playback=1\n",
- dai_link->name);
- if (dai_link->dpcm_capture)
- dev_warn(card->dev,
- "invalid configuration, dailink %s has flags no_pcm=0 and dpcm_capture=1\n",
- dai_link->name);
-
- /* convert normal link into DPCM one */
- if (!(dai_link->dpcm_playback ||
- dai_link->dpcm_capture)) {
- dai_link->dpcm_playback = !dai_link->capture_only;
- dai_link->dpcm_capture = !dai_link->playback_only;
- }
- }
+ dai_link->no_pcm = 1;
/*
* override any BE fixups
diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c
index 4e08892d24c6..34ba1a93a4c9 100644
--- a/sound/soc/soc-dai.c
+++ b/sound/soc/soc-dai.c
@@ -37,7 +37,7 @@ static inline int _soc_dai_ret(const struct snd_soc_dai *dai,
* In such case, we can update these macros.
*/
#define soc_dai_mark_push(dai, substream, tgt) ((dai)->mark_##tgt = substream)
-#define soc_dai_mark_pop(dai, substream, tgt) ((dai)->mark_##tgt = NULL)
+#define soc_dai_mark_pop(dai, tgt) ((dai)->mark_##tgt = NULL)
#define soc_dai_mark_match(dai, substream, tgt) ((dai)->mark_##tgt == substream)
/**
@@ -416,7 +416,7 @@ void snd_soc_dai_hw_free(struct snd_soc_dai *dai,
dai->driver->ops->hw_free(substream, dai);
/* remove marked substream */
- soc_dai_mark_pop(dai, substream, hw_params);
+ soc_dai_mark_pop(dai, hw_params);
}
int snd_soc_dai_startup(struct snd_soc_dai *dai,
@@ -453,16 +453,16 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
dai->driver->ops->shutdown(substream, dai);
/* remove marked substream */
- soc_dai_mark_pop(dai, substream, startup);
+ soc_dai_mark_pop(dai, startup);
}
int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
- struct snd_soc_pcm_runtime *rtd, int num)
+ struct snd_soc_pcm_runtime *rtd)
{
int ret = -ENOTSUPP;
if (dai->driver->ops &&
dai->driver->ops->compress_new)
- ret = dai->driver->ops->compress_new(rtd, num);
+ ret = dai->driver->ops->compress_new(rtd);
return soc_dai_ret(dai, ret);
}
@@ -640,7 +640,7 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream,
r = soc_dai_trigger(dai, substream, cmd);
if (r < 0)
ret = r; /* use last ret */
- soc_dai_mark_pop(dai, substream, trigger);
+ soc_dai_mark_pop(dai, trigger);
}
}
@@ -704,7 +704,7 @@ void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai,
dai->driver->cops->shutdown(cstream, dai);
/* remove marked cstream */
- soc_dai_mark_pop(dai, cstream, compr_startup);
+ soc_dai_mark_pop(dai, compr_startup);
}
EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 9330f1a3f758..99521c784a9b 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1147,6 +1147,8 @@ static int dapm_widget_list_create(struct snd_soc_dapm_widget_list **list,
if (*list == NULL)
return -ENOMEM;
+ (*list)->num_widgets = size;
+
list_for_each_entry(w, widgets, work_list)
(*list)->widgets[i++] = w;
@@ -2785,10 +2787,10 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_update_dai);
int snd_soc_dapm_widget_name_cmp(struct snd_soc_dapm_widget *widget, const char *s)
{
- struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+ struct snd_soc_component *component = widget->dapm->component;
const char *wname = widget->name;
- if (component->name_prefix)
+ if (component && component->name_prefix)
wname += strlen(component->name_prefix) + 1; /* plus space */
return strcmp(wname, s);
diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c
index 4534a1c03e8e..c6364caabc0e 100644
--- a/sound/soc/soc-devres.c
+++ b/sound/soc/soc-devres.c
@@ -9,43 +9,6 @@
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
-static void devm_dai_release(struct device *dev, void *res)
-{
- snd_soc_unregister_dai(*(struct snd_soc_dai **)res);
-}
-
-/**
- * devm_snd_soc_register_dai - resource-managed dai registration
- * @dev: Device used to manage component
- * @component: The component the DAIs are registered for
- * @dai_drv: DAI driver to use for the DAI
- * @legacy_dai_naming: if %true, use legacy single-name format;
- * if %false, use multiple-name format;
- */
-struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev,
- struct snd_soc_component *component,
- struct snd_soc_dai_driver *dai_drv,
- bool legacy_dai_naming)
-{
- struct snd_soc_dai **ptr;
- struct snd_soc_dai *dai;
-
- ptr = devres_alloc(devm_dai_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return NULL;
-
- dai = snd_soc_register_dai(component, dai_drv, legacy_dai_naming);
- if (dai) {
- *ptr = dai;
- devres_add(dev, ptr);
- } else {
- devres_free(ptr);
- }
-
- return dai;
-}
-EXPORT_SYMBOL_GPL(devm_snd_soc_register_dai);
-
static void devm_component_release(struct device *dev, void *res)
{
const struct snd_soc_component_driver **cmpnt_drv = res;
diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c
index fee4022708bc..7f1f1bc717e2 100644
--- a/sound/soc/soc-link.c
+++ b/sound/soc/soc-link.c
@@ -35,7 +35,7 @@ static inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd,
* In such case, we can update these macros.
*/
#define soc_link_mark_push(rtd, substream, tgt) ((rtd)->mark_##tgt = substream)
-#define soc_link_mark_pop(rtd, substream, tgt) ((rtd)->mark_##tgt = NULL)
+#define soc_link_mark_pop(rtd, tgt) ((rtd)->mark_##tgt = NULL)
#define soc_link_mark_match(rtd, substream, tgt) ((rtd)->mark_##tgt == substream)
int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd)
@@ -94,7 +94,7 @@ void snd_soc_link_shutdown(struct snd_pcm_substream *substream,
rtd->dai_link->ops->shutdown(substream);
/* remove marked substream */
- soc_link_mark_pop(rtd, substream, startup);
+ soc_link_mark_pop(rtd, startup);
}
int snd_soc_link_prepare(struct snd_pcm_substream *substream)
@@ -138,7 +138,7 @@ void snd_soc_link_hw_free(struct snd_pcm_substream *substream, int rollback)
rtd->dai_link->ops->hw_free(substream);
/* remove marked substream */
- soc_link_mark_pop(rtd, substream, hw_params);
+ soc_link_mark_pop(rtd, hw_params);
}
static int soc_link_trigger(struct snd_pcm_substream *substream, int cmd)
@@ -175,7 +175,7 @@ int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd,
break;
ret = soc_link_trigger(substream, cmd);
- soc_link_mark_pop(rtd, substream, startup);
+ soc_link_mark_pop(rtd, startup);
}
return ret;
@@ -209,7 +209,7 @@ void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream,
rtd->dai_link->compr_ops->shutdown)
rtd->dai_link->compr_ops->shutdown(cstream);
- soc_link_mark_pop(rtd, cstream, compr_startup);
+ soc_link_mark_pop(rtd, compr_startup);
}
EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown);
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 7a59121fc323..1150455619aa 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -416,22 +416,6 @@ bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd)
return true;
}
-/**
- * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
- * @substream: the pcm substream
- * @hw: the hardware parameters
- *
- * Sets the substream runtime hardware parameters.
- */
-int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
- const struct snd_pcm_hardware *hw)
-{
- substream->runtime->hw = *hw;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
-
/* DPCM stream event, send event to FE and all active BEs. */
int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
int event)
@@ -463,13 +447,13 @@ static void soc_pcm_set_dai_params(struct snd_soc_dai *dai,
struct snd_pcm_hw_params *params)
{
if (params) {
- dai->rate = params_rate(params);
- dai->channels = params_channels(params);
- dai->sample_bits = snd_pcm_format_physical_width(params_format(params));
+ dai->symmetric_rate = params_rate(params);
+ dai->symmetric_channels = params_channels(params);
+ dai->symmetric_sample_bits = snd_pcm_format_physical_width(params_format(params));
} else {
- dai->rate = 0;
- dai->channels = 0;
- dai->sample_bits = 0;
+ dai->symmetric_rate = 0;
+ dai->symmetric_channels = 0;
+ dai->symmetric_sample_bits = 0;
}
}
@@ -483,14 +467,14 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
return 0;
#define __soc_pcm_apply_symmetry(name, NAME) \
- if (soc_dai->name && (soc_dai->driver->symmetric_##name || \
- rtd->dai_link->symmetric_##name)) { \
+ if (soc_dai->symmetric_##name && \
+ (soc_dai->driver->symmetric_##name || rtd->dai_link->symmetric_##name)) { \
dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %s to %d\n",\
- #name, soc_dai->name); \
+ #name, soc_dai->symmetric_##name); \
\
ret = snd_pcm_hw_constraint_single(substream->runtime, \
SNDRV_PCM_HW_PARAM_##NAME,\
- soc_dai->name); \
+ soc_dai->symmetric_##name); \
if (ret < 0) { \
dev_err(soc_dai->dev, \
"ASoC: Unable to apply %s constraint: %d\n",\
@@ -526,9 +510,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
if (symmetry) \
for_each_rtd_cpu_dais(rtd, i, cpu_dai) \
if (!snd_soc_dai_is_dummy(cpu_dai) && \
- cpu_dai->xxx && cpu_dai->xxx != d.xxx) { \
+ cpu_dai->symmetric_##xxx && \
+ cpu_dai->symmetric_##xxx != d.symmetric_##xxx) { \
dev_err(rtd->dev, "ASoC: unmatched %s symmetry: %s:%d - %s:%d\n", \
- #xxx, cpu_dai->name, cpu_dai->xxx, d.name, d.xxx); \
+ #xxx, cpu_dai->name, cpu_dai->symmetric_##xxx, \
+ d.name, d.symmetric_##xxx); \
return -EINVAL; \
}
@@ -799,8 +785,7 @@ static int soc_pcm_clean(struct snd_soc_pcm_runtime *rtd,
/* Make sure DAI parameters cleared if the DAI becomes inactive */
for_each_rtd_dais(rtd, i, dai) {
- if (snd_soc_dai_active(dai) == 0 &&
- (dai->rate || dai->channels || dai->sample_bits))
+ if (snd_soc_dai_active(dai) == 0)
soc_pcm_set_dai_params(dai, NULL);
}
}
@@ -2838,7 +2823,11 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
{
struct snd_soc_dai_link *dai_link = rtd->dai_link;
struct snd_soc_dai *cpu_dai;
+ struct snd_soc_dai *codec_dai;
struct snd_soc_dai_link_ch_map *ch_maps;
+ struct snd_soc_dai *dummy_dai = snd_soc_find_dai(&snd_soc_dummy_dlc);
+ int cpu_capture;
+ int cpu_playback;
int has_playback = 0;
int has_capture = 0;
int i;
@@ -2848,73 +2837,38 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
return -EINVAL;
}
- if (dai_link->dynamic || dai_link->no_pcm) {
-
- for_each_rtd_ch_maps(rtd, i, ch_maps) {
- cpu_dai = snd_soc_rtd_to_cpu(rtd, ch_maps->cpu);
+ /* Adapt stream for codec2codec links */
+ cpu_capture = snd_soc_get_stream_cpu(dai_link, SNDRV_PCM_STREAM_CAPTURE);
+ cpu_playback = snd_soc_get_stream_cpu(dai_link, SNDRV_PCM_STREAM_PLAYBACK);
- if (snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
- has_playback = 1;
-
- if (snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
- has_capture = 1;
- }
+ /*
+ * see
+ * soc.h :: [dai_link->ch_maps Image sample]
+ */
+ for_each_rtd_ch_maps(rtd, i, ch_maps) {
+ cpu_dai = snd_soc_rtd_to_cpu(rtd, ch_maps->cpu);
+ codec_dai = snd_soc_rtd_to_codec(rtd, ch_maps->codec);
/*
- * REMOVE ME
+ * FIXME
+ *
+ * DPCM Codec has been no checked before.
+ * It should be checked, but it breaks compatibility.
*
- * dpcm_xxx flag will be removed soon, Indicates warning if dpcm_xxx flag was used
- * as availability limitation
+ * For example there is a case that CPU have loopback capabilities which is used
+ * for tests on boards where the Codec has no capture capabilities. In this case,
+ * Codec capture validation check will be fail, but system should allow capture
+ * capabilities. We have no solution for it today.
*/
- if (has_playback && has_capture) {
- if ( dai_link->dpcm_playback &&
- !dai_link->dpcm_capture &&
- !dai_link->playback_only) {
- dev_warn(rtd->card->dev,
- "both playback/capture are available,"
- " but not using playback_only flag (%s)\n",
- dai_link->stream_name);
- dev_warn(rtd->card->dev,
- "dpcm_playback/capture are no longer needed,"
- " please use playback/capture_only instead\n");
- has_capture = 0;
- }
-
- if (!dai_link->dpcm_playback &&
- dai_link->dpcm_capture &&
- !dai_link->capture_only) {
- dev_warn(rtd->card->dev,
- "both playback/capture are available,"
- " but not using capture_only flag (%s)\n",
- dai_link->stream_name);
- dev_warn(rtd->card->dev,
- "dpcm_playback/capture are no longer needed,"
- " please use playback/capture_only instead\n");
- has_playback = 0;
- }
- }
- } else {
- struct snd_soc_dai *codec_dai;
+ if (dai_link->dynamic || dai_link->no_pcm)
+ codec_dai = dummy_dai;
- /* Adapt stream for codec2codec links */
- int cpu_capture = snd_soc_get_stream_cpu(dai_link, SNDRV_PCM_STREAM_CAPTURE);
- int cpu_playback = snd_soc_get_stream_cpu(dai_link, SNDRV_PCM_STREAM_PLAYBACK);
-
- /*
- * see
- * soc.h :: [dai_link->ch_maps Image sample]
- */
- for_each_rtd_ch_maps(rtd, i, ch_maps) {
- cpu_dai = snd_soc_rtd_to_cpu(rtd, ch_maps->cpu);
- codec_dai = snd_soc_rtd_to_codec(rtd, ch_maps->codec);
-
- if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
- snd_soc_dai_stream_valid(cpu_dai, cpu_playback))
- has_playback = 1;
- if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
- snd_soc_dai_stream_valid(cpu_dai, cpu_capture))
- has_capture = 1;
- }
+ if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
+ snd_soc_dai_stream_valid(cpu_dai, cpu_playback))
+ has_playback = 1;
+ if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
+ snd_soc_dai_stream_valid(cpu_dai, cpu_capture))
+ has_capture = 1;
}
if (dai_link->playback_only)
@@ -2938,7 +2892,7 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
static int soc_create_pcm(struct snd_pcm **pcm,
struct snd_soc_pcm_runtime *rtd,
- int playback, int capture, int num)
+ int playback, int capture)
{
char new_name[64];
int ret;
@@ -2948,13 +2902,13 @@ static int soc_create_pcm(struct snd_pcm **pcm,
snprintf(new_name, sizeof(new_name), "codec2codec(%s)",
rtd->dai_link->stream_name);
- ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
+ ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, rtd->id,
playback, capture, pcm);
} else if (rtd->dai_link->no_pcm) {
snprintf(new_name, sizeof(new_name), "(%s)",
rtd->dai_link->stream_name);
- ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
+ ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, rtd->id,
playback, capture, pcm);
} else {
if (rtd->dai_link->dynamic)
@@ -2963,9 +2917,9 @@ static int soc_create_pcm(struct snd_pcm **pcm,
else
snprintf(new_name, sizeof(new_name), "%s %s-%d",
rtd->dai_link->stream_name,
- soc_codec_dai_name(rtd), num);
+ soc_codec_dai_name(rtd), rtd->id);
- ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
+ ret = snd_pcm_new(rtd->card->snd_card, new_name, rtd->id, playback,
capture, pcm);
}
if (ret < 0) {
@@ -2973,13 +2927,13 @@ static int soc_create_pcm(struct snd_pcm **pcm,
new_name, rtd->dai_link->name, ret);
return ret;
}
- dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name);
+ dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n", rtd->id, new_name);
return 0;
}
/* create a new pcm */
-int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
+int soc_new_pcm(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *component;
struct snd_pcm *pcm;
@@ -2990,7 +2944,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
if (ret < 0)
return ret;
- ret = soc_create_pcm(&pcm, rtd, playback, capture, num);
+ ret = soc_create_pcm(&pcm, rtd, playback, capture);
if (ret < 0)
return ret;
diff --git a/sound/soc/soc-topology-test.c b/sound/soc/soc-topology-test.c
index a2b08568f4e8..c8f2ec29e970 100644
--- a/sound/soc/soc-topology-test.c
+++ b/sound/soc/soc-topology-test.c
@@ -88,8 +88,6 @@ static struct snd_soc_dai_link kunit_dai_links[] = {
.nonatomic = 1,
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
- .dpcm_playback = 1,
- .dpcm_capture = 1,
SND_SOC_DAILINK_REG(dummy, dummy, platform),
},
};
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index af3158cdc8d5..43003d2d3666 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -889,7 +889,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size)
return ret;
/* register dynamic object */
- sbe = (struct soc_bytes_ext *)&kc.private_value;
+ sbe = (struct soc_bytes_ext *)kc.private_value;
INIT_LIST_HEAD(&sbe->dobj.list);
sbe->dobj.type = SND_SOC_DOBJ_BYTES;
@@ -923,7 +923,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size)
return ret;
/* register dynamic object */
- sm = (struct soc_mixer_control *)&kc.private_value;
+ sm = (struct soc_mixer_control *)kc.private_value;
INIT_LIST_HEAD(&sm->dobj.list);
sm->dobj.type = SND_SOC_DOBJ_MIXER;
@@ -1544,8 +1544,8 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
/* enable DPCM */
link->dynamic = 1;
link->ignore_pmdown_time = 1;
- link->dpcm_playback = le32_to_cpu(pcm->playback);
- link->dpcm_capture = le32_to_cpu(pcm->capture);
+ link->playback_only = le32_to_cpu(pcm->playback) && !le32_to_cpu(pcm->capture);
+ link->capture_only = !le32_to_cpu(pcm->playback) && le32_to_cpu(pcm->capture);
if (pcm->flag_mask)
set_link_flags(link,
le32_to_cpu(pcm->flag_mask),
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index 303823dc45d7..aa93e77ac937 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -103,8 +103,8 @@ static const struct snd_pcm_hardware dummy_dma_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER,
.buffer_bytes_max = 128*1024,
- .period_bytes_min = PAGE_SIZE,
- .period_bytes_max = PAGE_SIZE*2,
+ .period_bytes_min = 4096,
+ .period_bytes_max = 4096*2,
.periods_min = 2,
.periods_max = 128,
};
diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c
index dbcaac84cb73..fc792956bb97 100644
--- a/sound/soc/sof/amd/acp-common.c
+++ b/sound/soc/sof/amd/acp-common.c
@@ -145,8 +145,7 @@ static struct snd_soc_acpi_mach *amd_sof_sdw_machine_select(struct snd_sof_dev *
link = mach->links;
for (i = 0; i < acp_data->info.count && link->num_adr; link++, i++) {
if (!snd_soc_acpi_sdw_link_slaves_found(sdev->dev, link,
- acp_data->sdw->ids,
- acp_data->sdw->num_slaves))
+ acp_data->sdw->peripherals))
break;
}
if (i == acp_data->info.count || !link->num_adr)
diff --git a/sound/soc/sof/amd/acp-loader.c b/sound/soc/sof/amd/acp-loader.c
index 19f10dd77e4b..077af9e2af8d 100644
--- a/sound/soc/sof/amd/acp-loader.c
+++ b/sound/soc/sof/amd/acp-loader.c
@@ -206,7 +206,10 @@ int acp_dsp_pre_fw_run(struct snd_sof_dev *sdev)
configure_pte_for_fw_loading(FW_SRAM_DATA_BIN, ACP_SRAM_PAGE_COUNT, adata);
src_addr = ACP_SYSTEM_MEMORY_WINDOW + ACP_DEFAULT_SRAM_LENGTH +
(page_count * ACP_PAGE_SIZE);
- dest_addr = ACP_SRAM_BASE_ADDRESS;
+ if (adata->pci_rev > ACP63_PCI_ID)
+ dest_addr = ACP7X_SRAM_BASE_ADDRESS;
+ else
+ dest_addr = ACP_SRAM_BASE_ADDRESS;
ret = configure_and_run_dma(adata, src_addr, dest_addr,
adata->fw_sram_data_bin_size);
diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c
index f967e8498798..f7814dadf3ba 100644
--- a/sound/soc/sof/amd/acp.c
+++ b/sound/soc/sof/amd/acp.c
@@ -329,7 +329,9 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
fw_qualifier, fw_qualifier & DSP_FW_RUN_ENABLE,
ACP_REG_POLL_INTERVAL, ACP_DMA_COMPLETE_TIMEOUT_US);
if (ret < 0) {
- dev_err(sdev->dev, "PSP validation failed\n");
+ val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SHA_PSP_ACK);
+ dev_err(sdev->dev, "PSP validation failed: fw_qualifier = %#x, ACP_SHA_PSP_ACK = %#x\n",
+ fw_qualifier, val);
return ret;
}
@@ -340,11 +342,19 @@ int acp_dma_status(struct acp_dev_data *adata, unsigned char ch)
{
struct snd_sof_dev *sdev = adata->dev;
unsigned int val;
+ unsigned int acp_dma_ch_sts;
int ret = 0;
+ switch (adata->pci_rev) {
+ case ACP70_PCI_ID:
+ acp_dma_ch_sts = ACP70_DMA_CH_STS;
+ break;
+ default:
+ acp_dma_ch_sts = ACP_DMA_CH_STS;
+ }
val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_DMA_CNTL_0 + ch * sizeof(u32));
if (val & ACP_DMA_CH_RUN) {
- ret = snd_sof_dsp_read_poll_timeout(sdev, ACP_DSP_BAR, ACP_DMA_CH_STS, val, !val,
+ ret = snd_sof_dsp_read_poll_timeout(sdev, ACP_DSP_BAR, acp_dma_ch_sts, val, !val,
ACP_REG_POLL_INTERVAL,
ACP_DMA_COMPLETE_TIMEOUT_US);
if (ret < 0)
diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c
index 83fe0401baf8..24e779e8d650 100644
--- a/sound/soc/sof/core.c
+++ b/sound/soc/sof/core.c
@@ -19,11 +19,47 @@
#define CREATE_TRACE_POINTS
#include <trace/events/sof.h>
+/* Module parameters for firmware, topology and IPC type override */
+static char *override_fw_path;
+module_param_named(fw_path, override_fw_path, charp, 0444);
+MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware.");
+
+static char *override_fw_filename;
+module_param_named(fw_filename, override_fw_filename, charp, 0444);
+MODULE_PARM_DESC(fw_filename, "alternate filename for SOF firmware.");
+
+static char *override_lib_path;
+module_param_named(lib_path, override_lib_path, charp, 0444);
+MODULE_PARM_DESC(lib_path, "alternate path for SOF firmware libraries.");
+
+static char *override_tplg_path;
+module_param_named(tplg_path, override_tplg_path, charp, 0444);
+MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology.");
+
+static char *override_tplg_filename;
+module_param_named(tplg_filename, override_tplg_filename, charp, 0444);
+MODULE_PARM_DESC(tplg_filename, "alternate filename for SOF topology.");
+
+static int override_ipc_type = -1;
+module_param_named(ipc_type, override_ipc_type, int, 0444);
+MODULE_PARM_DESC(ipc_type, "Force SOF IPC type. 0 - IPC3, 1 - IPC4");
+
/* see SOF_DBG_ flags */
static int sof_core_debug = IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE);
module_param_named(sof_debug, sof_core_debug, int, 0444);
MODULE_PARM_DESC(sof_debug, "SOF core debug options (0x0 all off)");
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG)
+static unsigned int sof_ipc_timeout_ms;
+static unsigned int sof_boot_timeout_ms;
+module_param_named(ipc_timeout, sof_ipc_timeout_ms, uint, 0444);
+MODULE_PARM_DESC(ipc_timeout,
+ "Set the IPC timeout value in ms (0 to use the platform default)");
+module_param_named(boot_timeout, sof_boot_timeout_ms, uint, 0444);
+MODULE_PARM_DESC(boot_timeout,
+ "Set the DSP boot timeout value in ms (0 to use the platform default)");
+#endif
+
/* SOF defaults if not provided by the platform in ms */
#define TIMEOUT_DEFAULT_IPC_MS 500
#define TIMEOUT_DEFAULT_BOOT_MS 2000
@@ -570,6 +606,23 @@ static void sof_probe_work(struct work_struct *work)
}
}
+static void
+sof_apply_profile_override(struct sof_loadable_file_profile *path_override)
+{
+ if (override_ipc_type >= 0 && override_ipc_type < SOF_IPC_TYPE_COUNT)
+ path_override->ipc_type = override_ipc_type;
+ if (override_fw_path)
+ path_override->fw_path = override_fw_path;
+ if (override_fw_filename)
+ path_override->fw_name = override_fw_filename;
+ if (override_lib_path)
+ path_override->fw_lib_path = override_lib_path;
+ if (override_tplg_path)
+ path_override->tplg_path = override_tplg_path;
+ if (override_tplg_filename)
+ path_override->tplg_name = override_tplg_filename;
+}
+
int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
{
struct snd_sof_dev *sdev;
@@ -601,6 +654,8 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
}
}
+ sof_apply_profile_override(&plat_data->ipc_file_profile_base);
+
/* Initialize sof_ops based on the initial selected IPC version */
ret = sof_init_sof_ops(sdev);
if (ret)
@@ -632,6 +687,15 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
else
sdev->boot_timeout = plat_data->desc->boot_timeout;
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG)
+ /* Override the timeout values with module parameter, if set */
+ if (sof_ipc_timeout_ms)
+ sdev->ipc_timeout = sof_ipc_timeout_ms;
+
+ if (sof_boot_timeout_ms)
+ sdev->boot_timeout = sof_boot_timeout_ms;
+#endif
+
sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED);
/*
diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c
index 484c76147885..92681ca7f24d 100644
--- a/sound/soc/sof/intel/hda-dai-ops.c
+++ b/sound/soc/sof/intel/hda-dai-ops.c
@@ -346,20 +346,21 @@ static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
snd_hdac_ext_stream_start(hext_stream);
break;
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- snd_hdac_ext_stream_clear(hext_stream);
-
/*
- * Save the LLP registers in case the stream is
- * restarting due PAUSE_RELEASE, or START without a pcm
- * close/open since in this case the LLP register is not reset
- * to 0 and the delay calculation will return with invalid
- * results.
+ * Save the LLP registers since in case of PAUSE the LLP
+ * register are not reset to 0, the delay calculation will use
+ * the saved offsets for compensating the delay calculation.
*/
hext_stream->pplcllpl = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL);
hext_stream->pplcllpu = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU);
+ snd_hdac_ext_stream_clear(hext_stream);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_STOP:
+ hext_stream->pplcllpl = 0;
+ hext_stream->pplcllpu = 0;
+ snd_hdac_ext_stream_clear(hext_stream);
break;
default:
dev_err(sdev->dev, "unknown trigger command %d\n", cmd);
@@ -512,7 +513,6 @@ static const struct hda_dai_widget_dma_ops sdw_ipc4_chain_dma_ops = {
static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
struct snd_pcm_substream *substream, int cmd)
{
- struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream);
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
switch (cmd) {
@@ -527,9 +527,6 @@ static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
if (ret < 0)
return ret;
- if (cmd == SNDRV_PCM_TRIGGER_STOP)
- return hda_link_dma_cleanup(substream, hext_stream, cpu_dai);
-
break;
}
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c
index 1c823f9eea57..ee274d445515 100644
--- a/sound/soc/sof/intel/hda-dai.c
+++ b/sound/soc/sof/intel/hda-dai.c
@@ -302,6 +302,7 @@ static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, i
}
switch (cmd) {
+ case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
ret = hda_link_dma_cleanup(substream, hext_stream, dai);
if (ret < 0) {
@@ -370,6 +371,13 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
return -EINVAL;
}
+ sdev = widget_to_sdev(w);
+ hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
+
+ /* nothing more to do if the link is already prepared */
+ if (hext_stream && hext_stream->link_prepared)
+ return 0;
+
/* use HDaudio stream handling */
ret = hda_dai_hw_params_data(substream, params, cpu_dai, data, flags);
if (ret < 0) {
@@ -377,7 +385,6 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
return ret;
}
- sdev = widget_to_sdev(w);
if (sdev->dspless_mode_selected)
return 0;
@@ -482,6 +489,31 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
int ret;
int i;
+ ops = hda_dai_get_ops(substream, cpu_dai);
+ if (!ops) {
+ dev_err(cpu_dai->dev, "DAI widget ops not set\n");
+ return -EINVAL;
+ }
+
+ sdev = widget_to_sdev(w);
+ hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
+
+ /* nothing more to do if the link is already prepared */
+ if (hext_stream && hext_stream->link_prepared)
+ return 0;
+
+ /*
+ * reset the PCMSyCM registers to handle a prepare callback when the PCM is restarted
+ * due to xruns or after a call to snd_pcm_drain/drop()
+ */
+ ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id,
+ 0, 0, substream->stream);
+ if (ret < 0) {
+ dev_err(cpu_dai->dev, "%s: hdac_bus_eml_sdw_map_stream_ch failed %d\n",
+ __func__, ret);
+ return ret;
+ }
+
data.dai_index = (link_id << 8) | cpu_dai->id;
data.dai_node_id = intel_alh_id;
ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags);
@@ -490,10 +522,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
return ret;
}
- ops = hda_dai_get_ops(substream, cpu_dai);
- sdev = widget_to_sdev(w);
hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
-
if (!hext_stream)
return -ENODEV;
@@ -617,6 +646,10 @@ static int hda_dai_suspend(struct hdac_bus *bus)
sdai = swidget->private;
ops = sdai->platform_private;
+ if (rtd->dpcm[hext_stream->link_substream->stream].state !=
+ SND_SOC_DPCM_STATE_PAUSED)
+ continue;
+
/* for consistency with TRIGGER_SUSPEND */
if (ops->post_trigger) {
ret = ops->post_trigger(sdev, cpu_dai,
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c
index 4c88522d4048..6028a80418bb 100644
--- a/sound/soc/sof/intel/hda-dsp.c
+++ b/sound/soc/sof/intel/hda-dsp.c
@@ -858,7 +858,6 @@ skip_dsp:
static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume)
{
- const struct sof_intel_dsp_desc *chip;
int ret;
/* display codec must be powered before link reset */
@@ -891,10 +890,6 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume)
hda_dsp_ctrl_ppcap_int_enable(sdev, true);
}
- chip = get_chip_info(sdev->pdata);
- if (chip && chip->hw_ip_version >= SOF_INTEL_ACE_2_0)
- hda_sdw_int_enable(sdev, true);
-
cleanup:
/* display codec can powered off after controller init */
hda_codec_i915_display_power(sdev, false);
diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c
index 75f6240cf3e1..76a03b6b2728 100644
--- a/sound/soc/sof/intel/hda-loader.c
+++ b/sound/soc/sof/intel/hda-loader.c
@@ -26,6 +26,11 @@
#include "../sof-priv.h"
#include "hda.h"
+static bool persistent_cl_buffer = true;
+module_param(persistent_cl_buffer, bool, 0444);
+MODULE_PARM_DESC(persistent_cl_buffer, "Persistent Code Loader DMA buffer "
+ "(default = Y, use N to force buffer re-allocation)");
+
static void hda_ssp_set_cbp_cfp(struct snd_sof_dev *sdev)
{
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
@@ -43,9 +48,10 @@ static void hda_ssp_set_cbp_cfp(struct snd_sof_dev *sdev)
}
}
-struct hdac_ext_stream *hda_cl_prepare(struct device *dev, unsigned int format,
- unsigned int size, struct snd_dma_buffer *dmab,
- int direction, bool is_iccmax)
+struct hdac_ext_stream*
+hda_cl_prepare(struct device *dev, unsigned int format, unsigned int size,
+ struct snd_dma_buffer *dmab, bool persistent_buffer, int direction,
+ bool is_iccmax)
{
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct hdac_ext_stream *hext_stream;
@@ -61,11 +67,19 @@ struct hdac_ext_stream *hda_cl_prepare(struct device *dev, unsigned int format,
hstream = &hext_stream->hstream;
hstream->substream = NULL;
- /* allocate DMA buffer */
- ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, dev, size, dmab);
- if (ret < 0) {
- dev_err(sdev->dev, "error: memory alloc failed: %d\n", ret);
- goto out_put;
+ /*
+ * Allocate DMA buffer if it is temporary or if the buffer is intended
+ * to be persistent but not yet allocated.
+ * We cannot rely solely on !dmab->area as caller might use a struct on
+ * stack (when it is temporary) without clearing it to 0.
+ */
+ if (!persistent_buffer || !dmab->area) {
+ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, dev, size, dmab);
+ if (ret < 0) {
+ dev_err(sdev->dev, "%s: memory alloc failed: %d\n",
+ __func__, ret);
+ goto out_put;
+ }
}
hstream->period_bytes = 0;/* initialize period_bytes */
@@ -91,6 +105,10 @@ struct hdac_ext_stream *hda_cl_prepare(struct device *dev, unsigned int format,
out_free:
snd_dma_free_pages(dmab);
+ dmab->area = NULL;
+ dmab->bytes = 0;
+ hstream->bufsize = 0;
+ hstream->format_val = 0;
out_put:
hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
return ERR_PTR(ret);
@@ -255,7 +273,7 @@ int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int
EXPORT_SYMBOL_NS(hda_cl_trigger, SND_SOC_SOF_INTEL_HDA_COMMON);
int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab,
- struct hdac_ext_stream *hext_stream)
+ bool persistent_buffer, struct hdac_ext_stream *hext_stream)
{
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct hdac_stream *hstream = &hext_stream->hstream;
@@ -279,10 +297,14 @@ int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab,
sd_offset + SOF_HDA_ADSP_REG_SD_BDLPU, 0);
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, sd_offset, 0);
- snd_dma_free_pages(dmab);
- dmab->area = NULL;
- hstream->bufsize = 0;
- hstream->format_val = 0;
+
+ if (!persistent_buffer) {
+ snd_dma_free_pages(dmab);
+ dmab->area = NULL;
+ dmab->bytes = 0;
+ hstream->bufsize = 0;
+ hstream->format_val = 0;
+ }
return ret;
}
@@ -294,14 +316,9 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream
{
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
const struct sof_intel_dsp_desc *chip = hda->desc;
- struct sof_intel_hda_stream *hda_stream;
- unsigned long time_left;
unsigned int reg;
int ret, status;
- hda_stream = container_of(hext_stream, struct sof_intel_hda_stream,
- hext_stream);
-
dev_dbg(sdev->dev, "Code loader DMA starting\n");
ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_START);
@@ -310,18 +327,6 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream
return ret;
}
- if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) {
- /* Wait for completion of transfer */
- time_left = wait_for_completion_timeout(&hda_stream->ioc,
- msecs_to_jiffies(HDA_CL_DMA_IOC_TIMEOUT_MS));
-
- if (!time_left) {
- dev_err(sdev->dev, "Code loader DMA did not complete\n");
- return -ETIMEDOUT;
- }
- dev_dbg(sdev->dev, "Code loader DMA done\n");
- }
-
dev_dbg(sdev->dev, "waiting for FW_ENTERED status\n");
status = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
@@ -357,8 +362,8 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream
int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
{
+ struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
struct hdac_ext_stream *iccmax_stream;
- struct snd_dma_buffer dmab_bdl;
int ret, ret1;
u8 original_gb;
@@ -371,7 +376,8 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
* the data, so use a buffer of PAGE_SIZE for receiving.
*/
iccmax_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT, PAGE_SIZE,
- &dmab_bdl, SNDRV_PCM_STREAM_CAPTURE, true);
+ &hda->iccmax_dmab, persistent_cl_buffer,
+ SNDRV_PCM_STREAM_CAPTURE, true);
if (IS_ERR(iccmax_stream)) {
dev_err(sdev->dev, "error: dma prepare for ICCMAX stream failed\n");
return PTR_ERR(iccmax_stream);
@@ -383,7 +389,8 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
* Perform iccmax stream cleanup. This should be done even if firmware loading fails.
* If the cleanup also fails, we return the initial error
*/
- ret1 = hda_cl_cleanup(sdev->dev, &dmab_bdl, iccmax_stream);
+ ret1 = hda_cl_cleanup(sdev->dev, &hda->iccmax_dmab,
+ persistent_cl_buffer, iccmax_stream);
if (ret1 < 0) {
dev_err(sdev->dev, "error: ICCMAX stream cleanup failed\n");
@@ -425,7 +432,6 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
const struct sof_intel_dsp_desc *chip_info;
struct hdac_ext_stream *hext_stream;
struct firmware stripped_firmware;
- struct snd_dma_buffer dmab;
int ret, ret1, i;
if (hda->imrboot_supported && !sdev->first_boot && !hda->skip_imr_boot) {
@@ -449,23 +455,31 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
return -EINVAL;
}
- stripped_firmware.data = sdev->basefw.fw->data + sdev->basefw.payload_offset;
- stripped_firmware.size = sdev->basefw.fw->size - sdev->basefw.payload_offset;
-
/* init for booting wait */
init_waitqueue_head(&sdev->boot_wait);
/* prepare DMA for code loader stream */
+ stripped_firmware.size = sdev->basefw.fw->size - sdev->basefw.payload_offset;
hext_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT,
stripped_firmware.size,
- &dmab, SNDRV_PCM_STREAM_PLAYBACK, false);
+ &hda->cl_dmab, persistent_cl_buffer,
+ SNDRV_PCM_STREAM_PLAYBACK, false);
if (IS_ERR(hext_stream)) {
dev_err(sdev->dev, "error: dma prepare for fw loading failed\n");
return PTR_ERR(hext_stream);
}
- memcpy(dmab.area, stripped_firmware.data,
- stripped_firmware.size);
+ /*
+ * Copy the payload to the DMA buffer if it is temporary or if the
+ * buffer is persistent but it does not have the basefw payload either
+ * because this is the first boot and the buffer needs to be initialized,
+ * or a library got loaded and it replaced the basefw.
+ */
+ if (!persistent_cl_buffer || !hda->cl_dmab_contains_basefw) {
+ stripped_firmware.data = sdev->basefw.fw->data + sdev->basefw.payload_offset;
+ memcpy(hda->cl_dmab.area, stripped_firmware.data, stripped_firmware.size);
+ hda->cl_dmab_contains_basefw = true;
+ }
/* try ROM init a few times before giving up */
for (i = 0; i < HDA_FW_BOOT_ATTEMPTS; i++) {
@@ -531,7 +545,8 @@ cleanup:
* This should be done even if firmware loading fails.
* If the cleanup also fails, we return the initial error
*/
- ret1 = hda_cl_cleanup(sdev->dev, &dmab, hext_stream);
+ ret1 = hda_cl_cleanup(sdev->dev, &hda->cl_dmab,
+ persistent_cl_buffer, hext_stream);
if (ret1 < 0) {
dev_err(sdev->dev, "error: Code loader DSP cleanup failed\n");
@@ -562,7 +577,6 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev,
struct hdac_ext_stream *hext_stream;
struct firmware stripped_firmware;
struct sof_ipc4_msg msg = {};
- struct snd_dma_buffer dmab;
int ret, ret1;
/* if IMR booting is enabled and fw context is saved for D3 state, skip the loading */
@@ -573,16 +587,28 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev,
stripped_firmware.data = fw_lib->sof_fw.fw->data + fw_lib->sof_fw.payload_offset;
stripped_firmware.size = fw_lib->sof_fw.fw->size - fw_lib->sof_fw.payload_offset;
+ /*
+ * force re-allocation of the cl_dmab if the preserved DMA buffer is
+ * smaller than what is needed for the library
+ */
+ if (persistent_cl_buffer && stripped_firmware.size > hda->cl_dmab.bytes) {
+ snd_dma_free_pages(&hda->cl_dmab);
+ hda->cl_dmab.area = NULL;
+ hda->cl_dmab.bytes = 0;
+ }
+
/* prepare DMA for code loader stream */
hext_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT,
stripped_firmware.size,
- &dmab, SNDRV_PCM_STREAM_PLAYBACK, false);
+ &hda->cl_dmab, persistent_cl_buffer,
+ SNDRV_PCM_STREAM_PLAYBACK, false);
if (IS_ERR(hext_stream)) {
dev_err(sdev->dev, "%s: DMA prepare failed\n", __func__);
return PTR_ERR(hext_stream);
}
- memcpy(dmab.area, stripped_firmware.data, stripped_firmware.size);
+ memcpy(hda->cl_dmab.area, stripped_firmware.data, stripped_firmware.size);
+ hda->cl_dmab_contains_basefw = false;
/*
* 1st stage: SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE
@@ -645,7 +671,8 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev,
cleanup:
/* clean up even in case of error and return the first error */
- ret1 = hda_cl_cleanup(sdev->dev, &dmab, hext_stream);
+ ret1 = hda_cl_cleanup(sdev->dev, &hda->cl_dmab, persistent_cl_buffer,
+ hext_stream);
if (ret1 < 0) {
dev_err(sdev->dev, "%s: Code loader DSP cleanup failed\n", __func__);
diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c
index 9a3559c78b62..46f89d6d06f8 100644
--- a/sound/soc/sof/intel/hda-mlink.c
+++ b/sound/soc/sof/intel/hda-mlink.c
@@ -481,6 +481,24 @@ int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid)
}
EXPORT_SYMBOL_NS(hdac_bus_eml_get_count, SND_SOC_SOF_HDA_MLINK);
+void hdac_bus_eml_enable_interrupt_unlocked(struct hdac_bus *bus, bool alt, int elid, bool enable)
+{
+ struct hdac_ext2_link *h2link;
+ struct hdac_ext_link *hlink;
+
+ h2link = find_ext2_link(bus, alt, elid);
+ if (!h2link)
+ return;
+
+ if (!h2link->intc)
+ return;
+
+ hlink = &h2link->hext_link;
+
+ hdaml_link_enable_interrupt(hlink->ml_addr + AZX_REG_ML_LCTL, enable);
+}
+EXPORT_SYMBOL_NS(hdac_bus_eml_enable_interrupt_unlocked, SND_SOC_SOF_HDA_MLINK);
+
void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable)
{
struct hdac_ext2_link *h2link;
diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
index 3ac63ce67ab1..519bafd3b947 100644
--- a/sound/soc/sof/intel/hda-stream.c
+++ b/sound/soc/sof/intel/hda-stream.c
@@ -119,13 +119,39 @@ int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev,
int remain, ioc;
period_bytes = hstream->period_bytes;
- dev_dbg(sdev->dev, "period_bytes:0x%x\n", period_bytes);
- if (!period_bytes)
+ dev_dbg(sdev->dev, "period_bytes: %#x, bufsize: %#x\n", period_bytes,
+ hstream->bufsize);
+
+ if (!period_bytes) {
+ unsigned int chunk_size;
+
+ chunk_size = snd_sgbuf_get_chunk_size(dmab, 0, hstream->bufsize);
+
period_bytes = hstream->bufsize;
+ /*
+ * HDA spec demands that the LVI value must be at least one
+ * before the DMA operation can begin. This means that there
+ * must be at least two BDLE present for the transfer.
+ *
+ * If the buffer is not a single continuous area then the
+ * hda_setup_bdle() will create multiple BDLEs for each segment.
+ * If the memory is a single continuous area, force it to be
+ * split into two 'periods', otherwise the transfer will be
+ * split to multiple BDLE for each chunk in hda_setup_bdle()
+ *
+ * Note: period_bytes == 0 can only happen for firmware or
+ * library loading. The data size is 4K aligned, which ensures
+ * that the second chunk's start address will be 128-byte
+ * aligned.
+ */
+ if (chunk_size == hstream->bufsize)
+ period_bytes /= 2;
+ }
+
periods = hstream->bufsize / period_bytes;
- dev_dbg(sdev->dev, "periods:%d\n", periods);
+ dev_dbg(sdev->dev, "periods: %d\n", periods);
remain = hstream->bufsize % period_bytes;
if (remain)
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 70fc08c8fc99..01b135068b1f 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -866,8 +866,6 @@ skip_dsp_setup:
dev_err(sdev->dev, "could not startup SoundWire links\n");
goto disable_pp_cap;
}
-
- hda_sdw_int_enable(sdev, true);
}
init_waitqueue_head(&hdev->waitq);
@@ -938,6 +936,12 @@ void hda_dsp_remove(struct snd_sof_dev *sdev)
/* disable DSP */
hda_dsp_ctrl_ppcap_enable(sdev, false);
+ /* Free the persistent DMA buffers used for base firmware download */
+ if (hda->cl_dmab.area)
+ snd_dma_free_pages(&hda->cl_dmab);
+ if (hda->iccmax_dmab.area)
+ snd_dma_free_pages(&hda->iccmax_dmab);
+
skip_disable_dsp:
free_irq(sdev->ipc_irq, sdev);
if (sdev->msi_enabled)
@@ -1066,7 +1070,7 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
{
struct snd_sof_pdata *pdata = sdev->pdata;
const struct snd_soc_acpi_link_adr *link;
- struct sdw_extended_slave_id *ids;
+ struct sdw_peripherals *peripherals;
struct snd_soc_acpi_mach *mach;
struct sof_intel_hda_dev *hdev;
u32 link_mask;
@@ -1085,7 +1089,7 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
return NULL;
}
- if (!hdev->sdw->num_slaves) {
+ if (!hdev->sdw->peripherals || !hdev->sdw->peripherals->num_peripherals) {
dev_warn(sdev->dev, "No SoundWire peripheral detected in ACPI tables\n");
return NULL;
}
@@ -1121,13 +1125,13 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
* are not found on this link.
*/
if (!snd_soc_acpi_sdw_link_slaves_found(sdev->dev, link,
- hdev->sdw->ids,
- hdev->sdw->num_slaves))
+ hdev->sdw->peripherals))
break;
}
/* Found if all Slaves are checked */
if (i == hdev->info.count || !link->num_adr)
- break;
+ if (!mach->machine_check || mach->machine_check(hdev->sdw))
+ break;
}
if (mach && mach->link_mask) {
mach->mach_params.links = mach->links;
@@ -1138,10 +1142,13 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
}
dev_info(sdev->dev, "No SoundWire machine driver found for the ACPI-reported configuration:\n");
- ids = hdev->sdw->ids;
- for (i = 0; i < hdev->sdw->num_slaves; i++)
+ peripherals = hdev->sdw->peripherals;
+ for (i = 0; i < peripherals->num_peripherals; i++)
dev_info(sdev->dev, "link %d mfg_id 0x%04x part_id 0x%04x version %#x\n",
- ids[i].link_id, ids[i].id.mfg_id, ids[i].id.part_id, ids[i].id.sdw_version);
+ peripherals->array[i]->bus->link_id,
+ peripherals->array[i]->id.mfg_id,
+ peripherals->array[i]->id.part_id,
+ peripherals->array[i]->id.sdw_version);
return NULL;
}
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index b74a472435b5..22bd9c3c8216 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -495,6 +495,15 @@ struct sof_intel_hda_dev {
int boot_iteration;
+ /*
+ * DMA buffers for base firmware download. By default the buffers are
+ * allocated once and kept through the lifetime of the driver.
+ * See module parameter: persistent_cl_buffer
+ */
+ struct snd_dma_buffer cl_dmab;
+ bool cl_dmab_contains_basefw;
+ struct snd_dma_buffer iccmax_dmab;
+
struct hda_bus hbus;
/* hw config */
@@ -714,11 +723,12 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream
struct hdac_ext_stream *hda_cl_prepare(struct device *dev, unsigned int format,
unsigned int size, struct snd_dma_buffer *dmab,
- int direction, bool is_iccmax);
+ bool persistent_buffer, int direction,
+ bool is_iccmax);
int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int cmd);
int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab,
- struct hdac_ext_stream *hext_stream);
+ bool persistent_buffer, struct hdac_ext_stream *hext_stream);
int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot);
#define HDA_CL_STREAM_FORMAT 0x40
diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c
index 3d5a1f8b17e5..e3c4b4a0d705 100644
--- a/sound/soc/sof/intel/lnl.c
+++ b/sound/soc/sof/intel/lnl.c
@@ -192,16 +192,8 @@ static bool lnl_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
return hdac_bus_eml_check_interrupt(bus, true, AZX_REG_ML_LEPTR_ID_SDW);
}
-static void lnl_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable)
-{
- struct hdac_bus *bus = sof_to_bus(sdev);
-
- hdac_bus_eml_enable_interrupt(bus, true, AZX_REG_ML_LEPTR_ID_SDW, enable);
-}
-
static int lnl_dsp_disable_interrupts(struct snd_sof_dev *sdev)
{
- lnl_enable_sdw_irq(sdev, false);
mtl_disable_ipc_interrupts(sdev);
return mtl_enable_interrupts(sdev, false);
}
@@ -237,7 +229,6 @@ const struct sof_intel_dsp_desc lnl_chip_info = {
.ssp_count = MTL_SSP_COUNT,
.d0i3_offset = MTL_HDA_VS_D0I3C,
.read_sdw_lcount = hda_sdw_check_lcount_ext,
- .enable_sdw_irq = lnl_enable_sdw_irq,
.check_sdw_irq = lnl_dsp_check_sdw_irq,
.check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq,
.sdw_process_wakeen = hda_sdw_process_wakeen_common,
@@ -262,7 +253,6 @@ const struct sof_intel_dsp_desc ptl_chip_info = {
.ssp_count = MTL_SSP_COUNT,
.d0i3_offset = MTL_HDA_VS_D0I3C,
.read_sdw_lcount = hda_sdw_check_lcount_ext,
- .enable_sdw_irq = lnl_enable_sdw_irq,
.check_sdw_irq = lnl_dsp_check_sdw_irq,
.check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq,
.check_ipc_irq = mtl_dsp_check_ipc_irq,
diff --git a/sound/soc/sof/iomem-utils.c b/sound/soc/sof/iomem-utils.c
index cd9cb54e7b23..f6cb79082672 100644
--- a/sound/soc/sof/iomem-utils.c
+++ b/sound/soc/sof/iomem-utils.c
@@ -10,7 +10,7 @@
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/platform_device.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <sound/soc.h>
#include <sound/sof.h>
#include "sof-priv.h"
diff --git a/sound/soc/sof/ipc3-loader.c b/sound/soc/sof/ipc3-loader.c
index 35b89c2b9d4c..7e9c76d5b2c9 100644
--- a/sound/soc/sof/ipc3-loader.c
+++ b/sound/soc/sof/ipc3-loader.c
@@ -193,6 +193,9 @@ static size_t sof_ipc3_fw_parse_ext_man(struct snd_sof_dev *sdev)
case SOF_EXT_MAN_ELEM_CC_VERSION:
ret = ipc3_fw_ext_man_get_cc_info(sdev, elem_hdr);
break;
+ case SOF_EXT_MAN_ELEM_PROBE_INFO:
+ dev_dbg(sdev->dev, "Probe info (not parsed)\n");
+ break;
case SOF_EXT_MAN_ELEM_DBG_ABI:
ret = ipc3_fw_ext_man_get_dbg_abi_info(sdev, elem_hdr);
break;
diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c
index 83c22d4a4830..7de5e3d285e7 100644
--- a/sound/soc/sof/ipc3.c
+++ b/sound/soc/sof/ipc3.c
@@ -226,7 +226,7 @@ static inline void ipc3_log_header(struct device *dev, u8 *text, u32 cmd)
static void sof_ipc3_dump_payload(struct snd_sof_dev *sdev,
void *ipc_data, size_t size)
{
- printk(KERN_DEBUG "Size of payload following the header: %zu\n", size);
+ dev_dbg(sdev->dev, "Size of payload following the header: %zu\n", size);
print_hex_dump_debug("Message payload: ", DUMP_PREFIX_OFFSET,
16, 4, ipc_data, size, false);
}
diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c
index 4df2be3d39eb..18fff2df76f9 100644
--- a/sound/soc/sof/ipc4-pcm.c
+++ b/sound/soc/sof/ipc4-pcm.c
@@ -603,6 +603,9 @@ static int sof_ipc4_pcm_dai_link_fixup_rate(struct snd_sof_dev *sdev,
unsigned int be_rate;
int i;
+ if (WARN_ON_ONCE(!num_input_formats))
+ return -EINVAL;
+
/*
* Copier does not change sampling rate, so we
* need to only consider the input pin information.
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index 87be7f16e8c2..b55eb977e443 100644
--- a/sound/soc/sof/ipc4-topology.c
+++ b/sound/soc/sof/ipc4-topology.c
@@ -195,7 +195,7 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_fo
for (i = 0; i < num_formats; i++) {
struct sof_ipc4_audio_format *fmt = &pin_fmt[i].audio_fmt;
dev_dbg(dev,
- "Pin index #%d: %uHz, %ubit, %luch (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n",
+ "Pin #%d: %uHz, %ubit, %luch (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n",
pin_fmt[i].pin_index, fmt->sampling_frequency, fmt->bit_depth,
SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg),
fmt->ch_map, fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg,
@@ -203,6 +203,101 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_fo
}
}
+static void
+sof_ipc4_dbg_module_audio_format(struct device *dev,
+ struct snd_sof_widget *swidget,
+ struct sof_ipc4_available_audio_format *available_fmt,
+ int in_fmt_index, int out_fmt_index)
+{
+ struct sof_ipc4_audio_format *in_fmt, *out_fmt;
+ u32 out_rate, out_channels, out_valid_bits;
+ u32 in_rate, in_channels, in_valid_bits;
+ struct sof_ipc4_pin_format *pin_fmt;
+
+ if (!available_fmt->num_input_formats &&
+ !available_fmt->num_output_formats)
+ return;
+
+ /* Only input or output is supported by the module */
+ if (!available_fmt->num_input_formats) {
+ if (available_fmt->num_output_formats == 1)
+ dev_dbg(dev, "Output audio format for %s:\n",
+ swidget->widget->name);
+ else
+ dev_dbg(dev,
+ "Output audio format (format index: %d) for %s:\n",
+ out_fmt_index, swidget->widget->name);
+
+ pin_fmt = &available_fmt->output_pin_fmts[out_fmt_index];
+ sof_ipc4_dbg_audio_format(dev, pin_fmt, 1);
+
+ return;
+ } else if (!available_fmt->num_output_formats) {
+ if (available_fmt->num_input_formats == 1)
+ dev_dbg(dev, "Input audio format for %s:\n",
+ swidget->widget->name);
+ else
+ dev_dbg(dev,
+ "Input audio format (format index: %d) for %s:\n",
+ out_fmt_index, swidget->widget->name);
+
+ pin_fmt = &available_fmt->input_pin_fmts[in_fmt_index];
+ sof_ipc4_dbg_audio_format(dev, pin_fmt, 1);
+
+ return;
+ }
+
+ in_fmt = &available_fmt->input_pin_fmts[in_fmt_index].audio_fmt;
+ out_fmt = &available_fmt->output_pin_fmts[out_fmt_index].audio_fmt;
+
+ in_rate = in_fmt->sampling_frequency;
+ in_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
+ in_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
+
+ out_rate = out_fmt->sampling_frequency;
+ out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(out_fmt->fmt_cfg);
+ out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg);
+
+ if (!(in_valid_bits != out_valid_bits || in_rate != out_rate ||
+ in_channels != out_channels)) {
+ /* There is no change in format */
+ if (available_fmt->num_input_formats == 1 &&
+ available_fmt->num_output_formats == 1)
+ dev_dbg(dev, "Audio format for %s:\n",
+ swidget->widget->name);
+ else
+ dev_dbg(dev,
+ "Audio format (in/out format index: %d/%d) for %s:\n",
+ in_fmt_index, out_fmt_index, swidget->widget->name);
+
+ pin_fmt = &available_fmt->input_pin_fmts[in_fmt_index];
+ sof_ipc4_dbg_audio_format(dev, pin_fmt, 1);
+
+ return;
+ }
+
+ /* The format is changed by the module */
+ if (available_fmt->num_input_formats == 1)
+ dev_dbg(dev, "Input audio format for %s:\n",
+ swidget->widget->name);
+ else
+ dev_dbg(dev, "Input audio format (format index: %d) for %s:\n",
+ in_fmt_index, swidget->widget->name);
+
+ pin_fmt = &available_fmt->input_pin_fmts[in_fmt_index];
+ sof_ipc4_dbg_audio_format(dev, pin_fmt, 1);
+
+ if (available_fmt->num_output_formats == 1)
+ dev_dbg(dev, "Output audio format for %s:\n",
+ swidget->widget->name);
+ else
+ dev_dbg(dev, "Output audio format (format index: %d) for %s:\n",
+ out_fmt_index, swidget->widget->name);
+
+ pin_fmt = &available_fmt->output_pin_fmts[out_fmt_index];
+ sof_ipc4_dbg_audio_format(dev, pin_fmt, 1);
+}
+
static const struct sof_ipc4_audio_format *
sof_ipc4_get_input_pin_audio_fmt(struct snd_sof_widget *swidget, int pin_index)
{
@@ -660,7 +755,6 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget)
* It is fine to call kfree(ipc4_copier->copier_config) since
* ipc4_copier->copier_config is null.
*/
- ret = 0;
break;
}
@@ -1205,47 +1299,56 @@ static bool sof_ipc4_is_single_format(struct snd_sof_dev *sdev,
}
static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev,
+ struct snd_sof_widget *swidget,
struct sof_ipc4_base_module_cfg *base_config,
struct sof_ipc4_available_audio_format *available_fmt,
u32 out_ref_rate, u32 out_ref_channels,
u32 out_ref_valid_bits)
{
- struct sof_ipc4_audio_format *out_fmt;
+ struct sof_ipc4_pin_format *pin_fmts = available_fmt->output_pin_fmts;
+ u32 pin_fmts_size = available_fmt->num_output_formats;
bool single_format;
- int i;
+ int i = 0;
- if (!available_fmt->num_output_formats)
+ if (!pin_fmts_size) {
+ dev_err(sdev->dev, "no output formats for %s\n",
+ swidget->widget->name);
return -EINVAL;
+ }
- single_format = sof_ipc4_is_single_format(sdev, available_fmt->output_pin_fmts,
- available_fmt->num_output_formats);
+ single_format = sof_ipc4_is_single_format(sdev, pin_fmts, pin_fmts_size);
/* pick the first format if there's only one available or if all formats are the same */
- if (single_format) {
- base_config->obs = available_fmt->output_pin_fmts[0].buffer_size;
- return 0;
- }
+ if (single_format)
+ goto out_fmt;
/*
* if there are multiple output formats, then choose the output format that matches
* the reference params
*/
- for (i = 0; i < available_fmt->num_output_formats; i++) {
+ for (i = 0; i < pin_fmts_size; i++) {
+ struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt;
+
u32 _out_rate, _out_channels, _out_valid_bits;
- out_fmt = &available_fmt->output_pin_fmts[i].audio_fmt;
- _out_rate = out_fmt->sampling_frequency;
- _out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(out_fmt->fmt_cfg);
- _out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg);
+ _out_rate = fmt->sampling_frequency;
+ _out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
+ _out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
if (_out_rate == out_ref_rate && _out_channels == out_ref_channels &&
- _out_valid_bits == out_ref_valid_bits) {
- base_config->obs = available_fmt->output_pin_fmts[i].buffer_size;
- return i;
- }
+ _out_valid_bits == out_ref_valid_bits)
+ goto out_fmt;
}
+ dev_err(sdev->dev, "%s: Unsupported audio format: %uHz, %ubit, %u channels\n",
+ __func__, out_ref_rate, out_ref_valid_bits, out_ref_channels);
+
return -EINVAL;
+
+out_fmt:
+ base_config->obs = pin_fmts[i].buffer_size;
+
+ return i;
}
static int sof_ipc4_get_valid_bits(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params)
@@ -1278,13 +1381,12 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
int sample_valid_bits;
int i = 0;
- if (!available_fmt->num_input_formats) {
+ if (!pin_fmts_size) {
dev_err(sdev->dev, "no input formats for %s\n", swidget->widget->name);
return -EINVAL;
}
- single_format = sof_ipc4_is_single_format(sdev, available_fmt->input_pin_fmts,
- available_fmt->num_input_formats);
+ single_format = sof_ipc4_is_single_format(sdev, pin_fmts, pin_fmts_size);
if (single_format)
goto in_fmt;
@@ -1306,11 +1408,8 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
if (params_rate(params) == rate && params_channels(params) == channels &&
- sample_valid_bits == valid_bits) {
- dev_dbg(sdev->dev, "matched audio format index for %uHz, %ubit, %u channels: %d\n",
- rate, valid_bits, channels, i);
+ sample_valid_bits == valid_bits)
break;
- }
}
if (i == pin_fmts_size) {
@@ -1321,16 +1420,11 @@ static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
in_fmt:
/* copy input format */
- if (available_fmt->num_input_formats && i < available_fmt->num_input_formats) {
- memcpy(&base_config->audio_fmt, &available_fmt->input_pin_fmts[i].audio_fmt,
- sizeof(struct sof_ipc4_audio_format));
-
- /* set base_cfg ibs/obs */
- base_config->ibs = available_fmt->input_pin_fmts[i].buffer_size;
+ memcpy(&base_config->audio_fmt, &pin_fmts[i].audio_fmt,
+ sizeof(struct sof_ipc4_audio_format));
- dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name);
- sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->input_pin_fmts[i], 1);
- }
+ /* set base_cfg ibs/obs */
+ base_config->ibs = pin_fmts[i].buffer_size;
return i;
}
@@ -1706,6 +1800,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
struct snd_soc_component *scomp = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct sof_ipc4_copier_data *copier_data;
+ int input_fmt_index, output_fmt_index;
struct snd_pcm_hw_params ref_params;
struct sof_ipc4_copier *ipc4_copier;
struct snd_sof_dai *dai;
@@ -1717,7 +1812,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
int ipc_size, ret, out_ref_valid_bits;
u32 out_ref_rate, out_ref_channels;
u32 deep_buffer_dma_ms = 0;
- int output_fmt_index;
bool single_output_bitdepth;
int i;
@@ -1849,10 +1943,11 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
}
/* set input and output audio formats */
- ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &copier_data->base_config,
- &ref_params, available_fmt);
- if (ret < 0)
- return ret;
+ input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
+ &copier_data->base_config,
+ &ref_params, available_fmt);
+ if (input_fmt_index < 0)
+ return input_fmt_index;
/* set the reference params for output format selection */
single_output_bitdepth = sof_ipc4_copier_is_single_bitdepth(sdev,
@@ -1865,7 +1960,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
{
struct sof_ipc4_audio_format *in_fmt;
- in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt;
+ in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
out_ref_rate = in_fmt->sampling_frequency;
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
@@ -1904,17 +1999,12 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg);
}
- dev_dbg(sdev->dev, "copier %s: reference output rate %d, channels %d valid_bits %d\n",
- swidget->widget->name, out_ref_rate, out_ref_channels, out_ref_valid_bits);
-
- output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, &copier_data->base_config,
+ output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
+ &copier_data->base_config,
available_fmt, out_ref_rate,
out_ref_channels, out_ref_valid_bits);
- if (output_fmt_index < 0) {
- dev_err(sdev->dev, "Failed to initialize output format for %s",
- swidget->widget->name);
+ if (output_fmt_index < 0)
return output_fmt_index;
- }
/*
* Set the output format. Current topology defines pin 0 input and output formats in pairs.
@@ -1926,8 +2016,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
memcpy(&copier_data->out_format,
&available_fmt->output_pin_fmts[output_fmt_index].audio_fmt,
sizeof(struct sof_ipc4_audio_format));
- dev_dbg(sdev->dev, "Output audio format for %s\n", swidget->widget->name);
- sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->output_pin_fmts[output_fmt_index], 1);
switch (swidget->id) {
case snd_soc_dapm_dai_in:
@@ -2104,6 +2192,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
*ipc_config_size = ipc_size;
+ sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt,
+ input_fmt_index, output_fmt_index);
+
/* update pipeline memory usage */
sof_ipc4_update_resource_usage(sdev, swidget, &copier_data->base_config);
@@ -2139,25 +2230,31 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt;
struct sof_ipc4_audio_format *in_fmt;
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
- int ret;
+ int input_fmt_index, output_fmt_index;
- ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &gain->data.base_config,
- pipeline_params, available_fmt);
- if (ret < 0)
- return ret;
+ input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
+ &gain->data.base_config,
+ pipeline_params,
+ available_fmt);
+ if (input_fmt_index < 0)
+ return input_fmt_index;
- in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt;
+ in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
out_ref_rate = in_fmt->sampling_frequency;
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
- ret = sof_ipc4_init_output_audio_fmt(sdev, &gain->data.base_config, available_fmt,
- out_ref_rate, out_ref_channels, out_ref_valid_bits);
- if (ret < 0) {
- dev_err(sdev->dev, "Failed to initialize output format for %s",
- swidget->widget->name);
- return ret;
- }
+ output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
+ &gain->data.base_config,
+ available_fmt,
+ out_ref_rate,
+ out_ref_channels,
+ out_ref_valid_bits);
+ if (output_fmt_index < 0)
+ return output_fmt_index;
+
+ sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt,
+ input_fmt_index, output_fmt_index);
/* update pipeline memory usage */
sof_ipc4_update_resource_usage(sdev, swidget, &gain->data.base_config);
@@ -2176,25 +2273,31 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt;
struct sof_ipc4_audio_format *in_fmt;
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
- int ret;
+ int input_fmt_index, output_fmt_index;
- ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &mixer->base_config,
- pipeline_params, available_fmt);
- if (ret < 0)
- return ret;
+ input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
+ &mixer->base_config,
+ pipeline_params,
+ available_fmt);
+ if (input_fmt_index < 0)
+ return input_fmt_index;
- in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt;
+ in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
out_ref_rate = in_fmt->sampling_frequency;
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
- ret = sof_ipc4_init_output_audio_fmt(sdev, &mixer->base_config, available_fmt,
- out_ref_rate, out_ref_channels, out_ref_valid_bits);
- if (ret < 0) {
- dev_err(sdev->dev, "Failed to initialize output format for %s",
- swidget->widget->name);
- return ret;
- }
+ output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
+ &mixer->base_config,
+ available_fmt,
+ out_ref_rate,
+ out_ref_channels,
+ out_ref_valid_bits);
+ if (output_fmt_index < 0)
+ return output_fmt_index;
+
+ sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt,
+ input_fmt_index, output_fmt_index);
/* update pipeline memory usage */
sof_ipc4_update_resource_usage(sdev, swidget, &mixer->base_config);
@@ -2214,12 +2317,14 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
struct sof_ipc4_audio_format *out_audio_fmt;
struct sof_ipc4_audio_format *in_audio_fmt;
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
- int output_format_index, input_format_index;
+ int output_fmt_index, input_fmt_index;
- input_format_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, &src->data.base_config,
- pipeline_params, available_fmt);
- if (input_format_index < 0)
- return input_format_index;
+ input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
+ &src->data.base_config,
+ pipeline_params,
+ available_fmt);
+ if (input_fmt_index < 0)
+ return input_fmt_index;
/*
* For playback, the SRC sink rate will be configured based on the requested output
@@ -2235,7 +2340,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
* SRC does not perform format conversion, so the output channels and valid bit depth must
* be the same as that of the input.
*/
- in_audio_fmt = &available_fmt->input_pin_fmts[input_format_index].audio_fmt;
+ in_audio_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_audio_fmt->fmt_cfg);
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_audio_fmt->fmt_cfg);
@@ -2246,19 +2351,22 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
*/
out_ref_rate = params_rate(fe_params);
- output_format_index = sof_ipc4_init_output_audio_fmt(sdev, &src->data.base_config,
- available_fmt, out_ref_rate,
- out_ref_channels, out_ref_valid_bits);
- if (output_format_index < 0) {
- dev_err(sdev->dev, "Failed to initialize output format for %s",
- swidget->widget->name);
- return output_format_index;
- }
+ output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
+ &src->data.base_config,
+ available_fmt,
+ out_ref_rate,
+ out_ref_channels,
+ out_ref_valid_bits);
+ if (output_fmt_index < 0)
+ return output_fmt_index;
+
+ sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt,
+ input_fmt_index, output_fmt_index);
/* update pipeline memory usage */
sof_ipc4_update_resource_usage(sdev, swidget, &src->data.base_config);
- out_audio_fmt = &available_fmt->output_pin_fmts[output_format_index].audio_fmt;
+ out_audio_fmt = &available_fmt->output_pin_fmts[output_fmt_index].audio_fmt;
src->data.sink_rate = out_audio_fmt->sampling_frequency;
/* update pipeline_params for sink widgets */
@@ -2355,49 +2463,61 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget,
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct sof_ipc4_process *process = swidget->private;
struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt;
- struct sof_ipc4_audio_format *in_fmt;
- u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
void *cfg = process->ipc_config_data;
- int output_fmt_index;
+ int output_fmt_index = 0;
+ int input_fmt_index = 0;
int ret;
- ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &process->base_config,
- pipeline_params, available_fmt);
- if (ret < 0)
- return ret;
+ input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
+ &process->base_config,
+ pipeline_params,
+ available_fmt);
+ if (input_fmt_index < 0)
+ return input_fmt_index;
- in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt;
- out_ref_rate = in_fmt->sampling_frequency;
- out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
- out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
+ /* Configure output audio format only if the module supports output */
+ if (available_fmt->num_output_formats) {
+ struct sof_ipc4_audio_format *in_fmt;
+ struct sof_ipc4_pin_format *pin_fmt;
+ u32 out_ref_rate, out_ref_channels;
+ int out_ref_valid_bits;
- output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, &process->base_config,
- available_fmt, out_ref_rate,
- out_ref_channels, out_ref_valid_bits);
- if (output_fmt_index < 0 && available_fmt->num_output_formats) {
- dev_err(sdev->dev, "Failed to initialize output format for %s",
- swidget->widget->name);
- return output_fmt_index;
- }
+ in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
- /* copy Pin 0 output format */
- if (available_fmt->num_output_formats &&
- output_fmt_index < available_fmt->num_output_formats &&
- !available_fmt->output_pin_fmts[output_fmt_index].pin_index) {
- memcpy(&process->output_format,
- &available_fmt->output_pin_fmts[output_fmt_index].audio_fmt,
- sizeof(struct sof_ipc4_audio_format));
-
- /* modify the pipeline params with the pin 0 output format */
- ret = sof_ipc4_update_hw_params(sdev, pipeline_params,
- &process->output_format,
- BIT(SNDRV_PCM_HW_PARAM_FORMAT) |
- BIT(SNDRV_PCM_HW_PARAM_CHANNELS) |
- BIT(SNDRV_PCM_HW_PARAM_RATE));
- if (ret)
- return ret;
+ out_ref_rate = in_fmt->sampling_frequency;
+ out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
+ out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
+
+ output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
+ &process->base_config,
+ available_fmt,
+ out_ref_rate,
+ out_ref_channels,
+ out_ref_valid_bits);
+ if (output_fmt_index < 0)
+ return output_fmt_index;
+
+ pin_fmt = &available_fmt->output_pin_fmts[output_fmt_index];
+
+ /* copy Pin output format for Pin 0 only */
+ if (pin_fmt->pin_index == 0) {
+ memcpy(&process->output_format, &pin_fmt->audio_fmt,
+ sizeof(struct sof_ipc4_audio_format));
+
+ /* modify the pipeline params with the output format */
+ ret = sof_ipc4_update_hw_params(sdev, pipeline_params,
+ &process->output_format,
+ BIT(SNDRV_PCM_HW_PARAM_FORMAT) |
+ BIT(SNDRV_PCM_HW_PARAM_CHANNELS) |
+ BIT(SNDRV_PCM_HW_PARAM_RATE));
+ if (ret)
+ return ret;
+ }
}
+ sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt,
+ input_fmt_index, output_fmt_index);
+
/* update pipeline memory usage */
sof_ipc4_update_resource_usage(sdev, swidget, &process->base_config);
@@ -3129,9 +3249,20 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
* group_id during copier's ipc_prepare op.
*/
if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
+ struct sof_ipc4_alh_configuration_blob *blob;
+
+ blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;
ipc4_copier->dai_index = data->dai_node_id;
- copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
- copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_node_id);
+
+ /*
+ * no need to set the node_id for aggregated DAI's. These will be assigned
+ * a group_id during widget ipc_prepare
+ */
+ if (blob->alh_cfg.device_count == 1) {
+ copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
+ copier_data->gtw_cfg.node_id |=
+ SOF_IPC4_NODE_INDEX(data->dai_node_id);
+ }
}
break;
diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c
index b12b3d865ae3..c0c906a78eba 100644
--- a/sound/soc/sof/nocodec.c
+++ b/sound/soc/sof/nocodec.c
@@ -55,10 +55,9 @@ static int sof_nocodec_bes_setup(struct device *dev,
links[i].no_pcm = 1;
links[i].cpus->dai_name = drv[i].name;
links[i].platforms->name = dev_name(dev->parent);
- if (drv[i].playback.channels_min)
- links[i].dpcm_playback = 1;
- if (drv[i].capture.channels_min)
- links[i].dpcm_capture = 1;
+
+ links[i].playback_only = drv[i].playback.channels_min && !drv[i].capture.channels_min;
+ links[i].capture_only = !drv[i].playback.channels_min && drv[i].capture.channels_min;
links[i].be_hw_params_fixup = sof_pcm_dai_link_fixup;
}
diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
index 2584621c3b2d..d73644e85b6e 100644
--- a/sound/soc/sof/ops.h
+++ b/sound/soc/sof/ops.h
@@ -597,12 +597,12 @@ snd_sof_is_chain_dma_supported(struct snd_sof_dev *sdev, u32 dai_type)
* @addr: Address to poll
* @val: Variable to read the value into
* @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
* @timeout_us: Timeout in us, 0 means never timeout
*
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
* case, the last read value at @addr is stored in @val. Must not
* be called from atomic context if sleep_us or timeout_us are used.
*
diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c
index b196b2b74c26..76ff798a4a1e 100644
--- a/sound/soc/sof/sof-acpi-dev.c
+++ b/sound/soc/sof/sof-acpi-dev.c
@@ -24,11 +24,11 @@
static char *fw_path;
module_param(fw_path, charp, 0444);
-MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware.");
+MODULE_PARM_DESC(fw_path, "deprecated - moved to snd-sof module.");
static char *tplg_path;
module_param(tplg_path, charp, 0444);
-MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology.");
+MODULE_PARM_DESC(tplg_path, "deprecated - moved to snd-sof module.");
static int sof_acpi_debug;
module_param_named(sof_acpi_debug, sof_acpi_debug, int, 0444);
diff --git a/sound/soc/sof/sof-client-probes-ipc4.c b/sound/soc/sof/sof-client-probes-ipc4.c
index 796eac0a2e74..603aed222480 100644
--- a/sound/soc/sof/sof-client-probes-ipc4.c
+++ b/sound/soc/sof/sof-client-probes-ipc4.c
@@ -125,6 +125,7 @@ static int ipc4_probes_init(struct sof_client_dev *cdev, u32 stream_tag,
msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG);
msg.extension = SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE(INVALID_PIPELINE_ID);
msg.extension |= SOF_IPC4_MOD_EXT_CORE_ID(0);
+ msg.extension |= SOF_IPC4_MOD_EXT_PARAM_SIZE(sizeof(cfg) / sizeof(uint32_t));
msg.data_size = sizeof(cfg);
msg.data_ptr = &cfg;
diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c
index 71f7153cf79c..fb8c8a14d885 100644
--- a/sound/soc/sof/sof-of-dev.c
+++ b/sound/soc/sof/sof-of-dev.c
@@ -16,11 +16,19 @@
static char *fw_path;
module_param(fw_path, charp, 0444);
-MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware.");
+MODULE_PARM_DESC(fw_path, "deprecated - moved to snd-sof module.");
+
+static char *fw_filename;
+module_param(fw_filename, charp, 0444);
+MODULE_PARM_DESC(fw_filename, "deprecated - moved to snd-sof module.");
static char *tplg_path;
module_param(tplg_path, charp, 0444);
-MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology.");
+MODULE_PARM_DESC(tplg_path, "deprecated - moved to snd-sof module.");
+
+static char *tplg_filename;
+module_param(tplg_filename, charp, 0444);
+MODULE_PARM_DESC(tplg_filename, "deprecated - moved to snd-sof module.");
const struct dev_pm_ops sof_of_pm = {
.prepare = snd_sof_prepare,
@@ -68,6 +76,8 @@ int sof_of_probe(struct platform_device *pdev)
sof_pdata->ipc_file_profile_base.ipc_type = desc->ipc_default;
sof_pdata->ipc_file_profile_base.fw_path = fw_path;
sof_pdata->ipc_file_profile_base.tplg_path = tplg_path;
+ sof_pdata->ipc_file_profile_base.fw_name = fw_filename;
+ sof_pdata->ipc_file_profile_base.tplg_name = tplg_filename;
/* set callback to be called on successful device probe to enable runtime_pm */
sof_pdata->sof_probe_complete = sof_of_probe_complete;
diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c
index 38f2187da5de..fe5650616573 100644
--- a/sound/soc/sof/sof-pci-dev.c
+++ b/sound/soc/sof/sof-pci-dev.c
@@ -22,23 +22,23 @@
static char *fw_path;
module_param(fw_path, charp, 0444);
-MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware.");
+MODULE_PARM_DESC(fw_path, "deprecated - moved to snd-sof module.");
static char *fw_filename;
module_param(fw_filename, charp, 0444);
-MODULE_PARM_DESC(fw_filename, "alternate filename for SOF firmware.");
+MODULE_PARM_DESC(fw_filename, "deprecated - moved to snd-sof module.");
static char *lib_path;
module_param(lib_path, charp, 0444);
-MODULE_PARM_DESC(lib_path, "alternate path for SOF firmware libraries.");
+MODULE_PARM_DESC(lib_path, "deprecated - moved to snd-sof module.");
static char *tplg_path;
module_param(tplg_path, charp, 0444);
-MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology.");
+MODULE_PARM_DESC(tplg_path, "deprecated - moved to snd-sof module.");
static char *tplg_filename;
module_param(tplg_filename, charp, 0444);
-MODULE_PARM_DESC(tplg_filename, "alternate filename for SOF topology.");
+MODULE_PARM_DESC(tplg_filename, "deprecated - moved to snd-sof module.");
static int sof_pci_debug;
module_param_named(sof_pci_debug, sof_pci_debug, int, 0444);
@@ -46,7 +46,7 @@ MODULE_PARM_DESC(sof_pci_debug, "SOF PCI debug options (0x0 all off)");
static int sof_pci_ipc_type = -1;
module_param_named(ipc_type, sof_pci_ipc_type, int, 0444);
-MODULE_PARM_DESC(ipc_type, "Force SOF IPC type. 0 - IPC3, 1 - IPC4");
+MODULE_PARM_DESC(ipc_type, "deprecated - moved to snd-sof module.");
static const char *sof_dmi_override_tplg_name;
static bool sof_dmi_use_community_key;
diff --git a/sound/soc/sof/sof-utils.c b/sound/soc/sof/sof-utils.c
index 44608682e9f8..f70089317b8c 100644
--- a/sound/soc/sof/sof-utils.c
+++ b/sound/soc/sof/sof-utils.c
@@ -8,7 +8,7 @@
// Author: Keyon Jie <yang.jie@linux.intel.com>
//
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/device.h>
#include <sound/memalloc.h>
diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c
index 9351727dce1a..c914d1c46850 100644
--- a/sound/soc/stm/stm32_adfsdm.c
+++ b/sound/soc/stm/stm32_adfsdm.c
@@ -142,7 +142,7 @@ static const struct snd_soc_dai_driver stm32_adfsdm_dai = {
SNDRV_PCM_FMTBIT_S32_LE,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 8000,
- .rate_max = 48000,
+ .rate_max = 192000,
},
.ops = &stm32_adfsdm_dai_ops,
};
@@ -309,7 +309,7 @@ static void stm32_adfsdm_cleanup(void *data)
iio_channel_release_all_cb(data);
}
-static struct snd_soc_component_driver stm32_adfsdm_soc_platform = {
+static const struct snd_soc_component_driver stm32_adfsdm_soc_platform = {
.open = stm32_adfsdm_pcm_open,
.close = stm32_adfsdm_pcm_close,
.hw_params = stm32_adfsdm_pcm_hw_params,
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
index faa00103ee7f..19dc61008a75 100644
--- a/sound/soc/stm/stm32_i2s.c
+++ b/sound/soc/stm/stm32_i2s.c
@@ -200,10 +200,13 @@ enum i2s_datlen {
#define STM32_I2S_NAME_LEN 32
#define STM32_I2S_RATE_11K 11025
+#define STM32_I2S_MAX_SAMPLE_RATE_8K 192000
+#define STM32_I2S_MAX_SAMPLE_RATE_11K 176400
+#define STM32_I2S_CLK_RATE_TOLERANCE 1000 /* ppm */
/**
* struct stm32_i2s_data - private data of I2S
- * @regmap_conf: I2S register map configuration pointer
+ * @conf: I2S configuration pointer
* @regmap: I2S register map pointer
* @pdev: device data pointer
* @dai_drv: DAI driver pointer
@@ -224,11 +227,14 @@ enum i2s_datlen {
* @divider: prescaler division ratio
* @div: prescaler div field
* @odd: prescaler odd field
+ * @i2s_clk_flg: flag set while exclusivity on I2S kernel clock is active
* @refcount: keep count of opened streams on I2S
* @ms_flg: master mode flag.
+ * @set_i2s_clk_rate: set I2S kernel clock rate
+ * @put_i2s_clk_rate: put I2S kernel clock rate
*/
struct stm32_i2s_data {
- const struct regmap_config *regmap_conf;
+ const struct stm32_i2s_conf *conf;
struct regmap *regmap;
struct platform_device *pdev;
struct snd_soc_dai_driver *dai_drv;
@@ -249,8 +255,21 @@ struct stm32_i2s_data {
unsigned int divider;
unsigned int div;
bool odd;
+ bool i2s_clk_flg;
int refcount;
int ms_flg;
+ int (*set_i2s_clk_rate)(struct stm32_i2s_data *i2s, unsigned int rate);
+ void (*put_i2s_clk_rate)(struct stm32_i2s_data *i2s);
+};
+
+/**
+ * struct stm32_i2s_conf - I2S configuration
+ * @regmap_conf: regmap configuration pointer
+ * @get_i2s_clk_parent: get parent clock of I2S kernel clock
+ */
+struct stm32_i2s_conf {
+ const struct regmap_config *regmap_conf;
+ int (*get_i2s_clk_parent)(struct stm32_i2s_data *i2s);
};
struct stm32_i2smclk_data {
@@ -261,6 +280,8 @@ struct stm32_i2smclk_data {
#define to_mclk_data(_hw) container_of(_hw, struct stm32_i2smclk_data, hw)
+static int stm32_i2s_get_parent_clk(struct stm32_i2s_data *i2s);
+
static int stm32_i2s_calc_clk_div(struct stm32_i2s_data *i2s,
unsigned long input_rate,
unsigned long output_rate)
@@ -312,6 +333,33 @@ static int stm32_i2s_set_clk_div(struct stm32_i2s_data *i2s)
cgfr_mask, cgfr);
}
+static bool stm32_i2s_rate_accurate(struct stm32_i2s_data *i2s,
+ unsigned int max_rate, unsigned int rate)
+{
+ struct platform_device *pdev = i2s->pdev;
+ u64 delta, dividend;
+ int ratio;
+
+ if (!rate) {
+ dev_err(&pdev->dev, "Unexpected null rate\n");
+ return false;
+ }
+
+ ratio = DIV_ROUND_CLOSEST(max_rate, rate);
+ if (!ratio)
+ return false;
+
+ dividend = mul_u32_u32(1000000, abs(max_rate - (ratio * rate)));
+ delta = div_u64(dividend, max_rate);
+
+ if (delta <= STM32_I2S_CLK_RATE_TOLERANCE)
+ return true;
+
+ dev_dbg(&pdev->dev, "Rate [%u] not accurate\n", rate);
+
+ return false;
+}
+
static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s,
unsigned int rate)
{
@@ -332,6 +380,87 @@ static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s,
return ret;
}
+static void stm32_i2s_put_parent_rate(struct stm32_i2s_data *i2s)
+{
+ if (i2s->i2s_clk_flg) {
+ i2s->i2s_clk_flg = false;
+ clk_rate_exclusive_put(i2s->i2sclk);
+ }
+}
+
+static int stm32_i2s_set_parent_rate(struct stm32_i2s_data *i2s,
+ unsigned int rate)
+{
+ struct platform_device *pdev = i2s->pdev;
+ unsigned int i2s_clk_rate, i2s_clk_max_rate, i2s_curr_rate, i2s_new_rate;
+ int ret, div;
+
+ /*
+ * Set maximum expected kernel clock frequency
+ * - mclk on:
+ * f_i2s_ck = MCKDIV * mclk-fs * fs
+ * Here typical 256 ratio is assumed for mclk-fs
+ * - mclk off:
+ * f_i2s_ck = MCKDIV * FRL * fs
+ * Where FRL=[16,32], MCKDIV=[1..256]
+ * f_i2s_ck = i2s_clk_max_rate * 32 / 256
+ */
+ if (!(rate % STM32_I2S_RATE_11K))
+ i2s_clk_max_rate = STM32_I2S_MAX_SAMPLE_RATE_11K * 256;
+ else
+ i2s_clk_max_rate = STM32_I2S_MAX_SAMPLE_RATE_8K * 256;
+
+ if (!i2s->i2smclk)
+ i2s_clk_max_rate /= 8;
+
+ /* Request exclusivity, as the clock may be shared by I2S instances */
+ clk_rate_exclusive_get(i2s->i2sclk);
+ i2s->i2s_clk_flg = true;
+
+ /*
+ * Check current kernel clock rate. If it gives the expected accuracy
+ * return immediately.
+ */
+ i2s_curr_rate = clk_get_rate(i2s->i2sclk);
+ if (stm32_i2s_rate_accurate(i2s, i2s_clk_max_rate, i2s_curr_rate))
+ return 0;
+
+ /*
+ * Otherwise try to set the maximum rate and check the new actual rate.
+ * If the new rate does not give the expected accuracy, try to set
+ * lower rates for the kernel clock.
+ */
+ i2s_clk_rate = i2s_clk_max_rate;
+ div = 1;
+ do {
+ /* Check new rate accuracy. Return if ok */
+ i2s_new_rate = clk_round_rate(i2s->i2sclk, i2s_clk_rate);
+ if (stm32_i2s_rate_accurate(i2s, i2s_clk_rate, i2s_new_rate)) {
+ ret = clk_set_rate(i2s->i2sclk, i2s_clk_rate);
+ if (ret) {
+ dev_err(&pdev->dev, "Error %d setting i2s_clk_rate rate. %s",
+ ret, ret == -EBUSY ?
+ "Active stream rates may be in conflict\n" : "\n");
+ goto err;
+ }
+
+ return 0;
+ }
+
+ /* Try a lower frequency */
+ div++;
+ i2s_clk_rate = i2s_clk_max_rate / div;
+ } while (i2s_clk_rate > rate);
+
+ /* no accurate rate found */
+ dev_err(&pdev->dev, "Failed to find an accurate rate");
+
+err:
+ stm32_i2s_put_parent_rate(i2s);
+
+ return -EINVAL;
+}
+
static long stm32_i2smclk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
@@ -635,12 +764,16 @@ static int stm32_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
clk_rate_exclusive_put(i2s->i2smclk);
i2s->mclk_rate = 0;
}
+
+ if (i2s->put_i2s_clk_rate)
+ i2s->put_i2s_clk_rate(i2s);
+
return regmap_update_bits(i2s->regmap,
STM32_I2S_CGFR_REG,
I2S_CGFR_MCKOE, 0);
}
/* If master clock is used, set parent clock now */
- ret = stm32_i2s_set_parent_clock(i2s, freq);
+ ret = i2s->set_i2s_clk_rate(i2s, freq);
if (ret)
return ret;
ret = clk_set_rate_exclusive(i2s->i2smclk, freq);
@@ -667,10 +800,11 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai,
u32 cgfr;
int ret;
- if (!(rate % 11025))
- clk_set_parent(i2s->i2sclk, i2s->x11kclk);
- else
- clk_set_parent(i2s->i2sclk, i2s->x8kclk);
+ if (!i2s->mclk_rate) {
+ ret = i2s->set_i2s_clk_rate(i2s, rate);
+ if (ret)
+ return ret;
+ }
i2s_clock_rate = clk_get_rate(i2s->i2sclk);
/*
@@ -915,6 +1049,14 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream,
clk_disable_unprepare(i2s->i2sclk);
+ /*
+ * Release kernel clock if following conditions are fulfilled
+ * - Master clock is not used. Kernel clock won't be released trough sysclk
+ * - Put handler is defined. Involve that clock is managed exclusively
+ */
+ if (!i2s->i2smclk && i2s->put_i2s_clk_rate)
+ i2s->put_i2s_clk_rate(i2s);
+
spin_lock_irqsave(&i2s->irq_lock, flags);
i2s->substream = NULL;
spin_unlock_irqrestore(&i2s->irq_lock, flags);
@@ -1012,14 +1154,36 @@ static int stm32_i2s_dais_init(struct platform_device *pdev,
return 0;
}
+static const struct stm32_i2s_conf stm32_i2s_conf_h7 = {
+ .regmap_conf = &stm32_h7_i2s_regmap_conf,
+ .get_i2s_clk_parent = stm32_i2s_get_parent_clk,
+};
+
+static const struct stm32_i2s_conf stm32_i2s_conf_mp25 = {
+ .regmap_conf = &stm32_h7_i2s_regmap_conf
+};
+
static const struct of_device_id stm32_i2s_ids[] = {
- {
- .compatible = "st,stm32h7-i2s",
- .data = &stm32_h7_i2s_regmap_conf
- },
+ { .compatible = "st,stm32h7-i2s", .data = &stm32_i2s_conf_h7 },
+ { .compatible = "st,stm32mp25-i2s", .data = &stm32_i2s_conf_mp25 },
{},
};
+static int stm32_i2s_get_parent_clk(struct stm32_i2s_data *i2s)
+{
+ struct device *dev = &i2s->pdev->dev;
+
+ i2s->x8kclk = devm_clk_get(dev, "x8k");
+ if (IS_ERR(i2s->x8kclk))
+ return dev_err_probe(dev, PTR_ERR(i2s->x8kclk), "Cannot get x8k parent clock\n");
+
+ i2s->x11kclk = devm_clk_get(dev, "x11k");
+ if (IS_ERR(i2s->x11kclk))
+ return dev_err_probe(dev, PTR_ERR(i2s->x11kclk), "Cannot get x11k parent clock\n");
+
+ return 0;
+}
+
static int stm32_i2s_parse_dt(struct platform_device *pdev,
struct stm32_i2s_data *i2s)
{
@@ -1031,8 +1195,8 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
if (!np)
return -ENODEV;
- i2s->regmap_conf = device_get_match_data(&pdev->dev);
- if (!i2s->regmap_conf)
+ i2s->conf = device_get_match_data(&pdev->dev);
+ if (!i2s->conf)
return -EINVAL;
i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
@@ -1052,15 +1216,18 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
return dev_err_probe(&pdev->dev, PTR_ERR(i2s->i2sclk),
"Could not get i2sclk\n");
- i2s->x8kclk = devm_clk_get(&pdev->dev, "x8k");
- if (IS_ERR(i2s->x8kclk))
- return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x8kclk),
- "Could not get x8k parent clock\n");
+ if (i2s->conf->get_i2s_clk_parent) {
+ i2s->set_i2s_clk_rate = stm32_i2s_set_parent_clock;
+ } else {
+ i2s->set_i2s_clk_rate = stm32_i2s_set_parent_rate;
+ i2s->put_i2s_clk_rate = stm32_i2s_put_parent_rate;
+ }
- i2s->x11kclk = devm_clk_get(&pdev->dev, "x11k");
- if (IS_ERR(i2s->x11kclk))
- return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x11kclk),
- "Could not get x11k parent clock\n");
+ if (i2s->conf->get_i2s_clk_parent) {
+ ret = i2s->conf->get_i2s_clk_parent(i2s);
+ if (ret)
+ return ret;
+ }
/* Register mclk provider if requested */
if (of_property_present(np, "#clock-cells")) {
@@ -1126,7 +1293,7 @@ static int stm32_i2s_probe(struct platform_device *pdev)
return ret;
i2s->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "pclk",
- i2s->base, i2s->regmap_conf);
+ i2s->base, i2s->conf->regmap_conf);
if (IS_ERR(i2s->regmap))
return dev_err_probe(&pdev->dev, PTR_ERR(i2s->regmap),
"Regmap init error\n");
diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
index b45ee7e24f22..bc8180fc8462 100644
--- a/sound/soc/stm/stm32_sai.c
+++ b/sound/soc/stm/stm32_sai.c
@@ -19,26 +19,42 @@
#include "stm32_sai.h"
+static int stm32_sai_get_parent_clk(struct stm32_sai_data *sai);
+
static const struct stm32_sai_conf stm32_sai_conf_f4 = {
.version = STM_SAI_STM32F4,
.fifo_size = 8,
.has_spdif_pdm = false,
+ .get_sai_ck_parent = stm32_sai_get_parent_clk,
};
/*
- * Default settings for stm32 H7 socs and next.
+ * Default settings for STM32H7x socs and STM32MP1x.
* These default settings will be overridden if the soc provides
* support of hardware configuration registers.
+ * - STM32H7: rely on default settings
+ * - STM32MP1: retrieve settings from registers
*/
static const struct stm32_sai_conf stm32_sai_conf_h7 = {
.version = STM_SAI_STM32H7,
.fifo_size = 8,
.has_spdif_pdm = true,
+ .get_sai_ck_parent = stm32_sai_get_parent_clk,
+};
+
+/*
+ * STM32MP2x:
+ * - do not use SAI parent clock source selection
+ * - do not use DMA burst mode
+ */
+static const struct stm32_sai_conf stm32_sai_conf_mp25 = {
+ .no_dma_burst = true,
};
static const struct of_device_id stm32_sai_ids[] = {
{ .compatible = "st,stm32f4-sai", .data = (void *)&stm32_sai_conf_f4 },
{ .compatible = "st,stm32h7-sai", .data = (void *)&stm32_sai_conf_h7 },
+ { .compatible = "st,stm32mp25-sai", .data = (void *)&stm32_sai_conf_mp25 },
{}
};
@@ -148,6 +164,29 @@ error:
return ret;
}
+static int stm32_sai_get_parent_clk(struct stm32_sai_data *sai)
+{
+ struct device *dev = &sai->pdev->dev;
+
+ sai->clk_x8k = devm_clk_get(dev, "x8k");
+ if (IS_ERR(sai->clk_x8k)) {
+ if (PTR_ERR(sai->clk_x8k) != -EPROBE_DEFER)
+ dev_err(dev, "missing x8k parent clock: %ld\n",
+ PTR_ERR(sai->clk_x8k));
+ return PTR_ERR(sai->clk_x8k);
+ }
+
+ sai->clk_x11k = devm_clk_get(dev, "x11k");
+ if (IS_ERR(sai->clk_x11k)) {
+ if (PTR_ERR(sai->clk_x11k) != -EPROBE_DEFER)
+ dev_err(dev, "missing x11k parent clock: %ld\n",
+ PTR_ERR(sai->clk_x11k));
+ return PTR_ERR(sai->clk_x11k);
+ }
+
+ return 0;
+}
+
static int stm32_sai_probe(struct platform_device *pdev)
{
struct stm32_sai_data *sai;
@@ -160,6 +199,8 @@ static int stm32_sai_probe(struct platform_device *pdev)
if (!sai)
return -ENOMEM;
+ sai->pdev = pdev;
+
sai->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sai->base))
return PTR_ERR(sai->base);
@@ -178,15 +219,11 @@ static int stm32_sai_probe(struct platform_device *pdev)
"missing bus clock pclk\n");
}
- sai->clk_x8k = devm_clk_get(&pdev->dev, "x8k");
- if (IS_ERR(sai->clk_x8k))
- return dev_err_probe(&pdev->dev, PTR_ERR(sai->clk_x8k),
- "missing x8k parent clock\n");
-
- sai->clk_x11k = devm_clk_get(&pdev->dev, "x11k");
- if (IS_ERR(sai->clk_x11k))
- return dev_err_probe(&pdev->dev, PTR_ERR(sai->clk_x11k),
- "missing x11k parent clock\n");
+ if (sai->conf.get_sai_ck_parent) {
+ ret = sai->conf.get_sai_ck_parent(sai);
+ if (ret)
+ return ret;
+ }
/* init irqs */
sai->irq = platform_get_irq(pdev, 0);
@@ -227,7 +264,6 @@ static int stm32_sai_probe(struct platform_device *pdev)
}
clk_disable_unprepare(sai->pclk);
- sai->pdev = pdev;
sai->set_sync = &stm32_sai_set_sync;
platform_set_drvdata(pdev, sai);
diff --git a/sound/soc/stm/stm32_sai.h b/sound/soc/stm/stm32_sai.h
index 33e4bff8c2f5..07b71133db2a 100644
--- a/sound/soc/stm/stm32_sai.h
+++ b/sound/soc/stm/stm32_sai.h
@@ -264,16 +264,22 @@ enum stm32_sai_syncout {
STM_SAI_SYNC_OUT_B,
};
+struct stm32_sai_data;
+
/**
* struct stm32_sai_conf - SAI configuration
+ * @get_sai_ck_parent: get parent clock of SAI kernel clock
* @version: SAI version
* @fifo_size: SAI fifo size as words number
* @has_spdif_pdm: SAI S/PDIF and PDM features support flag
+ * @no_dma_burst: Support only DMA single transfers if set
*/
struct stm32_sai_conf {
+ int (*get_sai_ck_parent)(struct stm32_sai_data *sai);
u32 version;
u32 fifo_size;
bool has_spdif_pdm;
+ bool no_dma_burst;
};
/**
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 7bc4a96b7503..3efbf4aaf965 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -53,13 +53,16 @@
#define STM_SAI_PROTOCOL_IS_SPDIF(ip) ((ip)->spdif)
#define STM_SAI_HAS_SPDIF(x) ((x)->pdata->conf.has_spdif_pdm)
#define STM_SAI_HAS_PDM(x) ((x)->pdata->conf.has_spdif_pdm)
-#define STM_SAI_HAS_EXT_SYNC(x) (!STM_SAI_IS_F4(sai->pdata))
+#define STM_SAI_HAS_EXT_SYNC(x) (!STM_SAI_IS_F4((x)->pdata))
#define SAI_IEC60958_BLOCK_FRAMES 192
#define SAI_IEC60958_STATUS_BYTES 24
#define SAI_MCLK_NAME_LEN 32
#define SAI_RATE_11K 11025
+#define SAI_MAX_SAMPLE_RATE_8K 192000
+#define SAI_MAX_SAMPLE_RATE_11K 176400
+#define SAI_CK_RATE_TOLERANCE 1000 /* ppm */
/**
* struct stm32_sai_sub_data - private data of SAI sub block (block A or B)
@@ -80,6 +83,7 @@
* @dir: SAI block direction (playback or capture). set at init
* @master: SAI block mode flag. (true=master, false=slave) set at init
* @spdif: SAI S/PDIF iec60958 mode flag. set at init
+ * @sai_ck_used: flag set while exclusivity on SAI kernel clock is active
* @fmt: SAI block format. relevant only for custom protocols. set at init
* @sync: SAI block synchronization mode. (none, internal or external)
* @synco: SAI block ext sync source (provider setting). (none, sub-block A/B)
@@ -93,6 +97,8 @@
* @iec958: iec958 data
* @ctrl_lock: control lock
* @irq_lock: prevent race condition with IRQ
+ * @set_sai_ck_rate: set SAI kernel clock rate
+ * @put_sai_ck_rate: put SAI kernel clock rate
*/
struct stm32_sai_sub_data {
struct platform_device *pdev;
@@ -112,6 +118,7 @@ struct stm32_sai_sub_data {
int dir;
bool master;
bool spdif;
+ bool sai_ck_used;
int fmt;
int sync;
int synco;
@@ -125,6 +132,8 @@ struct stm32_sai_sub_data {
struct snd_aes_iec958 iec958;
struct mutex ctrl_lock; /* protect resources accessed by controls */
spinlock_t irq_lock; /* used to prevent race condition with IRQ */
+ int (*set_sai_ck_rate)(struct stm32_sai_sub_data *sai, unsigned int rate);
+ void (*put_sai_ck_rate)(struct stm32_sai_sub_data *sai);
};
enum stm32_sai_fifo_th {
@@ -317,7 +326,7 @@ static int stm32_sai_get_clk_div(struct stm32_sai_sub_data *sai,
int div;
div = DIV_ROUND_CLOSEST(input_rate, output_rate);
- if (div > SAI_XCR1_MCKDIV_MAX(version)) {
+ if (div > SAI_XCR1_MCKDIV_MAX(version) || div <= 0) {
dev_err(&sai->pdev->dev, "Divider %d out of range\n", div);
return -EINVAL;
}
@@ -351,8 +360,26 @@ static int stm32_sai_set_clk_div(struct stm32_sai_sub_data *sai,
return ret;
}
-static int stm32_sai_set_parent_clock(struct stm32_sai_sub_data *sai,
- unsigned int rate)
+static bool stm32_sai_rate_accurate(unsigned int max_rate, unsigned int rate)
+{
+ u64 delta, dividend;
+ int ratio;
+
+ ratio = DIV_ROUND_CLOSEST(max_rate, rate);
+ if (!ratio)
+ return false;
+
+ dividend = mul_u32_u32(1000000, abs(max_rate - (ratio * rate)));
+ delta = div_u64(dividend, max_rate);
+
+ if (delta <= SAI_CK_RATE_TOLERANCE)
+ return true;
+
+ return false;
+}
+
+static int stm32_sai_set_parent_clk(struct stm32_sai_sub_data *sai,
+ unsigned int rate)
{
struct platform_device *pdev = sai->pdev;
struct clk *parent_clk = sai->pdata->clk_x8k;
@@ -370,6 +397,92 @@ static int stm32_sai_set_parent_clock(struct stm32_sai_sub_data *sai,
return ret;
}
+static void stm32_sai_put_parent_rate(struct stm32_sai_sub_data *sai)
+{
+ if (sai->sai_ck_used) {
+ sai->sai_ck_used = false;
+ clk_rate_exclusive_put(sai->sai_ck);
+ }
+}
+
+static int stm32_sai_set_parent_rate(struct stm32_sai_sub_data *sai,
+ unsigned int rate)
+{
+ struct platform_device *pdev = sai->pdev;
+ unsigned int sai_ck_rate, sai_ck_max_rate, sai_curr_rate, sai_new_rate;
+ int div, ret;
+
+ /*
+ * Set maximum expected kernel clock frequency
+ * - mclk on or spdif:
+ * f_sai_ck = MCKDIV * mclk-fs * fs
+ * Here typical 256 ratio is assumed for mclk-fs
+ * - mclk off:
+ * f_sai_ck = MCKDIV * FRL * fs
+ * Where FRL=[8..256], MCKDIV=[1..n] (n depends on SAI version)
+ * Set constraint MCKDIV * FRL <= 256, to ensure MCKDIV is in available range
+ * f_sai_ck = sai_ck_max_rate * pow_of_two(FRL) / 256
+ */
+ if (!(rate % SAI_RATE_11K))
+ sai_ck_max_rate = SAI_MAX_SAMPLE_RATE_11K * 256;
+ else
+ sai_ck_max_rate = SAI_MAX_SAMPLE_RATE_8K * 256;
+
+ if (!sai->sai_mclk && !STM_SAI_PROTOCOL_IS_SPDIF(sai))
+ sai_ck_max_rate /= DIV_ROUND_CLOSEST(256, roundup_pow_of_two(sai->fs_length));
+
+ /*
+ * Request exclusivity, as the clock is shared by SAI sub-blocks and by
+ * some SAI instances. This allows to ensure that the rate cannot be
+ * changed while one or more SAIs are using the clock.
+ */
+ clk_rate_exclusive_get(sai->sai_ck);
+ sai->sai_ck_used = true;
+
+ /*
+ * Check current kernel clock rate. If it gives the expected accuracy
+ * return immediately.
+ */
+ sai_curr_rate = clk_get_rate(sai->sai_ck);
+ if (stm32_sai_rate_accurate(sai_ck_max_rate, sai_curr_rate))
+ return 0;
+
+ /*
+ * Otherwise try to set the maximum rate and check the new actual rate.
+ * If the new rate does not give the expected accuracy, try to set
+ * lower rates for the kernel clock.
+ */
+ sai_ck_rate = sai_ck_max_rate;
+ div = 1;
+ do {
+ /* Check new rate accuracy. Return if ok */
+ sai_new_rate = clk_round_rate(sai->sai_ck, sai_ck_rate);
+ if (stm32_sai_rate_accurate(sai_ck_rate, sai_new_rate)) {
+ ret = clk_set_rate(sai->sai_ck, sai_ck_rate);
+ if (ret) {
+ dev_err(&pdev->dev, "Error %d setting sai_ck rate. %s",
+ ret, ret == -EBUSY ?
+ "Active stream rates may be in conflict\n" : "\n");
+ goto err;
+ }
+
+ return 0;
+ }
+
+ /* Try a lower frequency */
+ div++;
+ sai_ck_rate = sai_ck_max_rate / div;
+ } while (sai_ck_rate > rate);
+
+ /* No accurate rate found */
+ dev_err(&pdev->dev, "Failed to find an accurate rate");
+
+err:
+ stm32_sai_put_parent_rate(sai);
+
+ return -EINVAL;
+}
+
static long stm32_sai_mclk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
@@ -378,8 +491,8 @@ static long stm32_sai_mclk_round_rate(struct clk_hw *hw, unsigned long rate,
int div;
div = stm32_sai_get_clk_div(sai, *prate, rate);
- if (div < 0)
- return div;
+ if (div <= 0)
+ return -EINVAL;
mclk->freq = *prate / div;
@@ -565,11 +678,15 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai,
clk_rate_exclusive_put(sai->sai_mclk);
sai->mclk_rate = 0;
}
+
+ if (sai->put_sai_ck_rate)
+ sai->put_sai_ck_rate(sai);
+
return 0;
}
- /* If master clock is used, set parent clock now */
- ret = stm32_sai_set_parent_clock(sai, freq);
+ /* If master clock is used, configure SAI kernel clock now */
+ ret = sai->set_sai_ck_rate(sai, freq);
if (ret)
return ret;
@@ -993,7 +1110,7 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
int ret;
if (!sai->sai_mclk) {
- ret = stm32_sai_set_parent_clock(sai, rate);
+ ret = sai->set_sai_ck_rate(sai, rate);
if (ret)
return ret;
}
@@ -1154,6 +1271,14 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream,
clk_disable_unprepare(sai->sai_ck);
+ /*
+ * Release kernel clock if following conditions are fulfilled
+ * - Master clock is not used. Kernel clock won't be released trough sysclk
+ * - Put handler is defined. Involve that clock is managed exclusively
+ */
+ if (!sai->sai_mclk && sai->put_sai_ck_rate)
+ sai->put_sai_ck_rate(sai);
+
spin_lock_irqsave(&sai->irq_lock, flags);
sai->substream = NULL;
spin_unlock_irqrestore(&sai->irq_lock, flags);
@@ -1188,7 +1313,7 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
* constraints).
*/
sai->dma_params.maxburst = 4;
- if (sai->pdata->conf.fifo_size < 8)
+ if (sai->pdata->conf.fifo_size < 8 || sai->pdata->conf.no_dma_burst)
sai->dma_params.maxburst = 1;
/* Buswidth will be set by framework at runtime */
sai->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
@@ -1526,6 +1651,13 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
return -EINVAL;
}
+ if (sai->pdata->conf.get_sai_ck_parent) {
+ sai->set_sai_ck_rate = stm32_sai_set_parent_clk;
+ } else {
+ sai->set_sai_ck_rate = stm32_sai_set_parent_rate;
+ sai->put_sai_ck_rate = stm32_sai_put_parent_rate;
+ }
+
ret = stm32_sai_sub_parse_of(pdev, sai);
if (ret)
return ret;
diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c
index d1b32ba1e1a2..9e30852de93c 100644
--- a/sound/soc/stm/stm32_spdifrx.c
+++ b/sound/soc/stm/stm32_spdifrx.c
@@ -939,7 +939,7 @@ static void stm32_spdifrx_remove(struct platform_device *pdev)
{
struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev);
- if (spdifrx->ctrl_chan)
+ if (!IS_ERR(spdifrx->ctrl_chan))
dma_release_channel(spdifrx->ctrl_chan);
if (spdifrx->dmab)
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index 330bc0c09f56..933a0913237c 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -226,6 +226,43 @@
#define SUN8I_H3_CODEC_DAC_DBG (0x48)
#define SUN8I_H3_CODEC_ADC_DBG (0x4c)
+/* H616 specific registers */
+#define SUN50I_H616_CODEC_DAC_FIFOC (0x10)
+
+#define SUN50I_DAC_FIFO_STA (0x14)
+#define SUN50I_DAC_TXE_INT (3)
+#define SUN50I_DAC_TXU_INT (2)
+#define SUN50I_DAC_TXO_INT (1)
+
+#define SUN50I_DAC_CNT (0x24)
+#define SUN50I_DAC_DG_REG (0x28)
+#define SUN50I_DAC_DAP_CTL (0xf0)
+
+#define SUN50I_H616_DAC_AC_DAC_REG (0x310)
+#define SUN50I_H616_DAC_LEN (15)
+#define SUN50I_H616_DAC_REN (14)
+#define SUN50I_H616_LINEOUTL_EN (13)
+#define SUN50I_H616_LMUTE (12)
+#define SUN50I_H616_LINEOUTR_EN (11)
+#define SUN50I_H616_RMUTE (10)
+#define SUN50I_H616_RSWITCH (9)
+#define SUN50I_H616_RAMPEN (8)
+#define SUN50I_H616_LINEOUTL_SEL (6)
+#define SUN50I_H616_LINEOUTR_SEL (5)
+#define SUN50I_H616_LINEOUT_VOL (0)
+
+#define SUN50I_H616_DAC_AC_MIXER_REG (0x314)
+#define SUN50I_H616_LMIX_LDAC (21)
+#define SUN50I_H616_LMIX_RDAC (20)
+#define SUN50I_H616_RMIX_RDAC (17)
+#define SUN50I_H616_RMIX_LDAC (16)
+#define SUN50I_H616_LMIXEN (11)
+#define SUN50I_H616_RMIXEN (10)
+
+#define SUN50I_H616_DAC_AC_RAMP_REG (0x31c)
+#define SUN50I_H616_RAMP_STEP (4)
+#define SUN50I_H616_RDEN (0)
+
/* TODO H3 DAP (Digital Audio Processing) bits */
struct sun4i_codec {
@@ -238,6 +275,8 @@ struct sun4i_codec {
/* ADC_FIFOC register is at different offset on different SoCs */
struct regmap_field *reg_adc_fifoc;
+ /* DAC_FIFOC register is at different offset on different SoCs */
+ struct regmap_field *reg_dac_fifoc;
struct snd_dmaengine_dai_dma_data capture_dma_data;
struct snd_dmaengine_dai_dma_data playback_dma_data;
@@ -246,19 +285,19 @@ struct sun4i_codec {
static void sun4i_codec_start_playback(struct sun4i_codec *scodec)
{
/* Flush TX FIFO */
- regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
+ regmap_field_set_bits(scodec->reg_dac_fifoc,
+ BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
/* Enable DAC DRQ */
- regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN));
+ regmap_field_set_bits(scodec->reg_dac_fifoc,
+ BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN));
}
static void sun4i_codec_stop_playback(struct sun4i_codec *scodec)
{
/* Disable DAC DRQ */
- regmap_clear_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN));
+ regmap_field_clear_bits(scodec->reg_dac_fifoc,
+ BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN));
}
static void sun4i_codec_start_capture(struct sun4i_codec *scodec)
@@ -356,13 +395,13 @@ static int sun4i_codec_prepare_playback(struct snd_pcm_substream *substream,
u32 val;
/* Flush the TX FIFO */
- regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
+ regmap_field_set_bits(scodec->reg_dac_fifoc,
+ BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
/* Set TX FIFO Empty Trigger Level */
- regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- 0x3f << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL,
- 0xf << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL);
+ regmap_field_update_bits(scodec->reg_dac_fifoc,
+ 0x3f << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL,
+ 0xf << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL);
if (substream->runtime->rate > 32000)
/* Use 64 bits FIR filter */
@@ -371,13 +410,13 @@ static int sun4i_codec_prepare_playback(struct snd_pcm_substream *substream,
/* Use 32 bits FIR filter */
val = BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION);
- regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION),
- val);
+ regmap_field_update_bits(scodec->reg_dac_fifoc,
+ BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION),
+ val);
/* Send zeros when we have an underrun */
- regmap_clear_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- BIT(SUN4I_CODEC_DAC_FIFOC_SEND_LASAT));
+ regmap_field_clear_bits(scodec->reg_dac_fifoc,
+ BIT(SUN4I_CODEC_DAC_FIFOC_SEND_LASAT));
return 0;
};
@@ -510,9 +549,9 @@ static int sun4i_codec_hw_params_playback(struct sun4i_codec *scodec,
u32 val;
/* Set DAC sample rate */
- regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- 7 << SUN4I_CODEC_DAC_FIFOC_DAC_FS,
- hwrate << SUN4I_CODEC_DAC_FIFOC_DAC_FS);
+ regmap_field_update_bits(scodec->reg_dac_fifoc,
+ 7 << SUN4I_CODEC_DAC_FIFOC_DAC_FS,
+ hwrate << SUN4I_CODEC_DAC_FIFOC_DAC_FS);
/* Set the number of channels we want to use */
if (params_channels(params) == 1)
@@ -520,27 +559,27 @@ static int sun4i_codec_hw_params_playback(struct sun4i_codec *scodec,
else
val = 0;
- regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN),
- val);
+ regmap_field_update_bits(scodec->reg_dac_fifoc,
+ BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN),
+ val);
/* Set the number of sample bits to either 16 or 24 bits */
if (hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min == 32) {
- regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS));
+ regmap_field_set_bits(scodec->reg_dac_fifoc,
+ BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS));
/* Set TX FIFO mode to padding the LSBs with 0 */
- regmap_clear_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE));
+ regmap_field_clear_bits(scodec->reg_dac_fifoc,
+ BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE));
scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
} else {
- regmap_clear_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS));
+ regmap_field_clear_bits(scodec->reg_dac_fifoc,
+ BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS));
/* Set TX FIFO mode to repeat the MSB */
- regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE));
+ regmap_field_set_bits(scodec->reg_dac_fifoc,
+ BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE));
scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
}
@@ -587,8 +626,8 @@ static int sun4i_codec_startup(struct snd_pcm_substream *substream,
* Stop issuing DRQ when we have room for less than 16 samples
* in our TX FIFO
*/
- regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
- 3 << SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT);
+ regmap_field_set_bits(scodec->reg_dac_fifoc,
+ 3 << SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT);
return clk_prepare_enable(scodec->clk_module);
}
@@ -1518,6 +1557,150 @@ static struct snd_soc_card *sun8i_v3s_codec_create_card(struct device *dev)
return card;
};
+static const struct snd_kcontrol_new sun50i_h616_codec_codec_controls[] = {
+ SOC_SINGLE_TLV("DAC Playback Volume", SUN4I_CODEC_DAC_DPC,
+ SUN4I_CODEC_DAC_DPC_DVOL, 0x3f, 1,
+ sun6i_codec_dvol_scale),
+ SOC_SINGLE_TLV("Line Out Playback Volume",
+ SUN50I_H616_DAC_AC_DAC_REG,
+ SUN50I_H616_LINEOUT_VOL, 0x1f, 0,
+ sun6i_codec_lineout_vol_scale),
+ SOC_DOUBLE("Line Out Playback Switch",
+ SUN50I_H616_DAC_AC_DAC_REG,
+ SUN50I_H616_LINEOUTL_EN,
+ SUN50I_H616_LINEOUTR_EN, 1, 0),
+};
+
+static const struct snd_kcontrol_new sun50i_h616_codec_mixer_controls[] = {
+ SOC_DAPM_DOUBLE("DAC Playback Switch",
+ SUN50I_H616_DAC_AC_MIXER_REG,
+ SUN50I_H616_LMIX_LDAC,
+ SUN50I_H616_RMIX_RDAC, 1, 0),
+ SOC_DAPM_DOUBLE("DAC Reversed Playback Switch",
+ SUN50I_H616_DAC_AC_MIXER_REG,
+ SUN50I_H616_LMIX_RDAC,
+ SUN50I_H616_RMIX_LDAC, 1, 0),
+};
+
+static SOC_ENUM_DOUBLE_DECL(sun50i_h616_codec_lineout_src_enum,
+ SUN50I_H616_DAC_AC_DAC_REG,
+ SUN50I_H616_LINEOUTL_SEL,
+ SUN50I_H616_LINEOUTR_SEL,
+ sun6i_codec_lineout_src_enum_text);
+
+static const struct snd_kcontrol_new sun50i_h616_codec_lineout_src[] = {
+ SOC_DAPM_ENUM("Line Out Source Playback Route",
+ sun50i_h616_codec_lineout_src_enum),
+};
+
+static const struct snd_soc_dapm_widget sun50i_h616_codec_codec_widgets[] = {
+ /* Digital parts of the DACs */
+ SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC,
+ SUN4I_CODEC_DAC_DPC_EN_DA, 0,
+ NULL, 0),
+
+ /* Analog parts of the DACs */
+ SND_SOC_DAPM_DAC("Left DAC", "Codec Playback",
+ SUN50I_H616_DAC_AC_DAC_REG,
+ SUN50I_H616_DAC_LEN, 0),
+ SND_SOC_DAPM_DAC("Right DAC", "Codec Playback",
+ SUN50I_H616_DAC_AC_DAC_REG,
+ SUN50I_H616_DAC_REN, 0),
+
+ /* Mixers */
+ SOC_MIXER_ARRAY("Left Mixer", SUN50I_H616_DAC_AC_MIXER_REG,
+ SUN50I_H616_LMIXEN, 0,
+ sun50i_h616_codec_mixer_controls),
+ SOC_MIXER_ARRAY("Right Mixer", SUN50I_H616_DAC_AC_MIXER_REG,
+ SUN50I_H616_RMIXEN, 0,
+ sun50i_h616_codec_mixer_controls),
+
+ /* Line Out path */
+ SND_SOC_DAPM_MUX("Line Out Source Playback Route",
+ SND_SOC_NOPM, 0, 0, sun50i_h616_codec_lineout_src),
+ SND_SOC_DAPM_OUT_DRV("Line Out Ramp Controller",
+ SUN50I_H616_DAC_AC_RAMP_REG,
+ SUN50I_H616_RDEN, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("LINEOUT"),
+};
+
+static const struct snd_soc_component_driver sun50i_h616_codec_codec = {
+ .controls = sun50i_h616_codec_codec_controls,
+ .num_controls = ARRAY_SIZE(sun50i_h616_codec_codec_controls),
+ .dapm_widgets = sun50i_h616_codec_codec_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sun50i_h616_codec_codec_widgets),
+ .idle_bias_on = 1,
+ .use_pmdown_time = 1,
+ .endianness = 1,
+};
+
+static const struct snd_kcontrol_new sun50i_h616_card_controls[] = {
+ SOC_DAPM_PIN_SWITCH("LINEOUT"),
+};
+
+static const struct snd_soc_dapm_widget sun50i_h616_codec_card_dapm_widgets[] = {
+ SND_SOC_DAPM_LINE("Line Out", NULL),
+ SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
+};
+
+/* Connect digital side enables to analog side widgets */
+static const struct snd_soc_dapm_route sun50i_h616_codec_card_routes[] = {
+ /* DAC Routes */
+ { "Left DAC", NULL, "DAC Enable" },
+ { "Right DAC", NULL, "DAC Enable" },
+
+ /* Left Mixer Routes */
+ { "Left Mixer", "DAC Playback Switch", "Left DAC" },
+ { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
+
+ /* Right Mixer Routes */
+ { "Right Mixer", "DAC Playback Switch", "Right DAC" },
+ { "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
+
+ /* Line Out Routes */
+ { "Line Out Source Playback Route", "Stereo", "Left Mixer" },
+ { "Line Out Source Playback Route", "Stereo", "Right Mixer" },
+ { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" },
+ { "Line Out Source Playback Route", "Mono Differential", "Right Mixer" },
+ { "Line Out Ramp Controller", NULL, "Line Out Source Playback Route" },
+ { "LINEOUT", NULL, "Line Out Ramp Controller" },
+};
+
+static struct snd_soc_card *sun50i_h616_codec_create_card(struct device *dev)
+{
+ struct snd_soc_card *card;
+ int ret;
+
+ card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
+ if (!card)
+ return ERR_PTR(-ENOMEM);
+
+ card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
+ if (!card->dai_link)
+ return ERR_PTR(-ENOMEM);
+
+ card->dai_link->playback_only = true;
+ card->dai_link->capture_only = false;
+
+ card->dev = dev;
+ card->owner = THIS_MODULE;
+ card->name = "H616 Audio Codec";
+ card->driver_name = "sun4i-codec";
+ card->controls = sun50i_h616_card_controls;
+ card->num_controls = ARRAY_SIZE(sun50i_h616_card_controls);
+ card->dapm_widgets = sun50i_h616_codec_card_dapm_widgets;
+ card->num_dapm_widgets = ARRAY_SIZE(sun50i_h616_codec_card_dapm_widgets);
+ card->dapm_routes = sun50i_h616_codec_card_routes;
+ card->num_dapm_routes = ARRAY_SIZE(sun50i_h616_codec_card_routes);
+ card->fully_routed = true;
+
+ ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
+ if (ret)
+ dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
+
+ return card;
+};
+
static const struct regmap_config sun4i_codec_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -1560,14 +1743,24 @@ static const struct regmap_config sun8i_v3s_codec_regmap_config = {
.max_register = SUN8I_H3_CODEC_ADC_DBG,
};
+static const struct regmap_config sun50i_h616_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = SUN50I_H616_DAC_AC_RAMP_REG,
+ .cache_type = REGCACHE_NONE,
+};
+
struct sun4i_codec_quirks {
const struct regmap_config *regmap_config;
const struct snd_soc_component_driver *codec;
struct snd_soc_card * (*create_card)(struct device *dev);
struct reg_field reg_adc_fifoc; /* used for regmap_field */
+ struct reg_field reg_dac_fifoc; /* used for regmap_field */
unsigned int reg_dac_txdata; /* TX FIFO offset for DMA config */
unsigned int reg_adc_rxdata; /* RX FIFO offset for DMA config */
bool has_reset;
+ bool playback_only;
};
static const struct sun4i_codec_quirks sun4i_codec_quirks = {
@@ -1575,6 +1768,7 @@ static const struct sun4i_codec_quirks sun4i_codec_quirks = {
.codec = &sun4i_codec_codec,
.create_card = sun4i_codec_create_card,
.reg_adc_fifoc = REG_FIELD(SUN4I_CODEC_ADC_FIFOC, 0, 31),
+ .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
.reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
.reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA,
};
@@ -1584,6 +1778,7 @@ static const struct sun4i_codec_quirks sun6i_a31_codec_quirks = {
.codec = &sun6i_codec_codec,
.create_card = sun6i_codec_create_card,
.reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
+ .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
.reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
.reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
.has_reset = true,
@@ -1594,6 +1789,7 @@ static const struct sun4i_codec_quirks sun7i_codec_quirks = {
.codec = &sun7i_codec_codec,
.create_card = sun4i_codec_create_card,
.reg_adc_fifoc = REG_FIELD(SUN4I_CODEC_ADC_FIFOC, 0, 31),
+ .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
.reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
.reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA,
};
@@ -1603,6 +1799,7 @@ static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = {
.codec = &sun8i_a23_codec_codec,
.create_card = sun8i_a23_codec_create_card,
.reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
+ .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
.reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
.reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
.has_reset = true,
@@ -1618,6 +1815,7 @@ static const struct sun4i_codec_quirks sun8i_h3_codec_quirks = {
.codec = &sun8i_a23_codec_codec,
.create_card = sun8i_h3_codec_create_card,
.reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
+ .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
.reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
.reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
.has_reset = true,
@@ -1632,11 +1830,21 @@ static const struct sun4i_codec_quirks sun8i_v3s_codec_quirks = {
.codec = &sun8i_a23_codec_codec,
.create_card = sun8i_v3s_codec_create_card,
.reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
+ .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
.reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
.reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
.has_reset = true,
};
+static const struct sun4i_codec_quirks sun50i_h616_codec_quirks = {
+ .regmap_config = &sun50i_h616_codec_regmap_config,
+ .codec = &sun50i_h616_codec_codec,
+ .create_card = sun50i_h616_codec_create_card,
+ .reg_dac_fifoc = REG_FIELD(SUN50I_H616_CODEC_DAC_FIFOC, 0, 31),
+ .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
+ .has_reset = true,
+};
+
static const struct of_device_id sun4i_codec_of_match[] = {
{
.compatible = "allwinner,sun4i-a10-codec",
@@ -1662,6 +1870,10 @@ static const struct of_device_id sun4i_codec_of_match[] = {
.compatible = "allwinner,sun8i-v3s-codec",
.data = &sun8i_v3s_codec_quirks,
},
+ {
+ .compatible = "allwinner,sun50i-h616-codec",
+ .data = &sun50i_h616_codec_quirks,
+ },
{}
};
MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
@@ -1739,6 +1951,16 @@ static int sun4i_codec_probe(struct platform_device *pdev)
return ret;
}
+ scodec->reg_dac_fifoc = devm_regmap_field_alloc(&pdev->dev,
+ scodec->regmap,
+ quirks->reg_dac_fifoc);
+ if (IS_ERR(scodec->reg_dac_fifoc)) {
+ ret = PTR_ERR(scodec->reg_dac_fifoc);
+ dev_err(&pdev->dev, "Failed to create regmap fields: %d\n",
+ ret);
+ return ret;
+ }
+
/* Enable the bus clock */
if (clk_prepare_enable(scodec->clk_apb)) {
dev_err(&pdev->dev, "Failed to enable the APB clock\n");
@@ -1760,10 +1982,13 @@ static int sun4i_codec_probe(struct platform_device *pdev)
scodec->playback_dma_data.maxburst = 8;
scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
- /* DMA configuration for RX FIFO */
- scodec->capture_dma_data.addr = res->start + quirks->reg_adc_rxdata;
- scodec->capture_dma_data.maxburst = 8;
- scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ if (!quirks->playback_only) {
+ /* DMA configuration for RX FIFO */
+ scodec->capture_dma_data.addr = res->start +
+ quirks->reg_adc_rxdata;
+ scodec->capture_dma_data.maxburst = 8;
+ scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ }
ret = devm_snd_soc_register_component(&pdev->dev, quirks->codec,
&sun4i_codec_dai, 1);
@@ -1837,4 +2062,5 @@ MODULE_AUTHOR("Emilio López <emilio@elopez.com.ar>");
MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
+MODULE_AUTHOR("Ryan Walklin <ryan@testtoast.com");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c
index 508128b7783e..1be6c09cbe1a 100644
--- a/sound/soc/tegra/tegra186_dspk.c
+++ b/sound/soc/tegra/tegra186_dspk.c
@@ -245,6 +245,7 @@ static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream,
cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
cif_conf.client_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
cif_conf.client_bits = TEGRA_ACIF_BITS_24;
@@ -313,6 +314,7 @@ static struct snd_soc_dai_driver tegra186_dspk_dais[] = {
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
},
@@ -324,6 +326,7 @@ static struct snd_soc_dai_driver tegra186_dspk_dais[] = {
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra186_dspk_dai_ops,
diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c
index a866aeb2719d..58fdb0e79954 100644
--- a/sound/soc/tegra/tegra210_admaif.c
+++ b/sound/soc/tegra/tegra210_admaif.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_admaif.c - Tegra ADMAIF driver
-//
-// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -285,6 +285,11 @@ static int tegra_admaif_hw_params(struct snd_pcm_substream *substream,
cif_conf.client_bits = TEGRA_ACIF_BITS_16;
valid_bit = DATA_16BIT;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
+ cif_conf.client_bits = TEGRA_ACIF_BITS_24;
+ valid_bit = DATA_32BIT;
+ break;
case SNDRV_PCM_FORMAT_S32_LE:
cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
cif_conf.client_bits = TEGRA_ACIF_BITS_32;
@@ -561,6 +566,7 @@ static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
@@ -570,6 +576,7 @@ static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra_admaif_dai_ops, \
diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c
index 109f763fe211..3e6e8f51f380 100644
--- a/sound/soc/tegra/tegra210_adx.c
+++ b/sound/soc/tegra/tegra210_adx.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_adx.c - Tegra210 ADX driver
-//
-// Copyright (c) 2021-2023 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -127,6 +127,7 @@ static int tegra210_adx_set_audio_cif(struct snd_soc_dai *dai,
case SNDRV_PCM_FORMAT_S16_LE:
audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -237,6 +238,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
@@ -246,6 +248,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra210_adx_in_dai_ops, \
@@ -261,6 +264,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
@@ -270,6 +274,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra210_adx_out_dai_ops, \
diff --git a/sound/soc/tegra/tegra210_amx.c b/sound/soc/tegra/tegra210_amx.c
index 38a2d6ec033b..a9ef22c19e81 100644
--- a/sound/soc/tegra/tegra210_amx.c
+++ b/sound/soc/tegra/tegra210_amx.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_amx.c - Tegra210 AMX driver
-//
-// Copyright (c) 2021-2023 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -144,6 +144,7 @@ static int tegra210_amx_set_audio_cif(struct snd_soc_dai *dai,
case SNDRV_PCM_FORMAT_S16_LE:
audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -266,6 +267,7 @@ static const struct snd_soc_dai_ops tegra210_amx_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
@@ -275,6 +277,7 @@ static const struct snd_soc_dai_ops tegra210_amx_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra210_amx_in_dai_ops, \
@@ -290,6 +293,7 @@ static const struct snd_soc_dai_ops tegra210_amx_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
@@ -299,6 +303,7 @@ static const struct snd_soc_dai_ops tegra210_amx_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra210_amx_out_dai_ops, \
diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c
index d9b577f146dc..7986be71f43d 100644
--- a/sound/soc/tegra/tegra210_dmic.c
+++ b/sound/soc/tegra/tegra210_dmic.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_dmic.c - Tegra210 DMIC driver
-//
-// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -139,6 +139,7 @@ static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream,
case SNDRV_PCM_FORMAT_S16_LE:
cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -325,6 +326,7 @@ static struct snd_soc_dai_driver tegra210_dmic_dais[] = {
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
},
@@ -336,6 +338,7 @@ static struct snd_soc_dai_driver tegra210_dmic_dais[] = {
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_dmic_dai_ops,
diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c
index a3908b15dfdc..07ce2dbe6c00 100644
--- a/sound/soc/tegra/tegra210_i2s.c
+++ b/sound/soc/tegra/tegra210_i2s.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_i2s.c - Tegra210 I2S driver
-//
-// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -629,6 +629,7 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
case SNDRV_PCM_FORMAT_S16_LE:
cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -656,6 +657,11 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
sample_size = 16;
cif_conf.client_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ val = I2S_BITS_24;
+ sample_size = 32;
+ cif_conf.client_bits = TEGRA_ACIF_BITS_24;
+ break;
case SNDRV_PCM_FORMAT_S32_LE:
val = I2S_BITS_32;
sample_size = 32;
@@ -720,6 +726,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -729,6 +736,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
},
@@ -741,6 +749,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -750,6 +759,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_i2s_dai_ops,
diff --git a/sound/soc/tegra/tegra210_i2s.h b/sound/soc/tegra/tegra210_i2s.h
index fe478f3d8435..543332de7405 100644
--- a/sound/soc/tegra/tegra210_i2s.h
+++ b/sound/soc/tegra/tegra210_i2s.h
@@ -1,8 +1,8 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * tegra210_i2s.h - Definitions for Tegra210 I2S driver
+/* SPDX-License-Identifier: GPL-2.0-only
+ * SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES.
+ * All rights reserved.
*
- * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
+ * tegra210_i2s.h - Definitions for Tegra210 I2S driver
*
*/
@@ -87,6 +87,7 @@
#define I2S_BITS_8 1
#define I2S_BITS_16 3
+#define I2S_BITS_24 5
#define I2S_BITS_32 7
#define I2S_CTRL_BIT_SIZE_MASK 0x7
diff --git a/sound/soc/tegra/tegra210_mixer.c b/sound/soc/tegra/tegra210_mixer.c
index e07e2f1d2f70..410259d98dfb 100644
--- a/sound/soc/tegra/tegra210_mixer.c
+++ b/sound/soc/tegra/tegra210_mixer.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_mixer.c - Tegra210 MIXER driver
-//
-// Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -248,6 +248,7 @@ static int tegra210_mixer_set_audio_cif(struct tegra210_mixer *mixer,
case SNDRV_PCM_FORMAT_S16_LE:
audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -312,6 +313,7 @@ static const struct snd_soc_dai_ops tegra210_mixer_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
@@ -321,6 +323,7 @@ static const struct snd_soc_dai_ops tegra210_mixer_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra210_mixer_in_dai_ops, \
@@ -336,6 +339,7 @@ static const struct snd_soc_dai_ops tegra210_mixer_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
@@ -345,6 +349,7 @@ static const struct snd_soc_dai_ops tegra210_mixer_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra210_mixer_out_dai_ops, \
diff --git a/sound/soc/tegra/tegra210_mvc.c b/sound/soc/tegra/tegra210_mvc.c
index 4ead52564ab6..119f17501478 100644
--- a/sound/soc/tegra/tegra210_mvc.c
+++ b/sound/soc/tegra/tegra210_mvc.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_mvc.c - Tegra210 MVC driver
-//
-// Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -441,6 +441,7 @@ static int tegra210_mvc_set_audio_cif(struct tegra210_mvc *mvc,
case SNDRV_PCM_FORMAT_S16_LE:
audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -569,6 +570,7 @@ static struct snd_soc_dai_driver tegra210_mvc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -578,6 +580,7 @@ static struct snd_soc_dai_driver tegra210_mvc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
},
@@ -592,6 +595,7 @@ static struct snd_soc_dai_driver tegra210_mvc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -601,6 +605,7 @@ static struct snd_soc_dai_driver tegra210_mvc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_mvc_dai_ops,
diff --git a/sound/soc/tegra/tegra210_ope.c b/sound/soc/tegra/tegra210_ope.c
index e2bc604e8b79..c595cec9baab 100644
--- a/sound/soc/tegra/tegra210_ope.c
+++ b/sound/soc/tegra/tegra210_ope.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_ope.c - Tegra210 OPE driver
-//
-// Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -47,6 +47,7 @@ static int tegra210_ope_set_audio_cif(struct tegra210_ope *ope,
case SNDRV_PCM_FORMAT_S16_LE:
audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -129,6 +130,7 @@ static struct snd_soc_dai_driver tegra210_ope_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -138,6 +140,7 @@ static struct snd_soc_dai_driver tegra210_ope_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
},
@@ -150,6 +153,7 @@ static struct snd_soc_dai_driver tegra210_ope_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -159,6 +163,7 @@ static struct snd_soc_dai_driver tegra210_ope_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_ope_dai_ops,
diff --git a/sound/soc/tegra/tegra210_sfc.c b/sound/soc/tegra/tegra210_sfc.c
index e16bbb44cc77..df88708c733c 100644
--- a/sound/soc/tegra/tegra210_sfc.c
+++ b/sound/soc/tegra/tegra210_sfc.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_sfc.c - Tegra210 SFC driver
-//
-// Copyright (c) 2021-2023 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -3133,6 +3133,7 @@ static int tegra210_sfc_set_audio_cif(struct tegra210_sfc *sfc,
case SNDRV_PCM_FORMAT_S16_LE:
audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -3395,6 +3396,7 @@ static struct snd_soc_dai_driver tegra210_sfc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -3404,6 +3406,7 @@ static struct snd_soc_dai_driver tegra210_sfc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_sfc_in_dai_ops,
@@ -3417,6 +3420,7 @@ static struct snd_soc_dai_driver tegra210_sfc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -3426,6 +3430,7 @@ static struct snd_soc_dai_driver tegra210_sfc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_sfc_out_dai_ops,
diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c
index 77296237575a..d9900c69e536 100644
--- a/sound/soc/ti/rx51.c
+++ b/sound/soc/ti/rx51.c
@@ -371,7 +371,7 @@ static int rx51_soc_probe(struct platform_device *pdev)
dai_node = of_parse_phandle(np, "nokia,cpu-dai", 0);
if (!dai_node) {
- dev_err(&pdev->dev, "McBSP node is not provided\n");
+ dev_err(card->dev, "McBSP node is not provided\n");
return -EINVAL;
}
rx51_dai[0].cpus->dai_name = NULL;
@@ -381,7 +381,7 @@ static int rx51_soc_probe(struct platform_device *pdev)
dai_node = of_parse_phandle(np, "nokia,audio-codec", 0);
if (!dai_node) {
- dev_err(&pdev->dev, "Codec node is not provided\n");
+ dev_err(card->dev, "Codec node is not provided\n");
return -EINVAL;
}
rx51_dai[0].codecs->name = NULL;
@@ -389,7 +389,7 @@ static int rx51_soc_probe(struct platform_device *pdev)
dai_node = of_parse_phandle(np, "nokia,audio-codec", 1);
if (!dai_node) {
- dev_err(&pdev->dev, "Auxiliary Codec node is not provided\n");
+ dev_err(card->dev, "Auxiliary Codec node is not provided\n");
return -EINVAL;
}
rx51_aux_dev[0].dlc.name = NULL;
@@ -399,7 +399,7 @@ static int rx51_soc_probe(struct platform_device *pdev)
dai_node = of_parse_phandle(np, "nokia,headphone-amplifier", 0);
if (!dai_node) {
- dev_err(&pdev->dev, "Headphone amplifier node is not provided\n");
+ dev_err(card->dev, "Headphone amplifier node is not provided\n");
return -EINVAL;
}
rx51_aux_dev[1].dlc.name = NULL;
@@ -408,7 +408,7 @@ static int rx51_soc_probe(struct platform_device *pdev)
rx51_codec_conf[1].dlc.of_node = dai_node;
}
- pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ pdata = devm_kzalloc(card->dev, sizeof(*pdata), GFP_KERNEL);
if (pdata == NULL)
return -ENOMEM;
@@ -439,7 +439,7 @@ static int rx51_soc_probe(struct platform_device *pdev)
err = devm_snd_soc_register_card(card->dev, card);
if (err) {
- dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", err);
+ dev_err(card->dev, "snd_soc_register_card failed (%d)\n", err);
return err;
}
diff --git a/sound/soc/uniphier/aio-core.c b/sound/soc/uniphier/aio-core.c
index 0eba60758134..d63def8615eb 100644
--- a/sound/soc/uniphier/aio-core.c
+++ b/sound/soc/uniphier/aio-core.c
@@ -838,6 +838,7 @@ int aio_oport_set_stream_type(struct uniphier_aio_sub *sub,
{
struct regmap *r = sub->aio->chip->regmap;
u32 repet = 0, pause = OPORTMXPAUDAT_PAUSEPC_CMN;
+ int ret;
switch (pc) {
case IEC61937_PC_AC3:
@@ -880,8 +881,13 @@ int aio_oport_set_stream_type(struct uniphier_aio_sub *sub,
break;
}
- regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet);
- regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause);
+ ret = regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause);
+ if (ret)
+ return ret;
return 0;
}
@@ -921,16 +927,19 @@ int aio_src_set_param(struct uniphier_aio_sub *sub,
{
struct regmap *r = sub->aio->chip->regmap;
u32 v;
+ int ret;
if (sub->swm->dir != PORT_DIR_OUTPUT)
return 0;
- regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map),
+ ret = regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map),
OPORTMXSRC1CTR_THMODE_SRC |
OPORTMXSRC1CTR_SRCPATH_CALC |
OPORTMXSRC1CTR_SYNC_ASYNC |
OPORTMXSRC1CTR_FSIIPSEL_INNER |
OPORTMXSRC1CTR_FSISEL_ACLK);
+ if (ret)
+ return ret;
switch (params_rate(params)) {
default:
@@ -951,12 +960,18 @@ int aio_src_set_param(struct uniphier_aio_sub *sub,
break;
}
- regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map),
+
+ ret = regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map),
v | OPORTMXRATE_I_ACLKSRC_APLL |
OPORTMXRATE_I_LRCKSTP_STOP);
- regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map),
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map),
OPORTMXRATE_I_LRCKSTP_MASK,
OPORTMXRATE_I_LRCKSTP_START);
+ if (ret)
+ return ret;
return 0;
}
diff --git a/sound/soc/uniphier/evea.c b/sound/soc/uniphier/evea.c
index 662e45882c90..f6c6eb95262a 100644
--- a/sound/soc/uniphier/evea.c
+++ b/sound/soc/uniphier/evea.c
@@ -384,7 +384,7 @@ err_out_clock:
return ret;
}
-static struct snd_soc_component_driver soc_codec_evea = {
+static const struct snd_soc_component_driver soc_codec_evea = {
.probe = evea_codec_probe,
.suspend = evea_codec_suspend,
.resume = evea_codec_resume,
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
index a2dd739fdf2d..7798957c6504 100644
--- a/sound/soc/ux500/ux500_msp_dai.c
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -733,7 +733,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev)
drvdata->reg_vape = devm_regulator_get(&pdev->dev, "v-ape");
if (IS_ERR(drvdata->reg_vape)) {
- ret = (int)PTR_ERR(drvdata->reg_vape);
+ ret = PTR_ERR(drvdata->reg_vape);
dev_err(&pdev->dev,
"%s: ERROR: Failed to get Vape supply (%d)!\n",
__func__, ret);
@@ -743,7 +743,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev)
drvdata->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
if (IS_ERR(drvdata->pclk)) {
- ret = (int)PTR_ERR(drvdata->pclk);
+ ret = PTR_ERR(drvdata->pclk);
dev_err(&pdev->dev,
"%s: ERROR: devm_clk_get of pclk failed (%d)!\n",
__func__, ret);
@@ -752,7 +752,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev)
drvdata->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(drvdata->clk)) {
- ret = (int)PTR_ERR(drvdata->clk);
+ ret = PTR_ERR(drvdata->clk);
dev_err(&pdev->dev,
"%s: ERROR: devm_clk_get failed (%d)!\n",
__func__, ret);
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index a1339f9ef12a..1b44119edfbc 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -2107,7 +2107,7 @@ static struct platform_driver cs4231_driver = {
.of_match_table = cs4231_match,
},
.probe = cs4231_probe,
- .remove_new = cs4231_remove,
+ .remove = cs4231_remove,
};
module_platform_driver(cs4231_driver);
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 050e98f32d36..69f1c9e37f4b 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -2616,7 +2616,7 @@ static int dbri_probe(struct platform_device *op)
strcpy(card->driver, "DBRI");
strcpy(card->shortname, "Sun DBRI");
rp = &op->resource[0];
- sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d",
+ sprintf(card->longname, "%s at 0x%02lx:0x%016llx, irq %d",
card->shortname,
rp->flags & 0xffL, (unsigned long long)rp->start, irq);
@@ -2682,7 +2682,7 @@ static struct platform_driver dbri_sbus_driver = {
.of_match_table = dbri_match,
},
.probe = dbri_probe,
- .remove_new = dbri_remove,
+ .remove = dbri_remove,
};
module_platform_driver(dbri_sbus_driver);
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
index 33e962178c93..d562a30b087f 100644
--- a/sound/usb/6fire/chip.c
+++ b/sound/usb/6fire/chip.c
@@ -61,8 +61,10 @@ static void usb6fire_chip_abort(struct sfire_chip *chip)
}
}
-static void usb6fire_chip_destroy(struct sfire_chip *chip)
+static void usb6fire_card_free(struct snd_card *card)
{
+ struct sfire_chip *chip = card->private_data;
+
if (chip) {
if (chip->pcm)
usb6fire_pcm_destroy(chip);
@@ -72,8 +74,6 @@ static void usb6fire_chip_destroy(struct sfire_chip *chip)
usb6fire_comm_destroy(chip);
if (chip->control)
usb6fire_control_destroy(chip);
- if (chip->card)
- snd_card_free(chip->card);
}
}
@@ -136,6 +136,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
chip->regidx = regidx;
chip->intf_count = 1;
chip->card = card;
+ card->private_free = usb6fire_card_free;
ret = usb6fire_comm_init(chip);
if (ret < 0)
@@ -162,7 +163,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
return 0;
destroy_chip:
- usb6fire_chip_destroy(chip);
+ snd_card_free(card);
return ret;
}
@@ -181,7 +182,6 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf)
chip->shutdown = true;
usb6fire_chip_abort(chip);
- usb6fire_chip_destroy(chip);
}
}
}
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
index 772c0ecb7077..05f964347ed6 100644
--- a/sound/usb/caiaq/audio.c
+++ b/sound/usb/caiaq/audio.c
@@ -858,14 +858,20 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev)
return 0;
}
-void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev)
+void snd_usb_caiaq_audio_disconnect(struct snd_usb_caiaqdev *cdev)
{
struct device *dev = caiaqdev_to_dev(cdev);
dev_dbg(dev, "%s(%p)\n", __func__, cdev);
stream_stop(cdev);
+}
+
+void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev)
+{
+ struct device *dev = caiaqdev_to_dev(cdev);
+
+ dev_dbg(dev, "%s(%p)\n", __func__, cdev);
free_urbs(cdev->data_urbs_in);
free_urbs(cdev->data_urbs_out);
kfree(cdev->data_cb_info);
}
-
diff --git a/sound/usb/caiaq/audio.h b/sound/usb/caiaq/audio.h
index 869bf6264d6a..07f5d064456c 100644
--- a/sound/usb/caiaq/audio.h
+++ b/sound/usb/caiaq/audio.h
@@ -3,6 +3,7 @@
#define CAIAQ_AUDIO_H
int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev);
+void snd_usb_caiaq_audio_disconnect(struct snd_usb_caiaqdev *cdev);
void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev);
#endif /* CAIAQ_AUDIO_H */
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index b5cbf1f195c4..dfd820483849 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -376,6 +376,17 @@ static void setup_card(struct snd_usb_caiaqdev *cdev)
dev_err(dev, "Unable to set up control system (ret=%d)\n", ret);
}
+static void card_free(struct snd_card *card)
+{
+ struct snd_usb_caiaqdev *cdev = caiaqdev(card);
+
+#ifdef CONFIG_SND_USB_CAIAQ_INPUT
+ snd_usb_caiaq_input_free(cdev);
+#endif
+ snd_usb_caiaq_audio_free(cdev);
+ usb_reset_device(cdev->chip.dev);
+}
+
static int create_card(struct usb_device *usb_dev,
struct usb_interface *intf,
struct snd_card **cardp)
@@ -489,6 +500,7 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
cdev->vendor_name, cdev->product_name, usbpath);
setup_card(cdev);
+ card->private_free = card_free;
return 0;
err_kill_urb:
@@ -534,15 +546,14 @@ static void snd_disconnect(struct usb_interface *intf)
snd_card_disconnect(card);
#ifdef CONFIG_SND_USB_CAIAQ_INPUT
- snd_usb_caiaq_input_free(cdev);
+ snd_usb_caiaq_input_disconnect(cdev);
#endif
- snd_usb_caiaq_audio_free(cdev);
+ snd_usb_caiaq_audio_disconnect(cdev);
usb_kill_urb(&cdev->ep1_in_urb);
usb_kill_urb(&cdev->midi_out_urb);
- snd_card_free(card);
- usb_reset_device(interface_to_usbdev(intf));
+ snd_card_free_when_closed(card);
}
diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
index 84f26dce7f5d..a9130891bb69 100644
--- a/sound/usb/caiaq/input.c
+++ b/sound/usb/caiaq/input.c
@@ -829,15 +829,21 @@ exit_free_idev:
return ret;
}
-void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev)
+void snd_usb_caiaq_input_disconnect(struct snd_usb_caiaqdev *cdev)
{
if (!cdev || !cdev->input_dev)
return;
usb_kill_urb(cdev->ep4_in_urb);
+ input_unregister_device(cdev->input_dev);
+}
+
+void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev)
+{
+ if (!cdev || !cdev->input_dev)
+ return;
+
usb_free_urb(cdev->ep4_in_urb);
cdev->ep4_in_urb = NULL;
-
- input_unregister_device(cdev->input_dev);
cdev->input_dev = NULL;
}
diff --git a/sound/usb/caiaq/input.h b/sound/usb/caiaq/input.h
index c42891e7be88..fbe267f85d02 100644
--- a/sound/usb/caiaq/input.h
+++ b/sound/usb/caiaq/input.h
@@ -4,6 +4,7 @@
void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *cdev, char *buf, unsigned int len);
int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev);
+void snd_usb_caiaq_input_disconnect(struct snd_usb_caiaqdev *cdev);
void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev);
#endif
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
index 970c9bdce0b2..84a9b7b76f43 100644
--- a/sound/usb/line6/capture.c
+++ b/sound/usb/line6/capture.c
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
#include <linux/slab.h>
diff --git a/sound/usb/line6/capture.h b/sound/usb/line6/capture.h
index 20e05a5eceb4..90572dae134e 100644
--- a/sound/usb/line6/capture.h
+++ b/sound/usb/line6/capture.h
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
#ifndef CAPTURE_H
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index 9df49a880b75..e9eb5c74d6c7 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
#include <linux/kernel.h>
@@ -20,7 +20,7 @@
#include "midi.h"
#include "playback.h"
-#define DRIVER_AUTHOR "Markus Grabner <grabner@icg.tugraz.at>"
+#define DRIVER_AUTHOR "Markus Grabner <line6@grabner-graz.at>"
#define DRIVER_DESC "Line 6 USB Driver"
/*
diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h
index dbb1d90d3647..5736ad4256a5 100644
--- a/sound/usb/line6/driver.h
+++ b/sound/usb/line6/driver.h
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
#ifndef DRIVER_H
diff --git a/sound/usb/line6/midi.c b/sound/usb/line6/midi.c
index 0838632c788e..9b5176086280 100644
--- a/sound/usb/line6/midi.c
+++ b/sound/usb/line6/midi.c
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
#include <linux/slab.h>
diff --git a/sound/usb/line6/midi.h b/sound/usb/line6/midi.h
index 918754e79be4..3409c742c173 100644
--- a/sound/usb/line6/midi.h
+++ b/sound/usb/line6/midi.h
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
#ifndef MIDI_H
diff --git a/sound/usb/line6/midibuf.c b/sound/usb/line6/midibuf.c
index e7f830f7526c..57fca134b337 100644
--- a/sound/usb/line6/midibuf.c
+++ b/sound/usb/line6/midibuf.c
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
#include <linux/slab.h>
diff --git a/sound/usb/line6/midibuf.h b/sound/usb/line6/midibuf.h
index 542e8d836f87..1dae5fac9dde 100644
--- a/sound/usb/line6/midibuf.h
+++ b/sound/usb/line6/midibuf.h
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
#ifndef MIDIBUF_H
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
index 6a4af725aedd..d4dbbc432505 100644
--- a/sound/usb/line6/pcm.c
+++ b/sound/usb/line6/pcm.c
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
#include <linux/slab.h>
diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h
index 9c683042ff06..a15913bf2a7a 100644
--- a/sound/usb/line6/pcm.h
+++ b/sound/usb/line6/pcm.h
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
/*
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c
index 8233c61e23f1..9f26f66e6792 100644
--- a/sound/usb/line6/playback.c
+++ b/sound/usb/line6/playback.c
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
#include <linux/slab.h>
diff --git a/sound/usb/line6/playback.h b/sound/usb/line6/playback.h
index 2ca832c83851..2e0ec0ade0bf 100644
--- a/sound/usb/line6/playback.h
+++ b/sound/usb/line6/playback.h
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
#ifndef PLAYBACK_H
diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c
index d173971e5f02..6f948c3e8f9e 100644
--- a/sound/usb/line6/pod.c
+++ b/sound/usb/line6/pod.c
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
#include <linux/slab.h>
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c
index ffd8c157a281..70de08635f54 100644
--- a/sound/usb/line6/podhd.c
+++ b/sound/usb/line6/podhd.c
@@ -507,7 +507,7 @@ static const struct line6_properties podhd_properties_table[] = {
[LINE6_PODHD500X] = {
.id = "PODHD500X",
.name = "POD HD500X",
- .capabilities = LINE6_CAP_CONTROL
+ .capabilities = LINE6_CAP_CONTROL | LINE6_CAP_HWMON_CTL
| LINE6_CAP_PCM | LINE6_CAP_HWMON,
.altsetting = 1,
.ep_ctrl_r = 0x81,
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
index e33df58740a9..ca2c6f5de407 100644
--- a/sound/usb/line6/toneport.c
+++ b/sound/usb/line6/toneport.c
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
* Emil Myhrman (emil.myhrman@gmail.com)
*/
diff --git a/sound/usb/line6/variax.c b/sound/usb/line6/variax.c
index c2245aa93b08..b2f6637c84b2 100644
--- a/sound/usb/line6/variax.c
+++ b/sound/usb/line6/variax.c
@@ -2,7 +2,7 @@
/*
* Line 6 Linux USB driver
*
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at)
*/
#include <linux/slab.h>
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 9945ae55b0d0..66976be06bc0 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1084,6 +1084,21 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
struct snd_kcontrol *kctl)
{
struct snd_usb_audio *chip = cval->head.mixer->chip;
+
+ if (chip->quirk_flags & QUIRK_FLAG_MIC_RES_384) {
+ if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
+ usb_audio_info(chip,
+ "set resolution quirk: cval->res = 384\n");
+ cval->res = 384;
+ }
+ } else if (chip->quirk_flags & QUIRK_FLAG_MIC_RES_16) {
+ if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
+ usb_audio_info(chip,
+ "set resolution quirk: cval->res = 16\n");
+ cval->res = 16;
+ }
+ }
+
switch (chip->usb_id) {
case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
@@ -1168,27 +1183,6 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
}
break;
- case USB_ID(0x046d, 0x0807): /* Logitech Webcam C500 */
- case USB_ID(0x046d, 0x0808):
- case USB_ID(0x046d, 0x0809):
- case USB_ID(0x046d, 0x0819): /* Logitech Webcam C210 */
- case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */
- case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */
- case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */
- case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */
- case USB_ID(0x046d, 0x08ca): /* Logitech Quickcam Fusion */
- case USB_ID(0x046d, 0x0991):
- case USB_ID(0x046d, 0x09a2): /* QuickCam Communicate Deluxe/S7500 */
- /* Most audio usb devices lie about volume resolution.
- * Most Logitech webcams have res = 384.
- * Probably there is some logitech magic behind this number --fishor
- */
- if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- usb_audio_info(chip,
- "set resolution quirk: cval->res = 384\n");
- cval->res = 384;
- }
- break;
case USB_ID(0x0495, 0x3042): /* ESS Technology Asus USB DAC */
if ((strstr(kctl->id.name, "Playback Volume") != NULL) ||
strstr(kctl->id.name, "Capture Volume") != NULL) {
@@ -1197,27 +1191,6 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
cval->res = 1;
}
break;
- case USB_ID(0x1224, 0x2a25): /* Jieli Technology USB PHY 2.0 */
- if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- usb_audio_info(chip,
- "set resolution quirk: cval->res = 16\n");
- cval->res = 16;
- }
- break;
- case USB_ID(0x1bcf, 0x2283): /* NexiGo N930AF FHD Webcam */
- if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- usb_audio_info(chip,
- "set resolution quirk: cval->res = 16\n");
- cval->res = 16;
- }
- break;
- case USB_ID(0x1bcf, 0x2281): /* HD Webcam */
- if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- usb_audio_info(chip,
- "set resolution quirk: cval->res = 16\n");
- cval->res = 16;
- }
- break;
}
}
@@ -2224,7 +2197,8 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
len = get_term_name(state->chip, iterm, kctl->id.name,
sizeof(kctl->id.name), 0);
if (!len)
- len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1);
+ snprintf(kctl->id.name, sizeof(kctl->id.name), "Mixer Source %d", in_ch + 1);
+
append_ctl_name(kctl, " Volume");
usb_audio_dbg(state->chip, "[%d] MU [%s] ch = %d, val = %d/%d\n",
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 2a9594f34dac..8bbf070b3676 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -3498,7 +3498,7 @@ static int snd_rme_digiface_controls_create(struct usb_mixer_interface *mixer)
}
/*
- * Pioneer DJ DJM Mixers
+ * Pioneer DJ / AlphaTheta DJM Mixers
*
* These devices generally have options for soft-switching the playback and
* capture sources in addition to the recording level. Although different
@@ -3515,17 +3515,23 @@ static int snd_rme_digiface_controls_create(struct usb_mixer_interface *mixer)
#define SND_DJM_CAP_CDLINE 0x01
#define SND_DJM_CAP_DIGITAL 0x02
#define SND_DJM_CAP_PHONO 0x03
+#define SND_DJM_CAP_PREFADER 0x05
#define SND_DJM_CAP_PFADER 0x06
#define SND_DJM_CAP_XFADERA 0x07
#define SND_DJM_CAP_XFADERB 0x08
#define SND_DJM_CAP_MIC 0x09
#define SND_DJM_CAP_AUX 0x0d
#define SND_DJM_CAP_RECOUT 0x0a
+#define SND_DJM_CAP_RECOUT_NOMIC 0x0e
#define SND_DJM_CAP_NONE 0x0f
#define SND_DJM_CAP_CH1PFADER 0x11
#define SND_DJM_CAP_CH2PFADER 0x12
#define SND_DJM_CAP_CH3PFADER 0x13
#define SND_DJM_CAP_CH4PFADER 0x14
+#define SND_DJM_CAP_CH1PREFADER 0x31
+#define SND_DJM_CAP_CH2PREFADER 0x32
+#define SND_DJM_CAP_CH3PREFADER 0x33
+#define SND_DJM_CAP_CH4PREFADER 0x34
// Playback types
#define SND_DJM_PB_CH1 0x00
@@ -3551,6 +3557,7 @@ static int snd_rme_digiface_controls_create(struct usb_mixer_interface *mixer)
#define SND_DJM_900NXS2_IDX 0x3
#define SND_DJM_750MK2_IDX 0x4
#define SND_DJM_450_IDX 0x5
+#define SND_DJM_A9_IDX 0x6
#define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \
@@ -3579,7 +3586,7 @@ struct snd_djm_ctl {
u16 wIndex;
};
-static const char *snd_djm_get_label_caplevel(u16 wvalue)
+static const char *snd_djm_get_label_caplevel_common(u16 wvalue)
{
switch (wvalue) {
case 0x0000: return "-19dB";
@@ -3590,6 +3597,20 @@ static const char *snd_djm_get_label_caplevel(u16 wvalue)
}
};
+// The DJM-A9 has different capture levels than other, older models
+static const char *snd_djm_get_label_caplevel_a9(u16 wvalue)
+{
+ switch (wvalue) {
+ case 0x0000: return "+15dB";
+ case 0x0100: return "+12dB";
+ case 0x0200: return "+9dB";
+ case 0x0300: return "+6dB";
+ case 0x0400: return "+3dB";
+ case 0x0500: return "0dB";
+ default: return NULL;
+ }
+};
+
static const char *snd_djm_get_label_cap_common(u16 wvalue)
{
switch (wvalue & 0x00ff) {
@@ -3602,8 +3623,13 @@ static const char *snd_djm_get_label_cap_common(u16 wvalue)
case SND_DJM_CAP_XFADERB: return "Cross Fader B";
case SND_DJM_CAP_MIC: return "Mic";
case SND_DJM_CAP_RECOUT: return "Rec Out";
+ case SND_DJM_CAP_RECOUT_NOMIC: return "Rec Out without Mic";
case SND_DJM_CAP_AUX: return "Aux";
case SND_DJM_CAP_NONE: return "None";
+ case SND_DJM_CAP_CH1PREFADER: return "Pre Fader Ch1";
+ case SND_DJM_CAP_CH2PREFADER: return "Pre Fader Ch2";
+ case SND_DJM_CAP_CH3PREFADER: return "Pre Fader Ch3";
+ case SND_DJM_CAP_CH4PREFADER: return "Pre Fader Ch4";
case SND_DJM_CAP_CH1PFADER: return "Post Fader Ch1";
case SND_DJM_CAP_CH2PFADER: return "Post Fader Ch2";
case SND_DJM_CAP_CH3PFADER: return "Post Fader Ch3";
@@ -3623,6 +3649,14 @@ static const char *snd_djm_get_label_cap_850(u16 wvalue)
}
};
+static const char *snd_djm_get_label_caplevel(u8 device_idx, u16 wvalue)
+{
+ switch (device_idx) {
+ case SND_DJM_A9_IDX: return snd_djm_get_label_caplevel_a9(wvalue);
+ default: return snd_djm_get_label_caplevel_common(wvalue);
+ }
+};
+
static const char *snd_djm_get_label_cap(u8 device_idx, u16 wvalue)
{
switch (device_idx) {
@@ -3644,7 +3678,7 @@ static const char *snd_djm_get_label_pb(u16 wvalue)
static const char *snd_djm_get_label(u8 device_idx, u16 wvalue, u16 windex)
{
switch (windex) {
- case SND_DJM_WINDEX_CAPLVL: return snd_djm_get_label_caplevel(wvalue);
+ case SND_DJM_WINDEX_CAPLVL: return snd_djm_get_label_caplevel(device_idx, wvalue);
case SND_DJM_WINDEX_CAP: return snd_djm_get_label_cap(device_idx, wvalue);
case SND_DJM_WINDEX_PB: return snd_djm_get_label_pb(wvalue);
default: return NULL;
@@ -3653,7 +3687,7 @@ static const char *snd_djm_get_label(u8 device_idx, u16 wvalue, u16 windex)
// common DJM capture level option values
static const u16 snd_djm_opts_cap_level[] = {
- 0x0000, 0x0100, 0x0200, 0x0300 };
+ 0x0000, 0x0100, 0x0200, 0x0300, 0x400, 0x500 };
// DJM-250MK2
@@ -3795,6 +3829,28 @@ static const struct snd_djm_ctl snd_djm_ctls_750mk2[] = {
};
+// DJM-A9
+static const u16 snd_djm_opts_a9_cap1[] = {
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010e,
+ 0x111, 0x112, 0x113, 0x114, 0x0131, 0x132, 0x133, 0x134 };
+static const u16 snd_djm_opts_a9_cap2[] = {
+ 0x0201, 0x0202, 0x0203, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a, 0x020e };
+static const u16 snd_djm_opts_a9_cap3[] = {
+ 0x0301, 0x0302, 0x0303, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a, 0x030e };
+static const u16 snd_djm_opts_a9_cap4[] = {
+ 0x0401, 0x0402, 0x0403, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040e };
+static const u16 snd_djm_opts_a9_cap5[] = {
+ 0x0501, 0x0502, 0x0503, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, 0x050a, 0x050e };
+
+static const struct snd_djm_ctl snd_djm_ctls_a9[] = {
+ SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Master Input", a9_cap1, 3, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch1 Input", a9_cap2, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch2 Input", a9_cap3, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch3 Input", a9_cap4, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch4 Input", a9_cap5, 2, SND_DJM_WINDEX_CAP)
+};
+
static const struct snd_djm_device snd_djm_devices[] = {
[SND_DJM_250MK2_IDX] = SND_DJM_DEVICE(250mk2),
[SND_DJM_750_IDX] = SND_DJM_DEVICE(750),
@@ -3802,6 +3858,7 @@ static const struct snd_djm_device snd_djm_devices[] = {
[SND_DJM_900NXS2_IDX] = SND_DJM_DEVICE(900nxs2),
[SND_DJM_750MK2_IDX] = SND_DJM_DEVICE(750mk2),
[SND_DJM_450_IDX] = SND_DJM_DEVICE(450),
+ [SND_DJM_A9_IDX] = SND_DJM_DEVICE(a9),
};
@@ -4042,6 +4099,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
break;
err = dell_dock_mixer_init(mixer);
break;
+ case USB_ID(0x0bda, 0x402e): /* Dell WD19 dock */
+ err = dell_dock_mixer_create(mixer);
+ break;
case USB_ID(0x2a39, 0x3fd2): /* RME ADI-2 Pro */
case USB_ID(0x2a39, 0x3fd3): /* RME ADI-2 DAC */
@@ -4076,6 +4136,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */
err = snd_djm_controls_create(mixer, SND_DJM_900NXS2_IDX);
break;
+ case USB_ID(0x2b73, 0x003c): /* Pioneer DJ / AlphaTheta DJM-A9 */
+ err = snd_djm_controls_create(mixer, SND_DJM_A9_IDX);
+ break;
}
return err;
diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c
index 1150cf104985..7f595c1752a5 100644
--- a/sound/usb/mixer_scarlett2.c
+++ b/sound/usb/mixer_scarlett2.c
@@ -11,7 +11,7 @@
* - Clarett 2Pre/4Pre/8Pre USB
* - Clarett+ 2Pre/4Pre/8Pre
*
- * Copyright (c) 2018-2023 by Geoffrey D. Bennett <g at b4.vu>
+ * Copyright (c) 2018-2024 by Geoffrey D. Bennett <g at b4.vu>
* Copyright (c) 2020-2021 by Vladimir Sadovnikov <sadko4u@gmail.com>
* Copyright (c) 2022 by Christian Colglazier <christian@cacolglazier.com>
*
@@ -1079,6 +1079,9 @@ struct scarlett2_device_info {
/* minimum firmware version required */
u16 min_firmware_version;
+ /* has a downloadable device map */
+ u8 has_devmap;
+
/* support for main/alt speaker switching */
u8 has_speaker_switching;
@@ -1253,7 +1256,7 @@ struct scarlett2_data {
u8 phantom_switch[SCARLETT2_PHANTOM_SWITCH_MAX];
u8 phantom_persistence;
u8 input_select_switch;
- u8 input_link_switch[SCARLETT2_INPUT_GAIN_MAX / 2];
+ u8 input_link_switch[SCARLETT2_INPUT_GAIN_MAX];
u8 gain[SCARLETT2_INPUT_GAIN_MAX];
u8 autogain_switch[SCARLETT2_INPUT_GAIN_MAX];
u8 autogain_status[SCARLETT2_INPUT_GAIN_MAX];
@@ -1284,7 +1287,7 @@ struct scarlett2_data {
struct snd_kcontrol *input_mute_ctls[SCARLETT2_INPUT_MUTE_SWITCH_MAX];
struct snd_kcontrol *phantom_ctls[SCARLETT2_PHANTOM_SWITCH_MAX];
struct snd_kcontrol *input_select_ctl;
- struct snd_kcontrol *input_link_ctls[SCARLETT2_INPUT_GAIN_MAX / 2];
+ struct snd_kcontrol *input_link_ctls[SCARLETT2_INPUT_GAIN_MAX];
struct snd_kcontrol *input_gain_ctls[SCARLETT2_INPUT_GAIN_MAX];
struct snd_kcontrol *autogain_ctls[SCARLETT2_INPUT_GAIN_MAX];
struct snd_kcontrol *autogain_status_ctls[SCARLETT2_INPUT_GAIN_MAX];
@@ -1773,6 +1776,7 @@ static const struct scarlett2_device_info s18i20_gen3_info = {
static const struct scarlett2_device_info vocaster_one_info = {
.config_set = &scarlett2_config_set_vocaster,
.min_firmware_version = 1769,
+ .has_devmap = 1,
.phantom_count = 1,
.inputs_per_phantom = 1,
@@ -1815,6 +1819,7 @@ static const struct scarlett2_device_info vocaster_one_info = {
static const struct scarlett2_device_info vocaster_two_info = {
.config_set = &scarlett2_config_set_vocaster,
.min_firmware_version = 1769,
+ .has_devmap = 1,
.phantom_count = 2,
.inputs_per_phantom = 1,
@@ -1858,6 +1863,7 @@ static const struct scarlett2_device_info vocaster_two_info = {
static const struct scarlett2_device_info solo_gen4_info = {
.config_set = &scarlett2_config_set_gen4_solo,
.min_firmware_version = 2115,
+ .has_devmap = 1,
.level_input_count = 1,
.air_input_count = 1,
@@ -1912,6 +1918,7 @@ static const struct scarlett2_device_info solo_gen4_info = {
static const struct scarlett2_device_info s2i2_gen4_info = {
.config_set = &scarlett2_config_set_gen4_2i2,
.min_firmware_version = 2115,
+ .has_devmap = 1,
.level_input_count = 2,
.air_input_count = 2,
@@ -1966,6 +1973,7 @@ static const struct scarlett2_device_info s2i2_gen4_info = {
static const struct scarlett2_device_info s4i4_gen4_info = {
.config_set = &scarlett2_config_set_gen4_4i4,
.min_firmware_version = 2089,
+ .has_devmap = 1,
.level_input_count = 2,
.air_input_count = 2,
@@ -2264,6 +2272,8 @@ static int scarlett2_get_port_start_num(
#define SCARLETT2_USB_GET_DATA 0x00800000
#define SCARLETT2_USB_SET_DATA 0x00800001
#define SCARLETT2_USB_DATA_CMD 0x00800002
+#define SCARLETT2_USB_INFO_DEVMAP 0x0080000c
+#define SCARLETT2_USB_GET_DEVMAP 0x0080000d
#define SCARLETT2_USB_CONFIG_SAVE 6
@@ -2277,6 +2287,14 @@ static int scarlett2_get_port_start_num(
#define SCARLETT2_SEGMENT_SETTINGS_NAME "App_Settings"
#define SCARLETT2_SEGMENT_FIRMWARE_NAME "App_Upgrade"
+/* Gen 4 device firmware provides access to a base64-encoded
+ * zlib-compressed JSON description of the device's capabilities and
+ * configuration. This device map is made available in
+ * /proc/asound/cardX/device-map.json.zz.b64
+ */
+#define SCARLETT2_DEVMAP_BLOCK_SIZE 1024
+#define SCARLETT2_DEVMAP_FILENAME "device-map.json.zz.b64"
+
/* proprietary request/response format */
struct scarlett2_usb_packet {
__le32 cmd;
@@ -3409,7 +3427,7 @@ static int scarlett2_update_autogain(struct usb_mixer_interface *mixer)
private->num_autogain_status_texts - 1;
- for (int i = 0; i < SCARLETT2_AG_TARGET_COUNT; i++)
+ for (i = 0; i < SCARLETT2_AG_TARGET_COUNT; i++)
if (scarlett2_has_config_item(private,
scarlett2_ag_target_configs[i])) {
err = scarlett2_usb_get_config(
@@ -3420,7 +3438,7 @@ static int scarlett2_update_autogain(struct usb_mixer_interface *mixer)
}
/* convert from negative dBFS as used by the device */
- for (int i = 0; i < SCARLETT2_AG_TARGET_COUNT; i++)
+ for (i = 0; i < SCARLETT2_AG_TARGET_COUNT; i++)
private->ag_targets[i] = -ag_target_values[i];
return 0;
@@ -3439,7 +3457,7 @@ static void scarlett2_autogain_update_access(struct usb_mixer_interface *mixer)
scarlett2_set_ctl_access(private->input_select_ctl, val);
if (scarlett2_has_config_item(private,
SCARLETT2_CONFIG_INPUT_LINK_SWITCH))
- for (i = 0; i < info->gain_input_count / 2; i++)
+ for (i = 0; i < info->gain_input_count; i++)
scarlett2_set_ctl_access(private->input_link_ctls[i],
val);
for (i = 0; i < info->gain_input_count; i++)
@@ -3480,7 +3498,7 @@ static void scarlett2_autogain_notify_access(struct usb_mixer_interface *mixer)
&private->input_select_ctl->id);
if (scarlett2_has_config_item(private,
SCARLETT2_CONFIG_INPUT_LINK_SWITCH))
- for (i = 0; i < info->gain_input_count / 2; i++)
+ for (i = 0; i < info->gain_input_count; i++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
&private->input_link_ctls[i]->id);
for (i = 0; i < info->gain_input_count; i++)
@@ -3825,7 +3843,7 @@ static int scarlett2_update_input_select(struct usb_mixer_interface *mixer)
{
struct scarlett2_data *private = mixer->private_data;
const struct scarlett2_device_info *info = private->info;
- int link_count = info->gain_input_count / 2;
+ int link_count = info->gain_input_count;
int err;
private->input_select_updated = 0;
@@ -3847,10 +3865,6 @@ static int scarlett2_update_input_select(struct usb_mixer_interface *mixer)
if (err < 0)
return err;
- /* simplified because no model yet has link_count > 1 */
- if (private->input_link_switch[0])
- private->input_select_switch = 0;
-
return 0;
}
@@ -3887,9 +3901,9 @@ static int scarlett2_input_select_ctl_put(
struct usb_mixer_elem_info *elem = kctl->private_data;
struct usb_mixer_interface *mixer = elem->head.mixer;
struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_device_info *info = private->info;
int oval, val, err;
- int max_val = private->input_link_switch[0] ? 0 : 1;
mutex_lock(&private->data_mutex);
@@ -3907,19 +3921,18 @@ static int scarlett2_input_select_ctl_put(
if (val < 0)
val = 0;
- else if (val > max_val)
- val = max_val;
+ else if (val >= info->gain_input_count)
+ val = info->gain_input_count - 1;
if (oval == val)
goto unlock;
private->input_select_switch = val;
- /* Send switch change to the device if inputs not linked */
- if (!private->input_link_switch[0])
- err = scarlett2_usb_set_config(
- mixer, SCARLETT2_CONFIG_INPUT_SELECT_SWITCH,
- 1, val);
+ /* Send new value to the device */
+ err = scarlett2_usb_set_config(
+ mixer, SCARLETT2_CONFIG_INPUT_SELECT_SWITCH,
+ 0, val);
if (err == 0)
err = 1;
@@ -3936,8 +3949,7 @@ static int scarlett2_input_select_ctl_info(
struct scarlett2_data *private = mixer->private_data;
int inputs = private->info->gain_input_count;
- int i, j;
- int err;
+ int i, err;
char **values = kcalloc(inputs, sizeof(char *), GFP_KERNEL);
if (!values)
@@ -3954,21 +3966,11 @@ static int scarlett2_input_select_ctl_info(
if (err < 0)
goto unlock;
- /* Loop through each input
- * Linked inputs have one value for the pair
- */
- for (i = 0, j = 0; i < inputs; i++) {
- if (private->input_link_switch[i / 2]) {
- values[j++] = kasprintf(
- GFP_KERNEL, "Input %d-%d", i + 1, i + 2);
- i++;
- } else {
- values[j++] = kasprintf(
- GFP_KERNEL, "Input %d", i + 1);
- }
- }
+ /* Loop through each input */
+ for (i = 0; i < inputs; i++)
+ values[i] = kasprintf(GFP_KERNEL, "Input %d", i + 1);
- err = snd_ctl_enum_info(uinfo, 1, j,
+ err = snd_ctl_enum_info(uinfo, 1, i,
(const char * const *)values);
unlock:
@@ -4077,18 +4079,8 @@ static int scarlett2_input_link_ctl_put(
private->input_link_switch[index] = val;
- /* Notify of change in input select options available */
- snd_ctl_notify(mixer->chip->card,
- SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
- &private->input_select_ctl->id);
- private->input_select_updated = 1;
-
- /* Send switch change to the device
- * Link for channels 1-2 is at index 1
- * No device yet has more than 2 channels linked
- */
err = scarlett2_usb_set_config(
- mixer, SCARLETT2_CONFIG_INPUT_LINK_SWITCH, index + 1, val);
+ mixer, SCARLETT2_CONFIG_INPUT_LINK_SWITCH, index, val);
if (err == 0)
err = 1;
@@ -5385,6 +5377,8 @@ static int scarlett2_compressor_ctl_put(
int index = elem->control;
int channel = index / SCARLETT2_COMPRESSOR_PARAM_COUNT;
int param_index = index % SCARLETT2_COMPRESSOR_PARAM_COUNT;
+ const struct compressor_param *param = &compressor_params[param_index];
+
int oval, val, err;
s32 scaled_val;
@@ -5406,8 +5400,6 @@ static int scarlett2_compressor_ctl_put(
private->compressor_values[index] = val;
- const struct compressor_param *param = &compressor_params[param_index];
-
scaled_val = val << param->scale_bits;
/* Send change to the device */
@@ -5613,6 +5605,8 @@ static int scarlett2_update_filter_values(struct usb_mixer_interface *mixer)
info->peq_flt_total_count *
SCARLETT2_BIQUAD_COEFFS,
peq_flt_values);
+ if (err < 0)
+ return err;
for (i = 0, dst_idx = 0; i < info->dsp_input_count; i++) {
src_idx = i *
@@ -6914,10 +6908,9 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer)
if (scarlett2_has_config_item(private,
SCARLETT2_CONFIG_INPUT_LINK_SWITCH)) {
- for (i = 0; i < info->gain_input_count / 2; i++) {
+ for (i = 0; i < info->gain_input_count; i++) {
scnprintf(s, sizeof(s),
- "Line In %d-%d Link Capture Switch",
- (i * 2) + 1, (i * 2) + 2);
+ "Line In %d Link Capture Switch", i + 1);
err = scarlett2_add_new_ctl(
mixer, &scarlett2_input_link_ctl,
i, 1, s, &private->input_link_ctls[i]);
@@ -8244,7 +8237,7 @@ static void scarlett2_notify_input_select(struct usb_mixer_interface *mixer)
SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
&private->input_select_ctl->id);
- for (i = 0; i < info->gain_input_count / 2; i++)
+ for (i = 0; i < info->gain_input_count; i++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
&private->input_link_ctls[i]->id);
}
@@ -9516,7 +9509,7 @@ static long scarlett2_hwdep_write(struct snd_hwdep *hw,
SCARLETT2_FLASH_BLOCK_SIZE;
if (count < 0 || *offset < 0 || *offset + count >= flash_size)
- return -EINVAL;
+ return -ENOSPC;
if (!count)
return 0;
@@ -9589,6 +9582,116 @@ static int scarlett2_hwdep_init(struct usb_mixer_interface *mixer)
return 0;
}
+/*** device-map file ***/
+
+static ssize_t scarlett2_devmap_read(
+ struct snd_info_entry *entry,
+ void *file_private_data,
+ struct file *file,
+ char __user *buf,
+ size_t count,
+ loff_t pos)
+{
+ struct usb_mixer_interface *mixer = entry->private_data;
+ u8 *resp_buf;
+ const size_t block_size = SCARLETT2_DEVMAP_BLOCK_SIZE;
+ size_t copied = 0;
+
+ if (pos >= entry->size)
+ return 0;
+
+ if (pos + count > entry->size)
+ count = entry->size - pos;
+
+ resp_buf = kmalloc(block_size, GFP_KERNEL);
+ if (!resp_buf)
+ return -ENOMEM;
+
+ while (count > 0) {
+ /* SCARLETT2_USB_GET_DEVMAP reads only on block boundaries,
+ * so we need to read a whole block and copy the requested
+ * chunk to userspace.
+ */
+
+ __le32 req;
+ int err;
+
+ /* offset within the block that we're reading */
+ size_t offset = pos % block_size;
+
+ /* read_size is block_size except for the last block */
+ size_t block_start = pos - offset;
+ size_t read_size = min_t(size_t,
+ block_size,
+ entry->size - block_start);
+
+ /* size of the chunk to copy to userspace */
+ size_t copy_size = min_t(size_t, count, read_size - offset);
+
+ /* request the block */
+ req = cpu_to_le32(pos / block_size);
+ err = scarlett2_usb(mixer, SCARLETT2_USB_GET_DEVMAP,
+ &req, sizeof(req), resp_buf, read_size);
+ if (err < 0) {
+ kfree(resp_buf);
+ return copied ? copied : err;
+ }
+
+ if (copy_to_user(buf, resp_buf + offset, copy_size)) {
+ kfree(resp_buf);
+ return -EFAULT;
+ }
+
+ buf += copy_size;
+ pos += copy_size;
+ copied += copy_size;
+ count -= copy_size;
+ }
+
+ kfree(resp_buf);
+ return copied;
+}
+
+static const struct snd_info_entry_ops scarlett2_devmap_ops = {
+ .read = scarlett2_devmap_read,
+};
+
+static int scarlett2_devmap_init(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_device_info *info = private->info;
+ __le16 config_len_buf[2];
+ int config_len;
+ struct snd_info_entry *entry;
+ int err;
+
+ /* If the device doesn't support the DEVMAP commands, don't
+ * create the /proc/asound/cardX/scarlett.json.zlib entry
+ */
+ if (!info->has_devmap)
+ return 0;
+
+ err = scarlett2_usb(mixer, SCARLETT2_USB_INFO_DEVMAP,
+ NULL, 0, &config_len_buf, sizeof(config_len_buf));
+ if (err < 0)
+ return err;
+
+ config_len = le16_to_cpu(config_len_buf[1]);
+
+ err = snd_card_proc_new(card, SCARLETT2_DEVMAP_FILENAME, &entry);
+ if (err < 0)
+ return err;
+
+ entry->content = SNDRV_INFO_CONTENT_DATA;
+ entry->private_data = mixer;
+ entry->c.ops = &scarlett2_devmap_ops;
+ entry->size = config_len;
+ entry->mode = S_IFREG | 0444;
+
+ return 0;
+}
+
int snd_scarlett2_init(struct usb_mixer_interface *mixer)
{
struct snd_usb_audio *chip = mixer->chip;
@@ -9639,11 +9742,20 @@ int snd_scarlett2_init(struct usb_mixer_interface *mixer)
}
err = scarlett2_hwdep_init(mixer);
- if (err < 0)
+ if (err < 0) {
usb_audio_err(mixer->chip,
"Error creating %s hwdep device: %d",
entry->series_name,
err);
+ return err;
+ }
+
+ err = scarlett2_devmap_init(mixer);
+ if (err < 0)
+ usb_audio_err(mixer->chip,
+ "Error creating %s devmap entry: %d",
+ entry->series_name,
+ err);
return err;
}
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 24c981c9b240..c49383e64678 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -324,7 +324,6 @@ YAMAHA_DEVICE(0x105a, NULL),
YAMAHA_DEVICE(0x105b, NULL),
YAMAHA_DEVICE(0x105c, NULL),
YAMAHA_DEVICE(0x105d, NULL),
-YAMAHA_DEVICE(0x1718, "P-125"),
{
USB_DEVICE(0x0499, 0x1503),
QUIRK_DRIVER_INFO {
@@ -391,6 +390,19 @@ YAMAHA_DEVICE(0x1718, "P-125"),
}
}
},
+{
+ USB_DEVICE(0x0499, 0x1718),
+ QUIRK_DRIVER_INFO {
+ /* .vendor_name = "Yamaha", */
+ /* .product_name = "P-125", */
+ QUIRK_DATA_COMPOSITE {
+ { QUIRK_DATA_STANDARD_AUDIO(1) },
+ { QUIRK_DATA_STANDARD_AUDIO(2) },
+ { QUIRK_DATA_MIDI_YAMAHA(3) },
+ QUIRK_COMPOSITE_END
+ }
+ }
+},
YAMAHA_DEVICE(0x2000, "DGP-7"),
YAMAHA_DEVICE(0x2001, "DGP-5"),
YAMAHA_DEVICE(0x2002, NULL),
@@ -3119,6 +3131,63 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
+{
+ /*
+ * Pioneer DJ / AlphaTheta DJM-A9
+ * 10 channels playback & 12 channels capture @ 44.1/48/96kHz S24LE
+ */
+ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x003c),
+ QUIRK_DRIVER_INFO {
+ QUIRK_DATA_COMPOSITE {
+ {
+ QUIRK_DATA_AUDIOFORMAT(0) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 10,
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .endpoint = 0x01,
+ .ep_attr = USB_ENDPOINT_XFER_ISOC|
+ USB_ENDPOINT_SYNC_ASYNC,
+ .rates = SNDRV_PCM_RATE_44100|
+ SNDRV_PCM_RATE_48000|
+ SNDRV_PCM_RATE_96000,
+ .rate_min = 44100,
+ .rate_max = 96000,
+ .nr_rates = 3,
+ .rate_table = (unsigned int[]) {
+ 44100, 48000, 96000
+ }
+ }
+ },
+ {
+ QUIRK_DATA_AUDIOFORMAT(0) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 12,
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .endpoint = 0x82,
+ .ep_idx = 1,
+ .ep_attr = USB_ENDPOINT_XFER_ISOC|
+ USB_ENDPOINT_SYNC_ASYNC|
+ USB_ENDPOINT_USAGE_IMPLICIT_FB,
+ .rates = SNDRV_PCM_RATE_44100|
+ SNDRV_PCM_RATE_48000|
+ SNDRV_PCM_RATE_96000,
+ .rate_min = 44100,
+ .rate_max = 96000,
+ .nr_rates = 3,
+ .rate_table = (unsigned int[]) {
+ 44100, 48000, 96000
+ }
+ }
+ },
+ QUIRK_COMPOSITE_END
+ }
+ }
+},
+
/*
* MacroSilicon MS2100/MS2106 based AV capture cards
*
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index f62631b54e10..cbfbb064a9c2 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2114,6 +2114,8 @@ struct usb_audio_quirk_flags_table {
static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
/* Device matches */
+ DEVICE_FLG(0x03f0, 0x654a, /* HP 320 FHD Webcam */
+ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */
QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */
@@ -2121,10 +2123,31 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
DEVICE_FLG(0x045e, 0x083c, /* MS USB Link headset */
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY |
QUIRK_FLAG_DISABLE_AUTOSUSPEND),
+ DEVICE_FLG(0x046d, 0x0807, /* Logitech Webcam C500 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x0808, /* Logitech Webcam C600 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x0809,
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x0819, /* Logitech Webcam C210 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x081b, /* HD Webcam c310 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x081d, /* HD Webcam c510 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x0825, /* HD Webcam c270 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x0826, /* HD Webcam c525 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
DEVICE_FLG(0x046d, 0x084c, /* Logitech ConferenceCam Connect */
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY_1M),
+ DEVICE_FLG(0x046d, 0x08ca, /* Logitech Quickcam Fusion */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
DEVICE_FLG(0x046d, 0x0991, /* Logitech QuickCam Pro */
- QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR |
+ QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x09a2, /* QuickCam Communicate Deluxe/S7500 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
DEVICE_FLG(0x046d, 0x09a4, /* Logitech QuickCam E 3500 */
QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */
@@ -2192,7 +2215,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */
- QUIRK_FLAG_GET_SAMPLE_RATE),
+ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x1397, 0x0507, /* Behringer UMC202HD */
@@ -2221,6 +2244,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_DISABLE_AUTOSUSPEND),
DEVICE_FLG(0x17aa, 0x104d, /* Lenovo ThinkStation P620 Internal Speaker + Front Headset */
QUIRK_FLAG_DISABLE_AUTOSUSPEND),
+ DEVICE_FLG(0x1852, 0x5062, /* Luxman D-08u */
+ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
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 */
@@ -2228,9 +2253,9 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
DEVICE_FLG(0x19f7, 0x0035, /* RODE NT-USB+ */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x1bcf, 0x2281, /* HD Webcam */
- QUIRK_FLAG_GET_SAMPLE_RATE),
+ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */
- QUIRK_FLAG_GET_SAMPLE_RATE),
+ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */
@@ -2279,6 +2304,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+ DEVICE_FLG(0x2d95, 0x8011, /* VIVO USB-C HEADSET */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M),
DEVICE_FLG(0x2d95, 0x8021, /* VIVO USB-C-XE710 HEADSET */
QUIRK_FLAG_CTL_MSG_DELAY_1M),
DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index d70c140813d6..c1ea8844a46f 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -1067,6 +1067,7 @@ found_clock:
UAC3_BADD_PD_ID10 : UAC3_BADD_PD_ID11;
pd->pd_d1d0_rec = UAC3_BADD_PD_RECOVER_D1D0;
pd->pd_d2d0_rec = UAC3_BADD_PD_RECOVER_D2D0;
+ pd->ctrl_iface = ctrl_intf;
} else {
fp->attributes = parse_uac_endpoint_attributes(chip, alts,
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index b0f042c99608..158ec053dc44 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -194,6 +194,8 @@ extern bool snd_usb_skip_validation;
* QUIRK_FLAG_FIXED_RATE
* Do not set PCM rate (frequency) when only one rate is available
* for the given endpoint.
+ * QUIRK_FLAG_MIC_RES_16 and QUIRK_FLAG_MIC_RES_384
+ * Set the fixed resolution for Mic Capture Volume (mostly for webcams)
*/
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0)
@@ -218,5 +220,7 @@ extern bool snd_usb_skip_validation;
#define QUIRK_FLAG_IFACE_SKIP_CLOSE (1U << 19)
#define QUIRK_FLAG_FORCE_IFACE_RESET (1U << 20)
#define QUIRK_FLAG_FIXED_RATE (1U << 21)
+#define QUIRK_FLAG_MIC_RES_16 (1U << 22)
+#define QUIRK_FLAG_MIC_RES_384 (1U << 23)
#endif /* __USBAUDIO_H */
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index 1be0e980feb9..6bcf8b859ebb 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -89,13 +89,6 @@ static void pt_info_set(struct usb_device *dev, u8 v)
v, 0, NULL, 0, 1000, GFP_NOIO);
}
-static void usb_stream_hwdep_vm_open(struct vm_area_struct *area)
-{
- struct us122l *us122l = area->vm_private_data;
-
- atomic_inc(&us122l->mmap_count);
-}
-
static vm_fault_t usb_stream_hwdep_vm_fault(struct vm_fault *vmf)
{
unsigned long offset;
@@ -132,17 +125,9 @@ unlock:
return VM_FAULT_SIGBUS;
}
-static void usb_stream_hwdep_vm_close(struct vm_area_struct *area)
-{
- struct us122l *us122l = area->vm_private_data;
-
- atomic_dec(&us122l->mmap_count);
-}
static const struct vm_operations_struct usb_stream_hwdep_vm_ops = {
- .open = usb_stream_hwdep_vm_open,
.fault = usb_stream_hwdep_vm_fault,
- .close = usb_stream_hwdep_vm_close,
};
static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file)
@@ -218,7 +203,6 @@ static int usb_stream_hwdep_mmap(struct snd_hwdep *hw,
if (!read)
vm_flags_set(area, VM_DONTEXPAND);
area->vm_private_data = us122l;
- atomic_inc(&us122l->mmap_count);
out:
mutex_unlock(&us122l->mutex);
return err;
@@ -606,10 +590,7 @@ static void snd_us122l_disconnect(struct usb_interface *intf)
usb_put_intf(usb_ifnum_to_if(us122l->dev, 1));
usb_put_dev(us122l->dev);
- while (atomic_read(&us122l->mmap_count))
- msleep(500);
-
- snd_card_free(card);
+ snd_card_free_when_closed(card);
}
static int snd_us122l_suspend(struct usb_interface *intf, pm_message_t message)
diff --git a/sound/usb/usx2y/us122l.h b/sound/usb/usx2y/us122l.h
index c32ae5e981e9..8e59b78d3514 100644
--- a/sound/usb/usx2y/us122l.h
+++ b/sound/usb/usx2y/us122l.h
@@ -16,8 +16,6 @@ struct us122l {
struct file *slave;
struct list_head midi_list;
- atomic_t mmap_count;
-
bool is_us144;
};
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index 2f9cede242b3..5f81c68fd42b 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -422,7 +422,7 @@ static void snd_usx2y_disconnect(struct usb_interface *intf)
}
if (usx2y->us428ctls_sharedmem)
wake_up(&usx2y->us428ctls_wait_queue_head);
- snd_card_free(card);
+ snd_card_free_when_closed(card);
}
static int snd_usx2y_probe(struct usb_interface *intf,