aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds2021-02-21 14:21:35 -0800
committerLinus Torvalds2021-02-21 14:21:35 -0800
commit10e2ec8edece2566b40f69bae035a555ece71ab4 (patch)
tree27eed009a4817948623bbc31a83911c5ace7a4b0
parentde1617578849acab8e16c9ffdce39b91fb50639d (diff)
parentc4294d7f057d05053412ebd0d5700228d0f2588d (diff)
Merge tag 'sound-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "A relatively calm release at this time, and no massive code changes are found in the stats, while a wide range of code refactoring and cleanup have been done. Note that this update includes the tree-wide trivial changes for dropping the return value from ISA remove callbacks, too. Below lists up some highlight: ALSA Core: - Support for the software jack injection via debugfs - Fixes for sync_stop PCM operations HD-audio and USB-audio: - A few usual HD-audio device quirks - Updates for Tegra HD-audio - More quirks for Pioneer and other USB-audio devices - Stricter state checks at USB-audio disconnection ASoC: - Continued code refactoring, cleanup and fixes in ASoC core API - A KUnit testsuite for the topology code - Lots of ASoC Intel driver Realtek codec updates, quirk additions and fixes - Support for Ingenic JZ4760(B), Intel AlderLake-P, DT configured nVidia cards, Qualcomm lpass-rx-macro and lpass-tx-macro - Removal of obsolete SIRF prima/atlas, Txx9 and ZTE zx drivers Others: - Drop return value from ISA driver remove callback - Cleanup with DIV_ROUND_UP() macro - FireWire updates, HDSP output loopback support" * tag 'sound-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (322 commits) ALSA: hda: intel-dsp-config: add Alder Lake support ASoC: soc-pcm: fix hw param limits calculation for multi-DAI ASoC: Intel: bytcr_rt5640: Add quirk for the Acer One S1002 tablet ASoC: Intel: bytcr_rt5651: Add quirk for the Jumper EZpad 7 tablet ASoC: Intel: bytcr_rt5640: Add quirk for the Voyo Winpad A15 tablet ASoC: Intel: bytcr_rt5640: Add quirk for the Estar Beauty HD MID 7316R tablet ASoC: soc-pcm: fix hwparams min/max init for dpcm ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup ALSA: usb-audio: Add implicit fb quirk for BOSS GP-10 ALSA: hda: Add another CometLake-H PCI ID ASoC: soc-pcm: add soc_pcm_hw_update_format() ASoC: soc-pcm: add soc_pcm_hw_update_chan() ASoC: soc-pcm: add soc_pcm_hw_update_rate() ASoC: wm_adsp: Remove unused control callback structure ASoC: SOF: relax ABI checks and avoid unnecessary warnings ASoC: codecs: lpass-tx-macro: add dapm widgets and route ASoC: codecs: lpass-tx-macro: add support for lpass tx macro ASoC: qcom: dt-bindings: add bindings for lpass tx macro codec ASoC: codecs: lpass-rx-macro: add iir widgets ASoC: codecs: lpass-rx-macro: add dapm widgets and route ...
-rw-r--r--Documentation/devicetree/bindings/sound/audio-graph-port.yaml3
-rw-r--r--Documentation/devicetree/bindings/sound/ingenic,codec.yaml11
-rw-r--r--Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml13
-rw-r--r--Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra-audio-graph-card.yaml190
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml18
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml13
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml13
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml18
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml18
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml62
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml67
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,rsnd.yaml6
-rw-r--r--Documentation/devicetree/bindings/sound/rt5659.txt11
-rw-r--r--Documentation/devicetree/bindings/sound/sirf-audio-codec.txt17
-rw-r--r--Documentation/devicetree/bindings/sound/sirf-usp.txt27
-rw-r--r--Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml4
-rw-r--r--Documentation/devicetree/bindings/sound/wm8962.txt4
-rw-r--r--Documentation/devicetree/bindings/sound/zte,tdm.txt30
-rw-r--r--Documentation/devicetree/bindings/sound/zte,zx-aud96p22.txt24
-rw-r--r--Documentation/devicetree/bindings/sound/zte,zx-i2s.txt45
-rw-r--r--Documentation/devicetree/bindings/sound/zte,zx-spdif.txt27
-rw-r--r--Documentation/sound/designs/index.rst1
-rw-r--r--Documentation/sound/designs/jack-injection.rst166
-rw-r--r--drivers/base/isa.c2
-rw-r--r--drivers/i2c/busses/i2c-elektor.c4
-rw-r--r--drivers/i2c/busses/i2c-pca-isa.c4
-rw-r--r--drivers/input/touchscreen/htcpen.c4
-rw-r--r--drivers/media/radio/radio-isa.c9
-rw-r--r--drivers/media/radio/radio-isa.h2
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c4
-rw-r--r--drivers/mfd/arizona-core.c11
-rw-r--r--drivers/mfd/arizona-i2c.c11
-rw-r--r--drivers/mfd/arizona-spi.c138
-rw-r--r--drivers/mfd/arizona.h9
-rw-r--r--drivers/net/can/sja1000/tscan1.c4
-rw-r--r--drivers/net/ethernet/3com/3c509.c3
-rw-r--r--drivers/scsi/advansys.c3
-rw-r--r--drivers/scsi/aha1542.c3
-rw-r--r--drivers/scsi/fdomain_isa.c3
-rw-r--r--drivers/scsi/g_NCR5380.c5
-rw-r--r--drivers/watchdog/pcwd.c7
-rw-r--r--include/linux/isa.h2
-rw-r--r--include/linux/platform_data/cros_ec_commands.h1
-rw-r--r--include/sound/core.h6
-rw-r--r--include/sound/dmaengine_pcm.h5
-rw-r--r--include/sound/graph_card.h6
-rw-r--r--include/sound/hdaudio.h14
-rw-r--r--include/sound/hdaudio_ext.h2
-rw-r--r--include/sound/hdmi-codec.h5
-rw-r--r--include/sound/jack.h1
-rw-r--r--include/sound/rt5645.h2
-rw-r--r--include/sound/soc-component.h6
-rw-r--r--include/sound/soc-dai.h4
-rw-r--r--include/sound/soc.h4
-rw-r--r--include/sound/sof/ext_manifest.h6
-rw-r--r--sound/ac97/bus.c2
-rw-r--r--sound/aoa/codecs/onyx.c2
-rw-r--r--sound/aoa/codecs/tas.c2
-rw-r--r--sound/aoa/codecs/toonie.c2
-rw-r--r--sound/aoa/core/alsa.c8
-rw-r--r--sound/aoa/fabrics/layout.c6
-rw-r--r--sound/aoa/soundbus/sysfs.c2
-rw-r--r--sound/arm/aaci.c6
-rw-r--r--sound/arm/pxa2xx-ac97.c2
-rw-r--r--sound/core/Kconfig9
-rw-r--r--sound/core/compress_offload.c2
-rw-r--r--sound/core/control.c20
-rw-r--r--sound/core/ctljack.c2
-rw-r--r--sound/core/hwdep.c6
-rw-r--r--sound/core/init.c23
-rw-r--r--sound/core/jack.c304
-rw-r--r--sound/core/oss/mixer_oss.c14
-rw-r--r--sound/core/oss/rate.c4
-rw-r--r--sound/core/pcm.c29
-rw-r--r--sound/core/pcm_dmaengine.c2
-rw-r--r--sound/core/pcm_local.h7
-rw-r--r--sound/core/pcm_memory.c12
-rw-r--r--sound/core/pcm_native.c60
-rw-r--r--sound/core/rawmidi.c2
-rw-r--r--sound/core/seq/oss/seq_oss_midi.c4
-rw-r--r--sound/core/seq/oss/seq_oss_synth.c6
-rw-r--r--sound/core/seq/seq_clientmgr.c2
-rw-r--r--sound/core/seq/seq_memory.c2
-rw-r--r--sound/core/seq/seq_ports.c6
-rw-r--r--sound/core/sound.c15
-rw-r--r--sound/core/timer.c10
-rw-r--r--sound/core/timer_compat.c4
-rw-r--r--sound/drivers/aloop.c2
-rw-r--r--sound/drivers/dummy.c2
-rw-r--r--sound/drivers/opl3/opl3_oss.c2
-rw-r--r--sound/drivers/opl3/opl3_synth.c2
-rw-r--r--sound/drivers/vx/vx_pcm.c3
-rw-r--r--sound/firewire/bebob/bebob_hwdep.c10
-rw-r--r--sound/firewire/dice/Makefile3
-rw-r--r--sound/firewire/dice/dice-harman.c26
-rw-r--r--sound/firewire/dice/dice-hwdep.c2
-rw-r--r--sound/firewire/dice/dice.c12
-rw-r--r--sound/firewire/dice/dice.h1
-rw-r--r--sound/firewire/digi00x/digi00x-hwdep.c2
-rw-r--r--sound/firewire/fireface/ff-hwdep.c12
-rw-r--r--sound/firewire/fireface/ff-protocol-latter.c118
-rw-r--r--sound/firewire/fireworks/fireworks_hwdep.c2
-rw-r--r--sound/firewire/motu/motu-hwdep.c2
-rw-r--r--sound/firewire/oxfw/oxfw-hwdep.c12
-rw-r--r--sound/firewire/tascam/tascam-hwdep.c2
-rw-r--r--sound/hda/Kconfig14
-rw-r--r--sound/hda/ext/hdac_ext_controller.c37
-rw-r--r--sound/hda/hdac_bus.c23
-rw-r--r--sound/hda/hdac_controller.c14
-rw-r--r--sound/hda/hdac_stream.c5
-rw-r--r--sound/hda/hdac_sysfs.c2
-rw-r--r--sound/hda/intel-dsp-config.c41
-rw-r--r--sound/i2c/i2c.c4
-rw-r--r--sound/isa/ad1848/ad1848.c7
-rw-r--r--sound/isa/adlib.c3
-rw-r--r--sound/isa/cmi8328.c3
-rw-r--r--sound/isa/cmi8330.c3
-rw-r--r--sound/isa/cs423x/cs4231.c7
-rw-r--r--sound/isa/cs423x/cs4236.c7
-rw-r--r--sound/isa/es1688/es1688.c7
-rw-r--r--sound/isa/es18xx.c5
-rw-r--r--sound/isa/galaxy/galaxy.c3
-rw-r--r--sound/isa/gus/gusclassic.c3
-rw-r--r--sound/isa/gus/gusextreme.c3
-rw-r--r--sound/isa/gus/gusmax.c3
-rw-r--r--sound/isa/gus/interwave.c3
-rw-r--r--sound/isa/msnd/msnd_pinnacle.c3
-rw-r--r--sound/isa/opl3sa2.c3
-rw-r--r--sound/isa/opti9xx/miro.c3
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c5
-rw-r--r--sound/isa/sb/jazz16.c3
-rw-r--r--sound/isa/sb/sb16.c3
-rw-r--r--sound/isa/sb/sb16_csp.c2
-rw-r--r--sound/isa/sb/sb8.c3
-rw-r--r--sound/isa/sb/sb_mixer.c2
-rw-r--r--sound/isa/sc6000.c3
-rw-r--r--sound/isa/sscape.c3
-rw-r--r--sound/isa/wavefront/wavefront.c3
-rw-r--r--sound/oss/dmasound/dmasound_core.c4
-rw-r--r--sound/pci/ad1889.c3
-rw-r--r--sound/pci/ali5451/ali5451.c3
-rw-r--r--sound/pci/als300.c3
-rw-r--r--sound/pci/als4000.c3
-rw-r--r--sound/pci/asihpi/hpidebug.c2
-rw-r--r--sound/pci/au88x0/au88x0.c3
-rw-r--r--sound/pci/aw2/aw2-alsa.c3
-rw-r--r--sound/pci/azt3328.c5
-rw-r--r--sound/pci/bt87x.c3
-rw-r--r--sound/pci/ca0106/ca0106_main.c3
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c2
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c3
-rw-r--r--sound/pci/cs5535audio/cs5535audio_olpc.c4
-rw-r--r--sound/pci/ctxfi/cthw20k1.c8
-rw-r--r--sound/pci/ctxfi/cthw20k2.c8
-rw-r--r--sound/pci/ctxfi/ctpcm.c2
-rw-r--r--sound/pci/ctxfi/ctresource.c2
-rw-r--r--sound/pci/emu10k1/emu10k1.c4
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c2
-rw-r--r--sound/pci/emu10k1/emufx.c6
-rw-r--r--sound/pci/emu10k1/memory.c2
-rw-r--r--sound/pci/ens1370.c4
-rw-r--r--sound/pci/es1938.c3
-rw-r--r--sound/pci/es1968.c5
-rw-r--r--sound/pci/fm801.c2
-rw-r--r--sound/pci/hda/hda_auto_parser.c2
-rw-r--r--sound/pci/hda/hda_codec.c2
-rw-r--r--sound/pci/hda/hda_controller.c2
-rw-r--r--sound/pci/hda/hda_eld.c2
-rw-r--r--sound/pci/hda/hda_generic.c2
-rw-r--r--sound/pci/hda/hda_intel.c16
-rw-r--r--sound/pci/hda/hda_jack.c2
-rw-r--r--sound/pci/hda/hda_tegra.c90
-rw-r--r--sound/pci/hda/patch_conexant.c2
-rw-r--r--sound/pci/hda/patch_hdmi.c1
-rw-r--r--sound/pci/hda/patch_realtek.c40
-rw-r--r--sound/pci/ice1712/ice1712.c3
-rw-r--r--sound/pci/ice1712/juli.c2
-rw-r--r--sound/pci/ice1712/psc724.c4
-rw-r--r--sound/pci/ice1712/quartet.c2
-rw-r--r--sound/pci/ice1712/wm8776.c2
-rw-r--r--sound/pci/intel8x0m.c3
-rw-r--r--sound/pci/lola/lola.c2
-rw-r--r--sound/pci/lola/lola_clock.c2
-rw-r--r--sound/pci/lola/lola_pcm.c2
-rw-r--r--sound/pci/maestro3.c5
-rw-r--r--sound/pci/rme9652/hdsp.c74
-rw-r--r--sound/pci/rme9652/hdspm.c2
-rw-r--r--sound/pci/sis7019.c2
-rw-r--r--sound/pci/sonicvibes.c5
-rw-r--r--sound/pci/trident/trident_main.c7
-rw-r--r--sound/ppc/keywest.c2
-rw-r--r--sound/soc/Kconfig20
-rw-r--r--sound/soc/Makefile8
-rw-r--r--sound/soc/adi/axi-i2s.c2
-rw-r--r--sound/soc/amd/acp3x-rt5682-max9836.c4
-rw-r--r--sound/soc/atmel/atmel-i2s.c2
-rw-r--r--sound/soc/atmel/atmel-pcm-pdc.c78
-rw-r--r--sound/soc/atmel/mchp-i2s-mcc.c4
-rw-r--r--sound/soc/au1x/i2sc.c2
-rw-r--r--sound/soc/bcm/bcm2835-i2s.c4
-rw-r--r--sound/soc/bcm/bcm63xx-i2s-whistler.c2
-rw-r--r--sound/soc/bcm/cygnus-pcm.c107
-rw-r--r--sound/soc/cirrus/ep93xx-i2s.c2
-rw-r--r--sound/soc/codecs/Kconfig31
-rw-r--r--sound/soc/codecs/Makefile10
-rw-r--r--sound/soc/codecs/ab8500-codec.c4
-rw-r--r--sound/soc/codecs/adau1372.c2
-rw-r--r--sound/soc/codecs/adau1373.c6
-rw-r--r--sound/soc/codecs/adau1701.c2
-rw-r--r--sound/soc/codecs/adau17x1.c3
-rw-r--r--sound/soc/codecs/ak4554.c2
-rw-r--r--sound/soc/codecs/ak4613.c2
-rw-r--r--sound/soc/codecs/ak4641.c4
-rw-r--r--sound/soc/codecs/ak4642.c2
-rw-r--r--sound/soc/codecs/alc5632.c2
-rw-r--r--sound/soc/codecs/cpcap.c139
-rw-r--r--sound/soc/codecs/cros_ec_codec.c12
-rw-r--r--sound/soc/codecs/cs35l32.c2
-rw-r--r--sound/soc/codecs/cs35l33.c2
-rw-r--r--sound/soc/codecs/cs35l34.c2
-rw-r--r--sound/soc/codecs/cs35l35.c2
-rw-r--r--sound/soc/codecs/cs35l36.c2
-rw-r--r--sound/soc/codecs/cs4234.c2
-rw-r--r--sound/soc/codecs/cs4271.c2
-rw-r--r--sound/soc/codecs/cs42l56.c3
-rw-r--r--sound/soc/codecs/cs42l73.c6
-rw-r--r--sound/soc/codecs/cs43130.c6
-rw-r--r--sound/soc/codecs/cs4341.c2
-rw-r--r--sound/soc/codecs/cs4349.c2
-rw-r--r--sound/soc/codecs/cs47l15.c12
-rw-r--r--sound/soc/codecs/cs47l24.c12
-rw-r--r--sound/soc/codecs/cs47l35.c12
-rw-r--r--sound/soc/codecs/cs47l85.c16
-rw-r--r--sound/soc/codecs/cs47l90.c16
-rw-r--r--sound/soc/codecs/cs47l92.c12
-rw-r--r--sound/soc/codecs/cs53l30.c2
-rw-r--r--sound/soc/codecs/cx2072x.c2
-rw-r--r--sound/soc/codecs/da7210.c2
-rw-r--r--sound/soc/codecs/da7213.c2
-rw-r--r--sound/soc/codecs/da7218.c8
-rw-r--r--sound/soc/codecs/da7219.c4
-rw-r--r--sound/soc/codecs/da9055.c2
-rw-r--r--sound/soc/codecs/es8316.c5
-rw-r--r--sound/soc/codecs/es8328.c5
-rw-r--r--sound/soc/codecs/hdmi-codec.c4
-rw-r--r--sound/soc/codecs/inno_rk3036.c2
-rw-r--r--sound/soc/codecs/jz4740.c2
-rw-r--r--sound/soc/codecs/jz4760.c889
-rw-r--r--sound/soc/codecs/lm49453.c2
-rw-r--r--sound/soc/codecs/lochnagar-sc.c12
-rw-r--r--sound/soc/codecs/lpass-rx-macro.c3599
-rw-r--r--sound/soc/codecs/lpass-tx-macro.c1862
-rw-r--r--sound/soc/codecs/lpass-wsa-macro.c43
-rw-r--r--sound/soc/codecs/max98373-sdw.c4
-rw-r--r--sound/soc/codecs/max98373.c2
-rw-r--r--sound/soc/codecs/max9860.c2
-rw-r--r--sound/soc/codecs/max9867.c2
-rw-r--r--sound/soc/codecs/mc13783.c2
-rw-r--r--sound/soc/codecs/ml26124.c2
-rw-r--r--sound/soc/codecs/mt6359.c18
-rw-r--r--sound/soc/codecs/mt6660.c4
-rw-r--r--sound/soc/codecs/nau8810.c2
-rw-r--r--sound/soc/codecs/nau8822.c2
-rw-r--r--sound/soc/codecs/rt1015.c122
-rw-r--r--sound/soc/codecs/rt1015.h5
-rw-r--r--sound/soc/codecs/rt1308-sdw.c2
-rw-r--r--sound/soc/codecs/rt274.c2
-rw-r--r--sound/soc/codecs/rt286.c4
-rw-r--r--sound/soc/codecs/rt298.c4
-rw-r--r--sound/soc/codecs/rt5645.c78
-rw-r--r--sound/soc/codecs/rt5670.c4
-rw-r--r--sound/soc/codecs/rt5682-i2c.c3
-rw-r--r--sound/soc/codecs/rt5682-sdw.c25
-rw-r--r--sound/soc/codecs/rt5682.c16
-rw-r--r--sound/soc/codecs/rt5682.h2
-rw-r--r--sound/soc/codecs/rt700-sdw.c6
-rw-r--r--sound/soc/codecs/rt711-sdw.c6
-rw-r--r--sound/soc/codecs/rt715-sdw.c2
-rw-r--r--sound/soc/codecs/sgtl5000.c2
-rw-r--r--sound/soc/codecs/sirf-audio-codec.c575
-rw-r--r--sound/soc/codecs/ssm2602.c4
-rw-r--r--sound/soc/codecs/tas2764.c2
-rw-r--r--sound/soc/codecs/tas2770.c2
-rw-r--r--sound/soc/codecs/tlv320adcx140.c2
-rw-r--r--sound/soc/codecs/tlv320aic31xx.c4
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c2
-rw-r--r--sound/soc/codecs/tlv320aic3x.c2
-rw-r--r--sound/soc/codecs/tscs42xx.c4
-rw-r--r--sound/soc/codecs/tscs454.c12
-rw-r--r--sound/soc/codecs/wm5102.c12
-rw-r--r--sound/soc/codecs/wm5110.c12
-rw-r--r--sound/soc/codecs/wm8510.c2
-rw-r--r--sound/soc/codecs/wm8731.c2
-rw-r--r--sound/soc/codecs/wm8770.c2
-rw-r--r--sound/soc/codecs/wm8804.c2
-rw-r--r--sound/soc/codecs/wm8903.c2
-rw-r--r--sound/soc/codecs/wm8904.c2
-rw-r--r--sound/soc/codecs/wm8940.c2
-rw-r--r--sound/soc/codecs/wm8960.c2
-rw-r--r--sound/soc/codecs/wm8962.c2
-rw-r--r--sound/soc/codecs/wm8974.c2
-rw-r--r--sound/soc/codecs/wm8978.c2
-rw-r--r--sound/soc/codecs/wm8983.c2
-rw-r--r--sound/soc/codecs/wm8985.c2
-rw-r--r--sound/soc/codecs/wm8988.c2
-rw-r--r--sound/soc/codecs/wm8993.c2
-rw-r--r--sound/soc/codecs/wm8994.c4
-rw-r--r--sound/soc/codecs/wm8997.c8
-rw-r--r--sound/soc/codecs/wm8998.c12
-rw-r--r--sound/soc/codecs/wm9713.c2
-rw-r--r--sound/soc/codecs/wm_adsp.c108
-rw-r--r--sound/soc/codecs/wmfw.h6
-rw-r--r--sound/soc/codecs/wsa881x.c1
-rw-r--r--sound/soc/codecs/zl38060.c4
-rw-r--r--sound/soc/codecs/zx_aud96p22.c401
-rw-r--r--sound/soc/fsl/Kconfig1
-rw-r--r--sound/soc/fsl/fsl_asrc.c5
-rw-r--r--sound/soc/fsl/fsl_easrc.c2
-rw-r--r--sound/soc/fsl/fsl_esai.c13
-rw-r--r--sound/soc/fsl/fsl_micfil.c9
-rw-r--r--sound/soc/fsl/fsl_sai.c8
-rw-r--r--sound/soc/fsl/fsl_spdif.c14
-rw-r--r--sound/soc/fsl/fsl_ssi.c12
-rw-r--r--sound/soc/fsl/fsl_xcvr.c7
-rw-r--r--sound/soc/generic/audio-graph-card.c17
-rw-r--r--sound/soc/generic/simple-card-utils.c13
-rw-r--r--sound/soc/intel/Kconfig2
-rw-r--r--sound/soc/intel/boards/Kconfig12
-rw-r--r--sound/soc/intel/boards/Makefile2
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c3
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c89
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c13
-rw-r--r--sound/soc/intel/boards/bytcr_wm5102.c465
-rw-r--r--sound/soc/intel/boards/cht_bsw_nau8824.c15
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.c5
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c7
-rw-r--r--sound/soc/intel/boards/sof_sdw.c131
-rw-r--r--sound/soc/intel/catpt/pcm.c14
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-adl-match.c1
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-bxt-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-byt-match.c19
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cfl-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cht-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cml-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cnl-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-ehl-match.c5
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-glk-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-icl-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-jsl-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-kbl-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-skl-match.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-tgl-match.c32
-rw-r--r--sound/soc/intel/common/soc-intel-quirks.h25
-rw-r--r--sound/soc/intel/keembay/kmb_platform.c230
-rw-r--r--sound/soc/intel/keembay/kmb_platform.h10
-rw-r--r--sound/soc/intel/skylake/skl.c8
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c2
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c79
-rw-r--r--sound/soc/mediatek/Kconfig2
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-afe-pcm.c10
-rw-r--r--sound/soc/mediatek/mt6797/mt6797-dai-pcm.c8
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-afe-pcm.c2
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c6
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-dai-pcm.c8
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c47
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-afe-pcm.c4
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-dai-pcm.c8
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-dai-tdm.c2
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c84
-rw-r--r--sound/soc/meson/aiu-fifo-i2s.c1
-rw-r--r--sound/soc/meson/aiu-fifo-spdif.c1
-rw-r--r--sound/soc/meson/aiu-fifo.c18
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c2
-rw-r--r--sound/soc/qcom/lpass-apq8016.c2
-rw-r--r--sound/soc/qcom/lpass-cpu.c47
-rw-r--r--sound/soc/qcom/lpass-lpaif-reg.h3
-rw-r--r--sound/soc/qcom/lpass-sc7180.c2
-rw-r--r--sound/soc/qcom/lpass.h1
-rw-r--r--sound/soc/qcom/qdsp6/q6afe.c2
-rw-r--r--sound/soc/qcom/qdsp6/q6asm-dai.c21
-rw-r--r--sound/soc/qcom/qdsp6/q6asm.c2
-rw-r--r--sound/soc/qcom/qdsp6/q6routing.c18
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c4
-rw-r--r--sound/soc/rockchip/rockchip_pdm.c2
-rw-r--r--sound/soc/samsung/i2s.c2
-rw-r--r--sound/soc/samsung/pcm.c2
-rw-r--r--sound/soc/sh/rcar/core.c6
-rw-r--r--sound/soc/sh/siu.h2
-rw-r--r--sound/soc/sh/siu_pcm.c2
-rw-r--r--sound/soc/sirf/Kconfig21
-rw-r--r--sound/soc/sirf/Makefile8
-rw-r--r--sound/soc/sirf/sirf-audio-port.c86
-rw-r--r--sound/soc/sirf/sirf-audio.c160
-rw-r--r--sound/soc/sirf/sirf-usp.c435
-rw-r--r--sound/soc/sirf/sirf-usp.h292
-rw-r--r--sound/soc/soc-component.c54
-rw-r--r--sound/soc/soc-dapm.c13
-rw-r--r--sound/soc/soc-pcm.c465
-rw-r--r--sound/soc/soc-topology-test.c843
-rw-r--r--sound/soc/soc-topology.c30
-rw-r--r--sound/soc/sof/core.c19
-rw-r--r--sound/soc/sof/debug.c2
-rw-r--r--sound/soc/sof/intel/hda-bus.c33
-rw-r--r--sound/soc/sof/intel/hda-compress.c4
-rw-r--r--sound/soc/sof/intel/hda-dsp.c24
-rw-r--r--sound/soc/sof/intel/hda-loader.c17
-rw-r--r--sound/soc/sof/intel/hda-pcm.c18
-rw-r--r--sound/soc/sof/intel/hda-stream.c38
-rw-r--r--sound/soc/sof/intel/hda-trace.c8
-rw-r--r--sound/soc/sof/intel/hda.c277
-rw-r--r--sound/soc/sof/intel/hda.h10
-rw-r--r--sound/soc/sof/intel/tgl.c3
-rw-r--r--sound/soc/sof/ipc.c4
-rw-r--r--sound/soc/sof/loader.c8
-rw-r--r--sound/soc/sof/ops.h43
-rw-r--r--sound/soc/sof/pcm.c7
-rw-r--r--sound/soc/sof/pm.c1
-rw-r--r--sound/soc/sof/sof-pci-dev.c22
-rw-r--r--sound/soc/sof/sof-priv.h8
-rw-r--r--sound/soc/sof/topology.c14
-rw-r--r--sound/soc/sprd/sprd-mcdt.c10
-rw-r--r--sound/soc/stm/stm32_i2s.c310
-rw-r--r--sound/soc/sunxi/sun4i-i2s.c2
-rw-r--r--sound/soc/sunxi/sun8i-codec.c12
-rw-r--r--sound/soc/tegra/Kconfig42
-rw-r--r--sound/soc/tegra/Makefile2
-rw-r--r--sound/soc/tegra/tegra186_dspk.c2
-rw-r--r--sound/soc/tegra/tegra20_i2s.c2
-rw-r--r--sound/soc/tegra/tegra210_dmic.c2
-rw-r--r--sound/soc/tegra/tegra210_i2s.c2
-rw-r--r--sound/soc/tegra/tegra30_ahub.c64
-rw-r--r--sound/soc/tegra/tegra30_ahub.h5
-rw-r--r--sound/soc/tegra/tegra30_i2s.c2
-rw-r--r--sound/soc/tegra/tegra_audio_graph_card.c252
-rw-r--r--sound/soc/tegra/tegra_pcm.c6
-rw-r--r--sound/soc/ti/davinci-mcasp.c2
-rw-r--r--sound/soc/txx9/Kconfig30
-rw-r--r--sound/soc/txx9/Makefile12
-rw-r--r--sound/soc/txx9/txx9aclc-ac97.c230
-rw-r--r--sound/soc/txx9/txx9aclc-generic.c88
-rw-r--r--sound/soc/txx9/txx9aclc.c422
-rw-r--r--sound/soc/txx9/txx9aclc.h71
-rw-r--r--sound/soc/zte/Kconfig26
-rw-r--r--sound/soc/zte/Makefile4
-rw-r--r--sound/soc/zte/zx-i2s.c452
-rw-r--r--sound/soc/zte/zx-spdif.c363
-rw-r--r--sound/soc/zte/zx-tdm.c458
-rw-r--r--sound/usb/bcd2000/bcd2000.c2
-rw-r--r--sound/usb/caiaq/audio.c2
-rw-r--r--sound/usb/caiaq/device.c6
-rw-r--r--sound/usb/caiaq/midi.c2
-rw-r--r--sound/usb/card.c15
-rw-r--r--sound/usb/card.h2
-rw-r--r--sound/usb/clock.c6
-rw-r--r--sound/usb/endpoint.c87
-rw-r--r--sound/usb/hiface/chip.c6
-rw-r--r--sound/usb/hiface/pcm.c2
-rw-r--r--sound/usb/implicit.c5
-rw-r--r--sound/usb/mixer.c30
-rw-r--r--sound/usb/mixer_quirks.c369
-rw-r--r--sound/usb/mixer_scarlett.c2
-rw-r--r--sound/usb/mixer_scarlett_gen2.c2
-rw-r--r--sound/usb/mixer_us16x08.c2
-rw-r--r--sound/usb/pcm.c7
-rw-r--r--sound/usb/quirks-table.h117
-rw-r--r--sound/usb/quirks.c20
-rw-r--r--sound/x86/intel_hdmi_audio.c5
-rw-r--r--sound/xen/xen_snd_front_cfg.c2
470 files changed, 12539 insertions, 6644 deletions
diff --git a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml
index 2005014161be..766e9109b2f7 100644
--- a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml
+++ b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml
@@ -71,9 +71,6 @@ properties:
description: CPU to Codec rate channels.
$ref: /schemas/types.yaml#/definitions/uint32
- required:
- - remote-endpoint
-
ports:
description: multi OF-Graph subnode
type: object
diff --git a/Documentation/devicetree/bindings/sound/ingenic,codec.yaml b/Documentation/devicetree/bindings/sound/ingenic,codec.yaml
index eb4be86464bb..97d5f3819b27 100644
--- a/Documentation/devicetree/bindings/sound/ingenic,codec.yaml
+++ b/Documentation/devicetree/bindings/sound/ingenic,codec.yaml
@@ -15,9 +15,14 @@ properties:
compatible:
oneOf:
- - const: ingenic,jz4770-codec
- - const: ingenic,jz4725b-codec
- - const: ingenic,jz4740-codec
+ - enum:
+ - ingenic,jz4770-codec
+ - ingenic,jz4760-codec
+ - ingenic,jz4725b-codec
+ - ingenic,jz4740-codec
+ - items:
+ - const: ingenic,jz4760b-codec
+ - const: ingenic,jz4760-codec
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml
index d346e61ab708..6f71294909a5 100644
--- a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml
@@ -18,6 +18,7 @@ properties:
enum:
- intel,keembay-i2s
- intel,keembay-tdm
+ - intel,keembay-hdmi-i2s
"#sound-dai-cells":
const: 0
@@ -45,6 +46,16 @@ properties:
- const: osc
- const: apb_clk
+ dmas:
+ items:
+ - description: DMA TX channel
+ - description: DMA RX channel
+
+ dma-names:
+ items:
+ - const: tx
+ - const: rx
+
required:
- compatible
- "#sound-dai-cells"
@@ -70,4 +81,6 @@ examples:
interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "osc", "apb_clk";
clocks = <&scmi_clk KEEM_BAY_PSS_AUX_I2S3>, <&scmi_clk KEEM_BAY_PSS_I2S3>;
+ dmas = <&axi_dma0 29 &axi_dma0 33>;
+ dma-names = "tx", "rx";
};
diff --git a/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml b/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml
index 54650823b29a..5a5b765b859a 100644
--- a/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml
+++ b/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml
@@ -23,6 +23,10 @@ properties:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of MT8192 ASoC platform.
+ mediatek,hdmi-codec:
+ $ref: "/schemas/types.yaml#/definitions/phandle"
+ description: The phandle of HDMI codec.
+
additionalProperties: false
required:
@@ -35,6 +39,7 @@ examples:
sound: mt8192-sound {
compatible = "mediatek,mt8192_mt6359_rt1015_rt5682";
mediatek,platform = <&afe>;
+ mediatek,hdmi-codec = <&anx_bridge_dp>;
pinctrl-names = "aud_clk_mosi_off",
"aud_clk_mosi_on";
pinctrl-0 = <&aud_clk_mosi_off>;
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-graph-card.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-graph-card.yaml
new file mode 100644
index 000000000000..249970952202
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-graph-card.yaml
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-graph-card.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Audio Graph based Tegra sound card driver
+
+description: |
+ This is based on generic audio graph card driver along with additional
+ customizations for Tegra platforms. It uses the same bindings with
+ additional standard clock DT bindings required for Tegra.
+
+maintainers:
+ - Jon Hunter <jonathanh@nvidia.com>
+ - Sameer Pujar <spujar@nvidia.com>
+
+allOf:
+ - $ref: audio-graph.yaml#
+
+properties:
+ compatible:
+ enum:
+ - nvidia,tegra210-audio-graph-card
+ - nvidia,tegra186-audio-graph-card
+
+ clocks:
+ minItems: 2
+
+ clock-names:
+ minItems: 2
+ items:
+ - const: pll_a
+ - const: plla_out0
+
+ assigned-clocks:
+ minItems: 1
+ maxItems: 3
+
+ assigned-clock-parents:
+ minItems: 1
+ maxItems: 3
+
+ assigned-clock-rates:
+ minItems: 1
+ maxItems: 3
+
+ iommus:
+ maxItems: 1
+
+required:
+ - clocks
+ - clock-names
+ - assigned-clocks
+ - assigned-clock-parents
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include<dt-bindings/clock/tegra210-car.h>
+
+ tegra_sound {
+ compatible = "nvidia,tegra210-audio-graph-card";
+
+ clocks = <&tegra_car TEGRA210_CLK_PLL_A>,
+ <&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
+ clock-names = "pll_a", "plla_out0";
+
+ assigned-clocks = <&tegra_car TEGRA210_CLK_PLL_A>,
+ <&tegra_car TEGRA210_CLK_PLL_A_OUT0>,
+ <&tegra_car TEGRA210_CLK_EXTERN1>;
+ assigned-clock-parents = <0>, <0>, <&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
+ assigned-clock-rates = <368640000>, <49152000>, <12288000>;
+
+ dais = /* FE */
+ <&admaif1_port>,
+ /* Router */
+ <&xbar_i2s1_port>,
+ /* I/O DAP Ports */
+ <&i2s1_port>;
+
+ label = "jetson-tx1-ape";
+ };
+
+ // The ports are defined for AHUB and its child devices.
+ ahub@702d0800 {
+ compatible = "nvidia,tegra210-ahub";
+ reg = <0x702d0800 0x800>;
+ clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>;
+ clock-names = "ahub";
+ assigned-clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>;
+ assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x702d0000 0x702d0000 0x0000e400>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0x0>;
+ xbar_admaif1_ep: endpoint {
+ remote-endpoint = <&admaif1_ep>;
+ };
+ };
+
+ // ...
+
+ xbar_i2s1_port: port@a {
+ reg = <0xa>;
+ xbar_i2s1_ep: endpoint {
+ remote-endpoint = <&i2s1_cif_ep>;
+ };
+ };
+ };
+
+ admaif@702d0000 {
+ compatible = "nvidia,tegra210-admaif";
+ reg = <0x702d0000 0x800>;
+ dmas = <&adma 1>, <&adma 1>,
+ <&adma 2>, <&adma 2>,
+ <&adma 3>, <&adma 3>,
+ <&adma 4>, <&adma 4>,
+ <&adma 5>, <&adma 5>,
+ <&adma 6>, <&adma 6>,
+ <&adma 7>, <&adma 7>,
+ <&adma 8>, <&adma 8>,
+ <&adma 9>, <&adma 9>,
+ <&adma 10>, <&adma 10>;
+ dma-names = "rx1", "tx1",
+ "rx2", "tx2",
+ "rx3", "tx3",
+ "rx4", "tx4",
+ "rx5", "tx5",
+ "rx6", "tx6",
+ "rx7", "tx7",
+ "rx8", "tx8",
+ "rx9", "tx9",
+ "rx10", "tx10";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ admaif1_port: port@0 {
+ reg = <0x0>;
+ admaif1_ep: endpoint {
+ remote-endpoint = <&xbar_admaif1_ep>;
+ };
+ };
+
+ // More ADMAIF ports to follow
+ };
+ };
+
+ i2s@702d1000 {
+ compatible = "nvidia,tegra210-i2s";
+ clocks = <&tegra_car TEGRA210_CLK_I2S0>;
+ clock-names = "i2s";
+ assigned-clocks = <&tegra_car TEGRA210_CLK_I2S0>;
+ assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
+ assigned-clock-rates = <1536000>;
+ reg = <0x702d1000 0x100>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0x0>;
+
+ i2s1_cif_ep: endpoint {
+ remote-endpoint = <&xbar_i2s1_ep>;
+ };
+ };
+
+ i2s1_port: port@1 {
+ reg = <0x1>;
+
+ i2s1_dap: endpoint {
+ dai-format = "i2s";
+ };
+ };
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml
index ed2fb32fcdd4..b8645d9c38ac 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml
@@ -17,6 +17,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
+allOf:
+ - $ref: audio-graph-port.yaml#
+
properties:
$nodename:
pattern: "^dspk@[0-9a-f]*$"
@@ -55,6 +58,19 @@ properties:
The name can be "DSPK1" or "DSPKx", where x depends on the maximum
available instances on a Tegra SoC.
+ ports:
+ type: object
+ properties:
+ port@0:
+ description: |
+ DSPK ACIF (Audio Client Interface) port connected to the
+ corresponding AHUB (Audio Hub) ACIF port.
+
+ port@1:
+ description: |
+ DSPK DAP (Digital Audio Port) interface which can be connected
+ to external audio codec for playback.
+
required:
- compatible
- reg
@@ -64,7 +80,7 @@ required:
- assigned-clock-parents
- sound-name-prefix
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml
index c028b259e822..7cee7722df41 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml
@@ -17,6 +17,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
+allOf:
+ - $ref: audio-graph-port.yaml#
+
properties:
$nodename:
pattern: "^admaif@[0-9a-f]*$"
@@ -37,6 +40,14 @@ properties:
dma-names: true
+ ports:
+ description: |
+ Contains list of ACIF (Audio CIF) port nodes for ADMAIF channels.
+ The number of port nodes depends on the number of ADMAIF channels
+ that SoC may have. These are interfaced with respective ACIF ports
+ in AHUB (Audio Hub). Each port is capable of data transfers in
+ both directions.
+
if:
properties:
compatible:
@@ -81,7 +92,7 @@ required:
- dmas
- dma-names
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml
index d77219727768..31f3e51974bb 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml
@@ -17,6 +17,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
+allOf:
+ - $ref: audio-graph-port.yaml#
+
properties:
$nodename:
pattern: "^ahub@[0-9a-f]*$"
@@ -56,6 +59,13 @@ properties:
ranges: true
+ ports:
+ description: |
+ Contains list of ACIF (Audio CIF) port nodes for AHUB (Audio Hub).
+ These are connected to ACIF interfaces of AHUB clients. Thus the
+ number of port nodes depend on the number of clients that AHUB may
+ have depending on the SoC revision.
+
required:
- compatible
- reg
@@ -67,8 +77,7 @@ required:
- "#size-cells"
- ranges
-additionalProperties:
- type: object
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml
index 2a3207b550e7..89f4f471be24 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml
@@ -16,6 +16,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
+allOf:
+ - $ref: audio-graph-port.yaml#
+
properties:
$nodename:
pattern: "^dmic@[0-9a-f]*$"
@@ -56,6 +59,19 @@ properties:
The name can be "DMIC1" or "DMIC2" ... "DMICx", where x depends
on the maximum available instances on a Tegra SoC.
+ ports:
+ type: object
+ properties:
+ port@0:
+ description: |
+ DMIC ACIF (Audio Client Interface) port connected to the
+ corresponding AHUB (Audio Hub) ACIF port.
+
+ port@1:
+ description: |
+ DMIC DAP (Digital Audio Port) interface which can be connected
+ to external audio codec for capture.
+
required:
- compatible
- reg
@@ -64,7 +80,7 @@ required:
- assigned-clocks
- assigned-clock-parents
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml
index dfc1bf7b7722..556460332ffb 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml
@@ -16,6 +16,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
+allOf:
+ - $ref: audio-graph-port.yaml#
+
properties:
$nodename:
pattern: "^i2s@[0-9a-f]*$"
@@ -74,6 +77,19 @@ properties:
The name can be "I2S1" or "I2S2" ... "I2Sx", where x depends
on the maximum available instances on a Tegra SoC.
+ ports:
+ type: object
+ properties:
+ port@0:
+ description: |
+ I2S ACIF (Audio Client Interface) port connected to the
+ corresponding AHUB (Audio Hub) ACIF port.
+
+ port@1:
+ description: |
+ I2S DAP (Digital Audio Port) interface which can be connected
+ to external audio codec for playback or capture.
+
required:
- compatible
- reg
@@ -82,7 +98,7 @@ required:
- assigned-clocks
- assigned-clock-parents
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml
new file mode 100644
index 000000000000..443d556caa69
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,lpass-rx-macro.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LPASS(Low Power Audio Subsystem) RX Macro audio codec DT bindings
+
+maintainers:
+ - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+properties:
+ compatible:
+ const: qcom,sm8250-lpass-rx-macro
+
+ reg:
+ maxItems: 1
+
+ "#sound-dai-cells":
+ const: 1
+
+ '#clock-cells':
+ const: 0
+
+ clocks:
+ maxItems: 5
+
+ clock-names:
+ items:
+ - const: mclk
+ - const: npl
+ - const: macro
+ - const: dcodec
+ - const: fsgen
+
+ clock-output-names:
+ items:
+ - const: mclk
+
+required:
+ - compatible
+ - reg
+ - "#sound-dai-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/sound/qcom,q6afe.h>
+ codec@3200000 {
+ compatible = "qcom,sm8250-lpass-rx-macro";
+ reg = <0x3200000 0x1000>;
+ #sound-dai-cells = <1>;
+ #clock-cells = <0>;
+ clocks = <&audiocc 0>,
+ <&audiocc 1>,
+ <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&vamacro>;
+ clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
+ clock-output-names = "mclk";
+ };
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml
new file mode 100644
index 000000000000..6b5ca02ccce4
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,lpass-tx-macro.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LPASS(Low Power Audio Subsystem) TX Macro audio codec DT bindings
+
+maintainers:
+ - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+properties:
+ compatible:
+ const: qcom,sm8250-lpass-tx-macro
+
+ reg:
+ maxItems: 1
+
+ "#sound-dai-cells":
+ const: 1
+
+ '#clock-cells':
+ const: 0
+
+ clocks:
+ maxItems: 5
+
+ clock-names:
+ items:
+ - const: mclk
+ - const: npl
+ - const: macro
+ - const: dcodec
+ - const: fsgen
+
+ clock-output-names:
+ items:
+ - const: mclk
+
+ qcom,dmic-sample-rate:
+ description: dmic sample rate
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+required:
+ - compatible
+ - reg
+ - "#sound-dai-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/sound/qcom,q6afe.h>
+ codec@3220000 {
+ compatible = "qcom,sm8250-lpass-tx-macro";
+ reg = <0x3220000 0x1000>;
+ #sound-dai-cells = <1>;
+ #clock-cells = <0>;
+ clocks = <&aoncc 0>,
+ <&aoncc 1>,
+ <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&vamacro>;
+ clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
+ clock-output-names = "mclk";
+ qcom,dmic-sample-rate = <600000>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml
index 0fd37aa84947..2e1046513603 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml
+++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml
@@ -404,7 +404,7 @@ examples:
/* DAI base */
rcar_sound,dai {
dai0 {
- playback = <&ssi5 &src5>;
+ playback = <&ssi5>, <&src5>;
capture = <&ssi6>;
};
dai1 {
@@ -430,8 +430,8 @@ examples:
bitclock-master = <&rsnd_endpoint0>;
frame-master = <&rsnd_endpoint0>;
- playback = <&ssi0 &src0 &dvc0>;
- capture = <&ssi1 &src1 &dvc1>;
+ playback = <&ssi0>, <&src0>, <&dvc0>;
+ capture = <&ssi1>, <&src1>, <&dvc1>;
};
};
};
diff --git a/Documentation/devicetree/bindings/sound/rt5659.txt b/Documentation/devicetree/bindings/sound/rt5659.txt
index 56788f50b6cf..c473df5c878c 100644
--- a/Documentation/devicetree/bindings/sound/rt5659.txt
+++ b/Documentation/devicetree/bindings/sound/rt5659.txt
@@ -37,10 +37,21 @@ Optional properties:
- realtek,jd-src
0: No JD is used
1: using JD3 as JD source
+ 2: JD source for Intel HDA header
- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
- realtek,reset-gpios : The GPIO that controls the CODEC's RESET pin.
+- sound-name-prefix: Please refer to name-prefix.txt
+
+- ports: A Codec may have a single or multiple I2S interfaces. These
+ interfaces on Codec side can be described under 'ports' or 'port'.
+ When the SoC or host device is connected to multiple interfaces of
+ the Codec, the connectivity can be described using 'ports' property.
+ If a single interface is used, then 'port' can be used. The usage
+ depends on the platform or board design.
+ Please refer to Documentation/devicetree/bindings/graph.txt
+
Pins on the device (for linking into audio routes) for RT5659/RT5658:
* DMIC L1
diff --git a/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt b/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt
deleted file mode 100644
index 062f5ec36f9b..000000000000
--- a/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-SiRF internal audio CODEC
-
-Required properties:
-
- - compatible : "sirf,atlas6-audio-codec" or "sirf,prima2-audio-codec"
-
- - reg : the register address of the device.
-
- - clocks: the clock of SiRF internal audio codec
-
-Example:
-
-audiocodec: audiocodec@b0040000 {
- compatible = "sirf,atlas6-audio-codec";
- reg = <0xb0040000 0x10000>;
- clocks = <&clks 27>;
-};
diff --git a/Documentation/devicetree/bindings/sound/sirf-usp.txt b/Documentation/devicetree/bindings/sound/sirf-usp.txt
deleted file mode 100644
index 02f85b32d359..000000000000
--- a/Documentation/devicetree/bindings/sound/sirf-usp.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-* SiRF SoC USP module
-
-Required properties:
-- compatible: "sirf,prima2-usp-pcm"
-- reg: Base address and size entries:
-- dmas: List of DMA controller phandle and DMA request line ordered pairs.
-- dma-names: Identifier string for each DMA request line in the dmas property.
- These strings correspond 1:1 with the ordered pairs in dmas.
-
- One of the DMA channels will be responsible for transmission (should be
- named "tx") and one for reception (should be named "rx").
-
-- clocks: USP controller clock source
-- pinctrl-names: Must contain a "default" entry.
-- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
-
-Example:
-usp0: usp@b0080000 {
- compatible = "sirf,prima2-usp-pcm";
- reg = <0xb0080000 0x10000>;
- clocks = <&clks 28>;
- dmas = <&dmac1 1>, <&dmac1 2>;
- dma-names = "rx", "tx";
- pinctrl-names = "default";
- pinctrl-0 = <&usp0_only_utfs_pins_a>;
-};
-
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
index f32410890589..6feb5a09c184 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
@@ -54,6 +54,10 @@ properties:
resets:
maxItems: 1
+ "#clock-cells":
+ description: Configure the I2S device as MCLK clock provider.
+ const: 0
+
required:
- compatible
- "#sound-dai-cells"
diff --git a/Documentation/devicetree/bindings/sound/wm8962.txt b/Documentation/devicetree/bindings/sound/wm8962.txt
index dcfa9a3369fd..c36c649ddfd0 100644
--- a/Documentation/devicetree/bindings/sound/wm8962.txt
+++ b/Documentation/devicetree/bindings/sound/wm8962.txt
@@ -9,6 +9,9 @@ Required properties:
- reg : the I2C address of the device.
Optional properties:
+
+ - clocks : The clock source of the mclk
+
- spk-mono: This is a boolean property. If present, the SPK_MONO bit
of R51 (Class D Control 2) gets set, indicating that the speaker is
in mono mode.
@@ -27,6 +30,7 @@ Example:
wm8962: codec@1a {
compatible = "wlf,wm8962";
reg = <0x1a>;
+ clocks = <&clks IMX6QDL_CLK_CKO>;
gpio-cfg = <
0x0000 /* 0:Default */
diff --git a/Documentation/devicetree/bindings/sound/zte,tdm.txt b/Documentation/devicetree/bindings/sound/zte,tdm.txt
deleted file mode 100644
index 2a07ca655264..000000000000
--- a/Documentation/devicetree/bindings/sound/zte,tdm.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-ZTE TDM DAI driver
-
-Required properties:
-
-- compatible : should be one of the following.
- * zte,zx296718-tdm
-- reg : physical base address of the controller and length of memory mapped
- region.
-- clocks : Pairs of phandle and specifier referencing the controller's clocks.
-- clock-names: "wclk" for the wclk.
- "pclk" for the pclk.
--#clock-cells: should be 1.
-- zte,tdm-dma-sysctrl : Reference to the sysctrl controller controlling
- the dma. includes:
- phandle of sysctrl.
- register offset in sysctrl for control dma.
- mask of the register that be written to sysctrl.
-
-Example:
-
- tdm: tdm@1487000 {
- compatible = "zte,zx296718-tdm";
- reg = <0x01487000 0x1000>;
- clocks = <&audiocrm AUDIO_TDM_WCLK>, <&audiocrm AUDIO_TDM_PCLK>;
- clock-names = "wclk", "pclk";
- #clock-cells = <1>;
- pinctrl-names = "default";
- pinctrl-0 = <&tdm_global_pin>;
- zte,tdm-dma-sysctrl = <&sysctrl 0x10c 4>;
- };
diff --git a/Documentation/devicetree/bindings/sound/zte,zx-aud96p22.txt b/Documentation/devicetree/bindings/sound/zte,zx-aud96p22.txt
deleted file mode 100644
index 41bb1040eb71..000000000000
--- a/Documentation/devicetree/bindings/sound/zte,zx-aud96p22.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-ZTE ZX AUD96P22 Audio Codec
-
-Required properties:
- - compatible: Must be "zte,zx-aud96p22"
- - #sound-dai-cells: Should be 0
- - reg: I2C bus slave address of AUD96P22
-
-Example:
-
- i2c0: i2c@1486000 {
- compatible = "zte,zx296718-i2c";
- reg = <0x01486000 0x1000>;
- interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&audiocrm AUDIO_I2C0_WCLK>;
- clock-frequency = <1600000>;
-
- aud96p22: codec@22 {
- compatible = "zte,zx-aud96p22";
- #sound-dai-cells = <0>;
- reg = <0x22>;
- };
- };
diff --git a/Documentation/devicetree/bindings/sound/zte,zx-i2s.txt b/Documentation/devicetree/bindings/sound/zte,zx-i2s.txt
deleted file mode 100644
index 3927251464f0..000000000000
--- a/Documentation/devicetree/bindings/sound/zte,zx-i2s.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-ZTE ZX296702 I2S controller
-
-Required properties:
- - compatible : Must be one of:
- "zte,zx296718-i2s", "zte,zx296702-i2s"
- "zte,zx296702-i2s"
- - reg : Must contain I2S core's registers location and length
- - clocks : Pairs of phandle and specifier referencing the controller's clocks.
- - clock-names: "wclk" for the wclk, "pclk" for the pclk to the I2S interface.
- - dmas: Pairs of phandle and specifier for the DMA channel that is used by
- the core. The core expects two dma channels for transmit.
- - dma-names : Must be "tx" and "rx"
-
-For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
-please check:
- * resource-names.txt
- * clock/clock-bindings.txt
- * dma/dma.txt
-
-Example:
- i2s0: i2s@b005000 {
- #sound-dai-cells = <0>;
- compatible = "zte,zx296718-i2s", "zte,zx296702-i2s";
- reg = <0x0b005000 0x1000>;
- clocks = <&audiocrm AUDIO_I2S0_WCLK>, <&audiocrm AUDIO_I2S0_PCLK>;
- clock-names = "wclk", "pclk";
- interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&dma 5>, <&dma 6>;
- dma-names = "tx", "rx";
- };
-
- sound {
- compatible = "simple-audio-card";
- simple-audio-card,name = "zx296702_snd";
- simple-audio-card,format = "left_j";
- simple-audio-card,bitclock-master = <&sndcodec>;
- simple-audio-card,frame-master = <&sndcodec>;
- sndcpu: simple-audio-card,cpu {
- sound-dai = <&i2s0>;
- };
-
- sndcodec: simple-audio-card,codec {
- sound-dai = <&acodec>;
- };
- };
diff --git a/Documentation/devicetree/bindings/sound/zte,zx-spdif.txt b/Documentation/devicetree/bindings/sound/zte,zx-spdif.txt
deleted file mode 100644
index 09231d7586b2..000000000000
--- a/Documentation/devicetree/bindings/sound/zte,zx-spdif.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-ZTE ZX296702 SPDIF controller
-
-Required properties:
- - compatible : Must be "zte,zx296702-spdif"
- - reg : Must contain SPDIF core's registers location and length
- - clocks : Pairs of phandle and specifier referencing the controller's clocks.
- - clock-names: "tx" for the clock to the SPDIF interface.
- - dmas: Pairs of phandle and specifier for the DMA channel that is used by
- the core. The core expects one dma channel for transmit.
- - dma-names : Must be "tx"
-
-For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
-please check:
- * resource-names.txt
- * clock/clock-bindings.txt
- * dma/dma.txt
-
-Example:
- spdif0: spdif0@b004000 {
- compatible = "zte,zx296702-spdif";
- reg = <0x0b004000 0x1000>;
- clocks = <&lsp0clk ZX296702_SPDIF0_DIV>;
- clock-names = "tx";
- interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&dma 4>;
- dma-names = "tx";
- };
diff --git a/Documentation/sound/designs/index.rst b/Documentation/sound/designs/index.rst
index f0749943ccb2..1eb08e7bae52 100644
--- a/Documentation/sound/designs/index.rst
+++ b/Documentation/sound/designs/index.rst
@@ -14,3 +14,4 @@ Designs and Implementations
powersave
oss-emulation
seq-oss
+ jack-injection
diff --git a/Documentation/sound/designs/jack-injection.rst b/Documentation/sound/designs/jack-injection.rst
new file mode 100644
index 000000000000..f9790521523e
--- /dev/null
+++ b/Documentation/sound/designs/jack-injection.rst
@@ -0,0 +1,166 @@
+============================
+ALSA Jack Software Injection
+============================
+
+Simple Introduction On Jack Injection
+=====================================
+
+Here jack injection means users could inject plugin or plugout events
+to the audio jacks through debugfs interface, it is helpful to
+validate ALSA userspace changes. For example, we change the audio
+profile switching code in the pulseaudio, and we want to verify if the
+change works as expected and if the change introduce the regression,
+in this case, we could inject plugin or plugout events to an audio
+jack or to some audio jacks, we don't need to physically access the
+machine and plug/unplug physical devices to the audio jack.
+
+In this design, an audio jack doesn't equal to a physical audio jack.
+Sometimes a physical audio jack contains multi functions, and the
+ALSA driver creates multi ``jack_kctl`` for a ``snd_jack``, here the
+``snd_jack`` represents a physical audio jack and the ``jack_kctl``
+represents a function, for example a physical jack has two functions:
+headphone and mic_in, the ALSA ASoC driver will build 2 ``jack_kctl``
+for this jack. The jack injection is implemented based on the
+``jack_kctl`` instead of ``snd_jack``.
+
+To inject events to audio jacks, we need to enable the jack injection
+via ``sw_inject_enable`` first, once it is enabled, this jack will not
+change the state by hardware events anymore, we could inject plugin or
+plugout events via ``jackin_inject`` and check the jack state via
+``status``, after we finish our test, we need to disable the jack
+injection via ``sw_inject_enable`` too, once it is disabled, the jack
+state will be restored according to the last reported hardware events
+and will change by future hardware events.
+
+The Layout of Jack Injection Interface
+======================================
+
+If users enable the SND_JACK_INJECTION_DEBUG in the kernel, the audio
+jack injection interface will be created as below:
+::
+
+ $debugfs_mount_dir/sound
+ |-- card0
+ |-- |-- HDMI_DP_pcm_10_Jack
+ |-- |-- |-- jackin_inject
+ |-- |-- |-- kctl_id
+ |-- |-- |-- mask_bits
+ |-- |-- |-- status
+ |-- |-- |-- sw_inject_enable
+ |-- |-- |-- type
+ ...
+ |-- |-- HDMI_DP_pcm_9_Jack
+ |-- |-- jackin_inject
+ |-- |-- kctl_id
+ |-- |-- mask_bits
+ |-- |-- status
+ |-- |-- sw_inject_enable
+ |-- |-- type
+ |-- card1
+ |-- HDMI_DP_pcm_5_Jack
+ |-- |-- jackin_inject
+ |-- |-- kctl_id
+ |-- |-- mask_bits
+ |-- |-- status
+ |-- |-- sw_inject_enable
+ |-- |-- type
+ ...
+ |-- Headphone_Jack
+ |-- |-- jackin_inject
+ |-- |-- kctl_id
+ |-- |-- mask_bits
+ |-- |-- status
+ |-- |-- sw_inject_enable
+ |-- |-- type
+ |-- Headset_Mic_Jack
+ |-- jackin_inject
+ |-- kctl_id
+ |-- mask_bits
+ |-- status
+ |-- sw_inject_enable
+ |-- type
+
+The Explanation Of The Nodes
+======================================
+
+kctl_id
+ read-only, get jack_kctl->kctl's id
+ ::
+
+ sound/card1/Headphone_Jack# cat kctl_id
+ Headphone Jack
+
+mask_bits
+ read-only, get jack_kctl's supported events mask_bits
+ ::
+
+ sound/card1/Headphone_Jack# cat mask_bits
+ 0x0001 HEADPHONE(0x0001)
+
+status
+ read-only, get jack_kctl's current status
+
+- headphone unplugged:
+
+ ::
+
+ sound/card1/Headphone_Jack# cat status
+ Unplugged
+
+- headphone plugged:
+
+ ::
+
+ sound/card1/Headphone_Jack# cat status
+ Plugged
+
+type
+ read-only, get snd_jack's supported events from type (all supported events on the physical audio jack)
+ ::
+
+ sound/card1/Headphone_Jack# cat type
+ 0x7803 HEADPHONE(0x0001) MICROPHONE(0x0002) BTN_3(0x0800) BTN_2(0x1000) BTN_1(0x2000) BTN_0(0x4000)
+
+sw_inject_enable
+ read-write, enable or disable injection
+
+- injection disabled:
+
+ ::
+
+ sound/card1/Headphone_Jack# cat sw_inject_enable
+ Jack: Headphone Jack Inject Enabled: 0
+
+- injection enabled:
+
+ ::
+
+ sound/card1/Headphone_Jack# cat sw_inject_enable
+ Jack: Headphone Jack Inject Enabled: 1
+
+- to enable jack injection:
+
+ ::
+
+ sound/card1/Headphone_Jack# echo 1 > sw_inject_enable
+
+- to disable jack injection:
+
+ ::
+
+ sound/card1/Headphone_Jack# echo 0 > sw_inject_enable
+
+jackin_inject
+ write-only, inject plugin or plugout
+
+- to inject plugin:
+
+ ::
+
+ sound/card1/Headphone_Jack# echo 1 > jackin_inject
+
+- to inject plugout:
+
+ ::
+
+ sound/card1/Headphone_Jack# echo 0 > jackin_inject
diff --git a/drivers/base/isa.c b/drivers/base/isa.c
index 2772f5d1948a..aa4737667026 100644
--- a/drivers/base/isa.c
+++ b/drivers/base/isa.c
@@ -51,7 +51,7 @@ static int isa_bus_remove(struct device *dev)
struct isa_driver *isa_driver = dev->platform_data;
if (isa_driver && isa_driver->remove)
- return isa_driver->remove(dev, to_isa_dev(dev)->id);
+ isa_driver->remove(dev, to_isa_dev(dev)->id);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 140426db28df..b72a3c3ef2ab 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -282,7 +282,7 @@ static int elektor_probe(struct device *dev, unsigned int id)
return -ENODEV;
}
-static int elektor_remove(struct device *dev, unsigned int id)
+static void elektor_remove(struct device *dev, unsigned int id)
{
i2c_del_adapter(&pcf_isa_ops);
@@ -298,8 +298,6 @@ static int elektor_remove(struct device *dev, unsigned int id)
iounmap(base_iomem);
release_mem_region(base, 2);
}
-
- return 0;
}
static struct isa_driver i2c_elektor_driver = {
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index f27bc1e55385..85e8cf58e8bf 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -161,7 +161,7 @@ static int pca_isa_probe(struct device *dev, unsigned int id)
return -ENODEV;
}
-static int pca_isa_remove(struct device *dev, unsigned int id)
+static void pca_isa_remove(struct device *dev, unsigned int id)
{
i2c_del_adapter(&pca_isa_ops);
@@ -170,8 +170,6 @@ static int pca_isa_remove(struct device *dev, unsigned int id)
free_irq(irq, &pca_isa_ops);
}
release_region(base, IO_SIZE);
-
- return 0;
}
static struct isa_driver pca_isa_driver = {
diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c
index 2f261a34f9c2..056ba76087e8 100644
--- a/drivers/input/touchscreen/htcpen.c
+++ b/drivers/input/touchscreen/htcpen.c
@@ -171,7 +171,7 @@ static int htcpen_isa_probe(struct device *dev, unsigned int id)
return err;
}
-static int htcpen_isa_remove(struct device *dev, unsigned int id)
+static void htcpen_isa_remove(struct device *dev, unsigned int id)
{
struct input_dev *htcpen_dev = dev_get_drvdata(dev);
@@ -182,8 +182,6 @@ static int htcpen_isa_remove(struct device *dev, unsigned int id)
release_region(HTCPEN_PORT_INDEX, 2);
release_region(HTCPEN_PORT_INIT, 1);
release_region(HTCPEN_PORT_IRQ_CLEAR, 1);
-
- return 0;
}
#ifdef CONFIG_PM
diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c
index ad2ac16ff12d..c591c0851fa2 100644
--- a/drivers/media/radio/radio-isa.c
+++ b/drivers/media/radio/radio-isa.c
@@ -273,8 +273,8 @@ err_dev_reg:
return res;
}
-static int radio_isa_common_remove(struct radio_isa_card *isa,
- unsigned region_size)
+static void radio_isa_common_remove(struct radio_isa_card *isa,
+ unsigned region_size)
{
const struct radio_isa_ops *ops = isa->drv->ops;
@@ -285,7 +285,6 @@ static int radio_isa_common_remove(struct radio_isa_card *isa,
release_region(isa->io, region_size);
v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card);
kfree(isa);
- return 0;
}
int radio_isa_probe(struct device *pdev, unsigned int dev)
@@ -338,11 +337,11 @@ int radio_isa_probe(struct device *pdev, unsigned int dev)
}
EXPORT_SYMBOL_GPL(radio_isa_probe);
-int radio_isa_remove(struct device *pdev, unsigned int dev)
+void radio_isa_remove(struct device *pdev, unsigned int dev)
{
struct radio_isa_card *isa = dev_get_drvdata(pdev);
- return radio_isa_common_remove(isa, isa->drv->region_size);
+ radio_isa_common_remove(isa, isa->drv->region_size);
}
EXPORT_SYMBOL_GPL(radio_isa_remove);
diff --git a/drivers/media/radio/radio-isa.h b/drivers/media/radio/radio-isa.h
index 2f0736edfda8..c9159958203e 100644
--- a/drivers/media/radio/radio-isa.h
+++ b/drivers/media/radio/radio-isa.h
@@ -91,7 +91,7 @@ struct radio_isa_driver {
int radio_isa_match(struct device *pdev, unsigned int dev);
int radio_isa_probe(struct device *pdev, unsigned int dev);
-int radio_isa_remove(struct device *pdev, unsigned int dev);
+void radio_isa_remove(struct device *pdev, unsigned int dev);
#ifdef CONFIG_PNP
int radio_isa_pnp_probe(struct pnp_dev *dev,
const struct pnp_device_id *dev_id);
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 0388894cfe41..d0dde55b7930 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -293,11 +293,9 @@ static void fmr2_remove(struct fmr2 *fmr2)
kfree(fmr2);
}
-static int fmr2_isa_remove(struct device *pdev, unsigned int ndev)
+static void fmr2_isa_remove(struct device *pdev, unsigned int ndev)
{
fmr2_remove(dev_get_drvdata(pdev));
-
- return 0;
}
static void fmr2_pnp_remove(struct pnp_dev *pdev)
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 000cb82023e3..75f1bc671d59 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -797,17 +797,6 @@ const struct dev_pm_ops arizona_pm_ops = {
EXPORT_SYMBOL_GPL(arizona_pm_ops);
#ifdef CONFIG_OF
-unsigned long arizona_of_get_type(struct device *dev)
-{
- const struct of_device_id *id = of_match_device(arizona_of_match, dev);
-
- if (id)
- return (unsigned long)id->data;
- else
- return 0;
-}
-EXPORT_SYMBOL_GPL(arizona_of_get_type);
-
static int arizona_of_get_core_pdata(struct arizona *arizona)
{
struct arizona_pdata *pdata = &arizona->pdata;
diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
index 4b58e3ad6eb6..5e83b730c4ce 100644
--- a/drivers/mfd/arizona-i2c.c
+++ b/drivers/mfd/arizona-i2c.c
@@ -23,14 +23,16 @@
static int arizona_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
+ const void *match_data;
struct arizona *arizona;
const struct regmap_config *regmap_config = NULL;
- unsigned long type;
+ unsigned long type = 0;
int ret;
- if (i2c->dev.of_node)
- type = arizona_of_get_type(&i2c->dev);
- else
+ match_data = device_get_match_data(&i2c->dev);
+ if (match_data)
+ type = (unsigned long)match_data;
+ else if (id)
type = id->driver_data;
switch (type) {
@@ -115,6 +117,7 @@ static struct i2c_driver arizona_i2c_driver = {
module_i2c_driver(arizona_i2c_driver);
+MODULE_SOFTDEP("pre: arizona_ldo1");
MODULE_DESCRIPTION("Arizona I2C bus interface");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
index 2633e147b76c..24a2c75d691a 100644
--- a/drivers/mfd/arizona-spi.c
+++ b/drivers/mfd/arizona-spi.c
@@ -7,7 +7,10 @@
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*/
+#include <linux/acpi.h>
#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
@@ -15,22 +18,141 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
+#include <uapi/linux/input-event-codes.h>
#include <linux/mfd/arizona/core.h>
#include "arizona.h"
+#ifdef CONFIG_ACPI
+const struct acpi_gpio_params reset_gpios = { 1, 0, false };
+const struct acpi_gpio_params ldoena_gpios = { 2, 0, false };
+
+static const struct acpi_gpio_mapping arizona_acpi_gpios[] = {
+ { "reset-gpios", &reset_gpios, 1, },
+ { "wlf,ldoena-gpios", &ldoena_gpios, 1 },
+ { }
+};
+
+/*
+ * The ACPI resources for the device only describe external GPIO-s. They do
+ * not provide mappings for the GPIO-s coming from the Arizona codec itself.
+ */
+static const struct gpiod_lookup arizona_soc_gpios[] = {
+ { "arizona", 2, "wlf,spkvdd-ena", 0, GPIO_ACTIVE_HIGH },
+ { "arizona", 4, "wlf,micd-pol", 0, GPIO_ACTIVE_LOW },
+};
+
+/*
+ * The AOSP 3.5 mm Headset: Accessory Specification gives the following values:
+ * Function A Play/Pause: 0 ohm
+ * Function D Voice assistant: 135 ohm
+ * Function B Volume Up 240 ohm
+ * Function C Volume Down 470 ohm
+ * Minimum Mic DC resistance 1000 ohm
+ * Minimum Ear speaker impedance 16 ohm
+ * Note the first max value below must be less then the min. speaker impedance,
+ * to allow CTIA/OMTP detection to work. The other max values are the closest
+ * value from extcon-arizona.c:arizona_micd_levels halfway 2 button resistances.
+ */
+static const struct arizona_micd_range arizona_micd_aosp_ranges[] = {
+ { .max = 11, .key = KEY_PLAYPAUSE },
+ { .max = 186, .key = KEY_VOICECOMMAND },
+ { .max = 348, .key = KEY_VOLUMEUP },
+ { .max = 752, .key = KEY_VOLUMEDOWN },
+};
+
+static void arizona_spi_acpi_remove_lookup(void *lookup)
+{
+ gpiod_remove_lookup_table(lookup);
+}
+
+static int arizona_spi_acpi_probe(struct arizona *arizona)
+{
+ struct gpiod_lookup_table *lookup;
+ acpi_status status;
+ int ret;
+
+ /* Add mappings for the 2 ACPI declared GPIOs used for reset and ldo-ena */
+ devm_acpi_dev_add_driver_gpios(arizona->dev, arizona_acpi_gpios);
+
+ /* Add lookups for the SoCs own GPIOs used for micdet-polarity and spkVDD-enable */
+ lookup = devm_kzalloc(arizona->dev,
+ struct_size(lookup, table, ARRAY_SIZE(arizona_soc_gpios) + 1),
+ GFP_KERNEL);
+ if (!lookup)
+ return -ENOMEM;
+
+ lookup->dev_id = dev_name(arizona->dev);
+ memcpy(lookup->table, arizona_soc_gpios, sizeof(arizona_soc_gpios));
+
+ gpiod_add_lookup_table(lookup);
+ ret = devm_add_action_or_reset(arizona->dev, arizona_spi_acpi_remove_lookup, lookup);
+ if (ret)
+ return ret;
+
+ /* Enable 32KHz clock from SoC to codec for jack-detect */
+ status = acpi_evaluate_object(ACPI_HANDLE(arizona->dev), "CLKE", NULL, NULL);
+ if (ACPI_FAILURE(status))
+ dev_warn(arizona->dev, "Failed to enable 32KHz clk ACPI error %d\n", status);
+
+ /*
+ * Some DSDTs wrongly declare the IRQ trigger-type as IRQF_TRIGGER_FALLING
+ * The IRQ line will stay low when a new IRQ event happens between reading
+ * the IRQ status flags and acknowledging them. When the IRQ line stays
+ * low like this the IRQ will never trigger again when its type is set
+ * to IRQF_TRIGGER_FALLING. Correct the IRQ trigger-type to fix this.
+ *
+ * Note theoretically it is possible that some boards are not capable
+ * of handling active low level interrupts. In that case setting the
+ * flag to IRQF_TRIGGER_FALLING would not be a bug (and we would need
+ * to work around this) but so far all known usages of IRQF_TRIGGER_FALLING
+ * are a bug in the board's DSDT.
+ */
+ arizona->pdata.irq_flags = IRQF_TRIGGER_LOW;
+
+ /* Wait 200 ms after jack insertion */
+ arizona->pdata.micd_detect_debounce = 200;
+
+ /* Use standard AOSP values for headset-button mappings */
+ arizona->pdata.micd_ranges = arizona_micd_aosp_ranges;
+ arizona->pdata.num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges);
+
+ return 0;
+}
+
+static const struct acpi_device_id arizona_acpi_match[] = {
+ {
+ .id = "WM510204",
+ .driver_data = WM5102,
+ },
+ {
+ .id = "WM510205",
+ .driver_data = WM5102,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, arizona_acpi_match);
+#else
+static int arizona_spi_acpi_probe(struct arizona *arizona)
+{
+ return -ENODEV;
+}
+#endif
+
static int arizona_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
+ const void *match_data;
struct arizona *arizona;
const struct regmap_config *regmap_config = NULL;
- unsigned long type;
+ unsigned long type = 0;
int ret;
- if (spi->dev.of_node)
- type = arizona_of_get_type(&spi->dev);
- else
+ match_data = device_get_match_data(&spi->dev);
+ if (match_data)
+ type = (unsigned long)match_data;
+ else if (id)
type = id->driver_data;
switch (type) {
@@ -75,6 +197,12 @@ static int arizona_spi_probe(struct spi_device *spi)
arizona->dev = &spi->dev;
arizona->irq = spi->irq;
+ if (has_acpi_companion(&spi->dev)) {
+ ret = arizona_spi_acpi_probe(arizona);
+ if (ret)
+ return ret;
+ }
+
return arizona_dev_init(arizona);
}
@@ -102,6 +230,7 @@ static struct spi_driver arizona_spi_driver = {
.name = "arizona",
.pm = &arizona_pm_ops,
.of_match_table = of_match_ptr(arizona_of_match),
+ .acpi_match_table = ACPI_PTR(arizona_acpi_match),
},
.probe = arizona_spi_probe,
.remove = arizona_spi_remove,
@@ -110,6 +239,7 @@ static struct spi_driver arizona_spi_driver = {
module_spi_driver(arizona_spi_driver);
+MODULE_SOFTDEP("pre: arizona_ldo1");
MODULE_DESCRIPTION("Arizona SPI bus interface");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/arizona.h b/drivers/mfd/arizona.h
index 995efc6d7f32..801cbbcd71cb 100644
--- a/drivers/mfd/arizona.h
+++ b/drivers/mfd/arizona.h
@@ -50,13 +50,4 @@ int arizona_dev_exit(struct arizona *arizona);
int arizona_irq_init(struct arizona *arizona);
int arizona_irq_exit(struct arizona *arizona);
-#ifdef CONFIG_OF
-unsigned long arizona_of_get_type(struct device *dev);
-#else
-static inline unsigned long arizona_of_get_type(struct device *dev)
-{
- return 0;
-}
-#endif
-
#endif
diff --git a/drivers/net/can/sja1000/tscan1.c b/drivers/net/can/sja1000/tscan1.c
index 6ea802c66124..3dbba8d61afb 100644
--- a/drivers/net/can/sja1000/tscan1.c
+++ b/drivers/net/can/sja1000/tscan1.c
@@ -159,7 +159,7 @@ static int tscan1_probe(struct device *dev, unsigned id)
return -ENXIO;
}
-static int tscan1_remove(struct device *dev, unsigned id /*unused*/)
+static void tscan1_remove(struct device *dev, unsigned id /*unused*/)
{
struct net_device *netdev;
struct sja1000_priv *priv;
@@ -179,8 +179,6 @@ static int tscan1_remove(struct device *dev, unsigned id /*unused*/)
release_region(pld_base, TSCAN1_PLD_SIZE);
free_sja1000dev(netdev);
-
- return 0;
}
static struct isa_driver tscan1_isa_driver = {
diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c
index 667f38c9e4c6..53e1f7e07959 100644
--- a/drivers/net/ethernet/3com/3c509.c
+++ b/drivers/net/ethernet/3com/3c509.c
@@ -335,12 +335,11 @@ static int el3_isa_match(struct device *pdev, unsigned int ndev)
return 1;
}
-static int el3_isa_remove(struct device *pdev,
+static void el3_isa_remove(struct device *pdev,
unsigned int ndev)
{
el3_device_remove(pdev);
dev_set_drvdata(pdev, NULL);
- return 0;
}
#ifdef CONFIG_PM
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 79830e77afa9..b1e97f75b0ba 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -11459,12 +11459,11 @@ static int advansys_isa_probe(struct device *dev, unsigned int id)
return err;
}
-static int advansys_isa_remove(struct device *dev, unsigned int id)
+static void advansys_isa_remove(struct device *dev, unsigned int id)
{
int ioport = _asc_def_iop_base[id];
advansys_release(dev_get_drvdata(dev));
release_region(ioport, ASC_IOADR_GAP);
- return 0;
}
static struct isa_driver advansys_isa_driver = {
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index dc5667afeb27..e0d8cca1c70b 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -1025,12 +1025,11 @@ static int aha1542_isa_match(struct device *pdev, unsigned int ndev)
return 1;
}
-static int aha1542_isa_remove(struct device *pdev,
+static void aha1542_isa_remove(struct device *pdev,
unsigned int ndev)
{
aha1542_release(dev_get_drvdata(pdev));
dev_set_drvdata(pdev, NULL);
- return 0;
}
static struct isa_driver aha1542_isa_driver = {
diff --git a/drivers/scsi/fdomain_isa.c b/drivers/scsi/fdomain_isa.c
index e0cdcd2003d0..2b4280a43a53 100644
--- a/drivers/scsi/fdomain_isa.c
+++ b/drivers/scsi/fdomain_isa.c
@@ -175,7 +175,7 @@ static int fdomain_isa_param_match(struct device *dev, unsigned int ndev)
return 1;
}
-static int fdomain_isa_remove(struct device *dev, unsigned int ndev)
+static void fdomain_isa_remove(struct device *dev, unsigned int ndev)
{
struct Scsi_Host *sh = dev_get_drvdata(dev);
int base = sh->io_port;
@@ -183,7 +183,6 @@ static int fdomain_isa_remove(struct device *dev, unsigned int ndev)
fdomain_destroy(sh);
release_region(base, FDOMAIN_REGION_SIZE);
dev_set_drvdata(dev, NULL);
- return 0;
}
static struct isa_driver fdomain_isa_driver = {
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 2df2f38a9b12..7ba3c9312731 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -720,12 +720,11 @@ static int generic_NCR5380_isa_match(struct device *pdev, unsigned int ndev)
return 1;
}
-static int generic_NCR5380_isa_remove(struct device *pdev,
- unsigned int ndev)
+static void generic_NCR5380_isa_remove(struct device *pdev,
+ unsigned int ndev)
{
generic_NCR5380_release_resources(dev_get_drvdata(pdev));
dev_set_drvdata(pdev, NULL);
- return 0;
}
static struct isa_driver generic_NCR5380_isa_driver = {
diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c
index e86fa7f8351d..a793b03a785d 100644
--- a/drivers/watchdog/pcwd.c
+++ b/drivers/watchdog/pcwd.c
@@ -951,14 +951,11 @@ error_request_region:
return ret;
}
-static int pcwd_isa_remove(struct device *dev, unsigned int id)
+static void pcwd_isa_remove(struct device *dev, unsigned int id)
{
if (debug >= DEBUG)
pr_debug("pcwd_isa_remove id=%d\n", id);
- if (!pcwd_private.io_addr)
- return 1;
-
/* Disable the board */
if (!nowayout)
pcwd_stop();
@@ -971,8 +968,6 @@ static int pcwd_isa_remove(struct device *dev, unsigned int id)
(pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
pcwd_private.io_addr = 0x0000;
cards_found--;
-
- return 0;
}
static void pcwd_isa_shutdown(struct device *dev, unsigned int id)
diff --git a/include/linux/isa.h b/include/linux/isa.h
index 41336da0f4e7..e30963190968 100644
--- a/include/linux/isa.h
+++ b/include/linux/isa.h
@@ -13,7 +13,7 @@
struct isa_driver {
int (*match)(struct device *, unsigned int);
int (*probe)(struct device *, unsigned int);
- int (*remove)(struct device *, unsigned int);
+ void (*remove)(struct device *, unsigned int);
void (*shutdown)(struct device *, unsigned int);
int (*suspend)(struct device *, unsigned int, pm_message_t);
int (*resume)(struct device *, unsigned int);
diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index 50e1caad81be..ca6f4fcad51f 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -4610,6 +4610,7 @@ enum ec_codec_i2s_rx_subcmd {
EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x2,
EC_CODEC_I2S_RX_SET_DAIFMT = 0x3,
EC_CODEC_I2S_RX_SET_BCLK = 0x4,
+ EC_CODEC_I2S_RX_RESET = 0x5,
EC_CODEC_I2S_RX_SUBCMD_COUNT,
};
diff --git a/include/sound/core.h b/include/sound/core.h
index 0462c577d7a3..2e24f194ef70 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -122,6 +122,9 @@ struct snd_card {
size_t total_pcm_alloc_bytes; /* total amount of allocated buffers */
struct mutex memory_mutex; /* protection for the above */
+#ifdef CONFIG_SND_DEBUG
+ struct dentry *debugfs_root; /* debugfs root for card */
+#endif
#ifdef CONFIG_PM
unsigned int power_state; /* power state */
@@ -180,6 +183,9 @@ static inline struct device *snd_card_get_device_link(struct snd_card *card)
extern int snd_major;
extern int snd_ecards_limit;
extern struct class *sound_class;
+#ifdef CONFIG_SND_DEBUG
+extern struct dentry *sound_debugfs_root;
+#endif
void snd_request_card(int card);
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index 8c5e38180fb0..96666efddb39 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -66,6 +66,9 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
* @chan_name: Custom channel name to use when requesting DMA channel.
* @fifo_size: FIFO size of the DAI controller in bytes
* @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now
+ * @peripheral_config: peripheral configuration for programming peripheral
+ * for dmaengine transfer
+ * @peripheral_size: peripheral configuration buffer size
*/
struct snd_dmaengine_dai_dma_data {
dma_addr_t addr;
@@ -76,6 +79,8 @@ struct snd_dmaengine_dai_dma_data {
const char *chan_name;
unsigned int fifo_size;
unsigned int flags;
+ void *peripheral_config;
+ size_t peripheral_size;
};
void snd_dmaengine_pcm_set_config_from_dai_data(
diff --git a/include/sound/graph_card.h b/include/sound/graph_card.h
index bbb5a137855c..013784467bec 100644
--- a/include/sound/graph_card.h
+++ b/include/sound/graph_card.h
@@ -9,8 +9,10 @@
#include <sound/simple_card_utils.h>
-int graph_card_probe(struct snd_soc_card *card);
+int audio_graph_card_probe(struct snd_soc_card *card);
-int graph_parse_of(struct asoc_simple_priv *priv, struct device *dev);
+int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev);
+
+int audio_graph_remove(struct platform_device *pdev);
#endif /* __GRAPH_CARD_H */
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index 6eed61e6cf8a..22af68b01426 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -241,6 +241,8 @@ struct hdac_bus_ops {
/* get a response from the last command */
int (*get_response)(struct hdac_bus *bus, unsigned int addr,
unsigned int *res);
+ /* notify of codec link power-up/down */
+ void (*link_power)(struct hdac_device *hdev, bool enable);
};
/*
@@ -378,15 +380,8 @@ void snd_hdac_bus_exit(struct hdac_bus *bus);
int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr,
unsigned int cmd, unsigned int *res);
-static inline void snd_hdac_codec_link_up(struct hdac_device *codec)
-{
- set_bit(codec->addr, &codec->bus->codec_powered);
-}
-
-static inline void snd_hdac_codec_link_down(struct hdac_device *codec)
-{
- clear_bit(codec->addr, &codec->bus->codec_powered);
-}
+void snd_hdac_codec_link_up(struct hdac_device *codec);
+void snd_hdac_codec_link_down(struct hdac_device *codec);
int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val);
int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
@@ -400,6 +395,7 @@ void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus);
void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus);
void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus);
int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset);
+void snd_hdac_bus_link_power(struct hdac_device *hdev, bool enable);
void snd_hdac_bus_update_rirb(struct hdac_bus *bus);
int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h
index 7abf74c1c474..a125e3814b58 100644
--- a/include/sound/hdaudio_ext.h
+++ b/include/sound/hdaudio_ext.h
@@ -131,6 +131,8 @@ void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link,
int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *link);
int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *link);
+void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable);
+
/* update register macro */
#define snd_hdac_updatel(addr, reg, mask, val) \
writel(((readl(addr + reg) & ~(mask)) | (val)), \
diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
index b55970859a13..4b3a1d374b90 100644
--- a/include/sound/hdmi-codec.h
+++ b/include/sound/hdmi-codec.h
@@ -34,6 +34,11 @@ struct hdmi_codec_daifmt {
unsigned int frame_clk_inv:1;
unsigned int bit_clk_master:1;
unsigned int frame_clk_master:1;
+ /* bit_fmt could be standard PCM format or
+ * IEC958 encoded format. ALSA IEC958 plugin will pass
+ * IEC958_SUBFRAME format to the underneath driver.
+ */
+ snd_pcm_format_t bit_fmt;
};
/*
diff --git a/include/sound/jack.h b/include/sound/jack.h
index 9eb2b5ec1ec4..1181f536557e 100644
--- a/include/sound/jack.h
+++ b/include/sound/jack.h
@@ -67,6 +67,7 @@ struct snd_jack {
char name[100];
unsigned int key[6]; /* Keep in sync with definitions above */
#endif /* CONFIG_SND_JACK_INPUT_DEV */
+ int hw_status_cache;
void *private_data;
void (*private_free)(struct snd_jack *);
};
diff --git a/include/sound/rt5645.h b/include/sound/rt5645.h
index 39a77c7cea36..710c95be5509 100644
--- a/include/sound/rt5645.h
+++ b/include/sound/rt5645.h
@@ -22,6 +22,8 @@ struct rt5645_platform_data {
bool level_trigger_irq;
/* Invert JD1_1 status polarity */
bool inv_jd1_1;
+ /* Invert HP detect status polarity */
+ bool inv_hp_pol;
/* Value to asign to snd_soc_card.long_name */
const char *long_name;
diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
index 0bce41fefd30..5b47768222b7 100644
--- a/include/sound/soc-component.h
+++ b/include/sound/soc-component.h
@@ -353,6 +353,12 @@ int snd_soc_component_test_bits(struct snd_soc_component *component,
unsigned int reg, unsigned int mask,
unsigned int value);
+unsigned int snd_soc_component_read_field(struct snd_soc_component *component,
+ unsigned int reg, unsigned int mask);
+int snd_soc_component_write_field(struct snd_soc_component *component,
+ unsigned int reg, unsigned int mask,
+ unsigned int val);
+
/* component wide operations */
int snd_soc_component_set_sysclk(struct snd_soc_component *component,
int clk_id, int source,
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 34d0dbf73ca9..1358a0ceb4d0 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -353,9 +353,9 @@ struct snd_soc_dai_driver {
/* DAI capabilities */
struct snd_soc_pcm_stream capture;
struct snd_soc_pcm_stream playback;
- unsigned int symmetric_rates:1;
+ unsigned int symmetric_rate:1;
unsigned int symmetric_channels:1;
- unsigned int symmetric_samplebits:1;
+ unsigned int symmetric_sample_bits:1;
/* probe ordering - for components with runtime dependencies */
int probe_order;
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 3fa6c40a63b7..bd38015d6c6d 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -685,9 +685,9 @@ struct snd_soc_dai_link {
unsigned int ignore_suspend:1;
/* Symmetry requirements */
- unsigned int symmetric_rates:1;
+ unsigned int symmetric_rate:1;
unsigned int symmetric_channels:1;
- unsigned int symmetric_samplebits:1;
+ unsigned int symmetric_sample_bits:1;
/* Do not create a PCM for this DAI link (Backend link) */
unsigned int no_pcm:1;
diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h
index 7abc4f0bd3ad..2a7e055584f9 100644
--- a/include/sound/sof/ext_manifest.h
+++ b/include/sound/sof/ext_manifest.h
@@ -58,9 +58,9 @@ struct sof_ext_man_header {
/* Extended manifest elements types */
enum sof_ext_man_elem_type {
SOF_EXT_MAN_ELEM_FW_VERSION = 0,
- SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW,
- SOF_EXT_MAN_ELEM_CC_VERSION = SOF_IPC_EXT_CC_INFO,
- SOF_EXT_MAN_ELEM_DBG_ABI = SOF_IPC_EXT_USER_ABI_INFO,
+ SOF_EXT_MAN_ELEM_WINDOW = 1,
+ SOF_EXT_MAN_ELEM_CC_VERSION = 2,
+ SOF_EXT_MAN_ELEM_DBG_ABI = 4,
SOF_EXT_MAN_ELEM_CONFIG_DATA = 5, /**< ABI3.17 */
SOF_EXT_MAN_ELEM_PLATFORM_CONFIG_DATA = 6,
};
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c
index 7985dd8198b6..d9077e91382b 100644
--- a/sound/ac97/bus.c
+++ b/sound/ac97/bus.c
@@ -273,7 +273,7 @@ static struct attribute *ac97_controller_device_attrs[] = {
NULL
};
-static struct attribute_group ac97_adapter_attr_group = {
+static const struct attribute_group ac97_adapter_attr_group = {
.name = "ac97_operations",
.attrs = ac97_controller_device_attrs,
};
diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c
index 12028b3e2eee..1abee841cc45 100644
--- a/sound/aoa/codecs/onyx.c
+++ b/sound/aoa/codecs/onyx.c
@@ -1013,7 +1013,7 @@ static int onyx_i2c_probe(struct i2c_client *client,
goto fail;
}
- strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN);
+ strscpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN);
onyx->codec.owner = THIS_MODULE;
onyx->codec.init = onyx_init_codec;
onyx->codec.exit = onyx_exit_codec;
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
index d3e37577b529..ac246dd3ab49 100644
--- a/sound/aoa/codecs/tas.c
+++ b/sound/aoa/codecs/tas.c
@@ -894,7 +894,7 @@ static int tas_i2c_probe(struct i2c_client *client,
/* seems that half is a saner default */
tas->drc_range = TAS3004_DRC_MAX / 2;
- strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN);
+ strscpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN);
tas->codec.owner = THIS_MODULE;
tas->codec.init = tas_init_codec;
tas->codec.exit = tas_exit_codec;
diff --git a/sound/aoa/codecs/toonie.c b/sound/aoa/codecs/toonie.c
index c2d014486c33..0da5af129492 100644
--- a/sound/aoa/codecs/toonie.c
+++ b/sound/aoa/codecs/toonie.c
@@ -126,7 +126,7 @@ static int __init toonie_init(void)
if (!toonie)
return -ENOMEM;
- strlcpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name));
+ strscpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name));
toonie->codec.owner = THIS_MODULE;
toonie->codec.init = toonie_init_codec;
toonie->codec.exit = toonie_exit_codec;
diff --git a/sound/aoa/core/alsa.c b/sound/aoa/core/alsa.c
index b61081342266..7fce8581ddbd 100644
--- a/sound/aoa/core/alsa.c
+++ b/sound/aoa/core/alsa.c
@@ -28,10 +28,10 @@ int aoa_alsa_init(char *name, struct module *mod, struct device *dev)
return err;
aoa_card = alsa_card->private_data;
aoa_card->alsa_card = alsa_card;
- strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver));
- strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname));
- strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname));
- strlcpy(alsa_card->mixername, name, sizeof(alsa_card->mixername));
+ strscpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver));
+ strscpy(alsa_card->shortname, name, sizeof(alsa_card->shortname));
+ strscpy(alsa_card->longname, name, sizeof(alsa_card->longname));
+ strscpy(alsa_card->mixername, name, sizeof(alsa_card->mixername));
err = snd_card_register(aoa_card->alsa_card);
if (err < 0) {
printk(KERN_ERR "snd-aoa: couldn't register alsa card\n");
diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c
index d2e85b83f7ed..ec4ef18555bc 100644
--- a/sound/aoa/fabrics/layout.c
+++ b/sound/aoa/fabrics/layout.c
@@ -948,7 +948,7 @@ static void layout_attached_codec(struct aoa_codec *codec)
ldev->gpio.methods->set_lineout(codec->gpio, 1);
ctl = snd_ctl_new1(&lineout_ctl, codec->gpio);
if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
- strlcpy(ctl->id.name,
+ strscpy(ctl->id.name,
"Headphone Switch", sizeof(ctl->id.name));
ldev->lineout_ctrl = ctl;
aoa_snd_ctl_add(ctl);
@@ -962,14 +962,14 @@ static void layout_attached_codec(struct aoa_codec *codec)
ctl = snd_ctl_new1(&lineout_detect_choice,
ldev);
if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
- strlcpy(ctl->id.name,
+ strscpy(ctl->id.name,
"Headphone Detect Autoswitch",
sizeof(ctl->id.name));
aoa_snd_ctl_add(ctl);
ctl = snd_ctl_new1(&lineout_detected,
ldev);
if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
- strlcpy(ctl->id.name,
+ strscpy(ctl->id.name,
"Headphone Detected",
sizeof(ctl->id.name));
ldev->lineout_detected_ctrl = ctl;
diff --git a/sound/aoa/soundbus/sysfs.c b/sound/aoa/soundbus/sysfs.c
index a2d55e15afbb..dead3105689b 100644
--- a/sound/aoa/soundbus/sysfs.c
+++ b/sound/aoa/soundbus/sysfs.c
@@ -13,7 +13,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
int length;
if (*sdev->modalias) {
- strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1);
+ strscpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1);
strcat(buf, "\n");
length = strlen(buf);
} else {
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index a0996c47e58f..f02a91bdaa97 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -890,8 +890,8 @@ static struct aaci *aaci_init_card(struct amba_device *dev)
card->private_free = aaci_free_card;
- strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
- strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));
+ strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));
+ strscpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));
snprintf(card->longname, sizeof(card->longname),
"%s PL%03x rev%u at 0x%08llx, irq %d",
card->shortname, amba_part(dev), amba_rev(dev),
@@ -921,7 +921,7 @@ static int aaci_init_pcm(struct aaci *aaci)
pcm->private_data = aaci;
pcm->info_flags = 0;
- strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
+ strscpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index ea8e233150c8..6322e6392594 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -235,7 +235,7 @@ static int pxa2xx_ac97_probe(struct platform_device *dev)
if (ret < 0)
goto err;
- strlcpy(card->driver, dev->dev.driver->name, sizeof(card->driver));
+ strscpy(card->driver, dev->dev.driver->name, sizeof(card->driver));
ret = pxa2xx_ac97_pcm_new(card);
if (ret)
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index d4554f376160..a4050f87f230 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -187,6 +187,15 @@ config SND_CTL_VALIDATION
from the driver are in the proper ranges or the check of the invalid
access at out-of-array areas.
+config SND_JACK_INJECTION_DEBUG
+ bool "Sound jack injection interface via debugfs"
+ depends on SND_JACK && SND_DEBUG && DEBUG_FS
+ help
+ This option can be used to enable or disable sound jack
+ software injection.
+ Say Y if you are debugging via jack injection interface.
+ If unsure select "N".
+
config SND_VMASTER
bool
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index debc30fcf5b3..21ce4c056a92 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -1132,7 +1132,7 @@ static void snd_compress_proc_done(struct snd_compr *compr)
static inline void snd_compress_set_id(struct snd_compr *compr, const char *id)
{
- strlcpy(compr->id, id, sizeof(compr->id));
+ strscpy(compr->id, id, sizeof(compr->id));
}
#else
static inline int snd_compress_proc_init(struct snd_compr *compr)
diff --git a/sound/core/control.c b/sound/core/control.c
index 3b44378b9dec..5165741a8400 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -261,7 +261,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
kctl->id.device = ncontrol->device;
kctl->id.subdevice = ncontrol->subdevice;
if (ncontrol->name) {
- strlcpy(kctl->id.name, ncontrol->name, sizeof(kctl->id.name));
+ strscpy(kctl->id.name, ncontrol->name, sizeof(kctl->id.name));
if (strcmp(ncontrol->name, kctl->id.name) != 0)
pr_warn("ALSA: Control name '%s' truncated to '%s'\n",
ncontrol->name, kctl->id.name);
@@ -701,12 +701,12 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
return -ENOMEM;
down_read(&snd_ioctl_rwsem);
info->card = card->number;
- strlcpy(info->id, card->id, sizeof(info->id));
- strlcpy(info->driver, card->driver, sizeof(info->driver));
- strlcpy(info->name, card->shortname, sizeof(info->name));
- strlcpy(info->longname, card->longname, sizeof(info->longname));
- strlcpy(info->mixername, card->mixername, sizeof(info->mixername));
- strlcpy(info->components, card->components, sizeof(info->components));
+ strscpy(info->id, card->id, sizeof(info->id));
+ strscpy(info->driver, card->driver, sizeof(info->driver));
+ strscpy(info->name, card->shortname, sizeof(info->name));
+ strscpy(info->longname, card->longname, sizeof(info->longname));
+ strscpy(info->mixername, card->mixername, sizeof(info->mixername));
+ strscpy(info->components, card->components, sizeof(info->components));
up_read(&snd_ioctl_rwsem);
if (copy_to_user(arg, info, sizeof(struct snd_ctl_card_info))) {
kfree(info);
@@ -836,7 +836,7 @@ static void fill_remaining_elem_value(struct snd_ctl_elem_value *control,
{
size_t offset = value_sizes[info->type] * info->count;
- offset = (offset + sizeof(u32) - 1) / sizeof(u32);
+ offset = DIV_ROUND_UP(offset, sizeof(u32));
memset32((u32 *)control->value.bytes.data + offset, pattern,
sizeof(control->value) / sizeof(u32) - offset);
}
@@ -928,7 +928,7 @@ static int sanity_check_elem_value(struct snd_card *card,
/* check whether the remaining area kept untouched */
offset = value_sizes[info->type] * info->count;
- offset = (offset + sizeof(u32) - 1) / sizeof(u32);
+ offset = DIV_ROUND_UP(offset, sizeof(u32));
p = (u32 *)control->value.bytes.data + offset;
for (; offset < sizeof(control->value) / sizeof(u32); offset++, p++) {
if (*p != pattern) {
@@ -2137,7 +2137,7 @@ int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
WARN(strlen(names[info->value.enumerated.item]) >= sizeof(info->value.enumerated.name),
"ALSA: too long item name '%s'\n",
names[info->value.enumerated.item]);
- strlcpy(info->value.enumerated.name,
+ strscpy(info->value.enumerated.name,
names[info->value.enumerated.item],
sizeof(info->value.enumerated.name));
return 0;
diff --git a/sound/core/ctljack.c b/sound/core/ctljack.c
index 9be4e282f2e0..709b1a9c2caa 100644
--- a/sound/core/ctljack.c
+++ b/sound/core/ctljack.c
@@ -35,7 +35,7 @@ static int get_available_index(struct snd_card *card, const char *name)
sid.index = 0;
sid.iface = SNDRV_CTL_ELEM_IFACE_CARD;
- strlcpy(sid.name, name, sizeof(sid.name));
+ strscpy(sid.name, name, sizeof(sid.name));
while (snd_ctl_find_id(card, &sid)) {
sid.index++;
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 0c029892880a..264b8ea64bc2 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -177,8 +177,8 @@ static int snd_hwdep_info(struct snd_hwdep *hw,
memset(&info, 0, sizeof(info));
info.card = hw->card->number;
- strlcpy(info.id, hw->id, sizeof(info.id));
- strlcpy(info.name, hw->name, sizeof(info.name));
+ strscpy(info.id, hw->id, sizeof(info.id));
+ strscpy(info.name, hw->name, sizeof(info.name));
info.iface = hw->iface;
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
@@ -379,7 +379,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device,
hwdep->card = card;
hwdep->device = device;
if (id)
- strlcpy(hwdep->id, id, sizeof(hwdep->id));
+ strscpy(hwdep->id, id, sizeof(hwdep->id));
snd_device_initialize(&hwdep->dev, card);
hwdep->dev.release = release_hwdep_device;
diff --git a/sound/core/init.c b/sound/core/init.c
index 75aec71c48a8..45f4b01de23f 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -13,7 +13,9 @@
#include <linux/time.h>
#include <linux/ctype.h>
#include <linux/pm.h>
+#include <linux/debugfs.h>
#include <linux/completion.h>
+#include <linux/interrupt.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -161,6 +163,9 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
{
struct snd_card *card;
int err;
+#ifdef CONFIG_SND_DEBUG
+ char name[8];
+#endif
if (snd_BUG_ON(!card_ret))
return -EINVAL;
@@ -174,7 +179,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
if (extra_size > 0)
card->private_data = (char *)card + sizeof(struct snd_card);
if (xid)
- strlcpy(card->id, xid, sizeof(card->id));
+ strscpy(card->id, xid, sizeof(card->id));
err = 0;
mutex_lock(&snd_card_mutex);
if (idx < 0) /* first check the matching module-name slot */
@@ -244,6 +249,12 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
dev_err(parent, "unable to create card info\n");
goto __error_ctl;
}
+
+#ifdef CONFIG_SND_DEBUG
+ sprintf(name, "card%d", idx);
+ card->debugfs_root = debugfs_create_dir(name, sound_debugfs_root);
+#endif
+
*card_ret = card;
return 0;
@@ -416,6 +427,9 @@ int snd_card_disconnect(struct snd_card *card)
/* notify all devices that we are disconnected */
snd_device_disconnect_all(card);
+ if (card->sync_irq > 0)
+ synchronize_irq(card->sync_irq);
+
snd_info_card_disconnect(card);
if (card->registered) {
device_del(&card->card_dev);
@@ -477,6 +491,10 @@ static int snd_card_do_free(struct snd_card *card)
dev_warn(card->dev, "unable to free card info\n");
/* Not fatal error */
}
+#ifdef CONFIG_SND_DEBUG
+ debugfs_remove(card->debugfs_root);
+ card->debugfs_root = NULL;
+#endif
if (card->release_completion)
complete(card->release_completion);
kfree(card);
@@ -526,6 +544,7 @@ int snd_card_free(struct snd_card *card)
return ret;
/* wait, until all devices are ready for the free operation */
wait_for_completion(&released);
+
return 0;
}
EXPORT_SYMBOL(snd_card_free);
@@ -623,7 +642,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *src,
/* last resort... */
dev_err(card->dev, "unable to set card id (%s)\n", id);
if (card->proc_root->name)
- strlcpy(card->id, card->proc_root->name, sizeof(card->id));
+ strscpy(card->id, card->proc_root->name, sizeof(card->id));
}
/**
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 503c8af79d55..32350c6aba84 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -8,6 +8,9 @@
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/mm.h>
+#include <linux/debugfs.h>
#include <sound/jack.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -16,6 +19,11 @@ struct snd_jack_kctl {
struct snd_kcontrol *kctl;
struct list_head list; /* list of controls belong to the same jack */
unsigned int mask_bits; /* only masked status bits are reported via kctl */
+ struct snd_jack *jack; /* pointer to struct snd_jack */
+ bool sw_inject_enable; /* allow to inject plug event via debugfs */
+#ifdef CONFIG_SND_JACK_INJECTION_DEBUG
+ struct dentry *jack_debugfs_root; /* jack_kctl debugfs root */
+#endif
};
#ifdef CONFIG_SND_JACK_INPUT_DEV
@@ -109,12 +117,291 @@ static int snd_jack_dev_register(struct snd_device *device)
}
#endif /* CONFIG_SND_JACK_INPUT_DEV */
+#ifdef CONFIG_SND_JACK_INJECTION_DEBUG
+static void snd_jack_inject_report(struct snd_jack_kctl *jack_kctl, int status)
+{
+ struct snd_jack *jack;
+#ifdef CONFIG_SND_JACK_INPUT_DEV
+ int i;
+#endif
+ if (!jack_kctl)
+ return;
+
+ jack = jack_kctl->jack;
+
+ if (jack_kctl->sw_inject_enable)
+ snd_kctl_jack_report(jack->card, jack_kctl->kctl,
+ status & jack_kctl->mask_bits);
+
+#ifdef CONFIG_SND_JACK_INPUT_DEV
+ if (!jack->input_dev)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
+ int testbit = ((SND_JACK_BTN_0 >> i) & jack_kctl->mask_bits);
+
+ if (jack->type & testbit)
+ input_report_key(jack->input_dev, jack->key[i],
+ status & testbit);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
+ int testbit = ((1 << i) & jack_kctl->mask_bits);
+
+ if (jack->type & testbit)
+ input_report_switch(jack->input_dev,
+ jack_switch_types[i],
+ status & testbit);
+ }
+
+ input_sync(jack->input_dev);
+#endif /* CONFIG_SND_JACK_INPUT_DEV */
+}
+
+static ssize_t sw_inject_enable_read(struct file *file,
+ char __user *to, size_t count, loff_t *ppos)
+{
+ struct snd_jack_kctl *jack_kctl = file->private_data;
+ int len, ret;
+ char buf[128];
+
+ len = scnprintf(buf, sizeof(buf), "%s: %s\t\t%s: %i\n", "Jack", jack_kctl->kctl->id.name,
+ "Inject Enabled", jack_kctl->sw_inject_enable);
+ ret = simple_read_from_buffer(to, count, ppos, buf, len);
+
+ return ret;
+}
+
+static ssize_t sw_inject_enable_write(struct file *file,
+ const char __user *from, size_t count, loff_t *ppos)
+{
+ struct snd_jack_kctl *jack_kctl = file->private_data;
+ int ret, err;
+ unsigned long enable;
+ char buf[8] = { 0 };
+
+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, from, count);
+ err = kstrtoul(buf, 0, &enable);
+ if (err)
+ return err;
+
+ if (jack_kctl->sw_inject_enable == (!!enable))
+ return ret;
+
+ jack_kctl->sw_inject_enable = !!enable;
+
+ if (!jack_kctl->sw_inject_enable)
+ snd_jack_report(jack_kctl->jack, jack_kctl->jack->hw_status_cache);
+
+ return ret;
+}
+
+static ssize_t jackin_inject_write(struct file *file,
+ const char __user *from, size_t count, loff_t *ppos)
+{
+ struct snd_jack_kctl *jack_kctl = file->private_data;
+ int ret, err;
+ unsigned long enable;
+ char buf[8] = { 0 };
+
+ if (!jack_kctl->sw_inject_enable)
+ return -EINVAL;
+
+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, from, count);
+ err = kstrtoul(buf, 0, &enable);
+ if (err)
+ return err;
+
+ snd_jack_inject_report(jack_kctl, !!enable ? jack_kctl->mask_bits : 0);
+
+ return ret;
+}
+
+static ssize_t jack_kctl_id_read(struct file *file,
+ char __user *to, size_t count, loff_t *ppos)
+{
+ struct snd_jack_kctl *jack_kctl = file->private_data;
+ char buf[64];
+ int len, ret;
+
+ len = scnprintf(buf, sizeof(buf), "%s\n", jack_kctl->kctl->id.name);
+ ret = simple_read_from_buffer(to, count, ppos, buf, len);
+
+ return ret;
+}
+
+/* the bit definition is aligned with snd_jack_types in jack.h */
+static const char * const jack_events_name[] = {
+ "HEADPHONE(0x0001)", "MICROPHONE(0x0002)", "LINEOUT(0x0004)",
+ "MECHANICAL(0x0008)", "VIDEOOUT(0x0010)", "LINEIN(0x0020)",
+ "", "", "", "BTN_5(0x0200)", "BTN_4(0x0400)", "BTN_3(0x0800)",
+ "BTN_2(0x1000)", "BTN_1(0x2000)", "BTN_0(0x4000)", "",
+};
+
+/* the recommended buffer size is 256 */
+static int parse_mask_bits(unsigned int mask_bits, char *buf, size_t buf_size)
+{
+ int i;
+
+ scnprintf(buf, buf_size, "0x%04x", mask_bits);
+
+ for (i = 0; i < ARRAY_SIZE(jack_events_name); i++)
+ if (mask_bits & (1 << i)) {
+ strlcat(buf, " ", buf_size);
+ strlcat(buf, jack_events_name[i], buf_size);
+ }
+ strlcat(buf, "\n", buf_size);
+
+ return strlen(buf);
+}
+
+static ssize_t jack_kctl_mask_bits_read(struct file *file,
+ char __user *to, size_t count, loff_t *ppos)
+{
+ struct snd_jack_kctl *jack_kctl = file->private_data;
+ char buf[256];
+ int len, ret;
+
+ len = parse_mask_bits(jack_kctl->mask_bits, buf, sizeof(buf));
+ ret = simple_read_from_buffer(to, count, ppos, buf, len);
+
+ return ret;
+}
+
+static ssize_t jack_kctl_status_read(struct file *file,
+ char __user *to, size_t count, loff_t *ppos)
+{
+ struct snd_jack_kctl *jack_kctl = file->private_data;
+ char buf[16];
+ int len, ret;
+
+ len = scnprintf(buf, sizeof(buf), "%s\n", jack_kctl->kctl->private_value ?
+ "Plugged" : "Unplugged");
+ ret = simple_read_from_buffer(to, count, ppos, buf, len);
+
+ return ret;
+}
+
+#ifdef CONFIG_SND_JACK_INPUT_DEV
+static ssize_t jack_type_read(struct file *file,
+ char __user *to, size_t count, loff_t *ppos)
+{
+ struct snd_jack_kctl *jack_kctl = file->private_data;
+ char buf[256];
+ int len, ret;
+
+ len = parse_mask_bits(jack_kctl->jack->type, buf, sizeof(buf));
+ ret = simple_read_from_buffer(to, count, ppos, buf, len);
+
+ return ret;
+}
+
+static const struct file_operations jack_type_fops = {
+ .open = simple_open,
+ .read = jack_type_read,
+ .llseek = default_llseek,
+};
+#endif
+
+static const struct file_operations sw_inject_enable_fops = {
+ .open = simple_open,
+ .read = sw_inject_enable_read,
+ .write = sw_inject_enable_write,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations jackin_inject_fops = {
+ .open = simple_open,
+ .write = jackin_inject_write,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations jack_kctl_id_fops = {
+ .open = simple_open,
+ .read = jack_kctl_id_read,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations jack_kctl_mask_bits_fops = {
+ .open = simple_open,
+ .read = jack_kctl_mask_bits_read,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations jack_kctl_status_fops = {
+ .open = simple_open,
+ .read = jack_kctl_status_read,
+ .llseek = default_llseek,
+};
+
+static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
+ struct snd_jack_kctl *jack_kctl)
+{
+ char *tname;
+ int i;
+
+ /* Don't create injection interface for Phantom jacks */
+ if (strstr(jack_kctl->kctl->id.name, "Phantom"))
+ return 0;
+
+ tname = kstrdup(jack_kctl->kctl->id.name, GFP_KERNEL);
+ if (!tname)
+ return -ENOMEM;
+
+ /* replace the chars which are not suitable for folder's name with _ */
+ for (i = 0; tname[i]; i++)
+ if (!isalnum(tname[i]))
+ tname[i] = '_';
+
+ jack_kctl->jack_debugfs_root = debugfs_create_dir(tname, jack->card->debugfs_root);
+ kfree(tname);
+
+ debugfs_create_file("sw_inject_enable", 0644, jack_kctl->jack_debugfs_root, jack_kctl,
+ &sw_inject_enable_fops);
+
+ debugfs_create_file("jackin_inject", 0200, jack_kctl->jack_debugfs_root, jack_kctl,
+ &jackin_inject_fops);
+
+ debugfs_create_file("kctl_id", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
+ &jack_kctl_id_fops);
+
+ debugfs_create_file("mask_bits", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
+ &jack_kctl_mask_bits_fops);
+
+ debugfs_create_file("status", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
+ &jack_kctl_status_fops);
+
+#ifdef CONFIG_SND_JACK_INPUT_DEV
+ debugfs_create_file("type", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
+ &jack_type_fops);
+#endif
+ return 0;
+}
+
+static void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl)
+{
+ debugfs_remove(jack_kctl->jack_debugfs_root);
+ jack_kctl->jack_debugfs_root = NULL;
+}
+#else /* CONFIG_SND_JACK_INJECTION_DEBUG */
+static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
+ struct snd_jack_kctl *jack_kctl)
+{
+ return 0;
+}
+
+static void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl)
+{
+}
+#endif /* CONFIG_SND_JACK_INJECTION_DEBUG */
+
static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl)
{
struct snd_jack_kctl *jack_kctl;
jack_kctl = kctl->private_data;
if (jack_kctl) {
+ snd_jack_debugfs_clear_inject_node(jack_kctl);
list_del(&jack_kctl->list);
kfree(jack_kctl);
}
@@ -122,7 +409,9 @@ static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl)
static void snd_jack_kctl_add(struct snd_jack *jack, struct snd_jack_kctl *jack_kctl)
{
+ jack_kctl->jack = jack;
list_add_tail(&jack_kctl->list, &jack->kctl_list);
+ snd_jack_debugfs_add_inject_node(jack, jack_kctl);
}
static struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const char *name, unsigned int mask)
@@ -340,6 +629,7 @@ EXPORT_SYMBOL(snd_jack_set_key);
void snd_jack_report(struct snd_jack *jack, int status)
{
struct snd_jack_kctl *jack_kctl;
+ unsigned int mask_bits = 0;
#ifdef CONFIG_SND_JACK_INPUT_DEV
int i;
#endif
@@ -347,16 +637,21 @@ void snd_jack_report(struct snd_jack *jack, int status)
if (!jack)
return;
+ jack->hw_status_cache = status;
+
list_for_each_entry(jack_kctl, &jack->kctl_list, list)
- snd_kctl_jack_report(jack->card, jack_kctl->kctl,
- status & jack_kctl->mask_bits);
+ if (jack_kctl->sw_inject_enable)
+ mask_bits |= jack_kctl->mask_bits;
+ else
+ snd_kctl_jack_report(jack->card, jack_kctl->kctl,
+ status & jack_kctl->mask_bits);
#ifdef CONFIG_SND_JACK_INPUT_DEV
if (!jack->input_dev)
return;
for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
- int testbit = SND_JACK_BTN_0 >> i;
+ int testbit = ((SND_JACK_BTN_0 >> i) & ~mask_bits);
if (jack->type & testbit)
input_report_key(jack->input_dev, jack->key[i],
@@ -364,7 +659,8 @@ void snd_jack_report(struct snd_jack *jack, int status)
}
for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
- int testbit = 1 << i;
+ int testbit = ((1 << i) & ~mask_bits);
+
if (jack->type & testbit)
input_report_switch(jack->input_dev,
jack_switch_types[i],
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index f702c96a7478..bec928327478 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -87,8 +87,8 @@ static int snd_mixer_oss_info(struct snd_mixer_oss_file *fmixer,
struct mixer_info info;
memset(&info, 0, sizeof(info));
- strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
- strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
+ strscpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
+ strscpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
info.modify_counter = card->mixer_oss_change_count;
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
@@ -103,8 +103,8 @@ static int snd_mixer_oss_info_obsolete(struct snd_mixer_oss_file *fmixer,
_old_mixer_info info;
memset(&info, 0, sizeof(info));
- strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
- strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
+ strscpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
+ strscpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
return 0;
@@ -418,7 +418,7 @@ static long snd_mixer_oss_conv(long val, long omin, long omax, long nmin, long n
if (orange == 0)
return 0;
- return ((nrange * (val - omin)) + (orange / 2)) / orange + nmin;
+ return DIV_ROUND_CLOSEST(nrange * (val - omin), orange) + nmin;
}
/* convert from alsa native to oss values (0-100) */
@@ -499,7 +499,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c
memset(&id, 0, sizeof(id));
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- strlcpy(id.name, name, sizeof(id.name));
+ strscpy(id.name, name, sizeof(id.name));
id.index = index;
return snd_ctl_find_id(card, &id);
}
@@ -1355,7 +1355,7 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd)
mixer->oss_dev_alloc = 1;
mixer->card = card;
if (*card->mixername)
- strlcpy(mixer->name, card->mixername, sizeof(mixer->name));
+ strscpy(mixer->name, card->mixername, sizeof(mixer->name));
else
snprintf(mixer->name, sizeof(mixer->name),
"mixer%i", card->number);
diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c
index d381f4c967c9..98269119347f 100644
--- a/sound/core/oss/rate.c
+++ b/sound/core/oss/rate.c
@@ -193,7 +193,7 @@ static snd_pcm_sframes_t rate_src_frames(struct snd_pcm_plugin *plugin, snd_pcm_
if (plugin->src_format.rate < plugin->dst_format.rate) {
res = (((frames * data->pitch) + (BITS/2)) >> SHIFT);
} else {
- res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch);
+ res = DIV_ROUND_CLOSEST(frames << SHIFT, data->pitch);
}
if (data->old_src_frames > 0) {
snd_pcm_sframes_t frames1 = frames, res1 = data->old_dst_frames;
@@ -224,7 +224,7 @@ static snd_pcm_sframes_t rate_dst_frames(struct snd_pcm_plugin *plugin, snd_pcm_
return 0;
data = (struct rate_priv *)plugin->extra_data;
if (plugin->src_format.rate < plugin->dst_format.rate) {
- res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch);
+ res = DIV_ROUND_CLOSEST(frames << SHIFT, data->pitch);
} else {
res = (((frames * data->pitch) + (BITS/2)) >> SHIFT);
}
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index be5714f1bb58..b163164a83ec 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -729,7 +729,7 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
init_waitqueue_head(&pcm->open_wait);
INIT_LIST_HEAD(&pcm->list);
if (id)
- strlcpy(pcm->id, id, sizeof(pcm->id));
+ strscpy(pcm->id, id, sizeof(pcm->id));
err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK,
playback_count);
@@ -1095,22 +1095,23 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
mutex_lock(&pcm->open_mutex);
wake_up(&pcm->open_wait);
list_del_init(&pcm->list);
- for (cidx = 0; cidx < 2; cidx++) {
- for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
- snd_pcm_stream_lock_irq(substream);
- if (substream->runtime) {
- if (snd_pcm_running(substream))
- snd_pcm_stop(substream,
- SNDRV_PCM_STATE_DISCONNECTED);
- /* to be sure, set the state unconditionally */
- substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
- wake_up(&substream->runtime->sleep);
- wake_up(&substream->runtime->tsleep);
- }
- snd_pcm_stream_unlock_irq(substream);
+
+ for_each_pcm_substream(pcm, cidx, substream) {
+ snd_pcm_stream_lock_irq(substream);
+ if (substream->runtime) {
+ if (snd_pcm_running(substream))
+ snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
+ /* to be sure, set the state unconditionally */
+ substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
+ wake_up(&substream->runtime->sleep);
+ wake_up(&substream->runtime->tsleep);
}
+ snd_pcm_stream_unlock_irq(substream);
}
+ for_each_pcm_substream(pcm, cidx, substream)
+ snd_pcm_sync_stop(substream, false);
+
pcm_call_notify(pcm, n_disconnect);
for (cidx = 0; cidx < 2; cidx++) {
snd_unregister_device(&pcm->streams[cidx].dev);
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index 4d0e8fe535a1..1fc2fa077574 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -125,6 +125,8 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
}
slave_config->slave_id = dma_data->slave_id;
+ slave_config->peripheral_config = dma_data->peripheral_config;
+ slave_config->peripheral_size = dma_data->peripheral_size;
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data);
diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h
index 17a1a5d87098..e3b3558aeab6 100644
--- a/sound/core/pcm_local.h
+++ b/sound/core/pcm_local.h
@@ -63,6 +63,7 @@ static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {}
void __snd_pcm_xrun(struct snd_pcm_substream *substream);
void snd_pcm_group_init(struct snd_pcm_group *group);
+void snd_pcm_sync_stop(struct snd_pcm_substream *substream, bool sync_irq);
#ifdef CONFIG_SND_DMA_SGBUF
struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream,
@@ -71,4 +72,10 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream,
#define PCM_RUNTIME_CHECK(sub) snd_BUG_ON(!(sub) || !(sub)->runtime)
+/* loop over all PCM substreams */
+#define for_each_pcm_substream(pcm, str, subs) \
+ for ((str) = 0; (str) < 2; (str)++) \
+ for ((subs) = (pcm)->streams[str].substream; (subs); \
+ (subs) = (subs)->next)
+
#endif /* __SOUND_CORE_PCM_LOCAL_H */
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index ee6e9c5eec45..289dd1fd8fe7 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -111,9 +111,8 @@ void snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
struct snd_pcm_substream *substream;
int stream;
- for (stream = 0; stream < 2; stream++)
- for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
- snd_pcm_lib_preallocate_free(substream);
+ for_each_pcm_substream(pcm, stream, substream)
+ snd_pcm_lib_preallocate_free(substream);
}
EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
@@ -246,11 +245,8 @@ static void preallocate_pages_for_all(struct snd_pcm *pcm, int type,
struct snd_pcm_substream *substream;
int stream;
- for (stream = 0; stream < 2; stream++)
- for (substream = pcm->streams[stream].substream; substream;
- substream = substream->next)
- preallocate_pages(substream, type, data, size, max,
- managed);
+ for_each_pcm_substream(pcm, stream, substream)
+ preallocate_pages(substream, type, data, size, max, managed);
}
/**
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index c4aac703dc22..17a85f4815d5 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -209,13 +209,13 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
info->device = pcm->device;
info->stream = substream->stream;
info->subdevice = substream->number;
- strlcpy(info->id, pcm->id, sizeof(info->id));
- strlcpy(info->name, pcm->name, sizeof(info->name));
+ strscpy(info->id, pcm->id, sizeof(info->id));
+ strscpy(info->name, pcm->name, sizeof(info->name));
info->dev_class = pcm->dev_class;
info->dev_subclass = pcm->dev_subclass;
info->subdevices_count = pstr->substream_count;
info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
- strlcpy(info->subname, substream->name, sizeof(info->subname));
+ strscpy(info->subname, substream->name, sizeof(info->subname));
return 0;
}
@@ -583,13 +583,13 @@ static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
#endif
}
-static void snd_pcm_sync_stop(struct snd_pcm_substream *substream)
+void snd_pcm_sync_stop(struct snd_pcm_substream *substream, bool sync_irq)
{
- if (substream->runtime->stop_operating) {
+ if (substream->runtime && substream->runtime->stop_operating) {
substream->runtime->stop_operating = false;
- if (substream->ops->sync_stop)
+ if (substream->ops && substream->ops->sync_stop)
substream->ops->sync_stop(substream);
- else if (substream->pcm->card->sync_irq > 0)
+ else if (sync_irq && substream->pcm->card->sync_irq > 0)
synchronize_irq(substream->pcm->card->sync_irq);
}
}
@@ -686,7 +686,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
if (atomic_read(&substream->mmap_count))
return -EBADFD;
- snd_pcm_sync_stop(substream);
+ snd_pcm_sync_stop(substream, true);
params->rmask = ~0U;
err = snd_pcm_hw_refine(substream, params);
@@ -809,7 +809,7 @@ static int do_hw_free(struct snd_pcm_substream *substream)
{
int result = 0;
- snd_pcm_sync_stop(substream);
+ snd_pcm_sync_stop(substream, true);
if (substream->ops->hw_free)
result = substream->ops->hw_free(substream);
if (substream->managed_buffer_alloc)
@@ -1421,8 +1421,10 @@ static int snd_pcm_do_stop(struct snd_pcm_substream *substream,
snd_pcm_state_t state)
{
if (substream->runtime->trigger_master == substream &&
- snd_pcm_running(substream))
+ snd_pcm_running(substream)) {
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
+ substream->runtime->stop_operating = true;
+ }
return 0; /* unconditonally stop all substreams */
}
@@ -1435,7 +1437,6 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream,
runtime->status->state = state;
snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTOP);
}
- runtime->stop_operating = true;
wake_up(&runtime->sleep);
wake_up(&runtime->tsleep);
}
@@ -1615,6 +1616,7 @@ static int snd_pcm_do_suspend(struct snd_pcm_substream *substream,
if (! snd_pcm_running(substream))
return 0;
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
+ runtime->stop_operating = true;
return 0; /* suspend unconditionally */
}
@@ -1672,25 +1674,26 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm)
if (! pcm)
return 0;
- for (stream = 0; stream < 2; stream++) {
- for (substream = pcm->streams[stream].substream;
- substream; substream = substream->next) {
- /* FIXME: the open/close code should lock this as well */
- if (substream->runtime == NULL)
- continue;
+ for_each_pcm_substream(pcm, stream, substream) {
+ /* FIXME: the open/close code should lock this as well */
+ if (!substream->runtime)
+ continue;
- /*
- * Skip BE dai link PCM's that are internal and may
- * not have their substream ops set.
- */
- if (!substream->ops)
- continue;
+ /*
+ * Skip BE dai link PCM's that are internal and may
+ * not have their substream ops set.
+ */
+ if (!substream->ops)
+ continue;
- err = snd_pcm_suspend(substream);
- if (err < 0 && err != -EBUSY)
- return err;
- }
+ err = snd_pcm_suspend(substream);
+ if (err < 0 && err != -EBUSY)
+ return err;
}
+
+ for_each_pcm_substream(pcm, stream, substream)
+ snd_pcm_sync_stop(substream, false);
+
return 0;
}
EXPORT_SYMBOL(snd_pcm_suspend_all);
@@ -1736,7 +1739,6 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream,
snd_pcm_trigger_tstamp(substream);
runtime->status->state = runtime->status->suspended_state;
snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME);
- snd_pcm_sync_stop(substream);
}
static const struct action_ops snd_pcm_action_resume = {
@@ -1866,7 +1868,7 @@ static int snd_pcm_do_prepare(struct snd_pcm_substream *substream,
snd_pcm_state_t state)
{
int err;
- snd_pcm_sync_stop(substream);
+ snd_pcm_sync_stop(substream, true);
err = substream->ops->prepare(substream);
if (err < 0)
return err;
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 257ad5206240..aca00af93afe 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -1686,7 +1686,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,
INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams);
if (id != NULL)
- strlcpy(rmidi->id, id, sizeof(rmidi->id));
+ strscpy(rmidi->id, id, sizeof(rmidi->id));
snd_device_initialize(&rmidi->dev, card);
rmidi->dev.release = release_rawmidi_device;
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index 2ddfe2226651..3f82c196de46 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -173,7 +173,7 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
snd_use_lock_init(&mdev->use_lock);
/* copy and truncate the name of synth device */
- strlcpy(mdev->name, pinfo->name, sizeof(mdev->name));
+ strscpy(mdev->name, pinfo->name, sizeof(mdev->name));
/* create MIDI coder */
if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) {
@@ -647,7 +647,7 @@ snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info
inf->device = dev;
inf->dev_type = 0; /* FIXME: ?? */
inf->capabilities = 0; /* FIXME: ?? */
- strlcpy(inf->name, mdev->name, sizeof(inf->name));
+ strscpy(inf->name, mdev->name, sizeof(inf->name));
snd_use_lock_free(&mdev->use_lock);
return 0;
}
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 1b8409ec2c97..722f5059b300 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -107,7 +107,7 @@ snd_seq_oss_synth_probe(struct device *_dev)
snd_use_lock_init(&rec->use_lock);
/* copy and truncate the name of synth device */
- strlcpy(rec->name, dev->name, sizeof(rec->name));
+ strscpy(rec->name, dev->name, sizeof(rec->name));
/* registration */
spin_lock_irqsave(&register_lock, flags);
@@ -617,7 +617,7 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
inf->synth_subtype = 0;
inf->nr_voices = 16;
inf->device = dev;
- strlcpy(inf->name, minf.name, sizeof(inf->name));
+ strscpy(inf->name, minf.name, sizeof(inf->name));
} else {
if ((rec = get_synthdev(dp, dev)) == NULL)
return -ENXIO;
@@ -625,7 +625,7 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
inf->synth_subtype = rec->synth_subtype;
inf->nr_voices = rec->nr_voices;
inf->device = dev;
- strlcpy(inf->name, rec->name, sizeof(inf->name));
+ strscpy(inf->name, rec->name, sizeof(inf->name));
snd_use_lock_free(&rec->use_lock);
}
return 0;
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index f9f2fea58b32..b6a24fb5e76b 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1584,7 +1584,7 @@ static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client,
info->queue = q->queue;
info->owner = q->owner;
info->locked = q->locked;
- strlcpy(info->name, q->name, sizeof(info->name));
+ strscpy(info->name, q->name, sizeof(info->name));
queuefree(q);
return 0;
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index 65db1a7c77b7..e245bb6ba533 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -290,7 +290,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
extlen = 0;
if (snd_seq_ev_is_variable(event)) {
extlen = event->data.ext.len & ~SNDRV_SEQ_EXT_MASK;
- ncells = (extlen + sizeof(struct snd_seq_event) - 1) / sizeof(struct snd_seq_event);
+ ncells = DIV_ROUND_UP(extlen, sizeof(struct snd_seq_event));
}
if (ncells >= pool->total_elements)
return -ENOMEM;
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 83be6b982a87..b9c2ce2b8d5a 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -327,7 +327,7 @@ int snd_seq_set_port_info(struct snd_seq_client_port * port,
/* set port name */
if (info->name[0])
- strlcpy(port->name, info->name, sizeof(port->name));
+ strscpy(port->name, info->name, sizeof(port->name));
/* set capabilities */
port->capability = info->capability;
@@ -356,7 +356,7 @@ int snd_seq_get_port_info(struct snd_seq_client_port * port,
return -EINVAL;
/* get port name */
- strlcpy(info->name, port->name, sizeof(info->name));
+ strscpy(info->name, port->name, sizeof(info->name));
/* get capabilities */
info->capability = port->capability;
@@ -654,7 +654,7 @@ int snd_seq_event_port_attach(int client,
/* Set up the port */
memset(&portinfo, 0, sizeof(portinfo));
portinfo.addr.client = client;
- strlcpy(portinfo.name, portname ? portname : "Unnamed port",
+ strscpy(portinfo.name, portname ? portname : "Unnamed port",
sizeof(portinfo.name));
portinfo.capability = cap;
diff --git a/sound/core/sound.c b/sound/core/sound.c
index b75f78f2c4b8..af89e51dd44a 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -9,6 +9,7 @@
#include <linux/time.h>
#include <linux/device.h>
#include <linux/module.h>
+#include <linux/debugfs.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/info.h>
@@ -39,6 +40,11 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
int snd_ecards_limit;
EXPORT_SYMBOL(snd_ecards_limit);
+#ifdef CONFIG_SND_DEBUG
+struct dentry *sound_debugfs_root;
+EXPORT_SYMBOL_GPL(sound_debugfs_root);
+#endif
+
static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
static DEFINE_MUTEX(sound_mutex);
@@ -337,6 +343,8 @@ static const char *snd_device_type_name(int type)
return "sequencer";
case SNDRV_DEVICE_TYPE_TIMER:
return "timer";
+ case SNDRV_DEVICE_TYPE_COMPRESS:
+ return "compress";
default:
return "?";
}
@@ -395,6 +403,10 @@ static int __init alsa_sound_init(void)
unregister_chrdev(major, "alsa");
return -ENOMEM;
}
+
+#ifdef CONFIG_SND_DEBUG
+ sound_debugfs_root = debugfs_create_dir("sound", NULL);
+#endif
#ifndef MODULE
pr_info("Advanced Linux Sound Architecture Driver Initialized.\n");
#endif
@@ -403,6 +415,9 @@ static int __init alsa_sound_init(void)
static void __exit alsa_sound_exit(void)
{
+#ifdef CONFIG_SND_DEBUG
+ debugfs_remove(sound_debugfs_root);
+#endif
snd_info_done();
unregister_chrdev(major, "alsa");
}
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 765ea66665a8..6898b1ac0d7f 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -959,7 +959,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
timer->tmr_device = tid->device;
timer->tmr_subdevice = tid->subdevice;
if (id)
- strlcpy(timer->id, id, sizeof(timer->id));
+ strscpy(timer->id, id, sizeof(timer->id));
timer->sticks = 1;
INIT_LIST_HEAD(&timer->device_list);
INIT_LIST_HEAD(&timer->open_list_head);
@@ -1659,8 +1659,8 @@ static int snd_timer_user_ginfo(struct file *file,
ginfo->card = t->card ? t->card->number : -1;
if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
ginfo->flags |= SNDRV_TIMER_FLG_SLAVE;
- strlcpy(ginfo->id, t->id, sizeof(ginfo->id));
- strlcpy(ginfo->name, t->name, sizeof(ginfo->name));
+ strscpy(ginfo->id, t->id, sizeof(ginfo->id));
+ strscpy(ginfo->name, t->name, sizeof(ginfo->name));
ginfo->resolution = t->hw.resolution;
if (t->hw.resolution_min > 0) {
ginfo->resolution_min = t->hw.resolution_min;
@@ -1814,8 +1814,8 @@ static int snd_timer_user_info(struct file *file,
info->card = t->card ? t->card->number : -1;
if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
info->flags |= SNDRV_TIMER_FLG_SLAVE;
- strlcpy(info->id, t->id, sizeof(info->id));
- strlcpy(info->name, t->name, sizeof(info->name));
+ strscpy(info->id, t->id, sizeof(info->id));
+ strscpy(info->name, t->name, sizeof(info->name));
info->resolution = t->hw.resolution;
if (copy_to_user(_info, info, sizeof(*_info)))
err = -EFAULT;
diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c
index 0103d16f6f9f..ee973b7b8044 100644
--- a/sound/core/timer_compat.c
+++ b/sound/core/timer_compat.c
@@ -61,8 +61,8 @@ static int snd_timer_user_info_compat(struct file *file,
info.card = t->card ? t->card->number : -1;
if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
info.flags |= SNDRV_TIMER_FLG_SLAVE;
- strlcpy(info.id, t->id, sizeof(info.id));
- strlcpy(info.name, t->name, sizeof(info.name));
+ strscpy(info.id, t->id, sizeof(info.id));
+ strscpy(info.name, t->name, sizeof(info.name));
info.resolution = t->hw.resolution;
if (copy_to_user(_info, &info, sizeof(*_info)))
return -EFAULT;
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 702f91b9c60f..8a24e5ae7cef 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -219,7 +219,7 @@ static int loopback_jiffies_timer_start(struct loopback_pcm *dpcm)
dpcm->period_update_pending = 1;
}
tick = dpcm->period_size_frac - dpcm->irq_pos;
- tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps;
+ tick = DIV_ROUND_UP(tick, dpcm->pcm_bps);
mod_timer(&dpcm->timer, jiffies + tick);
return 0;
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index b5486de08b97..316c9afadefe 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -236,7 +236,7 @@ struct dummy_systimer_pcm {
static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm)
{
mod_timer(&dpcm->timer, jiffies +
- (dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate);
+ DIV_ROUND_UP(dpcm->frac_period_rest, dpcm->rate));
}
static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm)
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
index 7bf0d5f3fedd..c82c7c1c0714 100644
--- a/sound/drivers/opl3/opl3_oss.c
+++ b/sound/drivers/opl3/opl3_oss.c
@@ -97,7 +97,7 @@ void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name)
return;
opl3->oss_seq_dev = dev;
- strlcpy(dev->name, name, sizeof(dev->name));
+ strscpy(dev->name, name, sizeof(dev->name));
arg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
arg->type = SYNTH_TYPE_FM;
if (opl3->hardware < OPL3_HW_OPL3) {
diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c
index 08c10ac9d6c8..97d30a833ac8 100644
--- a/sound/drivers/opl3/opl3_synth.c
+++ b/sound/drivers/opl3/opl3_synth.c
@@ -290,7 +290,7 @@ int snd_opl3_load_patch(struct snd_opl3 *opl3,
}
if (name)
- strlcpy(patch->name, name, sizeof(patch->name));
+ strscpy(patch->name, name, sizeof(patch->name));
return 0;
}
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index 3d2e3bcafca8..daffda99b4f7 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -1154,8 +1154,7 @@ static int vx_init_audio_io(struct vx_core *chip)
chip->ibl.size = 0;
vx_set_ibl(chip, &chip->ibl); /* query the info */
if (preferred > 0) {
- chip->ibl.size = ((preferred + chip->ibl.granularity - 1) /
- chip->ibl.granularity) * chip->ibl.granularity;
+ chip->ibl.size = roundup(preferred, chip->ibl.granularity);
if (chip->ibl.size > chip->ibl.max_size)
chip->ibl.size = chip->ibl.max_size;
} else
diff --git a/sound/firewire/bebob/bebob_hwdep.c b/sound/firewire/bebob/bebob_hwdep.c
index c362eb38ab90..6f9331655d43 100644
--- a/sound/firewire/bebob/bebob_hwdep.c
+++ b/sound/firewire/bebob/bebob_hwdep.c
@@ -37,11 +37,9 @@ hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
memset(&event, 0, sizeof(event));
count = min_t(long, count, sizeof(event.lock_status));
- if (bebob->dev_lock_changed) {
- event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
- event.lock_status.status = (bebob->dev_lock_count > 0);
- bebob->dev_lock_changed = false;
- }
+ event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
+ event.lock_status.status = (bebob->dev_lock_count > 0);
+ bebob->dev_lock_changed = false;
spin_unlock_irq(&bebob->lock);
@@ -80,7 +78,7 @@ hwdep_get_info(struct snd_bebob *bebob, void __user *arg)
info.card = dev->card->index;
*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
- strlcpy(info.device_name, dev_name(&dev->device),
+ strscpy(info.device_name, dev_name(&dev->device),
sizeof(info.device_name));
if (copy_to_user(arg, &info, sizeof(info)))
diff --git a/sound/firewire/dice/Makefile b/sound/firewire/dice/Makefile
index 7a62dafd0f78..9bf7b960a720 100644
--- a/sound/firewire/dice/Makefile
+++ b/sound/firewire/dice/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
snd-dice-objs := dice-transaction.o dice-stream.o dice-proc.o dice-midi.o \
dice-pcm.o dice-hwdep.o dice.o dice-tcelectronic.o \
- dice-alesis.o dice-extension.o dice-mytek.o dice-presonus.o
+ dice-alesis.o dice-extension.o dice-mytek.o dice-presonus.o \
+ dice-harman.o
obj-$(CONFIG_SND_DICE) += snd-dice.o
diff --git a/sound/firewire/dice/dice-harman.c b/sound/firewire/dice/dice-harman.c
new file mode 100644
index 000000000000..a8ca00c397e8
--- /dev/null
+++ b/sound/firewire/dice/dice-harman.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+// dice-harman.c - a part of driver for DICE based devices
+//
+// Copyright (c) 2021 Takashi Sakamoto
+//
+// Licensed under the terms of the GNU General Public License, version 2.
+
+#include "dice.h"
+
+int snd_dice_detect_harman_formats(struct snd_dice *dice)
+{
+ int i;
+
+ // Lexicon I-ONYX FW810s supports sampling transfer frequency up to
+ // 96.0 kHz, 12 PCM channels and 1 MIDI channel in its first tx stream
+ // , 10 PCM channels and 1 MIDI channel in its first rx stream for all
+ // of the frequencies.
+ for (i = 0; i < 2; ++i) {
+ dice->tx_pcm_chs[0][i] = 12;
+ dice->tx_midi_ports[0] = 1;
+ dice->rx_pcm_chs[0][i] = 10;
+ dice->rx_midi_ports[0] = 1;
+ }
+
+ return 0;
+}
diff --git a/sound/firewire/dice/dice-hwdep.c b/sound/firewire/dice/dice-hwdep.c
index f69f7996762f..ffc0b97782d6 100644
--- a/sound/firewire/dice/dice-hwdep.c
+++ b/sound/firewire/dice/dice-hwdep.c
@@ -79,7 +79,7 @@ static int hwdep_get_info(struct snd_dice *dice, void __user *arg)
info.card = dev->card->index;
*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
- strlcpy(info.device_name, dev_name(&dev->device),
+ strscpy(info.device_name, dev_name(&dev->device),
sizeof(info.device_name));
if (copy_to_user(arg, &info, sizeof(info)))
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c
index 06c94f009dfb..107a81691f0e 100644
--- a/sound/firewire/dice/dice.c
+++ b/sound/firewire/dice/dice.c
@@ -20,10 +20,12 @@ MODULE_LICENSE("GPL v2");
#define OUI_MYTEK 0x001ee8
#define OUI_SSL 0x0050c2 // Actually ID reserved by IEEE.
#define OUI_PRESONUS 0x000a92
+#define OUI_HARMAN 0x000fd7
#define DICE_CATEGORY_ID 0x04
#define WEISS_CATEGORY_ID 0x00
#define LOUD_CATEGORY_ID 0x10
+#define HARMAN_CATEGORY_ID 0x20
#define MODEL_ALESIS_IO_BOTH 0x000001
@@ -56,6 +58,8 @@ static int check_dice_category(struct fw_unit *unit)
category = WEISS_CATEGORY_ID;
else if (vendor == OUI_LOUD)
category = LOUD_CATEGORY_ID;
+ else if (vendor == OUI_HARMAN)
+ category = HARMAN_CATEGORY_ID;
else
category = DICE_CATEGORY_ID;
if (device->config_rom[3] != ((vendor << 8) | category) ||
@@ -388,6 +392,14 @@ static const struct ieee1394_device_id dice_id_table[] = {
.model_id = 0x000008,
.driver_data = (kernel_ulong_t)snd_dice_detect_presonus_formats,
},
+ // Lexicon I-ONYX FW810S.
+ {
+ .match_flags = IEEE1394_MATCH_VENDOR_ID |
+ IEEE1394_MATCH_MODEL_ID,
+ .vendor_id = OUI_HARMAN,
+ .model_id = 0x000001,
+ .driver_data = (kernel_ulong_t)snd_dice_detect_harman_formats,
+ },
{
.match_flags = IEEE1394_MATCH_VERSION,
.version = DICE_INTERFACE,
diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h
index 7fbffcab94c2..adc6f7c84460 100644
--- a/sound/firewire/dice/dice.h
+++ b/sound/firewire/dice/dice.h
@@ -233,5 +233,6 @@ int snd_dice_detect_alesis_mastercontrol_formats(struct snd_dice *dice);
int snd_dice_detect_extension_formats(struct snd_dice *dice);
int snd_dice_detect_mytek_formats(struct snd_dice *dice);
int snd_dice_detect_presonus_formats(struct snd_dice *dice);
+int snd_dice_detect_harman_formats(struct snd_dice *dice);
#endif
diff --git a/sound/firewire/digi00x/digi00x-hwdep.c b/sound/firewire/digi00x/digi00x-hwdep.c
index 41c5857c612e..aadf7d724856 100644
--- a/sound/firewire/digi00x/digi00x-hwdep.c
+++ b/sound/firewire/digi00x/digi00x-hwdep.c
@@ -87,7 +87,7 @@ static int hwdep_get_info(struct snd_dg00x *dg00x, void __user *arg)
info.card = dev->card->index;
*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
- strlcpy(info.device_name, dev_name(&dev->device),
+ strscpy(info.device_name, dev_name(&dev->device),
sizeof(info.device_name));
if (copy_to_user(arg, &info, sizeof(info)))
diff --git a/sound/firewire/fireface/ff-hwdep.c b/sound/firewire/fireface/ff-hwdep.c
index e73e8d2865a5..ea64a2a41eea 100644
--- a/sound/firewire/fireface/ff-hwdep.c
+++ b/sound/firewire/fireface/ff-hwdep.c
@@ -35,13 +35,11 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
}
memset(&event, 0, sizeof(event));
- if (ff->dev_lock_changed) {
- event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
- event.lock_status.status = (ff->dev_lock_count > 0);
- ff->dev_lock_changed = false;
+ event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
+ event.lock_status.status = (ff->dev_lock_count > 0);
+ ff->dev_lock_changed = false;
- count = min_t(long, count, sizeof(event.lock_status));
- }
+ count = min_t(long, count, sizeof(event.lock_status));
spin_unlock_irq(&ff->lock);
@@ -79,7 +77,7 @@ static int hwdep_get_info(struct snd_ff *ff, void __user *arg)
info.card = dev->card->index;
*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
- strlcpy(info.device_name, dev_name(&dev->device),
+ strscpy(info.device_name, dev_name(&dev->device),
sizeof(info.device_name));
if (copy_to_user(arg, &info, sizeof(info)))
diff --git a/sound/firewire/fireface/ff-protocol-latter.c b/sound/firewire/fireface/ff-protocol-latter.c
index 8d3b23778eb2..7ddb7b97f02d 100644
--- a/sound/firewire/fireface/ff-protocol-latter.c
+++ b/sound/firewire/fireface/ff-protocol-latter.c
@@ -15,6 +15,61 @@
#define LATTER_FETCH_MODE 0xffff00000010ULL
#define LATTER_SYNC_STATUS 0x0000801c0000ULL
+// The content of sync status register differs between models.
+//
+// Fireface UCX:
+// 0xf0000000: (unidentified)
+// 0x0f000000: effective rate of sampling clock
+// 0x00f00000: detected rate of word clock on BNC interface
+// 0x000f0000: detected rate of ADAT or S/PDIF on optical interface
+// 0x0000f000: detected rate of S/PDIF on coaxial interface
+// 0x00000e00: effective source of sampling clock
+// 0x00000e00: Internal
+// 0x00000800: (unidentified)
+// 0x00000600: Word clock on BNC interface
+// 0x00000400: ADAT on optical interface
+// 0x00000200: S/PDIF on coaxial or optical interface
+// 0x00000100: Optical interface is used for ADAT signal
+// 0x00000080: (unidentified)
+// 0x00000040: Synchronized to word clock on BNC interface
+// 0x00000020: Synchronized to ADAT or S/PDIF on optical interface
+// 0x00000010: Synchronized to S/PDIF on coaxial interface
+// 0x00000008: (unidentified)
+// 0x00000004: Lock word clock on BNC interface
+// 0x00000002: Lock ADAT or S/PDIF on optical interface
+// 0x00000001: Lock S/PDIF on coaxial interface
+//
+// Fireface 802 (and perhaps UFX):
+// 0xf0000000: effective rate of sampling clock
+// 0x0f000000: detected rate of ADAT-B on 2nd optical interface
+// 0x00f00000: detected rate of ADAT-A on 1st optical interface
+// 0x000f0000: detected rate of AES/EBU on XLR or coaxial interface
+// 0x0000f000: detected rate of word clock on BNC interface
+// 0x00000e00: effective source of sampling clock
+// 0x00000e00: internal
+// 0x00000800: ADAT-B
+// 0x00000600: ADAT-A
+// 0x00000400: AES/EBU
+// 0x00000200: Word clock
+// 0x00000080: Synchronized to ADAT-B on 2nd optical interface
+// 0x00000040: Synchronized to ADAT-A on 1st optical interface
+// 0x00000020: Synchronized to AES/EBU on XLR or 2nd optical interface
+// 0x00000010: Synchronized to word clock on BNC interface
+// 0x00000008: Lock ADAT-B on 2nd optical interface
+// 0x00000004: Lock ADAT-A on 1st optical interface
+// 0x00000002: Lock AES/EBU on XLR or 2nd optical interface
+// 0x00000001: Lock word clock on BNC interface
+//
+// The pattern for rate bits:
+// 0x00: 32.0 kHz
+// 0x01: 44.1 kHz
+// 0x02: 48.0 kHz
+// 0x04: 64.0 kHz
+// 0x05: 88.2 kHz
+// 0x06: 96.0 kHz
+// 0x08: 128.0 kHz
+// 0x09: 176.4 kHz
+// 0x0a: 192.0 kHz
static int parse_clock_bits(u32 data, unsigned int *rate,
enum snd_ff_clock_src *src,
enum snd_ff_unit_version unit_version)
@@ -23,35 +78,48 @@ static int parse_clock_bits(u32 data, unsigned int *rate,
unsigned int rate;
u32 flag;
} *rate_entry, rate_entries[] = {
- { 32000, 0x00000000, },
- { 44100, 0x01000000, },
- { 48000, 0x02000000, },
- { 64000, 0x04000000, },
- { 88200, 0x05000000, },
- { 96000, 0x06000000, },
- { 128000, 0x08000000, },
- { 176400, 0x09000000, },
- { 192000, 0x0a000000, },
+ { 32000, 0x00, },
+ { 44100, 0x01, },
+ { 48000, 0x02, },
+ { 64000, 0x04, },
+ { 88200, 0x05, },
+ { 96000, 0x06, },
+ { 128000, 0x08, },
+ { 176400, 0x09, },
+ { 192000, 0x0a, },
};
static const struct {
enum snd_ff_clock_src src;
u32 flag;
- } *clk_entry, clk_entries[] = {
+ } *clk_entry, *clk_entries, ucx_clk_entries[] = {
{ SND_FF_CLOCK_SRC_SPDIF, 0x00000200, },
{ SND_FF_CLOCK_SRC_ADAT1, 0x00000400, },
{ SND_FF_CLOCK_SRC_WORD, 0x00000600, },
{ SND_FF_CLOCK_SRC_INTERNAL, 0x00000e00, },
+ }, ufx_ff802_clk_entries[] = {
+ { SND_FF_CLOCK_SRC_WORD, 0x00000200, },
+ { SND_FF_CLOCK_SRC_SPDIF, 0x00000400, },
+ { SND_FF_CLOCK_SRC_ADAT1, 0x00000600, },
+ { SND_FF_CLOCK_SRC_ADAT2, 0x00000800, },
+ { SND_FF_CLOCK_SRC_INTERNAL, 0x00000e00, },
};
+ u32 rate_bits;
+ unsigned int clk_entry_count;
int i;
- if (unit_version != SND_FF_UNIT_VERSION_UCX) {
- // e.g. 0x00fe0f20 but expected 0x00eff002.
- data = ((data & 0xf0f0f0f0) >> 4) | ((data & 0x0f0f0f0f) << 4);
+ if (unit_version == SND_FF_UNIT_VERSION_UCX) {
+ rate_bits = (data & 0x0f000000) >> 24;
+ clk_entries = ucx_clk_entries;
+ clk_entry_count = ARRAY_SIZE(ucx_clk_entries);
+ } else {
+ rate_bits = (data & 0xf0000000) >> 28;
+ clk_entries = ufx_ff802_clk_entries;
+ clk_entry_count = ARRAY_SIZE(ufx_ff802_clk_entries);
}
for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) {
rate_entry = rate_entries + i;
- if ((data & 0x0f000000) == rate_entry->flag) {
+ if (rate_bits == rate_entry->flag) {
*rate = rate_entry->rate;
break;
}
@@ -59,14 +127,14 @@ static int parse_clock_bits(u32 data, unsigned int *rate,
if (i == ARRAY_SIZE(rate_entries))
return -EIO;
- for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
+ for (i = 0; i < clk_entry_count; ++i) {
clk_entry = clk_entries + i;
if ((data & 0x000e00) == clk_entry->flag) {
*src = clk_entry->src;
break;
}
}
- if (i == ARRAY_SIZE(clk_entries))
+ if (i == clk_entry_count)
return -EIO;
return 0;
@@ -249,16 +317,22 @@ static void latter_dump_status(struct snd_ff *ff, struct snd_info_buffer *buffer
char *const label;
u32 locked_mask;
u32 synced_mask;
- } *clk_entry, clk_entries[] = {
+ } *clk_entry, *clk_entries, ucx_clk_entries[] = {
{ "S/PDIF", 0x00000001, 0x00000010, },
{ "ADAT", 0x00000002, 0x00000020, },
{ "WDClk", 0x00000004, 0x00000040, },
+ }, ufx_ff802_clk_entries[] = {
+ { "WDClk", 0x00000001, 0x00000010, },
+ { "AES/EBU", 0x00000002, 0x00000020, },
+ { "ADAT-A", 0x00000004, 0x00000040, },
+ { "ADAT-B", 0x00000008, 0x00000080, },
};
__le32 reg;
u32 data;
unsigned int rate;
enum snd_ff_clock_src src;
const char *label;
+ unsigned int clk_entry_count;
int i;
int err;
@@ -270,7 +344,15 @@ static void latter_dump_status(struct snd_ff *ff, struct snd_info_buffer *buffer
snd_iprintf(buffer, "External source detection:\n");
- for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
+ if (ff->unit_version == SND_FF_UNIT_VERSION_UCX) {
+ clk_entries = ucx_clk_entries;
+ clk_entry_count = ARRAY_SIZE(ucx_clk_entries);
+ } else {
+ clk_entries = ufx_ff802_clk_entries;
+ clk_entry_count = ARRAY_SIZE(ufx_ff802_clk_entries);
+ }
+
+ for (i = 0; i < clk_entry_count; ++i) {
clk_entry = clk_entries + i;
snd_iprintf(buffer, "%s: ", clk_entry->label);
if (data & clk_entry->locked_mask) {
diff --git a/sound/firewire/fireworks/fireworks_hwdep.c b/sound/firewire/fireworks/fireworks_hwdep.c
index e93eb4616c5f..626c0c34b0b6 100644
--- a/sound/firewire/fireworks/fireworks_hwdep.c
+++ b/sound/firewire/fireworks/fireworks_hwdep.c
@@ -212,7 +212,7 @@ hwdep_get_info(struct snd_efw *efw, void __user *arg)
info.card = dev->card->index;
*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
- strlcpy(info.device_name, dev_name(&dev->device),
+ strscpy(info.device_name, dev_name(&dev->device),
sizeof(info.device_name));
if (copy_to_user(arg, &info, sizeof(info)))
diff --git a/sound/firewire/motu/motu-hwdep.c b/sound/firewire/motu/motu-hwdep.c
index 0764a477052a..b5ced5d27758 100644
--- a/sound/firewire/motu/motu-hwdep.c
+++ b/sound/firewire/motu/motu-hwdep.c
@@ -86,7 +86,7 @@ static int hwdep_get_info(struct snd_motu *motu, void __user *arg)
info.card = dev->card->index;
*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
- strlcpy(info.device_name, dev_name(&dev->device),
+ strscpy(info.device_name, dev_name(&dev->device),
sizeof(info.device_name));
if (copy_to_user(arg, &info, sizeof(info)))
diff --git a/sound/firewire/oxfw/oxfw-hwdep.c b/sound/firewire/oxfw/oxfw-hwdep.c
index eba33d050060..a0fe99618554 100644
--- a/sound/firewire/oxfw/oxfw-hwdep.c
+++ b/sound/firewire/oxfw/oxfw-hwdep.c
@@ -35,13 +35,11 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
}
memset(&event, 0, sizeof(event));
- if (oxfw->dev_lock_changed) {
- event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
- event.lock_status.status = (oxfw->dev_lock_count > 0);
- oxfw->dev_lock_changed = false;
+ event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
+ event.lock_status.status = (oxfw->dev_lock_count > 0);
+ oxfw->dev_lock_changed = false;
- count = min_t(long, count, sizeof(event.lock_status));
- }
+ count = min_t(long, count, sizeof(event.lock_status));
spin_unlock_irq(&oxfw->lock);
@@ -79,7 +77,7 @@ static int hwdep_get_info(struct snd_oxfw *oxfw, void __user *arg)
info.card = dev->card->index;
*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
- strlcpy(info.device_name, dev_name(&dev->device),
+ strscpy(info.device_name, dev_name(&dev->device),
sizeof(info.device_name));
if (copy_to_user(arg, &info, sizeof(info)))
diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c
index 6f38335fe10b..74eed9505665 100644
--- a/sound/firewire/tascam/tascam-hwdep.c
+++ b/sound/firewire/tascam/tascam-hwdep.c
@@ -154,7 +154,7 @@ static int hwdep_get_info(struct snd_tscm *tscm, void __user *arg)
info.card = dev->card->index;
*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
- strlcpy(info.device_name, dev_name(&dev->device),
+ strscpy(info.device_name, dev_name(&dev->device),
sizeof(info.device_name));
if (copy_to_user(arg, &info, sizeof(info)))
diff --git a/sound/hda/Kconfig b/sound/hda/Kconfig
index 3bc9224d5e4f..9ed5cfa3c18c 100644
--- a/sound/hda/Kconfig
+++ b/sound/hda/Kconfig
@@ -46,3 +46,17 @@ config SND_INTEL_DSP_CONFIG
select SND_INTEL_NHLT if ACPI
# this config should be selected only for Intel DSP platforms.
# A fallback is provided so that the code compiles in all cases.
+
+config SND_INTEL_BYT_PREFER_SOF
+ bool "Prefer SOF driver over SST on BY/CHT platforms"
+ depends on SND_SST_ATOM_HIFI2_PLATFORM_ACPI && SND_SOC_SOF_BAYTRAIL
+ default n
+ help
+ The kernel has 2 drivers for the Low Power Engine audio-block on
+ Bay- and Cherry-Trail SoCs. The old SST driver and the new SOF
+ driver. If both drivers are enabled then the kernel will default
+ to using the old SST driver, unless told otherwise through the
+ snd_intel_dspcfg.dsp_driver module-parameter.
+
+ Set this option to Y to make the kernel default to the new SOF
+ driver instead.
diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c
index b0c0ef824d7d..a9bd39b93697 100644
--- a/sound/hda/ext/hdac_ext_controller.c
+++ b/sound/hda/ext/hdac_ext_controller.c
@@ -332,3 +332,40 @@ int snd_hdac_ext_bus_link_put(struct hdac_bus *bus,
return ret;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_put);
+
+static void hdac_ext_codec_link_up(struct hdac_device *codec)
+{
+ const char *devname = dev_name(&codec->dev);
+ struct hdac_ext_link *hlink =
+ snd_hdac_ext_bus_get_link(codec->bus, devname);
+
+ if (hlink)
+ snd_hdac_ext_bus_link_get(codec->bus, hlink);
+}
+
+static void hdac_ext_codec_link_down(struct hdac_device *codec)
+{
+ const char *devname = dev_name(&codec->dev);
+ struct hdac_ext_link *hlink =
+ snd_hdac_ext_bus_get_link(codec->bus, devname);
+
+ if (hlink)
+ snd_hdac_ext_bus_link_put(codec->bus, hlink);
+}
+
+void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable)
+{
+ struct hdac_bus *bus = codec->bus;
+ bool oldstate = test_bit(codec->addr, &bus->codec_powered);
+
+ if (enable == oldstate)
+ return;
+
+ snd_hdac_bus_link_power(codec, enable);
+
+ if (enable)
+ hdac_ext_codec_link_up(codec);
+ else
+ hdac_ext_codec_link_down(codec);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power);
diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c
index 9766f6af8743..71db8592b33d 100644
--- a/sound/hda/hdac_bus.c
+++ b/sound/hda/hdac_bus.c
@@ -17,6 +17,7 @@ static void snd_hdac_bus_process_unsol_events(struct work_struct *work);
static const struct hdac_bus_ops default_ops = {
.command = snd_hdac_bus_send_cmd,
.get_response = snd_hdac_bus_get_response,
+ .link_power = snd_hdac_bus_link_power,
};
/**
@@ -264,3 +265,25 @@ void snd_hdac_aligned_write(unsigned int val, void __iomem *addr,
}
EXPORT_SYMBOL_GPL(snd_hdac_aligned_write);
#endif /* CONFIG_SND_HDA_ALIGNED_MMIO */
+
+void snd_hdac_codec_link_up(struct hdac_device *codec)
+{
+ struct hdac_bus *bus = codec->bus;
+
+ if (bus->ops->link_power)
+ bus->ops->link_power(codec, true);
+ else
+ snd_hdac_bus_link_power(codec, true);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_codec_link_up);
+
+void snd_hdac_codec_link_down(struct hdac_device *codec)
+{
+ struct hdac_bus *bus = codec->bus;
+
+ if (bus->ops->link_power)
+ bus->ops->link_power(codec, false);
+ else
+ snd_hdac_bus_link_power(codec, false);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_codec_link_down);
diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c
index b98449fd92f3..062da7a7a586 100644
--- a/sound/hda/hdac_controller.c
+++ b/sound/hda/hdac_controller.c
@@ -648,3 +648,17 @@ void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus)
snd_dma_free_pages(&bus->posbuf);
}
EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages);
+
+/**
+ * snd_hdac_bus_link_power - power up/down codec link
+ * @codec: HD-audio device
+ * @enable: whether to power-up the link
+ */
+void snd_hdac_bus_link_power(struct hdac_device *codec, bool enable)
+{
+ if (enable)
+ set_bit(codec->addr, &codec->bus->codec_powered);
+ else
+ clear_bit(codec->addr, &codec->bus->codec_powered);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_bus_link_power);
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c
index abe7a1b16fe1..a6ed3dc35f7e 100644
--- a/sound/hda/hdac_stream.c
+++ b/sound/hda/hdac_stream.c
@@ -435,12 +435,11 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev)
pos_adj = bus->bdl_pos_adj;
if (!azx_dev->no_period_wakeup && pos_adj > 0) {
pos_align = pos_adj;
- pos_adj = (pos_adj * runtime->rate + 47999) / 48000;
+ pos_adj = DIV_ROUND_UP(pos_adj * runtime->rate, 48000);
if (!pos_adj)
pos_adj = pos_align;
else
- pos_adj = ((pos_adj + pos_align - 1) / pos_align) *
- pos_align;
+ pos_adj = roundup(pos_adj, pos_align);
pos_adj = frames_to_bytes(runtime, pos_adj);
if (pos_adj >= period_bytes) {
dev_warn(bus->dev, "Too big adjustment %d\n",
diff --git a/sound/hda/hdac_sysfs.c b/sound/hda/hdac_sysfs.c
index e56e83325903..0d7771fca9f0 100644
--- a/sound/hda/hdac_sysfs.c
+++ b/sound/hda/hdac_sysfs.c
@@ -66,7 +66,7 @@ static struct attribute *hdac_dev_attrs[] = {
NULL
};
-static struct attribute_group hdac_dev_attr_group = {
+static const struct attribute_group hdac_dev_attr_group = {
.attrs = hdac_dev_attrs,
};
diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
index c45686172517..d1eb9d34993a 100644
--- a/sound/hda/intel-dsp-config.c
+++ b/sound/hda/intel-dsp-config.c
@@ -321,6 +321,18 @@ static const struct config_entry config_table[] = {
},
#endif
+/* Alder Lake */
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE)
+ {
+ .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+ .device = 0x7ad0,
+ },
+ {
+ .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+ .device = 0x51c8,
+ },
+#endif
+
};
static const struct config_entry *snd_intel_dsp_find_config
@@ -452,35 +464,30 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci)
}
EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe);
+/* Should we default to SOF or SST for BYT/CHT ? */
+#if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \
+ !IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI)
+#define FLAG_SST_OR_SOF_BYT FLAG_SOF
+#else
+#define FLAG_SST_OR_SOF_BYT FLAG_SST
+#endif
+
/*
* configuration table
* - the order of similar ACPI ID entries is important!
* - the first successful match will win
*/
static const struct config_entry acpi_config_table[] = {
+#if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \
+ IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
/* BayTrail */
-#if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI)
- {
- .flags = FLAG_SST,
- .acpi_hid = "80860F28",
- },
-#endif
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
{
- .flags = FLAG_SOF,
+ .flags = FLAG_SST_OR_SOF_BYT,
.acpi_hid = "80860F28",
},
-#endif
/* CherryTrail */
-#if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI)
{
- .flags = FLAG_SST,
- .acpi_hid = "808622A8",
- },
-#endif
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
- {
- .flags = FLAG_SOF,
+ .flags = FLAG_SST_OR_SOF_BYT,
.acpi_hid = "808622A8",
},
#endif
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c
index a684faa771ef..847e3b6ca601 100644
--- a/sound/i2c/i2c.c
+++ b/sound/i2c/i2c.c
@@ -84,7 +84,7 @@ int snd_i2c_bus_create(struct snd_card *card, const char *name,
list_add_tail(&bus->buses, &master->buses);
bus->master = master;
}
- strlcpy(bus->name, name, sizeof(bus->name));
+ strscpy(bus->name, name, sizeof(bus->name));
err = snd_device_new(card, SNDRV_DEV_BUS, bus, &ops);
if (err < 0) {
snd_i2c_bus_free(bus);
@@ -108,7 +108,7 @@ int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name,
if (device == NULL)
return -ENOMEM;
device->addr = addr;
- strlcpy(device->name, name, sizeof(device->name));
+ strscpy(device->name, name, sizeof(device->name));
list_add_tail(&device->list, &bus->devices);
device->bus = bus;
*rdevice = device;
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 593c6e959afe..6f221eed44e2 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -95,8 +95,8 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n)
if (error < 0)
goto out;
- strlcpy(card->driver, "AD1848", sizeof(card->driver));
- strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
+ strscpy(card->driver, "AD1848", sizeof(card->driver));
+ strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
if (!thinkpad[n])
snprintf(card->longname, sizeof(card->longname),
@@ -118,10 +118,9 @@ out: snd_card_free(card);
return error;
}
-static int snd_ad1848_remove(struct device *dev, unsigned int n)
+static void snd_ad1848_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
- return 0;
}
#ifdef CONFIG_PM
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
index 5105524b6f38..e6cd7c4da38e 100644
--- a/sound/isa/adlib.c
+++ b/sound/isa/adlib.c
@@ -97,10 +97,9 @@ out: snd_card_free(card);
return error;
}
-static int snd_adlib_remove(struct device *dev, unsigned int n)
+static void snd_adlib_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
- return 0;
}
static struct isa_driver snd_adlib_driver = {
diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c
index faca5dd95bfe..3b9fbb02864b 100644
--- a/sound/isa/cmi8328.c
+++ b/sound/isa/cmi8328.c
@@ -403,7 +403,7 @@ error:
return err;
}
-static int snd_cmi8328_remove(struct device *pdev, unsigned int dev)
+static void snd_cmi8328_remove(struct device *pdev, unsigned int dev)
{
struct snd_card *card = dev_get_drvdata(pdev);
struct snd_cmi8328 *cmi = card->private_data;
@@ -420,7 +420,6 @@ static int snd_cmi8328_remove(struct device *pdev, unsigned int dev)
snd_cmi8328_cfg_write(cmi->port, CFG2, 0);
snd_cmi8328_cfg_write(cmi->port, CFG3, 0);
snd_card_free(card);
- return 0;
}
#ifdef CONFIG_PM
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 4669eb0cc8ce..19e258527d69 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -631,11 +631,10 @@ static int snd_cmi8330_isa_probe(struct device *pdev,
return 0;
}
-static int snd_cmi8330_isa_remove(struct device *devptr,
+static void snd_cmi8330_isa_remove(struct device *devptr,
unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
- return 0;
}
#ifdef CONFIG_PM
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index 2135963eba78..c56cbc072918 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -95,8 +95,8 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n)
if (error < 0)
goto out;
- strlcpy(card->driver, "CS4231", sizeof(card->driver));
- strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
+ strscpy(card->driver, "CS4231", sizeof(card->driver));
+ strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
if (dma2[n] < 0)
snprintf(card->longname, sizeof(card->longname),
@@ -135,10 +135,9 @@ out: snd_card_free(card);
return error;
}
-static int snd_cs4231_remove(struct device *dev, unsigned int n)
+static void snd_cs4231_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
- return 0;
}
#ifdef CONFIG_PM
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index fa3c39cff5f8..63fb0cb754d0 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -405,8 +405,8 @@ static int snd_cs423x_probe(struct snd_card *card, int dev)
if (err < 0)
return err;
}
- strlcpy(card->driver, chip->pcm->name, sizeof(card->driver));
- strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
+ strscpy(card->driver, chip->pcm->name, sizeof(card->driver));
+ strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
if (dma2[dev] < 0)
snprintf(card->longname, sizeof(card->longname),
"%s at 0x%lx, irq %i, dma %i",
@@ -487,11 +487,10 @@ static int snd_cs423x_isa_probe(struct device *pdev,
return 0;
}
-static int snd_cs423x_isa_remove(struct device *pdev,
+static void snd_cs423x_isa_remove(struct device *pdev,
unsigned int dev)
{
snd_card_free(dev_get_drvdata(pdev));
- return 0;
}
#ifdef CONFIG_PM
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 64610571a5e1..4a1f61f1a331 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -133,8 +133,8 @@ static int snd_es1688_probe(struct snd_card *card, unsigned int n)
if (error < 0)
return error;
- strlcpy(card->driver, "ES1688", sizeof(card->driver));
- strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
+ strscpy(card->driver, "ES1688", sizeof(card->driver));
+ strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
snprintf(card->longname, sizeof(card->longname),
"%s at 0x%lx, irq %i, dma %i", chip->pcm->name, chip->port,
chip->irq, chip->dma8);
@@ -192,10 +192,9 @@ out:
return error;
}
-static int snd_es1688_isa_remove(struct device *dev, unsigned int n)
+static void snd_es1688_isa_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
- return 0;
}
static struct isa_driver snd_es1688_driver = {
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 5f8d7e8a5477..9beef8079177 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -2210,11 +2210,10 @@ static int snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
}
}
-static int snd_es18xx_isa_remove(struct device *devptr,
- unsigned int dev)
+static void snd_es18xx_isa_remove(struct device *devptr,
+ unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
- return 0;
}
#ifdef CONFIG_PM
diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c
index 65f9f46c9f58..d33d69f29924 100644
--- a/sound/isa/galaxy/galaxy.c
+++ b/sound/isa/galaxy/galaxy.c
@@ -608,10 +608,9 @@ error:
return err;
}
-static int snd_galaxy_remove(struct device *dev, unsigned int n)
+static void snd_galaxy_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
- return 0;
}
static struct isa_driver snd_galaxy_driver = {
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index 7419b1939754..015f88a11352 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -195,10 +195,9 @@ out: snd_card_free(card);
return error;
}
-static int snd_gusclassic_remove(struct device *dev, unsigned int n)
+static void snd_gusclassic_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
- return 0;
}
static struct isa_driver snd_gusclassic_driver = {
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index ed2f9d64efae..c9f31b4fb887 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -324,10 +324,9 @@ out: snd_card_free(card);
return error;
}
-static int snd_gusextreme_remove(struct device *dev, unsigned int n)
+static void snd_gusextreme_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
- return 0;
}
static struct isa_driver snd_gusextreme_driver = {
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index 05cd9be4dd8a..dc09fbd6f88d 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -338,10 +338,9 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
return err;
}
-static int snd_gusmax_remove(struct device *devptr, unsigned int dev)
+static void snd_gusmax_remove(struct device *devptr, unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
- return 0;
}
#define DEV_NAME "gusmax"
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 3e9ad930deae..e4d412e72b75 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -825,10 +825,9 @@ static int snd_interwave_isa_probe(struct device *pdev,
}
}
-static int snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
+static void snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
- return 0;
}
static struct isa_driver snd_interwave_driver = {
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
index 24b34ecf5e5b..69647b41300d 100644
--- a/sound/isa/msnd/msnd_pinnacle.c
+++ b/sound/isa/msnd/msnd_pinnacle.c
@@ -1049,10 +1049,9 @@ cfg_error:
#endif
}
-static int snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
+static void snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
{
snd_msnd_unload(dev_get_drvdata(pdev));
- return 0;
}
static struct isa_driver snd_msnd_driver = {
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 85a181acd388..7649a8a4128d 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -878,11 +878,10 @@ static int snd_opl3sa2_isa_probe(struct device *pdev,
return 0;
}
-static int snd_opl3sa2_isa_remove(struct device *devptr,
+static void snd_opl3sa2_isa_remove(struct device *devptr,
unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
- return 0;
}
#ifdef CONFIG_PM
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index 44ed1b65f6ce..20933342f5eb 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -1480,11 +1480,10 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
return 0;
}
-static int snd_miro_isa_remove(struct device *devptr,
+static void snd_miro_isa_remove(struct device *devptr,
unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
- return 0;
}
#define DEV_NAME "miro"
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 881d3b5711d2..758f5b579138 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -1024,11 +1024,10 @@ static int snd_opti9xx_isa_probe(struct device *devptr,
return 0;
}
-static int snd_opti9xx_isa_remove(struct device *devptr,
- unsigned int dev)
+static void snd_opti9xx_isa_remove(struct device *devptr,
+ unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
- return 0;
}
#ifdef CONFIG_PM
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
index ee379bbf70a4..0e2e0ab3b9e4 100644
--- a/sound/isa/sb/jazz16.c
+++ b/sound/isa/sb/jazz16.c
@@ -339,12 +339,11 @@ err_free:
return err;
}
-static int snd_jazz16_remove(struct device *devptr, unsigned int dev)
+static void snd_jazz16_remove(struct device *devptr, unsigned int dev)
{
struct snd_card *card = dev_get_drvdata(devptr);
snd_card_free(card);
- return 0;
}
#ifdef CONFIG_PM
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 479197c13803..db284b7b88a7 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -547,10 +547,9 @@ static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
}
}
-static int snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
+static void snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
{
snd_card_free(dev_get_drvdata(pdev));
- return 0;
}
#ifdef CONFIG_PM
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index 270af863e198..8635a2b6b36b 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -388,7 +388,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
return err;
/* fill in codec header */
- strlcpy(p->codec_name, info.codec_name, sizeof(p->codec_name));
+ strscpy(p->codec_name, info.codec_name, sizeof(p->codec_name));
p->func_nr = func_nr;
p->mode = le16_to_cpu(funcdesc_h.flags_play_rec);
switch (le16_to_cpu(funcdesc_h.VOC_type)) {
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index 438109f167d6..8e3e67b9a341 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -192,10 +192,9 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
return err;
}
-static int snd_sb8_remove(struct device *pdev, unsigned int dev)
+static void snd_sb8_remove(struct device *pdev, unsigned int dev)
{
snd_card_free(dev_get_drvdata(pdev));
- return 0;
}
#ifdef CONFIG_PM
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
index 3f703b4a304d..5de5506e7e60 100644
--- a/sound/isa/sb/sb_mixer.c
+++ b/sound/isa/sb/sb_mixer.c
@@ -482,7 +482,7 @@ int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int ty
ctl = snd_ctl_new1(&newctls[type], chip);
if (! ctl)
return -ENOMEM;
- strlcpy(ctl->id.name, name, sizeof(ctl->id.name));
+ strscpy(ctl->id.name, name, sizeof(ctl->id.name));
ctl->id.index = index;
ctl->private_value = value;
if ((err = snd_ctl_add(chip->card, ctl)) < 0)
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
index 3d0bea44f454..def137579717 100644
--- a/sound/isa/sc6000.c
+++ b/sound/isa/sc6000.c
@@ -672,7 +672,7 @@ err_exit:
return err;
}
-static int snd_sc6000_remove(struct device *devptr, unsigned int dev)
+static void snd_sc6000_remove(struct device *devptr, unsigned int dev)
{
struct snd_card *card = dev_get_drvdata(devptr);
char __iomem **vport = card->private_data;
@@ -684,7 +684,6 @@ static int snd_sc6000_remove(struct device *devptr, unsigned int dev)
release_region(mss_port[dev], 4);
snd_card_free(card);
- return 0;
}
static struct isa_driver snd_sc6000_driver = {
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 2e5a5c5279e8..e70ef9aee545 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -1183,10 +1183,9 @@ _release_card:
return ret;
}
-static int snd_sscape_remove(struct device *devptr, unsigned int dev)
+static void snd_sscape_remove(struct device *devptr, unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
- return 0;
}
#define DEV_NAME "sscape"
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 9e0f6b226775..b750a4fd40de 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -565,11 +565,10 @@ static int snd_wavefront_isa_probe(struct device *pdev,
return 0;
}
-static int snd_wavefront_isa_remove(struct device *devptr,
+static void snd_wavefront_isa_remove(struct device *devptr,
unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
- return 0;
}
#define DEV_NAME "wavefront"
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
index 38f25e97538f..49679aa8631d 100644
--- a/sound/oss/dmasound/dmasound_core.c
+++ b/sound/oss/dmasound/dmasound_core.c
@@ -355,8 +355,8 @@ static int mixer_ioctl(struct file *file, u_int cmd, u_long arg)
{
mixer_info info;
memset(&info, 0, sizeof(info));
- strlcpy(info.id, dmasound.mach.name2, sizeof(info.id));
- strlcpy(info.name, dmasound.mach.name2, sizeof(info.name));
+ strscpy(info.id, dmasound.mach.name2, sizeof(info.id));
+ strscpy(info.name, dmasound.mach.name2, sizeof(info.name));
info.modify_counter = mixer.modify_counter;
if (copy_to_user((void __user *)arg, &info, sizeof(info)))
return -EFAULT;
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 5d42c42491bf..5d835d2af054 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -857,8 +857,7 @@ snd_ad1889_create(struct snd_card *card,
return err;
/* check PCI availability (32bit DMA) */
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
dev_err(card->dev, "error setting 32-bit DMA mask.\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 4462375d2d82..51f24796f03f 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -2057,8 +2057,7 @@ static int snd_ali_create(struct snd_card *card,
if (err < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 31 bits */
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(31)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(31)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31))) {
dev_err(card->dev,
"architecture does not support 31bit PCI busmaster DMA\n");
pci_disable_device(pci);
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 8d2471ea090b..1dc8c4ed0592 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -625,8 +625,7 @@ static int snd_als300_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
dev_err(card->dev, "error setting 28bit DMA mask\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index ba6390e9a694..2edc7455285a 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -837,8 +837,7 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
return err;
}
/* check, if we can restrict PCI DMA transfers to 24 bits */
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
dev_err(&pci->dev, "architecture does not support 24bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/asihpi/hpidebug.c b/sound/pci/asihpi/hpidebug.c
index f37856ab05f8..9570d9a44fe8 100644
--- a/sound/pci/asihpi/hpidebug.c
+++ b/sound/pci/asihpi/hpidebug.c
@@ -52,7 +52,7 @@ void hpi_debug_data(u16 *pdata, u32 len)
int lines;
int cols = 8;
- lines = (len + cols - 1) / cols;
+ lines = DIV_ROUND_UP(len, cols);
if (lines > 8)
lines = 8;
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index be276fb3f5af..5dd98e6ff34b 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -151,8 +151,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
// check PCI availability (DMA).
if ((err = pci_enable_device(pci)) < 0)
return err;
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
dev_err(card->dev, "error to set DMA mask\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index f1865afedc59..43396849a01c 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -236,8 +236,7 @@ static int snd_aw2_create(struct snd_card *card,
pci_set_master(pci);
/* check PCI availability (32bit DMA) */
- if ((dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) ||
- (dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0)) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
dev_err(card->dev, "Impossible to set 32bit mask DMA\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 77c7030ebbfa..2ac594dcf21c 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -2379,8 +2379,7 @@ snd_azf3328_create(struct snd_card *card,
chip->irq = -1;
/* check if we can restrict PCI DMA transfers to 24 bits */
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
dev_err(card->dev,
"architecture does not support 24bit PCI busmaster DMA\n"
);
@@ -2448,7 +2447,7 @@ snd_azf3328_create(struct snd_card *card,
/* shutdown codecs to reduce power / noise */
/* have ...ctrl_codec_activity() act properly */
- codec->running = 1;
+ codec->running = true;
snd_azf3328_ctrl_codec_activity(chip, codec_type, 0);
spin_lock_irq(codec->lock);
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 54cb223caa2f..cf9f8d80a0b6 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -327,7 +327,8 @@ static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id)
current_block = chip->current_line * 16 / chip->lines;
irq_block = status >> INT_RISCS_SHIFT;
if (current_block != irq_block)
- chip->current_line = (irq_block * chip->lines + 15) / 16;
+ chip->current_line = DIV_ROUND_UP(irq_block * chip->lines,
+ 16);
snd_pcm_period_elapsed(chip->substream);
}
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index c189f70c82cb..ee20f9a1aae9 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1605,8 +1605,7 @@ static int snd_ca0106_create(int dev, struct snd_card *card,
err = pci_enable_device(pci);
if (err < 0)
return err;
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
dev_err(card->dev, "error to set 32bit mask DMA\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 4490dd7469d9..37f516e6a5c2 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -813,7 +813,7 @@ static void snd_cs46xx_set_capture_sample_rate(struct snd_cs46xx *chip, unsigned
correctionPerGOF = tmp1 / GOF_PER_SEC;
tmp1 -= correctionPerGOF * GOF_PER_SEC;
correctionPerSec = tmp1;
- initialDelay = ((48000 * 24) + rate - 1) / rate;
+ initialDelay = DIV_ROUND_UP(48000 * 24, rate);
/*
* Fill in the VariDecimate control block.
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 11ce3c4589fa..359bc6af8670 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -269,8 +269,7 @@ static int snd_cs5535audio_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
dev_warn(card->dev, "unable to get 32bit dma\n");
err = -ENXIO;
goto pcifail;
diff --git a/sound/pci/cs5535audio/cs5535audio_olpc.c b/sound/pci/cs5535audio/cs5535audio_olpc.c
index 4e295303b041..110d3209441b 100644
--- a/sound/pci/cs5535audio/cs5535audio_olpc.c
+++ b/sound/pci/cs5535audio/cs5535audio_olpc.c
@@ -158,13 +158,13 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
/* drop the original AD1888 HPF control */
memset(&elem, 0, sizeof(elem));
elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- strlcpy(elem.name, "High Pass Filter Enable", sizeof(elem.name));
+ strscpy(elem.name, "High Pass Filter Enable", sizeof(elem.name));
snd_ctl_remove_id(card, &elem);
/* drop the original V_REFOUT control */
memset(&elem, 0, sizeof(elem));
elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- strlcpy(elem.name, "V_REFOUT Enable", sizeof(elem.name));
+ strscpy(elem.name, "V_REFOUT Enable", sizeof(elem.name));
snd_ctl_remove_id(card, &elem);
/* add the OLPC-specific controls */
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c
index 108ab449c968..0cea4982ed7d 100644
--- a/sound/pci/ctxfi/cthw20k1.c
+++ b/sound/pci/ctxfi/cthw20k1.c
@@ -1901,12 +1901,8 @@ static int hw_card_start(struct hw *hw)
return err;
/* Set DMA transfer mask */
- if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) {
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits));
- } else {
- dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32));
- }
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(dma_bits)))
+ dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32));
if (!hw->io_base) {
err = pci_request_regions(pci, "XFi");
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c
index fc1bc18caee9..a855fb8c58bd 100644
--- a/sound/pci/ctxfi/cthw20k2.c
+++ b/sound/pci/ctxfi/cthw20k2.c
@@ -2026,12 +2026,8 @@ static int hw_card_start(struct hw *hw)
return err;
/* Set DMA transfer mask */
- if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) {
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits));
- } else {
- dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32));
- }
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(dma_bits)))
+ dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32));
if (!hw->io_base) {
err = pci_request_regions(pci, "XFi");
diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c
index 3f48ad0e27e7..81dfc6a76b18 100644
--- a/sound/pci/ctxfi/ctpcm.c
+++ b/sound/pci/ctxfi/ctpcm.c
@@ -433,7 +433,7 @@ int ct_alsa_pcm_create(struct ct_atc *atc,
pcm->private_data = atc;
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
- strlcpy(pcm->name, device_name, sizeof(pcm->name));
+ strscpy(pcm->name, device_name, sizeof(pcm->name));
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
diff --git a/sound/pci/ctxfi/ctresource.c b/sound/pci/ctxfi/ctresource.c
index 61e51e35ba16..6d0a01b189e1 100644
--- a/sound/pci/ctxfi/ctresource.c
+++ b/sound/pci/ctxfi/ctresource.c
@@ -209,7 +209,7 @@ int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
mgr->type = NUM_RSCTYP;
- mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL);
+ mgr->rscs = kzalloc(DIV_ROUND_UP(amount, 8), GFP_KERNEL);
if (!mgr->rscs)
return -ENOMEM;
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 29b7720d7961..353934c88cbd 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -168,9 +168,9 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
}
#endif
- strlcpy(card->driver, emu->card_capabilities->driver,
+ strscpy(card->driver, emu->card_capabilities->driver,
sizeof(card->driver));
- strlcpy(card->shortname, emu->card_capabilities->name,
+ strscpy(card->shortname, emu->card_capabilities->name,
sizeof(card->shortname));
snprintf(card->longname, sizeof(card->longname),
"%s (rev.%d, serial:0x%x) at 0x%lx, irq %i",
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index bd70e112ffd7..24a2fd706d69 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -1869,7 +1869,7 @@ int snd_emu10k1_create(struct snd_card *card,
emu->serial);
if (!*card->id && c->id)
- strlcpy(card->id, c->id, sizeof(card->id));
+ strscpy(card->id, c->id, sizeof(card->id));
is_audigy = emu->audigy = c->emu10k2_chip;
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 4e76ed0e91d5..80ef62a4a7c0 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -940,7 +940,7 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu,
memset(gctl, 0, sizeof(*gctl));
id = &ctl->kcontrol->id;
gctl->id.iface = (__force int)id->iface;
- strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name));
+ strscpy(gctl->id.name, id->name, sizeof(gctl->id.name));
gctl->id.index = id->index;
gctl->id.device = id->device;
gctl->id.subdevice = id->subdevice;
@@ -976,7 +976,7 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu,
err = snd_emu10k1_verify_controls(emu, icode, in_kernel);
if (err < 0)
goto __error;
- strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name));
+ strscpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name));
/* stop FX processor - this may be dangerous, but it's better to miss
some samples than generate wrong ones - [jk] */
if (emu->audigy)
@@ -1015,7 +1015,7 @@ static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu,
int err;
mutex_lock(&emu->fx8010.lock);
- strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name));
+ strscpy(icode->name, emu->fx8010.name, sizeof(icode->name));
/* ok, do the main job */
err = snd_emu10k1_gpr_peek(emu, icode);
if (err >= 0)
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c
index 94b8d5b08225..288e0fd2e47d 100644
--- a/sound/pci/emu10k1/memory.c
+++ b/sound/pci/emu10k1/memory.c
@@ -375,7 +375,7 @@ int snd_emu10k1_alloc_pages_maybe_wider(struct snd_emu10k1 *emu, size_t size,
struct snd_dma_buffer *dmab)
{
if (emu->iommu_workaround) {
- size_t npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+ size_t npages = DIV_ROUND_UP(size, PAGE_SIZE);
size_t size_real = npages * PAGE_SIZE;
/*
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index d9acef0826a9..93c4fd313311 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -752,7 +752,7 @@ static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate)
unsigned int freq, r;
mutex_lock(&ensoniq->src_mutex);
- freq = ((rate << 15) + 1500) / 3000;
+ freq = DIV_ROUND_CLOSEST(rate << 15, 3000);
r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
ES_1371_DIS_P2 | ES_1371_DIS_R1)) |
ES_1371_DIS_P1;
@@ -773,7 +773,7 @@ static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate)
unsigned int freq, r;
mutex_lock(&ensoniq->src_mutex);
- freq = ((rate << 15) + 1500) / 3000;
+ freq = DIV_ROUND_CLOSEST(rate << 15, 3000);
r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
ES_1371_DIS_P1 | ES_1371_DIS_R1)) |
ES_1371_DIS_P2;
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 09704a78d799..3b5d68ce9dd5 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1560,8 +1560,7 @@ static int snd_es1938_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 24 bits */
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
dev_err(card->dev,
"architecture does not support 24bit PCI busmaster DMA\n");
pci_disable_device(pci);
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 34332d008b27..747fa69bb1c9 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -2668,8 +2668,7 @@ static int snd_es1968_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 28 bits */
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
dev_err(card->dev,
"architecture does not support 28bit PCI busmaster DMA\n");
pci_disable_device(pci);
@@ -2768,7 +2767,7 @@ static int snd_es1968_create(struct snd_card *card,
if (!snd_tea575x_init(&chip->tea, THIS_MODULE)) {
dev_info(card->dev, "detected TEA575x radio type %s\n",
get_tea575x_gpio(chip)->name);
- strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name,
+ strscpy(chip->tea.card, get_tea575x_gpio(chip)->name,
sizeof(chip->tea.card));
break;
}
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 0a95032fd297..c6ad6235a669 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1300,7 +1300,7 @@ static int snd_fm801_create(struct snd_card *card,
chip->tea575x_tuner |= tuner_only;
}
if (!(chip->tea575x_tuner & TUNER_DISABLED)) {
- strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name,
+ strscpy(chip->tea.card, get_tea575x_gpio(chip)->name,
sizeof(chip->tea.card));
}
#endif
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 4dc01647753c..1a001ecf7f63 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -764,7 +764,7 @@ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
}
if (!name)
return 0;
- strlcpy(label, name, maxlen);
+ strscpy(label, name, maxlen);
return 1;
}
EXPORT_SYMBOL_GPL(snd_hda_get_pin_label);
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index eec1775dfffe..9b755062d841 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -3999,7 +3999,7 @@ int snd_hda_add_imux_item(struct hda_codec *codec,
sizeof(imux->items[imux->num_items].label),
"%s %d", label, label_idx);
else
- strlcpy(imux->items[imux->num_items].label, label,
+ strscpy(imux->items[imux->num_items].label, label,
sizeof(imux->items[imux->num_items].label));
imux->items[imux->num_items].index = index;
imux->num_items++;
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 80016b7b6849..9087981cd1f7 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -735,7 +735,7 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec,
&pcm);
if (err < 0)
return err;
- strlcpy(pcm->name, cpcm->name, sizeof(pcm->name));
+ strscpy(pcm->name, cpcm->name, sizeof(pcm->name));
apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
if (apcm == NULL) {
snd_device_free(chip->card, pcm);
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 136477ed46ae..9e97443795f8 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -260,7 +260,7 @@ int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e,
codec_info(codec, "HDMI: out of range MNL %d\n", mnl);
goto out_fail;
} else
- strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1);
+ strscpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1);
for (i = 0; i < e->sad_count; i++) {
if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) {
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 8060cc86dfea..5e40944e7342 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -5721,7 +5721,7 @@ static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
if (*str)
return;
- strlcpy(str, chip_name, len);
+ strscpy(str, chip_name, len);
/* drop non-alnum chars after a space */
for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 068847e263e8..5b492c3f816c 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1967,12 +1967,8 @@ static int azx_first_init(struct azx *chip)
/* allow 64bit DMA address if supported by H/W */
if (!(gcap & AZX_GCAP_64OK))
dma_bits = 32;
- if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) {
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits));
- } else {
- dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32));
- }
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(dma_bits)))
+ dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32));
/* read number of streams from GCAP register instead of using
* hardcoded value
@@ -2037,7 +2033,7 @@ static int azx_first_init(struct azx *chip)
return -EBUSY;
strcpy(card->driver, "HDA-Intel");
- strlcpy(card->shortname, driver_short_names[chip->driver_type],
+ strscpy(card->shortname, driver_short_names[chip->driver_type],
sizeof(card->shortname));
snprintf(card->longname, sizeof(card->longname),
"%s at 0x%lx irq %i",
@@ -2221,8 +2217,6 @@ static const struct snd_pci_quirk power_save_denylist[] = {
/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0),
/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
- SND_PCI_QUIRK(0x1558, 0x6504, "Clevo W65_67SB", 0),
- /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
SND_PCI_QUIRK(0x1028, 0x0497, "Dell Precision T3600", 0),
/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
/* Note the P55A-UD3 and Z87-D3HP share the subsys id for the HDA dev */
@@ -2304,7 +2298,7 @@ static int azx_probe_continue(struct azx *chip)
/* HSW/BDW controllers need this power */
if (CONTROLLER_IN_GPU(pci))
- hda->need_i915_power = 1;
+ hda->need_i915_power = true;
}
/* Request display power well for the HDA controller or codec. For
@@ -2481,6 +2475,8 @@ static const struct pci_device_id azx_ids[] = {
/* CometLake-H */
{ PCI_DEVICE(0x8086, 0x06C8),
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+ { PCI_DEVICE(0x8086, 0xf1c8),
+ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
/* CometLake-S */
{ PCI_DEVICE(0x8086, 0xa3f0),
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 588059428d8f..b8b568046592 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -530,7 +530,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
!is_jack_detectable(codec, nid);
if (base_name)
- strlcpy(name, base_name, sizeof(name));
+ strscpy(name, base_name, sizeof(name));
else
snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), NULL);
if (phantom_jack)
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
index 361cf2041911..6f2b743b9d75 100644
--- a/sound/pci/hda/hda_tegra.c
+++ b/sound/pci/hda/hda_tegra.c
@@ -17,6 +17,7 @@
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
+#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/string.h>
@@ -70,9 +71,9 @@
struct hda_tegra {
struct azx chip;
struct device *dev;
- struct clk *hda_clk;
- struct clk *hda2codec_2x_clk;
- struct clk *hda2hdmi_clk;
+ struct reset_control *reset;
+ struct clk_bulk_data clocks[3];
+ unsigned int nclocks;
void __iomem *regs;
struct work_struct probe_work;
};
@@ -113,36 +114,6 @@ static void hda_tegra_init(struct hda_tegra *hda)
writel(v, hda->regs + HDA_IPFS_INTR_MASK);
}
-static int hda_tegra_enable_clocks(struct hda_tegra *data)
-{
- int rc;
-
- rc = clk_prepare_enable(data->hda_clk);
- if (rc)
- return rc;
- rc = clk_prepare_enable(data->hda2codec_2x_clk);
- if (rc)
- goto disable_hda;
- rc = clk_prepare_enable(data->hda2hdmi_clk);
- if (rc)
- goto disable_codec_2x;
-
- return 0;
-
-disable_codec_2x:
- clk_disable_unprepare(data->hda2codec_2x_clk);
-disable_hda:
- clk_disable_unprepare(data->hda_clk);
- return rc;
-}
-
-static void hda_tegra_disable_clocks(struct hda_tegra *data)
-{
- clk_disable_unprepare(data->hda2hdmi_clk);
- clk_disable_unprepare(data->hda2codec_2x_clk);
- clk_disable_unprepare(data->hda_clk);
-}
-
/*
* power management
*/
@@ -186,7 +157,7 @@ static int __maybe_unused hda_tegra_runtime_suspend(struct device *dev)
azx_stop_chip(chip);
azx_enter_link_reset(chip);
}
- hda_tegra_disable_clocks(hda);
+ clk_bulk_disable_unprepare(hda->nclocks, hda->clocks);
return 0;
}
@@ -198,15 +169,27 @@ static int __maybe_unused hda_tegra_runtime_resume(struct device *dev)
struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
int rc;
- rc = hda_tegra_enable_clocks(hda);
+ if (!chip->running) {
+ rc = reset_control_assert(hda->reset);
+ if (rc)
+ return rc;
+ }
+
+ rc = clk_bulk_prepare_enable(hda->nclocks, hda->clocks);
if (rc != 0)
return rc;
- if (chip && chip->running) {
+ if (chip->running) {
hda_tegra_init(hda);
azx_init_chip(chip, 1);
/* disable controller wake up event*/
azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
~STATESTS_INT_MASK);
+ } else {
+ usleep_range(10, 100);
+
+ rc = reset_control_deassert(hda->reset);
+ if (rc)
+ return rc;
}
return 0;
@@ -268,29 +251,6 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev)
return 0;
}
-static int hda_tegra_init_clk(struct hda_tegra *hda)
-{
- struct device *dev = hda->dev;
-
- hda->hda_clk = devm_clk_get(dev, "hda");
- if (IS_ERR(hda->hda_clk)) {
- dev_err(dev, "failed to get hda clock\n");
- return PTR_ERR(hda->hda_clk);
- }
- hda->hda2codec_2x_clk = devm_clk_get(dev, "hda2codec_2x");
- if (IS_ERR(hda->hda2codec_2x_clk)) {
- dev_err(dev, "failed to get hda2codec_2x clock\n");
- return PTR_ERR(hda->hda2codec_2x_clk);
- }
- hda->hda2hdmi_clk = devm_clk_get(dev, "hda2hdmi");
- if (IS_ERR(hda->hda2hdmi_clk)) {
- dev_err(dev, "failed to get hda2hdmi clock\n");
- return PTR_ERR(hda->hda2hdmi_clk);
- }
-
- return 0;
-}
-
static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
{
struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
@@ -495,7 +455,17 @@ static int hda_tegra_probe(struct platform_device *pdev)
return err;
}
- err = hda_tegra_init_clk(hda);
+ hda->reset = devm_reset_control_array_get_exclusive(&pdev->dev);
+ if (IS_ERR(hda->reset)) {
+ err = PTR_ERR(hda->reset);
+ goto out_free;
+ }
+
+ hda->clocks[hda->nclocks++].id = "hda";
+ hda->clocks[hda->nclocks++].id = "hda2hdmi";
+ hda->clocks[hda->nclocks++].id = "hda2codec_2x";
+
+ err = devm_clk_bulk_get(&pdev->dev, hda->nclocks, hda->clocks);
if (err < 0)
goto out_free;
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index d49cc4409d59..f2aa226d1373 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -567,7 +567,7 @@ static void cxt_fixup_mute_led_eapd(struct hda_codec *codec,
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->mute_led_eapd = 0x1b;
- spec->dynamic_eapd = 1;
+ spec->dynamic_eapd = true;
snd_hda_gen_add_mute_led_cdev(codec, cx_auto_vmaster_mute_led);
}
}
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 97adff0cbcab..e405be7929e3 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -2130,7 +2130,6 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
goto unlock;
}
per_cvt = get_cvt(spec, cvt_idx);
- snd_BUG_ON(!per_cvt->assigned);
per_cvt->assigned = 0;
hinfo->nid = 0;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 290645516313..1927605f0f7e 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1905,6 +1905,7 @@ enum {
ALC889_FIXUP_FRONT_HP_NO_PRESENCE,
ALC889_FIXUP_VAIO_TT,
ALC888_FIXUP_EEE1601,
+ ALC886_FIXUP_EAPD,
ALC882_FIXUP_EAPD,
ALC883_FIXUP_EAPD,
ALC883_FIXUP_ACER_EAPD,
@@ -2238,6 +2239,15 @@ static const struct hda_fixup alc882_fixups[] = {
{ }
}
},
+ [ALC886_FIXUP_EAPD] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* change to EAPD mode */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0068 },
+ { }
+ }
+ },
[ALC882_FIXUP_EAPD] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
@@ -2510,6 +2520,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
+ SND_PCI_QUIRK(0x13fe, 0x1009, "Advantech MIT-W101", ALC886_FIXUP_EAPD),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950),
@@ -4280,6 +4291,28 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec,
}
}
+/* HP Spectre x360 14 model needs a unique workaround for enabling the amp;
+ * it needs to toggle the GPIO0 once on and off at each time (bko#210633)
+ */
+static void alc245_fixup_hp_x360_amp(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+
+ switch (action) {
+ case HDA_FIXUP_ACT_PRE_PROBE:
+ spec->gpio_mask |= 0x01;
+ spec->gpio_dir |= 0x01;
+ break;
+ case HDA_FIXUP_ACT_INIT:
+ /* need to toggle GPIO to enable the amp */
+ alc_update_gpio_data(codec, 0x01, true);
+ msleep(100);
+ alc_update_gpio_data(codec, 0x01, false);
+ break;
+ }
+}
+
static void alc_update_coef_led(struct hda_codec *codec,
struct alc_coef_led *led,
bool polarity, bool on)
@@ -6266,6 +6299,7 @@ enum {
ALC280_FIXUP_HP_DOCK_PINS,
ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED,
ALC280_FIXUP_HP_9480M,
+ ALC245_FIXUP_HP_X360_AMP,
ALC288_FIXUP_DELL_HEADSET_MODE,
ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC288_FIXUP_DELL_XPS_13,
@@ -6971,6 +7005,10 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc280_fixup_hp_9480m,
},
+ [ALC245_FIXUP_HP_X360_AMP] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc245_fixup_hp_x360_amp,
+ },
[ALC288_FIXUP_DELL_HEADSET_MODE] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_headset_mode_dell_alc288,
@@ -7985,6 +8023,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -8357,6 +8396,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{.id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc298-samsung-headphone"},
{.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
{.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},
+ {.id = ALC245_FIXUP_HP_X360_AMP, .name = "alc245-hp-x360-amp"},
{}
};
#define ALC225_STANDARD_PINS \
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 73e1e5400506..f814dbbec2a4 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -2486,8 +2486,7 @@ static int snd_ice1712_create(struct snd_card *card,
if (err < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 28 bits */
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
dev_err(card->dev,
"architecture does not support 28bit PCI busmaster DMA\n");
pci_disable_device(pci);
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index e57a55cebc5a..f0f8324b08b6 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -413,7 +413,7 @@ static struct snd_kcontrol *ctl_find(struct snd_card *card,
{
struct snd_ctl_elem_id sid = {0};
- strlcpy(sid.name, name, sizeof(sid.name));
+ strscpy(sid.name, name, sizeof(sid.name));
sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
return snd_ctl_find_id(card, &sid);
}
diff --git a/sound/pci/ice1712/psc724.c b/sound/pci/ice1712/psc724.c
index 7aa3f92040d0..82cf365cda10 100644
--- a/sound/pci/ice1712/psc724.c
+++ b/sound/pci/ice1712/psc724.c
@@ -189,12 +189,12 @@ static void psc724_set_jack_state(struct snd_ice1712 *ice, bool hp_connected)
/* notify about master speaker mute change */
memset(&elem_id, 0, sizeof(elem_id));
elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- strlcpy(elem_id.name, "Master Speakers Playback Switch",
+ strscpy(elem_id.name, "Master Speakers Playback Switch",
sizeof(elem_id.name));
kctl = snd_ctl_find_id(ice->card, &elem_id);
snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
/* and headphone mute change */
- strlcpy(elem_id.name, spec->wm8776.ctl[WM8776_CTL_HP_SW].name,
+ strscpy(elem_id.name, spec->wm8776.ctl[WM8776_CTL_HP_SW].name,
sizeof(elem_id.name));
kctl = snd_ctl_find_id(ice->card, &elem_id);
snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c
index 0e3e04aa9faf..0dfa093f7dca 100644
--- a/sound/pci/ice1712/quartet.c
+++ b/sound/pci/ice1712/quartet.c
@@ -771,7 +771,7 @@ static struct snd_kcontrol *ctl_find(struct snd_card *card,
{
struct snd_ctl_elem_id sid = {0};
- strlcpy(sid.name, name, sizeof(sid.name));
+ strscpy(sid.name, name, sizeof(sid.name));
sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
return snd_ctl_find_id(card, &sid);
}
diff --git a/sound/pci/ice1712/wm8776.c b/sound/pci/ice1712/wm8776.c
index d96008df880d..6eda86119dff 100644
--- a/sound/pci/ice1712/wm8776.c
+++ b/sound/pci/ice1712/wm8776.c
@@ -38,7 +38,7 @@ static void snd_wm8776_activate_ctl(struct snd_wm8776 *wm,
unsigned int index_offset;
memset(&elem_id, 0, sizeof(elem_id));
- strlcpy(elem_id.name, ctl_name, sizeof(elem_id.name));
+ strscpy(elem_id.name, ctl_name, sizeof(elem_id.name));
elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
kctl = snd_ctl_find_id(card, &elem_id);
if (!kctl)
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 1b7df0c4e57c..19872cecc9d2 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -1129,13 +1129,14 @@ static int snd_intel8x0m_create(struct snd_card *card,
chip->bmaddr = pci_iomap(pci, 3, 0);
else
chip->bmaddr = pci_iomap(pci, 1, 0);
+
+port_inited:
if (!chip->bmaddr) {
dev_err(card->dev, "Controller space ioremap problem\n");
snd_intel8x0m_free(chip);
return -EIO;
}
- port_inited:
/* initialize offsets */
chip->bdbars_count = 2;
tbl = intel_regs;
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index cdd8db79bcfa..491c90f83fbc 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -669,7 +669,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
}
strcpy(card->driver, "Lola");
- strlcpy(card->shortname, "Digigram Lola", sizeof(card->shortname));
+ strscpy(card->shortname, "Digigram Lola", sizeof(card->shortname));
snprintf(card->longname, sizeof(card->longname),
"%s at 0x%lx irq %i",
card->shortname, chip->bar[0].addr, chip->irq);
diff --git a/sound/pci/lola/lola_clock.c b/sound/pci/lola/lola_clock.c
index fdb85f256ed5..cafd30e30913 100644
--- a/sound/pci/lola/lola_clock.c
+++ b/sound/pci/lola/lola_clock.c
@@ -135,7 +135,7 @@ int lola_init_clock_widget(struct lola *chip, int nid)
}
nitems = chip->clock.items;
- nb_verbs = (nitems + 3) / 4;
+ nb_verbs = DIV_ROUND_UP(nitems, 4);
idx = 0;
idx_list = 0;
for (i = 0; i < nb_verbs; i++) {
diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c
index f647c7ed00c4..684faaf40f31 100644
--- a/sound/pci/lola/lola_pcm.c
+++ b/sound/pci/lola/lola_pcm.c
@@ -601,7 +601,7 @@ int lola_create_pcm(struct lola *chip)
&pcm);
if (err < 0)
return err;
- strlcpy(pcm->name, "Digigram Lola", sizeof(pcm->name));
+ strscpy(pcm->name, "Digigram Lola", sizeof(pcm->name));
pcm->private_data = chip;
for (i = 0; i < 2; i++) {
if (chip->pcm[i].num_streams)
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 40232a278b1a..d2c2cd6006f0 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -1245,7 +1245,7 @@ static void snd_m3_pcm_setup2(struct snd_m3 *chip, struct m3_dma *s,
snd_pcm_format_width(runtime->format) == 16 ? 0 : 1);
/* set up dac/adc rate */
- freq = ((runtime->rate << 15) + 24000 ) / 48000;
+ freq = DIV_ROUND_CLOSEST(runtime->rate << 15, 48000);
if (freq)
freq--;
@@ -2532,8 +2532,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
return -EIO;
/* check, if we can restrict PCI DMA transfers to 28 bits */
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
dev_err(card->dev,
"architecture does not support 28bit PCI busmaster DMA\n");
pci_disable_device(pci);
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index cea53a878c36..6d9029333a12 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -469,6 +469,7 @@ struct hdsp {
unsigned char qs_out_channels;
unsigned char ds_out_channels;
unsigned char ss_out_channels;
+ u32 io_loopback; /* output loopback channel states*/
struct snd_dma_buffer capture_dma_buf;
struct snd_dma_buffer playback_dma_buf;
@@ -3253,6 +3254,60 @@ static const struct snd_kcontrol_new snd_hdsp_96xx_aeb =
HDSP_AnalogExtensionBoard);
static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
+
+static bool hdsp_loopback_get(struct hdsp *const hdsp, const u8 channel)
+{
+ return hdsp->io_loopback & (1 << channel);
+}
+
+static int hdsp_loopback_set(struct hdsp *const hdsp, const u8 channel, const bool enable)
+{
+ if (hdsp_loopback_get(hdsp, channel) == enable)
+ return 0;
+
+ hdsp->io_loopback ^= (1 << channel);
+
+ hdsp_write(hdsp, HDSP_inputEnable + (4 * (hdsp->max_channels + channel)), enable);
+
+ return 1;
+}
+
+static int snd_hdsp_loopback_get(struct snd_kcontrol *const kcontrol,
+ struct snd_ctl_elem_value *const ucontrol)
+{
+ struct hdsp *const hdsp = snd_kcontrol_chip(kcontrol);
+ const u8 channel = snd_ctl_get_ioff(kcontrol, &ucontrol->id);
+
+ if (channel >= hdsp->max_channels)
+ return -ENOENT;
+
+ ucontrol->value.integer.value[0] = hdsp_loopback_get(hdsp, channel);
+
+ return 0;
+}
+
+static int snd_hdsp_loopback_put(struct snd_kcontrol *const kcontrol,
+ struct snd_ctl_elem_value *const ucontrol)
+{
+ struct hdsp *const hdsp = snd_kcontrol_chip(kcontrol);
+ const u8 channel = snd_ctl_get_ioff(kcontrol, &ucontrol->id);
+ const bool enable = ucontrol->value.integer.value[0] & 1;
+
+ if (channel >= hdsp->max_channels)
+ return -ENOENT;
+
+ return hdsp_loopback_set(hdsp, channel, enable);
+}
+
+static struct snd_kcontrol_new snd_hdsp_loopback_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP,
+ .name = "Output Loopback",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_ctl_boolean_mono_info,
+ .get = snd_hdsp_loopback_get,
+ .put = snd_hdsp_loopback_put
+};
+
static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
{
unsigned int idx;
@@ -3297,6 +3352,17 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
}
}
+ /* Output loopback controls for H9632 cards */
+ if (hdsp->io_type == H9632) {
+ snd_hdsp_loopback_control.count = hdsp->max_channels;
+ kctl = snd_ctl_new1(&snd_hdsp_loopback_control, hdsp);
+ if (kctl == NULL)
+ return -ENOMEM;
+ err = snd_ctl_add(card, kctl);
+ if (err < 0)
+ return err;
+ }
+
/* AEB control for H96xx card */
if (hdsp->io_type == H9632 || hdsp->io_type == H9652) {
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0)
@@ -4956,7 +5022,7 @@ static int snd_hdsp_enable_io (struct hdsp *hdsp)
static void snd_hdsp_initialize_channels(struct hdsp *hdsp)
{
- int status, aebi_channels, aebo_channels;
+ int status, aebi_channels, aebo_channels, i;
switch (hdsp->io_type) {
case Digiface:
@@ -4983,6 +5049,12 @@ static void snd_hdsp_initialize_channels(struct hdsp *hdsp)
hdsp->ss_out_channels = H9632_SS_CHANNELS+aebo_channels;
hdsp->ds_out_channels = H9632_DS_CHANNELS+aebo_channels;
hdsp->qs_out_channels = H9632_QS_CHANNELS+aebo_channels;
+ /* Disable loopback of output channels, as the set function
+ * only sets on a change we fake all bits (channels) as enabled.
+ */
+ hdsp->io_loopback = 0xffffffff;
+ for (i = 0; i < hdsp->max_channels; ++i)
+ hdsp_loopback_set(hdsp, i, false);
break;
case Multiface:
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 04e878a0f773..b66711574b1a 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -6329,7 +6329,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
memset(&hdspm_version, 0, sizeof(hdspm_version));
hdspm_version.card_type = hdspm->io_type;
- strlcpy(hdspm_version.cardname, hdspm->card_name,
+ strscpy(hdspm_version.cardname, hdspm->card_name,
sizeof(hdspm_version.cardname));
hdspm_version.serial = hdspm->serial;
hdspm_version.firmware_rev = hdspm->firmware_rev;
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index 7bf6059d50fb..8ffa2f53c0b5 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -363,7 +363,7 @@ static u32 sis_rate_to_delta(unsigned int rate)
else if (rate == 48000)
delta = 0x1000;
else
- delta = (((rate << 12) + 24000) / 48000) & 0x0000ffff;
+ delta = DIV_ROUND_CLOSEST(rate << 12, 48000) & 0x0000ffff;
return delta;
}
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index ecdd54d7a4e1..26fd1d08c179 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -570,7 +570,7 @@ static void snd_sonicvibes_set_dac_rate(struct sonicvibes * sonic, unsigned int
unsigned int div;
unsigned long flags;
- div = (rate * 65536 + SV_FULLRATE / 2) / SV_FULLRATE;
+ div = DIV_ROUND_CLOSEST(rate * 65536, SV_FULLRATE);
if (div > 65535)
div = 65535;
spin_lock_irqsave(&sonic->reg_lock, flags);
@@ -1230,8 +1230,7 @@ static int snd_sonicvibes_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 24 bits */
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
dev_err(card->dev,
"architecture does not support 24bit PCI busmaster DMA\n");
pci_disable_device(pci);
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 6e50376163a2..20145143f6a6 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -678,7 +678,7 @@ static unsigned int snd_trident_convert_rate(unsigned int rate)
else if (rate == 48000)
delta = 0x1000;
else
- delta = (((rate << 12) + 24000) / 48000) & 0x0000ffff;
+ delta = DIV_ROUND_CLOSEST(rate << 12, 48000) & 0x0000ffff;
return delta;
}
@@ -1034,7 +1034,7 @@ static int snd_trident_capture_prepare(struct snd_pcm_substream *substream)
ESO_bytes++;
// Set channel sample rate, 4.12 format
- val = (((unsigned int) 48000L << 12) + (runtime->rate/2)) / runtime->rate;
+ val = DIV_ROUND_CLOSEST(48000U << 12, runtime->rate);
outw(val, TRID_REG(trident, T4D_SBDELTA_DELTA_R));
// Set channel interrupt blk length
@@ -3497,8 +3497,7 @@ int snd_trident_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 30 bits */
- if (dma_set_mask(&pci->dev, DMA_BIT_MASK(30)) < 0 ||
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(30)) < 0) {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(30))) {
dev_err(card->dev,
"architecture does not support 30bit PCI busmaster DMA\n");
pci_disable_device(pci);
diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
index 9554a0c506af..a6c1905039de 100644
--- a/sound/ppc/keywest.c
+++ b/sound/ppc/keywest.c
@@ -49,7 +49,7 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
return -EINVAL; /* ignored */
memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "keywest", I2C_NAME_SIZE);
+ strscpy(info.type, "keywest", I2C_NAME_SIZE);
info.addr = keywest_ctx->addr;
client = i2c_new_client_device(adapter, &info);
if (IS_ERR(client))
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 71a6fe87d1a1..640494f76cbd 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -37,6 +37,23 @@ config SND_SOC_COMPRESS
config SND_SOC_TOPOLOGY
bool
+config SND_SOC_TOPOLOGY_KUNIT_TESTS
+ tristate "KUnit tests for SoC topology"
+ depends on KUNIT
+ depends on SND_SOC_TOPOLOGY
+ default KUNIT_ALL_TESTS
+ help
+ If you want to perform tests on ALSA SoC topology support say Y here.
+
+ This builds a module which can be later manually loaded to run KUNIT
+ test cases against soc-topology.c API. This should be primarily used
+ by developers to test their changes to ASoC.
+
+ Do note that it creates fake playback devices which do not interact
+ well with userspace. When running tests one may want to disable
+ userspace applications such as pulseaudio, to prevent unnecessary
+ problems.
+
config SND_SOC_ACPI
tristate
@@ -62,7 +79,6 @@ source "sound/soc/qcom/Kconfig"
source "sound/soc/rockchip/Kconfig"
source "sound/soc/samsung/Kconfig"
source "sound/soc/sh/Kconfig"
-source "sound/soc/sirf/Kconfig"
source "sound/soc/sof/Kconfig"
source "sound/soc/spear/Kconfig"
source "sound/soc/sprd/Kconfig"
@@ -71,12 +87,10 @@ source "sound/soc/stm/Kconfig"
source "sound/soc/sunxi/Kconfig"
source "sound/soc/tegra/Kconfig"
source "sound/soc/ti/Kconfig"
-source "sound/soc/txx9/Kconfig"
source "sound/soc/uniphier/Kconfig"
source "sound/soc/ux500/Kconfig"
source "sound/soc/xilinx/Kconfig"
source "sound/soc/xtensa/Kconfig"
-source "sound/soc/zte/Kconfig"
# Supported codecs
source "sound/soc/codecs/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index ddbac3a2169f..f56ad996eae8 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -7,6 +7,11 @@ ifneq ($(CONFIG_SND_SOC_TOPOLOGY),)
snd-soc-core-objs += soc-topology.o
endif
+ifneq ($(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TESTS),)
+# snd-soc-test-objs := soc-topology-test.o
+obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TESTS) := soc-topology-test.o
+endif
+
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
endif
@@ -45,7 +50,6 @@ obj-$(CONFIG_SND_SOC) += qcom/
obj-$(CONFIG_SND_SOC) += rockchip/
obj-$(CONFIG_SND_SOC) += samsung/
obj-$(CONFIG_SND_SOC) += sh/
-obj-$(CONFIG_SND_SOC) += sirf/
obj-$(CONFIG_SND_SOC) += sof/
obj-$(CONFIG_SND_SOC) += spear/
obj-$(CONFIG_SND_SOC) += sprd/
@@ -54,9 +58,7 @@ obj-$(CONFIG_SND_SOC) += stm/
obj-$(CONFIG_SND_SOC) += sunxi/
obj-$(CONFIG_SND_SOC) += tegra/
obj-$(CONFIG_SND_SOC) += ti/
-obj-$(CONFIG_SND_SOC) += txx9/
obj-$(CONFIG_SND_SOC) += uniphier/
obj-$(CONFIG_SND_SOC) += ux500/
obj-$(CONFIG_SND_SOC) += xilinx/
obj-$(CONFIG_SND_SOC) += xtensa/
-obj-$(CONFIG_SND_SOC) += zte/
diff --git a/sound/soc/adi/axi-i2s.c b/sound/soc/adi/axi-i2s.c
index 8c4dc82be0df..aa082131fb90 100644
--- a/sound/soc/adi/axi-i2s.c
+++ b/sound/soc/adi/axi-i2s.c
@@ -156,7 +156,7 @@ static const struct snd_soc_dai_ops axi_i2s_dai_ops = {
static struct snd_soc_dai_driver axi_i2s_dai = {
.probe = axi_i2s_dai_probe,
.ops = &axi_i2s_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static const struct snd_soc_component_driver axi_i2s_component = {
diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c
index 1a4e8ca0f99c..cea320ad0e1c 100644
--- a/sound/soc/amd/acp3x-rt5682-max9836.c
+++ b/sound/soc/amd/acp3x-rt5682-max9836.c
@@ -140,9 +140,7 @@ static int acp3x_1015_hw_params(struct snd_pcm_substream *substream,
for_each_rtd_codec_dais(rtd, i, codec_dai) {
if (strcmp(codec_dai->name, "rt1015-aif"))
continue;
- ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
- if (ret < 0)
- return ret;
+
ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
64 * srate, 256 * srate);
if (ret < 0)
diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c
index 232300dda548..7c6187e41f2b 100644
--- a/sound/soc/atmel/atmel-i2s.c
+++ b/sound/soc/atmel/atmel-i2s.c
@@ -541,7 +541,7 @@ static struct snd_soc_dai_driver atmel_i2s_dai = {
.formats = ATMEL_I2S_FORMATS,
},
.ops = &atmel_i2s_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static const struct snd_soc_component_driver atmel_i2s_component = {
diff --git a/sound/soc/atmel/atmel-pcm-pdc.c b/sound/soc/atmel/atmel-pcm-pdc.c
index 704f700013d3..3e7ea2021b46 100644
--- a/sound/soc/atmel/atmel-pcm-pdc.c
+++ b/sound/soc/atmel/atmel-pcm-pdc.c
@@ -34,86 +34,21 @@
#include "atmel-pcm.h"
-static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
- int stream)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- size_t size = ATMEL_SSC_DMABUF_SIZE;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
- buf->area = dma_alloc_coherent(pcm->card->dev, size,
- &buf->addr, GFP_KERNEL);
- pr_debug("atmel-pcm: alloc dma buffer: area=%p, addr=%p, size=%zu\n",
- (void *)buf->area, (void *)(long)buf->addr, size);
-
- if (!buf->area)
- return -ENOMEM;
-
- buf->bytes = size;
- return 0;
-}
-
-static int atmel_pcm_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- return remap_pfn_range(vma, vma->vm_start,
- substream->dma_buffer.addr >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start, vma->vm_page_prot);
-}
-
static int atmel_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_pcm *pcm = rtd->pcm;
int ret;
ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
- pr_debug("atmel-pcm: allocating PCM playback DMA buffer\n");
- ret = atmel_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- goto out;
- }
+ snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+ card->dev, ATMEL_SSC_DMABUF_SIZE,
+ ATMEL_SSC_DMABUF_SIZE);
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- pr_debug("atmel-pcm: allocating PCM capture DMA buffer\n");
- ret = atmel_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- goto out;
- }
- out:
- return ret;
-}
-
-static void atmel_pcm_free(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
-
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
- dma_free_coherent(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
+ return 0;
}
/*--------------------------------------------------------------------------*\
@@ -210,9 +145,6 @@ static int atmel_pcm_hw_params(struct snd_soc_component *component,
/* this may get called several times by oss emulation
* with different params */
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = params_buffer_bytes(params);
-
prtd->params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
@@ -384,9 +316,7 @@ static const struct snd_soc_component_driver atmel_soc_platform = {
.prepare = atmel_pcm_prepare,
.trigger = atmel_pcm_trigger,
.pointer = atmel_pcm_pointer,
- .mmap = atmel_pcm_mmap,
.pcm_construct = atmel_pcm_new,
- .pcm_destruct = atmel_pcm_free,
};
int atmel_pcm_pdc_platform_register(struct device *dev)
diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 04acc18f2d72..6d5ae18f8b38 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -859,8 +859,8 @@ static struct snd_soc_dai_driver mchp_i2s_mcc_dai = {
.formats = MCHP_I2SMCC_FORMATS,
},
.ops = &mchp_i2s_mcc_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
.symmetric_channels = 1,
};
diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c
index 7fd08fafa490..65bd39f5032d 100644
--- a/sound/soc/au1x/i2sc.c
+++ b/sound/soc/au1x/i2sc.c
@@ -210,7 +210,7 @@ static const struct snd_soc_dai_ops au1xi2s_dai_ops = {
};
static struct snd_soc_dai_driver au1xi2s_dai_driver = {
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
.playback = {
.rates = AU1XI2SC_RATES,
.formats = AU1XI2SC_FMTS,
diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c
index c2f7631e8705..3d668f449bc1 100644
--- a/sound/soc/bcm/bcm2835-i2s.c
+++ b/sound/soc/bcm/bcm2835-i2s.c
@@ -783,8 +783,8 @@ static struct snd_soc_dai_driver bcm2835_i2s_dai = {
| SNDRV_PCM_FMTBIT_S32_LE
},
.ops = &bcm2835_i2s_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
};
static bool bcm2835_i2s_volatile_reg(struct device *dev, unsigned int reg)
diff --git a/sound/soc/bcm/bcm63xx-i2s-whistler.c b/sound/soc/bcm/bcm63xx-i2s-whistler.c
index 246a57ac6679..527caf430715 100644
--- a/sound/soc/bcm/bcm63xx-i2s-whistler.c
+++ b/sound/soc/bcm/bcm63xx-i2s-whistler.c
@@ -212,7 +212,7 @@ static struct snd_soc_dai_driver bcm63xx_i2s_dai = {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &bcm63xx_i2s_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
.symmetric_channels = 1,
};
diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c
index 7ad07239f99c..56b71b965624 100644
--- a/sound/soc/bcm/cygnus-pcm.c
+++ b/sound/soc/bcm/cygnus-pcm.c
@@ -636,36 +636,6 @@ static int cygnus_pcm_close(struct snd_soc_component *component,
return 0;
}
-static int cygnus_pcm_hw_params(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct cygnus_aio_port *aio;
-
- aio = cygnus_dai_get_dma_data(substream);
- dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s port %d\n", __func__, aio->portnum);
-
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = params_buffer_bytes(params);
-
- return 0;
-}
-
-static int cygnus_pcm_hw_free(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- struct cygnus_aio_port *aio;
-
- aio = cygnus_dai_get_dma_data(substream);
- dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s port %d\n", __func__, aio->portnum);
-
- snd_pcm_set_runtime_buffer(substream, NULL);
- return 0;
-}
-
static int cygnus_pcm_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
@@ -730,87 +700,19 @@ static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_soc_component *component,
return bytes_to_frames(substream->runtime, res);
}
-static int cygnus_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- size_t size;
-
- size = cygnus_pcm_hw.buffer_bytes_max;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
- buf->area = dma_alloc_coherent(pcm->card->dev, size,
- &buf->addr, GFP_KERNEL);
-
- dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s: size 0x%zx @ %pK\n",
- __func__, size, buf->area);
-
- if (!buf->area) {
- dev_err(asoc_rtd_to_cpu(rtd, 0)->dev, "%s: dma_alloc failed\n", __func__);
- return -ENOMEM;
- }
- buf->bytes = size;
-
- return 0;
-}
-
-static void cygnus_dma_free_dma_buffers(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
-
- substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
- if (substream) {
- buf = &substream->dma_buffer;
- if (buf->area) {
- dma_free_coherent(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
- }
-
- substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
- if (substream) {
- buf = &substream->dma_buffer;
- if (buf->area) {
- dma_free_coherent(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
- }
-}
-
static int cygnus_dma_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
+ size_t size = cygnus_pcm_hw.buffer_bytes_max;
struct snd_card *card = rtd->card->snd_card;
- struct snd_pcm *pcm = rtd->pcm;
- int ret;
if (!card->dev->dma_mask)
card->dev->dma_mask = &cygnus_dma_dmamask;
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
- ret = cygnus_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- return ret;
- }
-
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- ret = cygnus_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret) {
- cygnus_dma_free_dma_buffers(component, pcm);
- return ret;
- }
- }
+ snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+ card->dev, size, size);
return 0;
}
@@ -818,13 +720,10 @@ static int cygnus_dma_new(struct snd_soc_component *component,
static struct snd_soc_component_driver cygnus_soc_platform = {
.open = cygnus_pcm_open,
.close = cygnus_pcm_close,
- .hw_params = cygnus_pcm_hw_params,
- .hw_free = cygnus_pcm_hw_free,
.prepare = cygnus_pcm_prepare,
.trigger = cygnus_pcm_trigger,
.pointer = cygnus_pcm_pointer,
.pcm_construct = cygnus_dma_new,
- .pcm_destruct = cygnus_dma_free_dma_buffers,
};
int cygnus_soc_platform_register(struct device *dev,
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c
index 371708b17c09..0d26550d0df8 100644
--- a/sound/soc/cirrus/ep93xx-i2s.c
+++ b/sound/soc/cirrus/ep93xx-i2s.c
@@ -404,7 +404,7 @@ static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_driver ep93xx_i2s_dai = {
- .symmetric_rates= 1,
+ .symmetric_rate = 1,
.probe = ep93xx_i2s_dai_probe,
.playback = {
.channels_min = 2,
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 9bf6bfdaf11e..e4cf14e66a51 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -104,6 +104,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_ISABELLE
imply SND_SOC_JZ4740_CODEC
imply SND_SOC_JZ4725B_CODEC
+ imply SND_SOC_JZ4760_CODEC
imply SND_SOC_JZ4770_CODEC
imply SND_SOC_LM4857
imply SND_SOC_LM49453
@@ -227,6 +228,8 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_UDA1380
imply SND_SOC_WCD9335
imply SND_SOC_WCD934X
+ imply SND_SOC_LPASS_RX_MACRO
+ imply SND_SOC_LPASS_TX_MACRO
imply SND_SOC_WL1273
imply SND_SOC_WM0010
imply SND_SOC_WM1250_EV1
@@ -712,7 +715,7 @@ config SND_SOC_CX2072X
Enable support for Conexant CX20721 and CX20723 codec chips.
config SND_SOC_JZ4740_CODEC
- depends on MIPS || COMPILE_TEST
+ depends on MACH_INGENIC || COMPILE_TEST
depends on OF
select REGMAP_MMIO
tristate "Ingenic JZ4740 internal CODEC"
@@ -724,7 +727,7 @@ config SND_SOC_JZ4740_CODEC
will be called snd-soc-jz4740-codec.
config SND_SOC_JZ4725B_CODEC
- depends on MIPS || COMPILE_TEST
+ depends on MACH_INGENIC || COMPILE_TEST
depends on OF
select REGMAP
tristate "Ingenic JZ4725B internal CODEC"
@@ -735,8 +738,20 @@ config SND_SOC_JZ4725B_CODEC
This driver can also be built as a module. If so, the module
will be called snd-soc-jz4725b-codec.
+config SND_SOC_JZ4760_CODEC
+ depends on MACH_INGENIC || COMPILE_TEST
+ depends on OF
+ select REGMAP
+ tristate "Ingenic JZ4760 internal CODEC"
+ help
+ Enable support for the internal CODEC found in the JZ4760 SoC
+ from Ingenic.
+
+ This driver can also be built as a module. If so, the module
+ will be called snd-soc-jz4760-codec.
+
config SND_SOC_JZ4770_CODEC
- depends on MIPS || COMPILE_TEST
+ depends on MACH_INGENIC || COMPILE_TEST
depends on OF
select REGMAP
tristate "Ingenic JZ4770 internal CODEC"
@@ -1162,7 +1177,7 @@ config SND_SOC_RT5651
depends on I2C
config SND_SOC_RT5659
- tristate
+ tristate "Realtek RT5658/RT5659 Codec"
depends on I2C
config SND_SOC_RT5660
@@ -1820,4 +1835,12 @@ config SND_SOC_LPASS_VA_MACRO
depends on COMMON_CLK
tristate "Qualcomm VA Macro in LPASS(Low Power Audio SubSystem)"
+config SND_SOC_LPASS_RX_MACRO
+ depends on COMMON_CLK
+ tristate "Qualcomm RX Macro in LPASS(Low Power Audio SubSystem)"
+
+config SND_SOC_LPASS_TX_MACRO
+ depends on COMMON_CLK
+ tristate "Qualcomm TX Macro in LPASS(Low Power Audio SubSystem)"
+
endmenu
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index d277f0366e09..81357dc62ea0 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -101,11 +101,14 @@ snd-soc-inno-rk3036-objs := inno_rk3036.o
snd-soc-isabelle-objs := isabelle.o
snd-soc-jz4740-codec-objs := jz4740.o
snd-soc-jz4725b-codec-objs := jz4725b.o
+snd-soc-jz4760-codec-objs := jz4760.o
snd-soc-jz4770-codec-objs := jz4770.o
snd-soc-l3-objs := l3.o
snd-soc-lm4857-objs := lm4857.o
snd-soc-lm49453-objs := lm49453.o
snd-soc-lochnagar-sc-objs := lochnagar-sc.o
+snd-soc-lpass-rx-macro-objs := lpass-rx-macro.o
+snd-soc-lpass-tx-macro-objs := lpass-tx-macro.o
snd-soc-lpass-wsa-macro-objs := lpass-wsa-macro.o
snd-soc-lpass-va-macro-objs := lpass-va-macro.o
snd-soc-madera-objs := madera.o
@@ -201,7 +204,6 @@ snd-soc-sigmadsp-objs := sigmadsp.o
snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o
snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o
snd-soc-si476x-objs := si476x.o
-snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o
snd-soc-spdif-tx-objs := spdif_transmitter.o
snd-soc-spdif-rx-objs := spdif_receiver.o
snd-soc-ssm2305-objs := ssm2305.o
@@ -302,7 +304,6 @@ snd-soc-wm9713-objs := wm9713.o
snd-soc-wm-hubs-objs := wm_hubs.o
snd-soc-wsa881x-objs := wsa881x.o
snd-soc-zl38060-objs := zl38060.o
-snd-soc-zx-aud96p22-objs := zx_aud96p22.o
# Amp
snd-soc-max9877-objs := max9877.o
snd-soc-max98504-objs := max98504.o
@@ -418,6 +419,7 @@ obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o
obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
obj-$(CONFIG_SND_SOC_JZ4725B_CODEC) += snd-soc-jz4725b-codec.o
+obj-$(CONFIG_SND_SOC_JZ4760_CODEC) += snd-soc-jz4760-codec.o
obj-$(CONFIG_SND_SOC_JZ4770_CODEC) += snd-soc-jz4770-codec.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
@@ -516,7 +518,6 @@ 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_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
-obj-$(CONFIG_SND_SOC_SIRF_AUDIO_CODEC) += sirf-audio-codec.o
obj-$(CONFIG_SND_SOC_SSM2305) += snd-soc-ssm2305.o
obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
@@ -618,7 +619,6 @@ obj-$(CONFIG_SND_SOC_WM_ADSP) += snd-soc-wm-adsp.o
obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
obj-$(CONFIG_SND_SOC_WSA881X) += snd-soc-wsa881x.o
obj-$(CONFIG_SND_SOC_ZL38060) += snd-soc-zl38060.o
-obj-$(CONFIG_SND_SOC_ZX_AUD96P22) += snd-soc-zx-aud96p22.o
# Amp
obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
@@ -627,6 +627,8 @@ obj-$(CONFIG_SND_SOC_SIMPLE_AMPLIFIER) += snd-soc-simple-amplifier.o
obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
obj-$(CONFIG_SND_SOC_LPASS_WSA_MACRO) += snd-soc-lpass-wsa-macro.o
obj-$(CONFIG_SND_SOC_LPASS_VA_MACRO) += snd-soc-lpass-va-macro.o
+obj-$(CONFIG_SND_SOC_LPASS_RX_MACRO) += snd-soc-lpass-rx-macro.o
+obj-$(CONFIG_SND_SOC_LPASS_TX_MACRO) += snd-soc-lpass-tx-macro.o
# Mux
obj-$(CONFIG_SND_SOC_SIMPLE_MUX) += snd-soc-simple-mux.o
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index 31a8c4162d20..c95f007cede1 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -2384,7 +2384,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
.formats = AB8500_SUPPORTED_FMT,
},
.ops = &ab8500_codec_ops,
- .symmetric_rates = 1
+ .symmetric_rate = 1
},
{
.name = "ab8500-codec-dai.1",
@@ -2397,7 +2397,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
.formats = AB8500_SUPPORTED_FMT,
},
.ops = &ab8500_codec_ops,
- .symmetric_rates = 1
+ .symmetric_rate = 1
}
};
diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
index 5ccbf1b6bcf5..6811a8b3866d 100644
--- a/sound/soc/codecs/adau1372.c
+++ b/sound/soc/codecs/adau1372.c
@@ -890,7 +890,7 @@ static struct snd_soc_dai_driver adau1372_dai_driver = {
.sig_bits = 24,
},
.ops = &adau1372_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int adau1372_setup_pll(struct adau1372 *adau1372, unsigned int rate)
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index e71fde001b46..9887aa6f0be5 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -1205,7 +1205,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = {
.formats = ADAU1373_FORMATS,
},
.ops = &adau1373_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.id = 1,
@@ -1225,7 +1225,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = {
.formats = ADAU1373_FORMATS,
},
.ops = &adau1373_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.id = 2,
@@ -1245,7 +1245,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = {
.formats = ADAU1373_FORMATS,
},
.ops = &adau1373_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 68130eaa64a4..5ce74697564a 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -653,7 +653,7 @@ static struct snd_soc_dai_driver adau1701_dai = {
.formats = ADAU1701_FORMATS,
},
.ops = &adau1701_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
#ifdef CONFIG_OF
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c
index 30e072c80ac1..546ee8178038 100644
--- a/sound/soc/codecs/adau17x1.c
+++ b/sound/soc/codecs/adau17x1.c
@@ -1095,8 +1095,7 @@ void adau17x1_remove(struct device *dev)
{
struct adau *adau = dev_get_drvdata(dev);
- if (adau->mclk)
- clk_disable_unprepare(adau->mclk);
+ clk_disable_unprepare(adau->mclk);
}
EXPORT_SYMBOL_GPL(adau17x1_remove);
diff --git a/sound/soc/codecs/ak4554.c b/sound/soc/codecs/ak4554.c
index 2fa83a1a84cf..8e60e2b56ad6 100644
--- a/sound/soc/codecs/ak4554.c
+++ b/sound/soc/codecs/ak4554.c
@@ -56,7 +56,7 @@ static struct snd_soc_dai_driver ak4554_dai = {
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static const struct snd_soc_component_driver soc_component_dev_ak4554 = {
diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c
index 8d663e8d64c4..fe208cfdd3ba 100644
--- a/sound/soc/codecs/ak4613.c
+++ b/sound/soc/codecs/ak4613.c
@@ -575,7 +575,7 @@ static struct snd_soc_dai_driver ak4613_dai = {
.formats = AK4613_PCM_FMTBIT,
},
.ops = &ak4613_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int ak4613_suspend(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index 77004cd7caa3..04aef0e72aa5 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -499,7 +499,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = {
.formats = AK4641_FORMATS,
},
.ops = &ak4641_i2s_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "ak4641-voice",
@@ -519,7 +519,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = {
.formats = AK4641_FORMATS,
},
.ops = &ak4641_pcm_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 353237025514..c49c58eeb476 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -516,7 +516,7 @@ static struct snd_soc_dai_driver ak4642_dai = {
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE },
.ops = &ak4642_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int ak4642_suspend(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
index bde5ded67754..79813882a955 100644
--- a/sound/soc/codecs/alc5632.c
+++ b/sound/soc/codecs/alc5632.c
@@ -1032,7 +1032,7 @@ static struct snd_soc_dai_driver alc5632_dai = {
.formats = ALC5632_FORMATS,},
.ops = &alc5632_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
#ifdef CONFIG_PM
diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c
index f046987ee4cd..05bbacd0d174 100644
--- a/sound/soc/codecs/cpcap.c
+++ b/sound/soc/codecs/cpcap.c
@@ -16,6 +16,14 @@
#include <sound/soc.h>
#include <sound/tlv.h>
+/* Register 512 CPCAP_REG_VAUDIOC --- Audio Regulator and Bias Voltage */
+#define CPCAP_BIT_AUDIO_LOW_PWR 6
+#define CPCAP_BIT_AUD_LOWPWR_SPEED 5
+#define CPCAP_BIT_VAUDIOPRISTBY 4
+#define CPCAP_BIT_VAUDIO_MODE1 2
+#define CPCAP_BIT_VAUDIO_MODE0 1
+#define CPCAP_BIT_V_AUDIO_EN 0
+
/* Register 513 CPCAP_REG_CC --- CODEC */
#define CPCAP_BIT_CDC_CLK2 15
#define CPCAP_BIT_CDC_CLK1 14
@@ -221,6 +229,7 @@ struct cpcap_reg_info {
};
static const struct cpcap_reg_info cpcap_default_regs[] = {
+ { CPCAP_REG_VAUDIOC, 0x003F, 0x0000 },
{ CPCAP_REG_CC, 0xFFFF, 0x0000 },
{ CPCAP_REG_CC, 0xFFFF, 0x0000 },
{ CPCAP_REG_CDI, 0xBFFF, 0x0000 },
@@ -1264,12 +1273,12 @@ static int cpcap_voice_hw_params(struct snd_pcm_substream *substream,
if (direction == SNDRV_PCM_STREAM_CAPTURE) {
mask = 0x0000;
- mask |= CPCAP_BIT_MIC1_RX_TIMESLOT0;
- mask |= CPCAP_BIT_MIC1_RX_TIMESLOT1;
- mask |= CPCAP_BIT_MIC1_RX_TIMESLOT2;
- mask |= CPCAP_BIT_MIC2_TIMESLOT0;
- mask |= CPCAP_BIT_MIC2_TIMESLOT1;
- mask |= CPCAP_BIT_MIC2_TIMESLOT2;
+ mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0);
+ mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT1);
+ mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT2);
+ mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT0);
+ mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT1);
+ mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT2);
val = 0x0000;
if (channels >= 2)
val = BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0);
@@ -1371,8 +1380,121 @@ static int cpcap_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}
-static int cpcap_voice_set_mute(struct snd_soc_dai *dai,
- int mute, int direction)
+
+/*
+ * Configure codec for voice call if requested.
+ *
+ * We can configure most with snd_soc_dai_set_sysclk(), snd_soc_dai_set_fmt()
+ * and snd_soc_dai_set_tdm_slot(). This function configures the rest of the
+ * cpcap related hardware as CPU is not involved in the voice call.
+ */
+static int cpcap_voice_call(struct cpcap_audio *cpcap, struct snd_soc_dai *dai,
+ bool voice_call)
+{
+ int mask, err;
+
+ /* Modem to codec VAUDIO_MODE1 */
+ mask = BIT(CPCAP_BIT_VAUDIO_MODE1);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_VAUDIOC,
+ mask, voice_call ? mask : 0);
+ if (err)
+ return err;
+
+ /* Clear MIC1_MUX for call */
+ mask = BIT(CPCAP_BIT_MIC1_MUX);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
+ mask, voice_call ? 0 : mask);
+ if (err)
+ return err;
+
+ /* Set MIC2_MUX for call */
+ mask = BIT(CPCAP_BIT_MB_ON1L) | BIT(CPCAP_BIT_MB_ON1R) |
+ BIT(CPCAP_BIT_MIC2_MUX) | BIT(CPCAP_BIT_MIC2_PGA_EN);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
+ mask, voice_call ? mask : 0);
+ if (err)
+ return err;
+
+ /* Enable LDSP for call */
+ mask = BIT(CPCAP_BIT_A2_LDSP_L_EN) | BIT(CPCAP_BIT_A2_LDSP_R_EN);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXOA,
+ mask, voice_call ? mask : 0);
+ if (err)
+ return err;
+
+ /* Enable CPCAP_BIT_PGA_CDC_EN for call */
+ mask = BIT(CPCAP_BIT_PGA_CDC_EN);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXCOA,
+ mask, voice_call ? mask : 0);
+ if (err)
+ return err;
+
+ /* Unmute voice for call */
+ if (dai) {
+ err = snd_soc_dai_digital_mute(dai, !voice_call,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ if (err)
+ return err;
+ }
+
+ /* Set modem to codec mic CDC and HPF for call */
+ mask = BIT(CPCAP_BIT_MIC2_CDC_EN) | BIT(CPCAP_BIT_CDC_EN_RX) |
+ BIT(CPCAP_BIT_AUDOHPF_1) | BIT(CPCAP_BIT_AUDOHPF_0) |
+ BIT(CPCAP_BIT_AUDIHPF_1) | BIT(CPCAP_BIT_AUDIHPF_0);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CC,
+ mask, voice_call ? mask : 0);
+ if (err)
+ return err;
+
+ /* Enable modem to codec CDC for call*/
+ mask = BIT(CPCAP_BIT_CDC_CLK_EN);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,
+ mask, voice_call ? mask : 0);
+
+ return err;
+}
+
+static int cpcap_voice_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 cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
+ int err, ts_mask, mask;
+ bool voice_call;
+
+ /*
+ * Primitive test for voice call, probably needs more checks
+ * later on for 16-bit calls detected, Bluetooth headset etc.
+ */
+ if (tx_mask == 0 && rx_mask == 1 && slot_width == 8)
+ voice_call = true;
+ else
+ voice_call = false;
+
+ ts_mask = 0x7 << CPCAP_BIT_MIC2_TIMESLOT0;
+ ts_mask |= 0x7 << CPCAP_BIT_MIC1_RX_TIMESLOT0;
+
+ mask = (tx_mask & 0x7) << CPCAP_BIT_MIC2_TIMESLOT0;
+ mask |= (rx_mask & 0x7) << CPCAP_BIT_MIC1_RX_TIMESLOT0;
+
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,
+ ts_mask, mask);
+ if (err)
+ return err;
+
+ err = cpcap_set_samprate(cpcap, CPCAP_DAI_VOICE, slot_width * 1000);
+ if (err)
+ return err;
+
+ err = cpcap_voice_call(cpcap, dai, voice_call);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int cpcap_voice_set_mute(struct snd_soc_dai *dai, int mute, int direction)
{
struct snd_soc_component *component = dai->component;
struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
@@ -1393,6 +1515,7 @@ static const struct snd_soc_dai_ops cpcap_dai_voice_ops = {
.hw_params = cpcap_voice_hw_params,
.set_sysclk = cpcap_voice_set_dai_sysclk,
.set_fmt = cpcap_voice_set_dai_fmt,
+ .set_tdm_slot = cpcap_voice_set_tdm_slot,
.mute_stream = cpcap_voice_set_mute,
.no_capture_mute = 1,
};
diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
index f33a2a9654e7..c4772f82485a 100644
--- a/sound/soc/codecs/cros_ec_codec.c
+++ b/sound/soc/codecs/cros_ec_codec.c
@@ -1011,6 +1011,18 @@ static int cros_ec_codec_platform_probe(struct platform_device *pdev)
}
priv->ec_capabilities = r.capabilities;
+ /* Reset EC codec i2s rx. */
+ p.cmd = EC_CODEC_I2S_RX_RESET;
+ ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
+ (uint8_t *)&p, sizeof(p), NULL, 0);
+ if (ret == -ENOPROTOOPT) {
+ dev_info(dev,
+ "Missing reset command. Please update EC firmware.\n");
+ } else if (ret) {
+ dev_err(dev, "failed to EC_CODEC_I2S_RESET: %d\n", ret);
+ return ret;
+ }
+
platform_set_drvdata(pdev, priv);
ret = devm_snd_soc_register_component(dev, &i2s_rx_component_driver,
diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c
index 3a644a35c464..f4067230ac42 100644
--- a/sound/soc/codecs/cs35l32.c
+++ b/sound/soc/codecs/cs35l32.c
@@ -194,7 +194,7 @@ static struct snd_soc_dai_driver cs35l32_dai[] = {
.formats = CS35L32_FORMATS,
},
.ops = &cs35l32_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
}
};
diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c
index 6042194d95d3..7ad7b733af9b 100644
--- a/sound/soc/codecs/cs35l33.c
+++ b/sound/soc/codecs/cs35l33.c
@@ -691,7 +691,7 @@ static struct snd_soc_dai_driver cs35l33_dai = {
.formats = CS35L33_FORMATS,
},
.ops = &cs35l33_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int cs35l33_set_hg_data(struct snd_soc_component *component,
diff --git a/sound/soc/codecs/cs35l34.c b/sound/soc/codecs/cs35l34.c
index b792c006e530..110ee2d06358 100644
--- a/sound/soc/codecs/cs35l34.c
+++ b/sound/soc/codecs/cs35l34.c
@@ -666,7 +666,7 @@ static struct snd_soc_dai_driver cs35l34_dai = {
.formats = CS35L34_FORMATS,
},
.ops = &cs35l34_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int cs35l34_boost_inductor(struct cs35l34_private *cs35l34,
diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c
index e330427a4314..55d529aa0011 100644
--- a/sound/soc/codecs/cs35l35.c
+++ b/sound/soc/codecs/cs35l35.c
@@ -692,7 +692,7 @@ static struct snd_soc_dai_driver cs35l35_dai[] = {
.formats = CS35L35_FORMATS,
},
.ops = &cs35l35_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "cs35l35-pdm",
diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c
index e9b5f76f27a8..4451ca9f4916 100644
--- a/sound/soc/codecs/cs35l36.c
+++ b/sound/soc/codecs/cs35l36.c
@@ -995,7 +995,7 @@ static struct snd_soc_dai_driver cs35l36_dai[] = {
.formats = CS35L36_TX_FORMATS,
},
.ops = &cs35l36_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/codecs/cs4234.c b/sound/soc/codecs/cs4234.c
index 2ea83233c3f1..20126cc675b1 100644
--- a/sound/soc/codecs/cs4234.c
+++ b/sound/soc/codecs/cs4234.c
@@ -585,7 +585,7 @@ static struct snd_soc_dai_driver cs4234_dai[] = {
.formats = CS4234_FORMATS,
},
.ops = &cs4234_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index d43762ae8f3d..7663f89ac6a2 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -481,7 +481,7 @@ static struct snd_soc_dai_driver cs4271_dai = {
.formats = CS4271_PCM_FORMATS,
},
.ops = &cs4271_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int cs4271_reset(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c
index bb9599cc832b..c44a5cdb796e 100644
--- a/sound/soc/codecs/cs42l56.c
+++ b/sound/soc/codecs/cs42l56.c
@@ -1250,6 +1250,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
dev_err(&i2c_client->dev,
"CS42L56 Device ID (%X). Expected %X\n",
devid, CS42L56_DEVID);
+ ret = -EINVAL;
goto err_enable;
}
alpha_rev = reg & CS42L56_AREV_MASK;
@@ -1307,7 +1308,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
ret = devm_snd_soc_register_component(&i2c_client->dev,
&soc_component_dev_cs42l56, &cs42l56_dai, 1);
if (ret < 0)
- return ret;
+ goto err_enable;
return 0;
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index 988ca7e19821..c3f974ec78e5 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -1181,7 +1181,7 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
.formats = CS42L73_FORMATS,
},
.ops = &cs42l73_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "cs42l73-asp",
@@ -1201,7 +1201,7 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
.formats = CS42L73_FORMATS,
},
.ops = &cs42l73_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "cs42l73-vsp",
@@ -1221,7 +1221,7 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
.formats = CS42L73_FORMATS,
},
.ops = &cs42l73_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
}
};
diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c
index 7fb34422a2a4..80bc7c10ed75 100644
--- a/sound/soc/codecs/cs43130.c
+++ b/sound/soc/codecs/cs43130.c
@@ -1581,7 +1581,7 @@ static struct snd_soc_dai_driver cs43130_dai[] = {
.formats = CS43130_PCM_FORMATS,
},
.ops = &cs43130_pcm_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "cs43130-asp-dop",
@@ -1594,7 +1594,7 @@ static struct snd_soc_dai_driver cs43130_dai[] = {
.formats = CS43130_DOP_FORMATS,
},
.ops = &cs43130_dop_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "cs43130-xsp-dop",
@@ -1607,7 +1607,7 @@ static struct snd_soc_dai_driver cs43130_dai[] = {
.formats = CS43130_DOP_FORMATS,
},
.ops = &cs43130_dop_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "cs43130-xsp-dsd",
diff --git a/sound/soc/codecs/cs4341.c b/sound/soc/codecs/cs4341.c
index f566604de78c..7d3e54d8eef3 100644
--- a/sound/soc/codecs/cs4341.c
+++ b/sound/soc/codecs/cs4341.c
@@ -189,7 +189,7 @@ static struct snd_soc_dai_driver cs4341_dai = {
SNDRV_PCM_FMTBIT_S24_LE,
},
.ops = &cs4341_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static const struct snd_soc_component_driver soc_component_cs4341 = {
diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c
index fd5526319779..786c69a8ec4a 100644
--- a/sound/soc/codecs/cs4349.c
+++ b/sound/soc/codecs/cs4349.c
@@ -250,7 +250,7 @@ static struct snd_soc_dai_driver cs4349_dai = {
.formats = CS4349_PCM_FORMATS,
},
.ops = &cs4349_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static const struct snd_soc_component_driver soc_component_dev_cs4349 = {
diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c
index 254f9d96e766..1ee83160b83f 100644
--- a/sound/soc/codecs/cs47l15.c
+++ b/sound/soc/codecs/cs47l15.c
@@ -1160,8 +1160,8 @@ static struct snd_soc_dai_driver cs47l15_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l15-aif2",
@@ -1182,8 +1182,8 @@ static struct snd_soc_dai_driver cs47l15_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l15-aif3",
@@ -1204,8 +1204,8 @@ static struct snd_soc_dai_driver cs47l15_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l15-cpu-trace",
diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c
index f6d173d0120e..eaabbb56a173 100644
--- a/sound/soc/codecs/cs47l24.c
+++ b/sound/soc/codecs/cs47l24.c
@@ -977,8 +977,8 @@ static struct snd_soc_dai_driver cs47l24_dai[] = {
.formats = CS47L24_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l24-aif2",
@@ -999,8 +999,8 @@ static struct snd_soc_dai_driver cs47l24_dai[] = {
.formats = CS47L24_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l24-aif3",
@@ -1021,8 +1021,8 @@ static struct snd_soc_dai_driver cs47l24_dai[] = {
.formats = CS47L24_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l24-cpu-voicectrl",
diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c
index e967609da8a3..3f04a2a74521 100644
--- a/sound/soc/codecs/cs47l35.c
+++ b/sound/soc/codecs/cs47l35.c
@@ -1368,8 +1368,8 @@ static struct snd_soc_dai_driver cs47l35_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l35-aif2",
@@ -1390,8 +1390,8 @@ static struct snd_soc_dai_driver cs47l35_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l35-aif3",
@@ -1412,8 +1412,8 @@ static struct snd_soc_dai_driver cs47l35_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l35-slim1",
diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c
index 47b16466b6c1..748a180870bc 100644
--- a/sound/soc/codecs/cs47l85.c
+++ b/sound/soc/codecs/cs47l85.c
@@ -2269,8 +2269,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l85-aif2",
@@ -2291,8 +2291,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l85-aif3",
@@ -2313,8 +2313,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l85-aif4",
@@ -2335,8 +2335,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l85-slim1",
diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c
index 8838dd557321..d2911c014b86 100644
--- a/sound/soc/codecs/cs47l90.c
+++ b/sound/soc/codecs/cs47l90.c
@@ -2188,8 +2188,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l90-aif2",
@@ -2210,8 +2210,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l90-aif3",
@@ -2232,8 +2232,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l90-aif4",
@@ -2254,8 +2254,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l90-slim1",
diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c
index 52dc29942ec2..1a0280416d92 100644
--- a/sound/soc/codecs/cs47l92.c
+++ b/sound/soc/codecs/cs47l92.c
@@ -1704,8 +1704,8 @@ static struct snd_soc_dai_driver cs47l92_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l92-aif2",
@@ -1726,8 +1726,8 @@ static struct snd_soc_dai_driver cs47l92_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l92-aif3",
@@ -1748,8 +1748,8 @@ static struct snd_soc_dai_driver cs47l92_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "cs47l92-slim1",
diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c
index ed22361b35c1..3d67cbf9eaaa 100644
--- a/sound/soc/codecs/cs53l30.c
+++ b/sound/soc/codecs/cs53l30.c
@@ -869,7 +869,7 @@ static struct snd_soc_dai_driver cs53l30_dai = {
.formats = CS53L30_FORMATS,
},
.ops = &cs53l30_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int cs53l30_component_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c
index 2f10991a8bdb..8ab22815c2c9 100644
--- a/sound/soc/codecs/cx2072x.c
+++ b/sound/soc/codecs/cx2072x.c
@@ -1572,7 +1572,7 @@ static struct snd_soc_dai_driver soc_codec_cx2072x_dai[] = {
.formats = CX2072X_FORMATS,
},
.ops = &cx2072x_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{ /* plabayck only, return echo reference to Conexant DSP chip */
.name = "cx2072x-dsp",
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index 3d05c37f676e..8af344b2fdbf 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -1059,7 +1059,7 @@ static struct snd_soc_dai_driver da7210_dai = {
.formats = DA7210_FORMATS,
},
.ops = &da7210_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int da7210_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c
index 72402467adcc..3ab89387b4e6 100644
--- a/sound/soc/codecs/da7213.c
+++ b/sound/soc/codecs/da7213.c
@@ -1551,7 +1551,7 @@ static struct snd_soc_dai_driver da7213_dai = {
.formats = DA7213_FORMATS,
},
.ops = &da7213_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int da7213_set_auto_pll(struct snd_soc_component *component, bool enable)
diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c
index 2bfafbe9e3dc..ea426d986d4c 100644
--- a/sound/soc/codecs/da7218.c
+++ b/sound/soc/codecs/da7218.c
@@ -2194,9 +2194,9 @@ static struct snd_soc_dai_driver da7218_dai = {
.formats = DA7218_FORMATS,
},
.ops = &da7218_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
.symmetric_channels = 1,
- .symmetric_samplebits = 1,
+ .symmetric_sample_bits = 1,
};
@@ -2278,14 +2278,12 @@ static irqreturn_t da7218_irq_thread(int irq, void *data)
* DT
*/
-#ifdef CONFIG_OF
static const struct of_device_id da7218_of_match[] = {
{ .compatible = "dlg,da7217", .data = (void *) DA7217_DEV_ID },
{ .compatible = "dlg,da7218", .data = (void *) DA7218_DEV_ID },
{ }
};
MODULE_DEVICE_TABLE(of, da7218_of_match);
-#endif
static inline int da7218_of_get_id(struct device *dev)
{
@@ -3311,7 +3309,7 @@ MODULE_DEVICE_TABLE(i2c, da7218_i2c_id);
static struct i2c_driver da7218_i2c_driver = {
.driver = {
.name = "da7218",
- .of_match_table = of_match_ptr(da7218_of_match),
+ .of_match_table = da7218_of_match,
},
.probe = da7218_i2c_probe,
.id_table = da7218_i2c_id,
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index e9b45daec0ca..13009d08b09a 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -1692,9 +1692,9 @@ static struct snd_soc_dai_driver da7219_dai = {
.formats = DA7219_FORMATS,
},
.ops = &da7219_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
.symmetric_channels = 1,
- .symmetric_samplebits = 1,
+ .symmetric_sample_bits = 1,
};
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c
index aed92f615b02..a9676b261129 100644
--- a/sound/soc/codecs/da9055.c
+++ b/sound/soc/codecs/da9055.c
@@ -1347,7 +1347,7 @@ static struct snd_soc_dai_driver da9055_dai = {
.formats = DA9055_FORMATS,
},
.ops = &da9055_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int da9055_set_bias_level(struct snd_soc_component *component,
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index f9ec5cf82599..d632055370e0 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -543,7 +543,7 @@ static struct snd_soc_dai_driver es8316_dai = {
.formats = ES8316_FORMATS,
},
.ops = &es8316_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static void es8316_enable_micbias_for_mic_gnd_short_detect(
@@ -681,6 +681,9 @@ static void es8316_disable_jack_detect(struct snd_soc_component *component)
{
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
+ if (!es8316->jack)
+ return; /* Already disabled (or never enabled) */
+
disable_irq(es8316->irq);
mutex_lock(&es8316->lock);
diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c
index 7e26231a596a..9632afc2d4d6 100644
--- a/sound/soc/codecs/es8328.c
+++ b/sound/soc/codecs/es8328.c
@@ -715,7 +715,7 @@ static struct snd_soc_dai_driver es8328_dai = {
.formats = ES8328_FORMATS,
},
.ops = &es8328_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int es8328_suspend(struct snd_soc_component *component)
@@ -809,8 +809,7 @@ static void es8328_remove(struct snd_soc_component *component)
es8328 = snd_soc_component_get_drvdata(component);
- if (es8328->clk)
- clk_disable_unprepare(es8328->clk);
+ clk_disable_unprepare(es8328->clk);
regulator_bulk_disable(ARRAY_SIZE(es8328->supplies),
es8328->supplies);
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 0f3ac22f2cf8..422539f933de 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -489,6 +489,7 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
hp.sample_rate = params_rate(params);
hp.channels = params_channels(params);
+ cf->bit_fmt = params_format(params);
return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data,
cf, &hp);
}
@@ -617,7 +618,8 @@ static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = {
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\
- SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
+ SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |\
+ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_dai *dai)
diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c
index 4dbce24c5f76..e05c4f27486e 100644
--- a/sound/soc/codecs/inno_rk3036.c
+++ b/sound/soc/codecs/inno_rk3036.c
@@ -325,7 +325,7 @@ static struct snd_soc_dai_driver rk3036_codec_dai_driver[] = {
.formats = RK3036_CODEC_FMTS,
},
.ops = &rk3036_codec_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index 5e58bfee2b49..081485f784e9 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -214,7 +214,7 @@ static struct snd_soc_dai_driver jz4740_codec_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
},
.ops = &jz4740_codec_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static void jz4740_codec_wakeup(struct regmap *regmap)
diff --git a/sound/soc/codecs/jz4760.c b/sound/soc/codecs/jz4760.c
new file mode 100644
index 000000000000..e8f28ccc145a
--- /dev/null
+++ b/sound/soc/codecs/jz4760.c
@@ -0,0 +1,889 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Ingenic JZ4760 CODEC driver
+//
+// Copyright (C) 2021, Christophe Branchereau <cbranchereau@gmail.com>
+// Copyright (C) 2021, Paul Cercueil <paul@crapouillou.net>
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/time64.h>
+
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+
+#define ICDC_RGADW_OFFSET 0x00
+#define ICDC_RGDATA_OFFSET 0x04
+
+/* ICDC internal register access control register(RGADW) */
+#define ICDC_RGADW_RGWR BIT(16)
+#define ICDC_RGADW_RGADDR_MASK GENMASK(14, 8)
+#define ICDC_RGADW_RGDIN_MASK GENMASK(7, 0)
+
+/* ICDC internal register data output register (RGDATA)*/
+#define ICDC_RGDATA_IRQ BIT(8)
+#define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, 0)
+
+/* Internal register space, accessed through regmap */
+enum {
+ JZ4760_CODEC_REG_SR,
+ JZ4760_CODEC_REG_AICR,
+ JZ4760_CODEC_REG_CR1,
+ JZ4760_CODEC_REG_CR2,
+ JZ4760_CODEC_REG_CR3,
+ JZ4760_CODEC_REG_CR4,
+ JZ4760_CODEC_REG_CCR1,
+ JZ4760_CODEC_REG_CCR2,
+ JZ4760_CODEC_REG_PMR1,
+ JZ4760_CODEC_REG_PMR2,
+ JZ4760_CODEC_REG_ICR,
+ JZ4760_CODEC_REG_IFR,
+ JZ4760_CODEC_REG_GCR1,
+ JZ4760_CODEC_REG_GCR2,
+ JZ4760_CODEC_REG_GCR3,
+ JZ4760_CODEC_REG_GCR4,
+ JZ4760_CODEC_REG_GCR5,
+ JZ4760_CODEC_REG_GCR6,
+ JZ4760_CODEC_REG_GCR7,
+ JZ4760_CODEC_REG_GCR8,
+ JZ4760_CODEC_REG_GCR9,
+ JZ4760_CODEC_REG_AGC1,
+ JZ4760_CODEC_REG_AGC2,
+ JZ4760_CODEC_REG_AGC3,
+ JZ4760_CODEC_REG_AGC4,
+ JZ4760_CODEC_REG_AGC5,
+ JZ4760_CODEC_REG_MIX1,
+ JZ4760_CODEC_REG_MIX2,
+};
+
+#define REG_AICR_DAC_ADWL_MASK GENMASK(7, 6)
+#define REG_AICR_DAC_SERIAL BIT(3)
+#define REG_AICR_DAC_I2S BIT(1)
+
+#define REG_AICR_ADC_ADWL_MASK GENMASK(5, 4)
+
+#define REG_AICR_ADC_SERIAL BIT(2)
+#define REG_AICR_ADC_I2S BIT(0)
+
+#define REG_CR1_HP_LOAD BIT(7)
+#define REG_CR1_HP_MUTE BIT(5)
+#define REG_CR1_LO_MUTE_OFFSET 4
+#define REG_CR1_BTL_MUTE_OFFSET 3
+#define REG_CR1_OUTSEL_OFFSET 0
+#define REG_CR1_OUTSEL_MASK GENMASK(1, REG_CR1_OUTSEL_OFFSET)
+
+#define REG_CR2_DAC_MONO BIT(7)
+#define REG_CR2_DAC_MUTE BIT(5)
+#define REG_CR2_DAC_NOMAD BIT(1)
+#define REG_CR2_DAC_RIGHT_ONLY BIT(0)
+
+#define REG_CR3_ADC_INSEL_OFFSET 2
+#define REG_CR3_ADC_INSEL_MASK GENMASK(3, REG_CR3_ADC_INSEL_OFFSET)
+#define REG_CR3_MICSTEREO_OFFSET 1
+#define REG_CR3_MICDIFF_OFFSET 0
+
+#define REG_CR4_ADC_HPF_OFFSET 7
+#define REG_CR4_ADC_RIGHT_ONLY BIT(0)
+
+#define REG_CCR1_CRYSTAL_MASK GENMASK(3, 0)
+
+#define REG_CCR2_DAC_FREQ_MASK GENMASK(7, 4)
+#define REG_CCR2_ADC_FREQ_MASK GENMASK(3, 0)
+
+#define REG_PMR1_SB BIT(7)
+#define REG_PMR1_SB_SLEEP BIT(6)
+#define REG_PMR1_SB_AIP_OFFSET 5
+#define REG_PMR1_SB_LINE_OFFSET 4
+#define REG_PMR1_SB_MIC1_OFFSET 3
+#define REG_PMR1_SB_MIC2_OFFSET 2
+#define REG_PMR1_SB_BYPASS_OFFSET 1
+#define REG_PMR1_SB_MICBIAS_OFFSET 0
+
+#define REG_PMR2_SB_ADC_OFFSET 4
+#define REG_PMR2_SB_HP_OFFSET 3
+#define REG_PMR2_SB_BTL_OFFSET 2
+#define REG_PMR2_SB_LOUT_OFFSET 1
+#define REG_PMR2_SB_DAC_OFFSET 0
+
+#define REG_ICR_INT_FORM_MASK GENMASK(7, 6)
+#define REG_ICR_ALL_MASK GENMASK(5, 0)
+#define REG_ICR_JACK_MASK BIT(5)
+#define REG_ICR_SCMC_MASK BIT(4)
+#define REG_ICR_RUP_MASK BIT(3)
+#define REG_ICR_RDO_MASK BIT(2)
+#define REG_ICR_GUP_MASK BIT(1)
+#define REG_ICR_GDO_MASK BIT(0)
+
+#define REG_IFR_ALL_MASK GENMASK(5, 0)
+#define REG_IFR_JACK BIT(6)
+#define REG_IFR_JACK_EVENT BIT(5)
+#define REG_IFR_SCMC BIT(4)
+#define REG_IFR_RUP BIT(3)
+#define REG_IFR_RDO BIT(2)
+#define REG_IFR_GUP BIT(1)
+#define REG_IFR_GDO BIT(0)
+
+#define REG_GCR_GAIN_OFFSET 0
+#define REG_GCR_GAIN_MAX 0x1f
+
+#define REG_GCR_RL BIT(7)
+
+#define REG_GCR_GIM1_MASK GENMASK(5, 3)
+#define REG_GCR_GIM2_MASK GENMASK(2, 0)
+#define REG_GCR_GIM_GAIN_MAX 7
+
+#define REG_AGC1_EN BIT(7)
+#define REG_AGC1_TARGET_MASK GENMASK(5, 2)
+
+#define REG_AGC2_NG_THR_MASK GENMASK(6, 4)
+#define REG_AGC2_HOLD_MASK GENMASK(3, 0)
+
+#define REG_AGC3_ATK_MASK GENMASK(7, 4)
+#define REG_AGC3_DCY_MASK GENMASK(3, 0)
+
+#define REG_AGC4_AGC_MAX_MASK GENMASK(4, 0)
+
+#define REG_AGC5_AGC_MIN_MASK GENMASK(4, 0)
+
+#define REG_MIX1_MIX_REC_MASK GENMASK(7, 6)
+#define REG_MIX1_GIMIX_MASK GENMASK(4, 0)
+
+#define REG_MIX2_DAC_MIX_MASK GENMASK(7, 6)
+#define REG_MIX2_GOMIX_MASK GENMASK(4, 0)
+
+/* codec private data */
+struct jz_codec {
+ struct device *dev;
+ struct regmap *regmap;
+ void __iomem *base;
+ struct clk *clk;
+};
+
+static int jz4760_codec_set_bias_level(struct snd_soc_component *codec,
+ enum snd_soc_bias_level level)
+{
+ struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
+ struct regmap *regmap = jz_codec->regmap;
+
+ switch (level) {
+ case SND_SOC_BIAS_PREPARE:
+ /* Reset all interrupt flags. */
+ regmap_write(regmap, JZ4760_CODEC_REG_IFR, REG_IFR_ALL_MASK);
+
+ regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB);
+ msleep(250);
+ regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP);
+ msleep(400);
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP);
+ regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int jz4760_codec_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *codec = dai->component;
+ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
+ int ret;
+
+ /*
+ * SYSCLK output from the codec to the AIC is required to keep the
+ * DMA transfer going during playback when all audible outputs have
+ * been disabled.
+ */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");
+ return 0;
+}
+
+static void jz4760_codec_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *codec = dai->component;
+ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_dapm_disable_pin(dapm, "SYSCLK");
+}
+
+
+static int jz4760_codec_pcm_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *codec = dai->component;
+ int ret = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_component_force_bias_level(codec, SND_SOC_BIAS_ON);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ /* do nothing */
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int jz4760_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
+{
+ struct snd_soc_component *codec = dai->component;
+ struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
+ unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP;
+ unsigned int val, reg;
+ int change, err;
+
+ change = snd_soc_component_update_bits(codec, JZ4760_CODEC_REG_CR2,
+ REG_CR2_DAC_MUTE,
+ mute ? REG_CR2_DAC_MUTE : 0);
+ if (change == 1) {
+ regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_PMR2, &val);
+
+ if (val & BIT(REG_PMR2_SB_DAC_OFFSET))
+ return 1;
+
+ err = regmap_read_poll_timeout(jz_codec->regmap,
+ JZ4760_CODEC_REG_IFR,
+ val, val & gain_bit,
+ 1000, 1 * USEC_PER_SEC);
+ if (err) {
+ dev_err(jz_codec->dev,
+ "Timeout while setting digital mute: %d", err);
+ return err;
+ }
+
+ /* clear GUP/GDO flag */
+ regmap_write(jz_codec->regmap, JZ4760_CODEC_REG_IFR, gain_bit);
+ }
+
+ regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_CR2, &reg);
+
+ return 0;
+}
+
+/* unit: 0.01dB */
+static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 100);
+static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
+static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 100);
+static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
+
+/* Unconditional controls. */
+static const struct snd_kcontrol_new jz4760_codec_snd_controls[] = {
+ /* record gain control */
+ SOC_DOUBLE_R_TLV("PCM Capture Volume",
+ JZ4760_CODEC_REG_GCR9, JZ4760_CODEC_REG_GCR8,
+ REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 0, adc_tlv),
+
+ SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume",
+ JZ4760_CODEC_REG_GCR4, JZ4760_CODEC_REG_GCR3,
+ REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv),
+
+ SOC_SINGLE("High-Pass Filter Capture Switch",
+ JZ4760_CODEC_REG_CR4,
+ REG_CR4_ADC_HPF_OFFSET, 1, 0),
+};
+
+static const struct snd_kcontrol_new jz4760_codec_pcm_playback_controls[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Volume",
+ .info = snd_soc_info_volsw,
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
+ | SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .tlv.p = dac_tlv,
+ .get = snd_soc_dapm_get_volsw,
+ .put = snd_soc_dapm_put_volsw,
+ .private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR6,
+ JZ4760_CODEC_REG_GCR5,
+ REG_GCR_GAIN_OFFSET,
+ REG_GCR_GAIN_MAX, 1),
+ },
+};
+
+static const struct snd_kcontrol_new jz4760_codec_hp_playback_controls[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Volume",
+ .info = snd_soc_info_volsw,
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
+ | SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .tlv.p = out_tlv,
+ .get = snd_soc_dapm_get_volsw,
+ .put = snd_soc_dapm_put_volsw,
+ .private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR2,
+ JZ4760_CODEC_REG_GCR1,
+ REG_GCR_GAIN_OFFSET,
+ REG_GCR_GAIN_MAX, 1),
+ },
+};
+
+static int hpout_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
+ struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
+ unsigned int val;
+ int err;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* unmute HP */
+ regmap_clear_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1,
+ REG_CR1_HP_MUTE);
+ break;
+
+ case SND_SOC_DAPM_POST_PMU:
+ /* wait for ramp-up complete (RUP) */
+ err = regmap_read_poll_timeout(jz_codec->regmap,
+ JZ4760_CODEC_REG_IFR,
+ val, val & REG_IFR_RUP,
+ 1000, 1 * USEC_PER_SEC);
+ if (err) {
+ dev_err(jz_codec->dev, "RUP timeout: %d", err);
+ return err;
+ }
+
+ /* clear RUP flag */
+ regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR,
+ REG_IFR_RUP);
+
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ /* mute HP */
+ regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1,
+ REG_CR1_HP_MUTE);
+
+ err = regmap_read_poll_timeout(jz_codec->regmap,
+ JZ4760_CODEC_REG_IFR,
+ val, val & REG_IFR_RDO,
+ 1000, 1 * USEC_PER_SEC);
+ if (err) {
+ dev_err(jz_codec->dev, "RDO timeout: %d", err);
+ return err;
+ }
+
+ /* clear RDO flag */
+ regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR,
+ REG_IFR_RDO);
+
+ break;
+ }
+
+ return 0;
+}
+
+static const char * const jz4760_codec_hp_texts[] = {
+ "PCM", "Line In", "Mic 1", "Mic 2"
+};
+
+static const unsigned int jz4760_codec_hp_values[] = { 3, 2, 0, 1 };
+
+static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_hp_enum,
+ JZ4760_CODEC_REG_CR1,
+ REG_CR1_OUTSEL_OFFSET,
+ REG_CR1_OUTSEL_MASK >> REG_CR1_OUTSEL_OFFSET,
+ jz4760_codec_hp_texts,
+ jz4760_codec_hp_values);
+static const struct snd_kcontrol_new jz4760_codec_hp_source =
+ SOC_DAPM_ENUM("Route", jz4760_codec_hp_enum);
+
+static const char * const jz4760_codec_cap_texts[] = {
+ "Line In", "Mic 1", "Mic 2"
+};
+
+static const unsigned int jz4760_codec_cap_values[] = { 2, 0, 1 };
+
+static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_cap_enum,
+ JZ4760_CODEC_REG_CR3,
+ REG_CR3_ADC_INSEL_OFFSET,
+ REG_CR3_ADC_INSEL_MASK >> REG_CR3_ADC_INSEL_OFFSET,
+ jz4760_codec_cap_texts,
+ jz4760_codec_cap_values);
+static const struct snd_kcontrol_new jz4760_codec_cap_source =
+ SOC_DAPM_ENUM("Route", jz4760_codec_cap_enum);
+
+static const struct snd_kcontrol_new jz4760_codec_mic_controls[] = {
+ SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4760_CODEC_REG_CR3,
+ REG_CR3_MICSTEREO_OFFSET, 1, 0),
+};
+
+static const struct snd_kcontrol_new jz4760_codec_line_out_switch =
+ SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1,
+ REG_CR1_LO_MUTE_OFFSET, 0, 0);
+static const struct snd_kcontrol_new jz4760_codec_btl_out_switch =
+ SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1,
+ REG_CR1_BTL_MUTE_OFFSET, 0, 0);
+
+static const struct snd_soc_dapm_widget jz4760_codec_dapm_widgets[] = {
+ SND_SOC_DAPM_PGA_E("HP Out", JZ4760_CODEC_REG_PMR2,
+ REG_PMR2_SB_HP_OFFSET, 1, NULL, 0, hpout_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SWITCH("Line Out", JZ4760_CODEC_REG_PMR2,
+ REG_PMR2_SB_LOUT_OFFSET, 1,
+ &jz4760_codec_line_out_switch),
+
+ SND_SOC_DAPM_SWITCH("BTL Out", JZ4760_CODEC_REG_PMR2,
+ REG_PMR2_SB_BTL_OFFSET, 1,
+ &jz4760_codec_btl_out_switch),
+
+ SND_SOC_DAPM_PGA("Line In", JZ4760_CODEC_REG_PMR1,
+ REG_PMR1_SB_LINE_OFFSET, 1, NULL, 0),
+
+ SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,
+ &jz4760_codec_hp_source),
+
+ SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
+ &jz4760_codec_cap_source),
+
+ SND_SOC_DAPM_PGA("Mic 1", JZ4760_CODEC_REG_PMR1,
+ REG_PMR1_SB_MIC1_OFFSET, 1, NULL, 0),
+
+ SND_SOC_DAPM_PGA("Mic 2", JZ4760_CODEC_REG_PMR1,
+ REG_PMR1_SB_MIC2_OFFSET, 1, NULL, 0),
+
+ SND_SOC_DAPM_PGA("Mic Diff", JZ4760_CODEC_REG_CR3,
+ REG_CR3_MICDIFF_OFFSET, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
+ jz4760_codec_mic_controls,
+ ARRAY_SIZE(jz4760_codec_mic_controls)),
+
+ SND_SOC_DAPM_PGA("Line In Bypass", JZ4760_CODEC_REG_PMR1,
+ REG_PMR1_SB_BYPASS_OFFSET, 1, NULL, 0),
+
+ SND_SOC_DAPM_ADC("ADC", "Capture", JZ4760_CODEC_REG_PMR2,
+ REG_PMR2_SB_ADC_OFFSET, 1),
+
+ SND_SOC_DAPM_DAC("DAC", "Playback", JZ4760_CODEC_REG_PMR2,
+ REG_PMR2_SB_DAC_OFFSET, 1),
+
+ SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,
+ jz4760_codec_pcm_playback_controls,
+ ARRAY_SIZE(jz4760_codec_pcm_playback_controls)),
+
+ SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,
+ jz4760_codec_hp_playback_controls,
+ ARRAY_SIZE(jz4760_codec_hp_playback_controls)),
+
+ SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4760_CODEC_REG_PMR1,
+ REG_PMR1_SB_MICBIAS_OFFSET, 1, NULL, 0),
+
+ SND_SOC_DAPM_INPUT("MIC1P"),
+ SND_SOC_DAPM_INPUT("MIC1N"),
+ SND_SOC_DAPM_INPUT("MIC2P"),
+ SND_SOC_DAPM_INPUT("MIC2N"),
+
+ SND_SOC_DAPM_INPUT("LLINEIN"),
+ SND_SOC_DAPM_INPUT("RLINEIN"),
+
+ SND_SOC_DAPM_OUTPUT("LHPOUT"),
+ SND_SOC_DAPM_OUTPUT("RHPOUT"),
+
+ SND_SOC_DAPM_OUTPUT("LOUT"),
+ SND_SOC_DAPM_OUTPUT("ROUT"),
+
+ SND_SOC_DAPM_OUTPUT("BTLP"),
+ SND_SOC_DAPM_OUTPUT("BTLN"),
+
+ SND_SOC_DAPM_OUTPUT("SYSCLK"),
+};
+
+/* Unconditional routes. */
+static const struct snd_soc_dapm_route jz4760_codec_dapm_routes[] = {
+ { "Mic 1", NULL, "MIC1P" },
+ { "Mic Diff", NULL, "MIC1N" },
+ { "Mic 1", NULL, "Mic Diff" },
+ { "Mic 2", NULL, "MIC2P" },
+ { "Mic Diff", NULL, "MIC2N" },
+ { "Mic 2", NULL, "Mic Diff" },
+
+ { "Line In", NULL, "LLINEIN" },
+ { "Line In", NULL, "RLINEIN" },
+
+ { "Mic", "Stereo Capture Switch", "Mic 1" },
+ { "Mic", "Stereo Capture Switch", "Mic 2" },
+ { "Headphones Source", "Mic 1", "Mic" },
+ { "Headphones Source", "Mic 2", "Mic" },
+ { "Capture Source", "Mic 1", "Mic" },
+ { "Capture Source", "Mic 2", "Mic" },
+
+ { "Capture Source", "Line In", "Line In" },
+ { "Capture Source", "Mic 1", "Mic 1" },
+ { "Capture Source", "Mic 2", "Mic 2" },
+ { "ADC", NULL, "Capture Source" },
+
+ { "Line In Bypass", NULL, "Line In" },
+
+ { "Headphones Source", "Mic 1", "Mic 1" },
+ { "Headphones Source", "Mic 2", "Mic 2" },
+ { "Headphones Source", "Line In", "Line In Bypass" },
+ { "Headphones Source", "PCM", "Headphones Playback" },
+ { "HP Out", NULL, "Headphones Source" },
+
+ { "LHPOUT", NULL, "HP Out" },
+ { "RHPOUT", NULL, "HP Out" },
+ { "Line Out", "Switch", "HP Out" },
+
+ { "LOUT", NULL, "Line Out" },
+ { "ROUT", NULL, "Line Out" },
+ { "BTL Out", "Switch", "Line Out" },
+
+ { "BTLP", NULL, "BTL Out"},
+ { "BTLN", NULL, "BTL Out"},
+
+ { "PCM Playback", "Volume", "DAC" },
+ { "Headphones Playback", "Volume", "PCM Playback" },
+
+ { "SYSCLK", NULL, "DAC" },
+};
+
+static void jz4760_codec_codec_init_regs(struct snd_soc_component *codec)
+{
+ struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
+ struct regmap *regmap = jz_codec->regmap;
+
+ /* Collect updates for later sending. */
+ regcache_cache_only(regmap, true);
+
+ /* default Amp output to PCM */
+ regmap_set_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_OUTSEL_MASK);
+
+ /* Disable stereo mic */
+ regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3,
+ BIT(REG_CR3_MICSTEREO_OFFSET));
+
+ /* Set mic 1 as default source for ADC */
+ regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3,
+ REG_CR3_ADC_INSEL_MASK);
+
+ /* ADC/DAC: serial + i2s */
+ regmap_set_bits(regmap, JZ4760_CODEC_REG_AICR,
+ REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S |
+ REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);
+
+ /* The generated IRQ is a high level */
+ regmap_clear_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_INT_FORM_MASK);
+ regmap_update_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_ALL_MASK,
+ REG_ICR_JACK_MASK | REG_ICR_RUP_MASK |
+ REG_ICR_RDO_MASK | REG_ICR_GUP_MASK |
+ REG_ICR_GDO_MASK);
+
+ /* 12M oscillator */
+ regmap_clear_bits(regmap, JZ4760_CODEC_REG_CCR1, REG_CCR1_CRYSTAL_MASK);
+
+ /* 0: 16ohm/220uF, 1: 10kohm/1uF */
+ regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_HP_LOAD);
+
+ /* default to NOMAD */
+ regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR2,
+ REG_CR2_DAC_NOMAD);
+
+ /* disable automatic gain */
+ regmap_clear_bits(regmap, JZ4760_CODEC_REG_AGC1, REG_AGC1_EN);
+
+ /* Independent L/R DAC gain control */
+ regmap_clear_bits(regmap, JZ4760_CODEC_REG_GCR5,
+ REG_GCR_RL);
+
+ /* Send collected updates. */
+ regcache_cache_only(regmap, false);
+ regcache_sync(regmap);
+}
+
+static int jz4760_codec_codec_probe(struct snd_soc_component *codec)
+{
+ struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
+
+ clk_prepare_enable(jz_codec->clk);
+
+ jz4760_codec_codec_init_regs(codec);
+
+ return 0;
+}
+
+static void jz4760_codec_codec_remove(struct snd_soc_component *codec)
+{
+ struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
+
+ clk_disable_unprepare(jz_codec->clk);
+}
+
+static const struct snd_soc_component_driver jz4760_codec_soc_codec_dev = {
+ .probe = jz4760_codec_codec_probe,
+ .remove = jz4760_codec_codec_remove,
+ .set_bias_level = jz4760_codec_set_bias_level,
+ .controls = jz4760_codec_snd_controls,
+ .num_controls = ARRAY_SIZE(jz4760_codec_snd_controls),
+ .dapm_widgets = jz4760_codec_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(jz4760_codec_dapm_widgets),
+ .dapm_routes = jz4760_codec_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(jz4760_codec_dapm_routes),
+ .suspend_bias_off = 1,
+ .use_pmdown_time = 1,
+};
+
+static const unsigned int jz4760_codec_sample_rates[] = {
+ 96000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000,
+ 11025, 9600, 8000,
+};
+
+static int jz4760_codec_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
+ unsigned int rate, bit_width;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ bit_width = 0;
+ break;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ bit_width = 1;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ bit_width = 2;
+ break;
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ bit_width = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (rate = 0; rate < ARRAY_SIZE(jz4760_codec_sample_rates); rate++) {
+ if (jz4760_codec_sample_rates[rate] == params_rate(params))
+ break;
+ }
+
+ if (rate == ARRAY_SIZE(jz4760_codec_sample_rates))
+ return -EINVAL;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR,
+ REG_AICR_DAC_ADWL_MASK,
+ FIELD_PREP(REG_AICR_DAC_ADWL_MASK, bit_width));
+ regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2,
+ REG_CCR2_DAC_FREQ_MASK,
+ FIELD_PREP(REG_CCR2_DAC_FREQ_MASK, rate));
+ } else {
+ regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR,
+ REG_AICR_ADC_ADWL_MASK,
+ FIELD_PREP(REG_AICR_ADC_ADWL_MASK, bit_width));
+ regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2,
+ REG_CCR2_ADC_FREQ_MASK,
+ FIELD_PREP(REG_CCR2_ADC_FREQ_MASK, rate));
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops jz4760_codec_dai_ops = {
+ .startup = jz4760_codec_startup,
+ .shutdown = jz4760_codec_shutdown,
+ .hw_params = jz4760_codec_hw_params,
+ .trigger = jz4760_codec_pcm_trigger,
+ .mute_stream = jz4760_codec_mute_stream,
+ .no_capture_mute = 1,
+};
+
+#define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S18_3LE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_3LE)
+
+static struct snd_soc_dai_driver jz4760_codec_dai = {
+ .name = "jz4760-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = JZ_CODEC_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = JZ_CODEC_FORMATS,
+ },
+ .ops = &jz4760_codec_dai_ops,
+};
+
+static bool jz4760_codec_volatile(struct device *dev, unsigned int reg)
+{
+ return reg == JZ4760_CODEC_REG_SR || reg == JZ4760_CODEC_REG_IFR;
+}
+
+static bool jz4760_codec_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case JZ4760_CODEC_REG_SR:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static int jz4760_codec_io_wait(struct jz_codec *codec)
+{
+ u32 reg;
+
+ return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
+ !(reg & ICDC_RGADW_RGWR),
+ 1000, 1 * USEC_PER_SEC);
+}
+
+static int jz4760_codec_reg_read(void *context, unsigned int reg,
+ unsigned int *val)
+{
+ struct jz_codec *codec = context;
+ unsigned int i;
+ u32 tmp;
+ int ret;
+
+ ret = jz4760_codec_io_wait(codec);
+ if (ret)
+ return ret;
+
+ tmp = readl(codec->base + ICDC_RGADW_OFFSET);
+ tmp &= ~ICDC_RGADW_RGADDR_MASK;
+ tmp |= FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg);
+ writel(tmp, codec->base + ICDC_RGADW_OFFSET);
+
+ /* wait 6+ cycles */
+ for (i = 0; i < 6; i++)
+ *val = readl(codec->base + ICDC_RGDATA_OFFSET) &
+ ICDC_RGDATA_RGDOUT_MASK;
+
+ return 0;
+}
+
+static int jz4760_codec_reg_write(void *context, unsigned int reg,
+ unsigned int val)
+{
+ struct jz_codec *codec = context;
+ int ret;
+
+ ret = jz4760_codec_io_wait(codec);
+ if (ret)
+ return ret;
+
+ writel(ICDC_RGADW_RGWR | FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg) | val,
+ codec->base + ICDC_RGADW_OFFSET);
+
+ ret = jz4760_codec_io_wait(codec);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const u8 jz4760_codec_reg_defaults[] = {
+ 0x00, 0xFC, 0x1B, 0x20, 0x00, 0x80, 0x00, 0x00,
+ 0xFF, 0x1F, 0x3F, 0x00, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x07, 0x44,
+ 0x1F, 0x00, 0x00, 0x00
+};
+
+static struct regmap_config jz4760_codec_regmap_config = {
+ .reg_bits = 7,
+ .val_bits = 8,
+
+ .max_register = JZ4760_CODEC_REG_MIX2,
+ .volatile_reg = jz4760_codec_volatile,
+ .writeable_reg = jz4760_codec_writeable,
+
+ .reg_read = jz4760_codec_reg_read,
+ .reg_write = jz4760_codec_reg_write,
+
+ .reg_defaults_raw = jz4760_codec_reg_defaults,
+ .num_reg_defaults_raw = ARRAY_SIZE(jz4760_codec_reg_defaults),
+ .cache_type = REGCACHE_FLAT,
+};
+
+static int jz4760_codec_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct jz_codec *codec;
+ int ret;
+
+ codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
+ if (!codec)
+ return -ENOMEM;
+
+ codec->dev = dev;
+
+ codec->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(codec->base)) {
+ ret = PTR_ERR(codec->base);
+ dev_err(dev, "Failed to ioremap mmio memory: %d\n", ret);
+ return ret;
+ }
+
+ codec->regmap = devm_regmap_init(dev, NULL, codec,
+ &jz4760_codec_regmap_config);
+ if (IS_ERR(codec->regmap))
+ return PTR_ERR(codec->regmap);
+
+ codec->clk = devm_clk_get(dev, "aic");
+ if (IS_ERR(codec->clk))
+ return PTR_ERR(codec->clk);
+
+ platform_set_drvdata(pdev, codec);
+
+ ret = devm_snd_soc_register_component(dev, &jz4760_codec_soc_codec_dev,
+ &jz4760_codec_dai, 1);
+ if (ret) {
+ dev_err(dev, "Failed to register codec: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id jz4760_codec_of_matches[] = {
+ { .compatible = "ingenic,jz4760-codec", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, jz4760_codec_of_matches);
+
+static struct platform_driver jz4760_codec_driver = {
+ .probe = jz4760_codec_probe,
+ .driver = {
+ .name = "jz4760-codec",
+ .of_match_table = jz4760_codec_of_matches,
+ },
+};
+module_platform_driver(jz4760_codec_driver);
+
+MODULE_DESCRIPTION("JZ4760 SoC internal codec driver");
+MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");
+MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c
index 06ab61f6f719..eb3dd0bd80d9 100644
--- a/sound/soc/codecs/lm49453.c
+++ b/sound/soc/codecs/lm49453.c
@@ -1343,7 +1343,7 @@ static struct snd_soc_dai_driver lm49453_dai[] = {
.formats = LM49453_FORMATS,
},
.ops = &lm49453_headset_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "LM49453 Speaker",
diff --git a/sound/soc/codecs/lochnagar-sc.c b/sound/soc/codecs/lochnagar-sc.c
index 3209b39e46af..54426a90bc0b 100644
--- a/sound/soc/codecs/lochnagar-sc.c
+++ b/sound/soc/codecs/lochnagar-sc.c
@@ -166,8 +166,8 @@ static struct snd_soc_dai_driver lochnagar_sc_dai[] = {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &lochnagar_sc_line_ops,
- .symmetric_rates = true,
- .symmetric_samplebits = true,
+ .symmetric_rate = true,
+ .symmetric_sample_bits = true,
},
{
.name = "lochnagar-usb1",
@@ -186,8 +186,8 @@ static struct snd_soc_dai_driver lochnagar_sc_dai[] = {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &lochnagar_sc_usb_ops,
- .symmetric_rates = true,
- .symmetric_samplebits = true,
+ .symmetric_rate = true,
+ .symmetric_sample_bits = true,
},
{
.name = "lochnagar-usb2",
@@ -206,8 +206,8 @@ static struct snd_soc_dai_driver lochnagar_sc_dai[] = {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &lochnagar_sc_usb_ops,
- .symmetric_rates = true,
- .symmetric_samplebits = true,
+ .symmetric_rate = true,
+ .symmetric_sample_bits = true,
},
};
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c
new file mode 100644
index 000000000000..c9c21d22c2c4
--- /dev/null
+++ b/sound/soc/codecs/lpass-rx-macro.c
@@ -0,0 +1,3599 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <linux/of_clk.h>
+#include <linux/clk-provider.h>
+
+#define CDC_RX_TOP_TOP_CFG0 (0x0000)
+#define CDC_RX_TOP_SWR_CTRL (0x0008)
+#define CDC_RX_TOP_DEBUG (0x000C)
+#define CDC_RX_TOP_DEBUG_BUS (0x0010)
+#define CDC_RX_TOP_DEBUG_EN0 (0x0014)
+#define CDC_RX_TOP_DEBUG_EN1 (0x0018)
+#define CDC_RX_TOP_DEBUG_EN2 (0x001C)
+#define CDC_RX_TOP_HPHL_COMP_WR_LSB (0x0020)
+#define CDC_RX_TOP_HPHL_COMP_WR_MSB (0x0024)
+#define CDC_RX_TOP_HPHL_COMP_LUT (0x0028)
+#define CDC_RX_TOP_HPH_LUT_BYPASS_MASK BIT(7)
+#define CDC_RX_TOP_HPHL_COMP_RD_LSB (0x002C)
+#define CDC_RX_TOP_HPHL_COMP_RD_MSB (0x0030)
+#define CDC_RX_TOP_HPHR_COMP_WR_LSB (0x0034)
+#define CDC_RX_TOP_HPHR_COMP_WR_MSB (0x0038)
+#define CDC_RX_TOP_HPHR_COMP_LUT (0x003C)
+#define CDC_RX_TOP_HPHR_COMP_RD_LSB (0x0040)
+#define CDC_RX_TOP_HPHR_COMP_RD_MSB (0x0044)
+#define CDC_RX_TOP_DSD0_DEBUG_CFG0 (0x0070)
+#define CDC_RX_TOP_DSD0_DEBUG_CFG1 (0x0074)
+#define CDC_RX_TOP_DSD0_DEBUG_CFG2 (0x0078)
+#define CDC_RX_TOP_DSD0_DEBUG_CFG3 (0x007C)
+#define CDC_RX_TOP_DSD1_DEBUG_CFG0 (0x0080)
+#define CDC_RX_TOP_DSD1_DEBUG_CFG1 (0x0084)
+#define CDC_RX_TOP_DSD1_DEBUG_CFG2 (0x0088)
+#define CDC_RX_TOP_DSD1_DEBUG_CFG3 (0x008C)
+#define CDC_RX_TOP_RX_I2S_CTL (0x0090)
+#define CDC_RX_TOP_TX_I2S2_CTL (0x0094)
+#define CDC_RX_TOP_I2S_CLK (0x0098)
+#define CDC_RX_TOP_I2S_RESET (0x009C)
+#define CDC_RX_TOP_I2S_MUX (0x00A0)
+#define CDC_RX_CLK_RST_CTRL_MCLK_CONTROL (0x0100)
+#define CDC_RX_CLK_MCLK_EN_MASK BIT(0)
+#define CDC_RX_CLK_MCLK_ENABLE BIT(0)
+#define CDC_RX_CLK_MCLK2_EN_MASK BIT(1)
+#define CDC_RX_CLK_MCLK2_ENABLE BIT(1)
+#define CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL (0x0104)
+#define CDC_RX_FS_MCLK_CNT_EN_MASK BIT(0)
+#define CDC_RX_FS_MCLK_CNT_ENABLE BIT(0)
+#define CDC_RX_FS_MCLK_CNT_CLR_MASK BIT(1)
+#define CDC_RX_FS_MCLK_CNT_CLR BIT(1)
+#define CDC_RX_CLK_RST_CTRL_SWR_CONTROL (0x0108)
+#define CDC_RX_SWR_CLK_EN_MASK BIT(0)
+#define CDC_RX_SWR_RESET_MASK BIT(1)
+#define CDC_RX_SWR_RESET BIT(1)
+#define CDC_RX_CLK_RST_CTRL_DSD_CONTROL (0x010C)
+#define CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL (0x0110)
+#define CDC_RX_SOFTCLIP_CRC (0x0140)
+#define CDC_RX_SOFTCLIP_CLK_EN_MASK BIT(0)
+#define CDC_RX_SOFTCLIP_SOFTCLIP_CTRL (0x0144)
+#define CDC_RX_SOFTCLIP_EN_MASK BIT(0)
+#define CDC_RX_INP_MUX_RX_INT0_CFG0 (0x0180)
+#define CDC_RX_INTX_1_MIX_INP0_SEL_MASK GENMASK(3, 0)
+#define CDC_RX_INTX_1_MIX_INP1_SEL_MASK GENMASK(7, 4)
+#define CDC_RX_INP_MUX_RX_INT0_CFG1 (0x0184)
+#define CDC_RX_INTX_2_SEL_MASK GENMASK(3, 0)
+#define CDC_RX_INTX_1_MIX_INP2_SEL_MASK GENMASK(7, 4)
+#define CDC_RX_INP_MUX_RX_INT1_CFG0 (0x0188)
+#define CDC_RX_INP_MUX_RX_INT1_CFG1 (0x018C)
+#define CDC_RX_INP_MUX_RX_INT2_CFG0 (0x0190)
+#define CDC_RX_INP_MUX_RX_INT2_CFG1 (0x0194)
+#define CDC_RX_INP_MUX_RX_MIX_CFG4 (0x0198)
+#define CDC_RX_INP_MUX_RX_MIX_CFG5 (0x019C)
+#define CDC_RX_INP_MUX_SIDETONE_SRC_CFG0 (0x01A0)
+#define CDC_RX_CLSH_CRC (0x0200)
+#define CDC_RX_CLSH_CLK_EN_MASK BIT(0)
+#define CDC_RX_CLSH_DLY_CTRL (0x0204)
+#define CDC_RX_CLSH_DECAY_CTRL (0x0208)
+#define CDC_RX_CLSH_DECAY_RATE_MASK GENMASK(2, 0)
+#define CDC_RX_CLSH_HPH_V_PA (0x020C)
+#define CDC_RX_CLSH_HPH_V_PA_MIN_MASK GENMASK(5, 0)
+#define CDC_RX_CLSH_EAR_V_PA (0x0210)
+#define CDC_RX_CLSH_HPH_V_HD (0x0214)
+#define CDC_RX_CLSH_EAR_V_HD (0x0218)
+#define CDC_RX_CLSH_K1_MSB (0x021C)
+#define CDC_RX_CLSH_K1_MSB_COEFF_MASK GENMASK(3, 0)
+#define CDC_RX_CLSH_K1_LSB (0x0220)
+#define CDC_RX_CLSH_K2_MSB (0x0224)
+#define CDC_RX_CLSH_K2_LSB (0x0228)
+#define CDC_RX_CLSH_IDLE_CTRL (0x022C)
+#define CDC_RX_CLSH_IDLE_HPH (0x0230)
+#define CDC_RX_CLSH_IDLE_EAR (0x0234)
+#define CDC_RX_CLSH_TEST0 (0x0238)
+#define CDC_RX_CLSH_TEST1 (0x023C)
+#define CDC_RX_CLSH_OVR_VREF (0x0240)
+#define CDC_RX_CLSH_CLSG_CTL (0x0244)
+#define CDC_RX_CLSH_CLSG_CFG1 (0x0248)
+#define CDC_RX_CLSH_CLSG_CFG2 (0x024C)
+#define CDC_RX_BCL_VBAT_PATH_CTL (0x0280)
+#define CDC_RX_BCL_VBAT_CFG (0x0284)
+#define CDC_RX_BCL_VBAT_ADC_CAL1 (0x0288)
+#define CDC_RX_BCL_VBAT_ADC_CAL2 (0x028C)
+#define CDC_RX_BCL_VBAT_ADC_CAL3 (0x0290)
+#define CDC_RX_BCL_VBAT_PK_EST1 (0x0294)
+#define CDC_RX_BCL_VBAT_PK_EST2 (0x0298)
+#define CDC_RX_BCL_VBAT_PK_EST3 (0x029C)
+#define CDC_RX_BCL_VBAT_RF_PROC1 (0x02A0)
+#define CDC_RX_BCL_VBAT_RF_PROC2 (0x02A4)
+#define CDC_RX_BCL_VBAT_TAC1 (0x02A8)
+#define CDC_RX_BCL_VBAT_TAC2 (0x02AC)
+#define CDC_RX_BCL_VBAT_TAC3 (0x02B0)
+#define CDC_RX_BCL_VBAT_TAC4 (0x02B4)
+#define CDC_RX_BCL_VBAT_GAIN_UPD1 (0x02B8)
+#define CDC_RX_BCL_VBAT_GAIN_UPD2 (0x02BC)
+#define CDC_RX_BCL_VBAT_GAIN_UPD3 (0x02C0)
+#define CDC_RX_BCL_VBAT_GAIN_UPD4 (0x02C4)
+#define CDC_RX_BCL_VBAT_GAIN_UPD5 (0x02C8)
+#define CDC_RX_BCL_VBAT_DEBUG1 (0x02CC)
+#define CDC_RX_BCL_VBAT_GAIN_UPD_MON (0x02D0)
+#define CDC_RX_BCL_VBAT_GAIN_MON_VAL (0x02D4)
+#define CDC_RX_BCL_VBAT_BAN (0x02D8)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD1 (0x02DC)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD2 (0x02E0)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD3 (0x02E4)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD4 (0x02E8)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD5 (0x02EC)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD6 (0x02F0)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD7 (0x02F4)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD8 (0x02F8)
+#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD9 (0x02FC)
+#define CDC_RX_BCL_VBAT_ATTN1 (0x0300)
+#define CDC_RX_BCL_VBAT_ATTN2 (0x0304)
+#define CDC_RX_BCL_VBAT_ATTN3 (0x0308)
+#define CDC_RX_BCL_VBAT_DECODE_CTL1 (0x030C)
+#define CDC_RX_BCL_VBAT_DECODE_CTL2 (0x0310)
+#define CDC_RX_BCL_VBAT_DECODE_CFG1 (0x0314)
+#define CDC_RX_BCL_VBAT_DECODE_CFG2 (0x0318)
+#define CDC_RX_BCL_VBAT_DECODE_CFG3 (0x031C)
+#define CDC_RX_BCL_VBAT_DECODE_CFG4 (0x0320)
+#define CDC_RX_BCL_VBAT_DECODE_ST (0x0324)
+#define CDC_RX_INTR_CTRL_CFG (0x0340)
+#define CDC_RX_INTR_CTRL_CLR_COMMIT (0x0344)
+#define CDC_RX_INTR_CTRL_PIN1_MASK0 (0x0360)
+#define CDC_RX_INTR_CTRL_PIN1_STATUS0 (0x0368)
+#define CDC_RX_INTR_CTRL_PIN1_CLEAR0 (0x0370)
+#define CDC_RX_INTR_CTRL_PIN2_MASK0 (0x0380)
+#define CDC_RX_INTR_CTRL_PIN2_STATUS0 (0x0388)
+#define CDC_RX_INTR_CTRL_PIN2_CLEAR0 (0x0390)
+#define CDC_RX_INTR_CTRL_LEVEL0 (0x03C0)
+#define CDC_RX_INTR_CTRL_BYPASS0 (0x03C8)
+#define CDC_RX_INTR_CTRL_SET0 (0x03D0)
+#define CDC_RX_RXn_RX_PATH_CTL(n) (0x0400 + 0x80 * n)
+#define CDC_RX_RX0_RX_PATH_CTL (0x0400)
+#define CDC_RX_PATH_RESET_EN_MASK BIT(6)
+#define CDC_RX_PATH_CLK_EN_MASK BIT(5)
+#define CDC_RX_PATH_CLK_ENABLE BIT(5)
+#define CDC_RX_PATH_PGA_MUTE_MASK BIT(4)
+#define CDC_RX_PATH_PGA_MUTE_ENABLE BIT(4)
+#define CDC_RX_PATH_PCM_RATE_MASK GENMASK(3, 0)
+#define CDC_RX_RXn_RX_PATH_CFG0(n) (0x0404 + 0x80 * n)
+#define CDC_RX_RXn_COMP_EN_MASK BIT(1)
+#define CDC_RX_RX0_RX_PATH_CFG0 (0x0404)
+#define CDC_RX_RXn_CLSH_EN_MASK BIT(6)
+#define CDC_RX_DLY_ZN_EN_MASK BIT(3)
+#define CDC_RX_DLY_ZN_ENABLE BIT(3)
+#define CDC_RX_RXn_HD2_EN_MASK BIT(2)
+#define CDC_RX_RXn_RX_PATH_CFG1(n) (0x0408 + 0x80 * n)
+#define CDC_RX_RXn_SIDETONE_EN_MASK BIT(4)
+#define CDC_RX_RX0_RX_PATH_CFG1 (0x0408)
+#define CDC_RX_RX0_HPH_L_EAR_SEL_MASK BIT(1)
+#define CDC_RX_RXn_RX_PATH_CFG2(n) (0x040C + 0x80 * n)
+#define CDC_RX_RXn_HPF_CUT_FREQ_MASK GENMASK(1, 0)
+#define CDC_RX_RX0_RX_PATH_CFG2 (0x040C)
+#define CDC_RX_RXn_RX_PATH_CFG3(n) (0x0410 + 0x80 * n)
+#define CDC_RX_RX0_RX_PATH_CFG3 (0x0410)
+#define CDC_RX_DC_COEFF_SEL_MASK GENMASK(1, 0)
+#define CDC_RX_DC_COEFF_SEL_TWO 0x2
+#define CDC_RX_RXn_RX_VOL_CTL(n) (0x0414 + 0x80 * n)
+#define CDC_RX_RX0_RX_VOL_CTL (0x0414)
+#define CDC_RX_RXn_RX_PATH_MIX_CTL(n) (0x0418 + 0x80 * n)
+#define CDC_RX_RXn_MIX_PCM_RATE_MASK GENMASK(3, 0)
+#define CDC_RX_RXn_MIX_RESET_MASK BIT(6)
+#define CDC_RX_RXn_MIX_RESET BIT(6)
+#define CDC_RX_RXn_MIX_CLK_EN_MASK BIT(5)
+#define CDC_RX_RX0_RX_PATH_MIX_CTL (0x0418)
+#define CDC_RX_RX0_RX_PATH_MIX_CFG (0x041C)
+#define CDC_RX_RXn_RX_VOL_MIX_CTL(n) (0x0420 + 0x80 * n)
+#define CDC_RX_RX0_RX_VOL_MIX_CTL (0x0420)
+#define CDC_RX_RX0_RX_PATH_SEC1 (0x0424)
+#define CDC_RX_RX0_RX_PATH_SEC2 (0x0428)
+#define CDC_RX_RX0_RX_PATH_SEC3 (0x042C)
+#define CDC_RX_RX0_RX_PATH_SEC4 (0x0430)
+#define CDC_RX_RX0_RX_PATH_SEC7 (0x0434)
+#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(n) (0x0440 + 0x80 * n)
+#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)
+#define CDC_RX_RX0_RX_PATH_DSM_DATA2 (0x0448)
+#define CDC_RX_RX0_RX_PATH_DSM_DATA3 (0x044C)
+#define CDC_RX_RX0_RX_PATH_DSM_DATA4 (0x0450)
+#define CDC_RX_RX0_RX_PATH_DSM_DATA5 (0x0454)
+#define CDC_RX_RX0_RX_PATH_DSM_DATA6 (0x0458)
+#define CDC_RX_RX1_RX_PATH_CTL (0x0480)
+#define CDC_RX_RX1_RX_PATH_CFG0 (0x0484)
+#define CDC_RX_RX1_RX_PATH_CFG1 (0x0488)
+#define CDC_RX_RX1_RX_PATH_CFG2 (0x048C)
+#define CDC_RX_RX1_RX_PATH_CFG3 (0x0490)
+#define CDC_RX_RX1_RX_VOL_CTL (0x0494)
+#define CDC_RX_RX1_RX_PATH_MIX_CTL (0x0498)
+#define CDC_RX_RX1_RX_PATH_MIX_CFG (0x049C)
+#define CDC_RX_RX1_RX_VOL_MIX_CTL (0x04A0)
+#define CDC_RX_RX1_RX_PATH_SEC1 (0x04A4)
+#define CDC_RX_RX1_RX_PATH_SEC2 (0x04A8)
+#define CDC_RX_RX1_RX_PATH_SEC3 (0x04AC)
+#define CDC_RX_RXn_HD2_ALPHA_MASK GENMASK(5, 2)
+#define CDC_RX_RX1_RX_PATH_SEC4 (0x04B0)
+#define CDC_RX_RX1_RX_PATH_SEC7 (0x04B4)
+#define CDC_RX_RX1_RX_PATH_MIX_SEC0 (0x04B8)
+#define CDC_RX_RX1_RX_PATH_MIX_SEC1 (0x04BC)
+#define CDC_RX_RX1_RX_PATH_DSM_CTL (0x04C0)
+#define CDC_RX_RX1_RX_PATH_DSM_DATA1 (0x04C4)
+#define CDC_RX_RX1_RX_PATH_DSM_DATA2 (0x04C8)
+#define CDC_RX_RX1_RX_PATH_DSM_DATA3 (0x04CC)
+#define CDC_RX_RX1_RX_PATH_DSM_DATA4 (0x04D0)
+#define CDC_RX_RX1_RX_PATH_DSM_DATA5 (0x04D4)
+#define CDC_RX_RX1_RX_PATH_DSM_DATA6 (0x04D8)
+#define CDC_RX_RX2_RX_PATH_CTL (0x0500)
+#define CDC_RX_RX2_RX_PATH_CFG0 (0x0504)
+#define CDC_RX_RX2_CLSH_EN_MASK BIT(4)
+#define CDC_RX_RX2_DLY_Z_EN_MASK BIT(3)
+#define CDC_RX_RX2_RX_PATH_CFG1 (0x0508)
+#define CDC_RX_RX2_RX_PATH_CFG2 (0x050C)
+#define CDC_RX_RX2_RX_PATH_CFG3 (0x0510)
+#define CDC_RX_RX2_RX_VOL_CTL (0x0514)
+#define CDC_RX_RX2_RX_PATH_MIX_CTL (0x0518)
+#define CDC_RX_RX2_RX_PATH_MIX_CFG (0x051C)
+#define CDC_RX_RX2_RX_VOL_MIX_CTL (0x0520)
+#define CDC_RX_RX2_RX_PATH_SEC0 (0x0524)
+#define CDC_RX_RX2_RX_PATH_SEC1 (0x0528)
+#define CDC_RX_RX2_RX_PATH_SEC2 (0x052C)
+#define CDC_RX_RX2_RX_PATH_SEC3 (0x0530)
+#define CDC_RX_RX2_RX_PATH_SEC4 (0x0534)
+#define CDC_RX_RX2_RX_PATH_SEC5 (0x0538)
+#define CDC_RX_RX2_RX_PATH_SEC6 (0x053C)
+#define CDC_RX_RX2_RX_PATH_SEC7 (0x0540)
+#define CDC_RX_RX2_RX_PATH_MIX_SEC0 (0x0544)
+#define CDC_RX_RX2_RX_PATH_MIX_SEC1 (0x0548)
+#define CDC_RX_RX2_RX_PATH_DSM_CTL (0x054C)
+#define CDC_RX_IDLE_DETECT_PATH_CTL (0x0780)
+#define CDC_RX_IDLE_DETECT_CFG0 (0x0784)
+#define CDC_RX_IDLE_DETECT_CFG1 (0x0788)
+#define CDC_RX_IDLE_DETECT_CFG2 (0x078C)
+#define CDC_RX_IDLE_DETECT_CFG3 (0x0790)
+#define CDC_RX_COMPANDERn_CTL0(n) (0x0800 + 0x40 * n)
+#define CDC_RX_COMPANDERn_CLK_EN_MASK BIT(0)
+#define CDC_RX_COMPANDERn_SOFT_RST_MASK BIT(1)
+#define CDC_RX_COMPANDERn_HALT_MASK BIT(2)
+#define CDC_RX_COMPANDER0_CTL0 (0x0800)
+#define CDC_RX_COMPANDER0_CTL1 (0x0804)
+#define CDC_RX_COMPANDER0_CTL2 (0x0808)
+#define CDC_RX_COMPANDER0_CTL3 (0x080C)
+#define CDC_RX_COMPANDER0_CTL4 (0x0810)
+#define CDC_RX_COMPANDER0_CTL5 (0x0814)
+#define CDC_RX_COMPANDER0_CTL6 (0x0818)
+#define CDC_RX_COMPANDER0_CTL7 (0x081C)
+#define CDC_RX_COMPANDER1_CTL0 (0x0840)
+#define CDC_RX_COMPANDER1_CTL1 (0x0844)
+#define CDC_RX_COMPANDER1_CTL2 (0x0848)
+#define CDC_RX_COMPANDER1_CTL3 (0x084C)
+#define CDC_RX_COMPANDER1_CTL4 (0x0850)
+#define CDC_RX_COMPANDER1_CTL5 (0x0854)
+#define CDC_RX_COMPANDER1_CTL6 (0x0858)
+#define CDC_RX_COMPANDER1_CTL7 (0x085C)
+#define CDC_RX_COMPANDER1_HPH_LOW_PWR_MODE_MASK BIT(5)
+#define CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL (0x0A00)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL (0x0A04)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL (0x0A08)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL (0x0A0C)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL (0x0A10)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL (0x0A14)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL (0x0A18)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL (0x0A1C)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL (0x0A20)
+#define CDC_RX_SIDETONE_IIR0_IIR_CTL (0x0A24)
+#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL (0x0A28)
+#define CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL (0x0A2C)
+#define CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL (0x0A30)
+#define CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL (0x0A80)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL (0x0A84)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL (0x0A88)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL (0x0A8C)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL (0x0A90)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL (0x0A94)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL (0x0A98)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL (0x0A9C)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL (0x0AA0)
+#define CDC_RX_SIDETONE_IIR1_IIR_CTL (0x0AA4)
+#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL (0x0AA8)
+#define CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL (0x0AAC)
+#define CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL (0x0AB0)
+#define CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0 (0x0B00)
+#define CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1 (0x0B04)
+#define CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2 (0x0B08)
+#define CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3 (0x0B0C)
+#define CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0 (0x0B10)
+#define CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1 (0x0B14)
+#define CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2 (0x0B18)
+#define CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3 (0x0B1C)
+#define CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL (0x0B40)
+#define CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1 (0x0B44)
+#define CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL (0x0B50)
+#define CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1 (0x0B54)
+#define CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL (0x0C00)
+#define CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0 (0x0C04)
+#define CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL (0x0C40)
+#define CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0 (0x0C44)
+#define CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL (0x0C80)
+#define CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0 (0x0C84)
+#define CDC_RX_EC_ASRC0_CLK_RST_CTL (0x0D00)
+#define CDC_RX_EC_ASRC0_CTL0 (0x0D04)
+#define CDC_RX_EC_ASRC0_CTL1 (0x0D08)
+#define CDC_RX_EC_ASRC0_FIFO_CTL (0x0D0C)
+#define CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB (0x0D10)
+#define CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB (0x0D14)
+#define CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB (0x0D18)
+#define CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB (0x0D1C)
+#define CDC_RX_EC_ASRC0_STATUS_FIFO (0x0D20)
+#define CDC_RX_EC_ASRC1_CLK_RST_CTL (0x0D40)
+#define CDC_RX_EC_ASRC1_CTL0 (0x0D44)
+#define CDC_RX_EC_ASRC1_CTL1 (0x0D48)
+#define CDC_RX_EC_ASRC1_FIFO_CTL (0x0D4C)
+#define CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB (0x0D50)
+#define CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB (0x0D54)
+#define CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB (0x0D58)
+#define CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB (0x0D5C)
+#define CDC_RX_EC_ASRC1_STATUS_FIFO (0x0D60)
+#define CDC_RX_EC_ASRC2_CLK_RST_CTL (0x0D80)
+#define CDC_RX_EC_ASRC2_CTL0 (0x0D84)
+#define CDC_RX_EC_ASRC2_CTL1 (0x0D88)
+#define CDC_RX_EC_ASRC2_FIFO_CTL (0x0D8C)
+#define CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB (0x0D90)
+#define CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB (0x0D94)
+#define CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB (0x0D98)
+#define CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB (0x0D9C)
+#define CDC_RX_EC_ASRC2_STATUS_FIFO (0x0DA0)
+#define CDC_RX_DSD0_PATH_CTL (0x0F00)
+#define CDC_RX_DSD0_CFG0 (0x0F04)
+#define CDC_RX_DSD0_CFG1 (0x0F08)
+#define CDC_RX_DSD0_CFG2 (0x0F0C)
+#define CDC_RX_DSD1_PATH_CTL (0x0F80)
+#define CDC_RX_DSD1_CFG0 (0x0F84)
+#define CDC_RX_DSD1_CFG1 (0x0F88)
+#define CDC_RX_DSD1_CFG2 (0x0F8C)
+#define RX_MAX_OFFSET (0x0F8C)
+
+#define MCLK_FREQ 9600000
+
+#define RX_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
+ SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\
+ SNDRV_PCM_RATE_384000)
+/* Fractional Rates */
+#define RX_MACRO_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\
+ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800)
+
+#define RX_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+#define RX_MACRO_ECHO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_48000)
+#define RX_MACRO_ECHO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S24_3LE)
+
+#define RX_MACRO_MAX_DMA_CH_PER_PORT 2
+
+#define RX_MACRO_EC_MIX_TX0_MASK 0xf0
+#define RX_MACRO_EC_MIX_TX1_MASK 0x0f
+#define RX_MACRO_EC_MIX_TX2_MASK 0x0f
+
+#define COMP_MAX_COEFF 25
+#define RX_NUM_CLKS_MAX 5
+
+struct comp_coeff_val {
+ u8 lsb;
+ u8 msb;
+};
+
+enum {
+ HPH_ULP,
+ HPH_LOHIFI,
+ HPH_MODE_MAX,
+};
+
+static const struct comp_coeff_val comp_coeff_table[HPH_MODE_MAX][COMP_MAX_COEFF] = {
+ {
+ {0x40, 0x00},
+ {0x4C, 0x00},
+ {0x5A, 0x00},
+ {0x6B, 0x00},
+ {0x7F, 0x00},
+ {0x97, 0x00},
+ {0xB3, 0x00},
+ {0xD5, 0x00},
+ {0xFD, 0x00},
+ {0x2D, 0x01},
+ {0x66, 0x01},
+ {0xA7, 0x01},
+ {0xF8, 0x01},
+ {0x57, 0x02},
+ {0xC7, 0x02},
+ {0x4B, 0x03},
+ {0xE9, 0x03},
+ {0xA3, 0x04},
+ {0x7D, 0x05},
+ {0x90, 0x06},
+ {0xD1, 0x07},
+ {0x49, 0x09},
+ {0x00, 0x0B},
+ {0x01, 0x0D},
+ {0x59, 0x0F},
+ },
+ {
+ {0x40, 0x00},
+ {0x4C, 0x00},
+ {0x5A, 0x00},
+ {0x6B, 0x00},
+ {0x80, 0x00},
+ {0x98, 0x00},
+ {0xB4, 0x00},
+ {0xD5, 0x00},
+ {0xFE, 0x00},
+ {0x2E, 0x01},
+ {0x66, 0x01},
+ {0xA9, 0x01},
+ {0xF8, 0x01},
+ {0x56, 0x02},
+ {0xC4, 0x02},
+ {0x4F, 0x03},
+ {0xF0, 0x03},
+ {0xAE, 0x04},
+ {0x8B, 0x05},
+ {0x8E, 0x06},
+ {0xBC, 0x07},
+ {0x56, 0x09},
+ {0x0F, 0x0B},
+ {0x13, 0x0D},
+ {0x6F, 0x0F},
+ },
+};
+
+struct rx_macro_reg_mask_val {
+ u16 reg;
+ u8 mask;
+ u8 val;
+};
+
+enum {
+ INTERP_HPHL,
+ INTERP_HPHR,
+ INTERP_AUX,
+ INTERP_MAX
+};
+
+enum {
+ RX_MACRO_RX0,
+ RX_MACRO_RX1,
+ RX_MACRO_RX2,
+ RX_MACRO_RX3,
+ RX_MACRO_RX4,
+ RX_MACRO_RX5,
+ RX_MACRO_PORTS_MAX
+};
+
+enum {
+ RX_MACRO_COMP1, /* HPH_L */
+ RX_MACRO_COMP2, /* HPH_R */
+ RX_MACRO_COMP_MAX
+};
+
+enum {
+ RX_MACRO_EC0_MUX = 0,
+ RX_MACRO_EC1_MUX,
+ RX_MACRO_EC2_MUX,
+ RX_MACRO_EC_MUX_MAX,
+};
+
+enum {
+ INTn_1_INP_SEL_ZERO = 0,
+ INTn_1_INP_SEL_DEC0,
+ INTn_1_INP_SEL_DEC1,
+ INTn_1_INP_SEL_IIR0,
+ INTn_1_INP_SEL_IIR1,
+ INTn_1_INP_SEL_RX0,
+ INTn_1_INP_SEL_RX1,
+ INTn_1_INP_SEL_RX2,
+ INTn_1_INP_SEL_RX3,
+ INTn_1_INP_SEL_RX4,
+ INTn_1_INP_SEL_RX5,
+};
+
+enum {
+ INTn_2_INP_SEL_ZERO = 0,
+ INTn_2_INP_SEL_RX0,
+ INTn_2_INP_SEL_RX1,
+ INTn_2_INP_SEL_RX2,
+ INTn_2_INP_SEL_RX3,
+ INTn_2_INP_SEL_RX4,
+ INTn_2_INP_SEL_RX5,
+};
+
+enum {
+ INTERP_MAIN_PATH,
+ INTERP_MIX_PATH,
+};
+
+/* Codec supports 2 IIR filters */
+enum {
+ IIR0 = 0,
+ IIR1,
+ IIR_MAX,
+};
+
+/* Each IIR has 5 Filter Stages */
+enum {
+ BAND1 = 0,
+ BAND2,
+ BAND3,
+ BAND4,
+ BAND5,
+ BAND_MAX,
+};
+
+#define RX_MACRO_IIR_FILTER_SIZE (sizeof(u32) * BAND_MAX)
+
+#define RX_MACRO_IIR_FILTER_CTL(xname, iidx, bidx) \
+{ \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = rx_macro_iir_filter_info, \
+ .get = rx_macro_get_iir_band_audio_mixer, \
+ .put = rx_macro_put_iir_band_audio_mixer, \
+ .private_value = (unsigned long)&(struct wcd_iir_filter_ctl) { \
+ .iir_idx = iidx, \
+ .band_idx = bidx, \
+ .bytes_ext = {.max = RX_MACRO_IIR_FILTER_SIZE, }, \
+ } \
+}
+
+struct interp_sample_rate {
+ int sample_rate;
+ int rate_val;
+};
+
+static struct interp_sample_rate sr_val_tbl[] = {
+ {8000, 0x0}, {16000, 0x1}, {32000, 0x3}, {48000, 0x4}, {96000, 0x5},
+ {192000, 0x6}, {384000, 0x7}, {44100, 0x9}, {88200, 0xA},
+ {176400, 0xB}, {352800, 0xC},
+};
+
+enum {
+ RX_MACRO_AIF_INVALID = 0,
+ RX_MACRO_AIF1_PB,
+ RX_MACRO_AIF2_PB,
+ RX_MACRO_AIF3_PB,
+ RX_MACRO_AIF4_PB,
+ RX_MACRO_AIF_ECHO,
+ RX_MACRO_MAX_DAIS,
+};
+
+enum {
+ RX_MACRO_AIF1_CAP = 0,
+ RX_MACRO_AIF2_CAP,
+ RX_MACRO_AIF3_CAP,
+ RX_MACRO_MAX_AIF_CAP_DAIS
+};
+
+struct rx_macro {
+ struct device *dev;
+ int comp_enabled[RX_MACRO_COMP_MAX];
+ /* Main path clock users count */
+ int main_clk_users[INTERP_MAX];
+ int rx_port_value[RX_MACRO_PORTS_MAX];
+ u16 prim_int_users[INTERP_MAX];
+ int rx_mclk_users;
+ bool reset_swr;
+ int clsh_users;
+ int rx_mclk_cnt;
+ bool is_ear_mode_on;
+ bool hph_pwr_mode;
+ bool hph_hd2_mode;
+ struct snd_soc_component *component;
+ unsigned long active_ch_mask[RX_MACRO_MAX_DAIS];
+ unsigned long active_ch_cnt[RX_MACRO_MAX_DAIS];
+ u16 bit_width[RX_MACRO_MAX_DAIS];
+ int is_softclip_on;
+ int is_aux_hpf_on;
+ int softclip_clk_users;
+
+ struct regmap *regmap;
+ struct clk_bulk_data clks[RX_NUM_CLKS_MAX];
+ struct clk_hw hw;
+};
+#define to_rx_macro(_hw) container_of(_hw, struct rx_macro, hw)
+
+struct wcd_iir_filter_ctl {
+ unsigned int iir_idx;
+ unsigned int band_idx;
+ struct soc_bytes_ext bytes_ext;
+};
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400);
+
+static const char * const rx_int_mix_mux_text[] = {
+ "ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5"
+};
+
+static const char * const rx_prim_mix_text[] = {
+ "ZERO", "DEC0", "DEC1", "IIR0", "IIR1", "RX0", "RX1", "RX2",
+ "RX3", "RX4", "RX5"
+};
+
+static const char * const rx_sidetone_mix_text[] = {
+ "ZERO", "SRC0", "SRC1", "SRC_SUM"
+};
+
+static const char * const iir_inp_mux_text[] = {
+ "ZERO", "DEC0", "DEC1", "DEC2", "DEC3",
+ "RX0", "RX1", "RX2", "RX3", "RX4", "RX5"
+};
+
+static const char * const rx_int_dem_inp_mux_text[] = {
+ "NORMAL_DSM_OUT", "CLSH_DSM_OUT",
+};
+
+static const char * const rx_int0_1_interp_mux_text[] = {
+ "ZERO", "RX INT0_1 MIX1",
+};
+
+static const char * const rx_int1_1_interp_mux_text[] = {
+ "ZERO", "RX INT1_1 MIX1",
+};
+
+static const char * const rx_int2_1_interp_mux_text[] = {
+ "ZERO", "RX INT2_1 MIX1",
+};
+
+static const char * const rx_int0_2_interp_mux_text[] = {
+ "ZERO", "RX INT0_2 MUX",
+};
+
+static const char * const rx_int1_2_interp_mux_text[] = {
+ "ZERO", "RX INT1_2 MUX",
+};
+
+static const char * const rx_int2_2_interp_mux_text[] = {
+ "ZERO", "RX INT2_2 MUX",
+};
+
+static const char *const rx_macro_mux_text[] = {
+ "ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB", "AIF4_PB"
+};
+
+static const char *const rx_macro_hph_pwr_mode_text[] = {
+ "ULP", "LOHIFI"
+};
+
+static const char * const rx_echo_mux_text[] = {
+ "ZERO", "RX_MIX0", "RX_MIX1", "RX_MIX2"
+};
+
+static const struct soc_enum rx_macro_hph_pwr_mode_enum =
+ SOC_ENUM_SINGLE_EXT(2, rx_macro_hph_pwr_mode_text);
+static const struct soc_enum rx_mix_tx2_mux_enum =
+ SOC_ENUM_SINGLE(CDC_RX_INP_MUX_RX_MIX_CFG5, 0, 4, rx_echo_mux_text);
+static const struct soc_enum rx_mix_tx1_mux_enum =
+ SOC_ENUM_SINGLE(CDC_RX_INP_MUX_RX_MIX_CFG4, 0, 4, rx_echo_mux_text);
+static const struct soc_enum rx_mix_tx0_mux_enum =
+ SOC_ENUM_SINGLE(CDC_RX_INP_MUX_RX_MIX_CFG4, 4, 4, rx_echo_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(rx_int0_2_enum, CDC_RX_INP_MUX_RX_INT0_CFG1, 0,
+ rx_int_mix_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_2_enum, CDC_RX_INP_MUX_RX_INT1_CFG1, 0,
+ rx_int_mix_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_2_enum, CDC_RX_INP_MUX_RX_INT2_CFG1, 0,
+ rx_int_mix_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(rx_int0_1_mix_inp0_enum, CDC_RX_INP_MUX_RX_INT0_CFG0, 0,
+ rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int0_1_mix_inp1_enum, CDC_RX_INP_MUX_RX_INT0_CFG0, 4,
+ rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int0_1_mix_inp2_enum, CDC_RX_INP_MUX_RX_INT0_CFG1, 4,
+ rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_1_mix_inp0_enum, CDC_RX_INP_MUX_RX_INT1_CFG0, 0,
+ rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_1_mix_inp1_enum, CDC_RX_INP_MUX_RX_INT1_CFG0, 4,
+ rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_1_mix_inp2_enum, CDC_RX_INP_MUX_RX_INT1_CFG1, 4,
+ rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_1_mix_inp0_enum, CDC_RX_INP_MUX_RX_INT2_CFG0, 0,
+ rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_1_mix_inp1_enum, CDC_RX_INP_MUX_RX_INT2_CFG0, 4,
+ rx_prim_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_1_mix_inp2_enum, CDC_RX_INP_MUX_RX_INT2_CFG1, 4,
+ rx_prim_mix_text);
+
+static SOC_ENUM_SINGLE_DECL(rx_int0_mix2_inp_enum, CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2,
+ rx_sidetone_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_mix2_inp_enum, CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4,
+ rx_sidetone_mix_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_mix2_inp_enum, CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 6,
+ rx_sidetone_mix_text);
+static SOC_ENUM_SINGLE_DECL(iir0_inp0_enum, CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0, 0,
+ iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir0_inp1_enum, CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1, 0,
+ iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir0_inp2_enum, CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2, 0,
+ iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir0_inp3_enum, CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3, 0,
+ iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir1_inp0_enum, CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0, 0,
+ iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir1_inp1_enum, CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1, 0,
+ iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir1_inp2_enum, CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2, 0,
+ iir_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(iir1_inp3_enum, CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3, 0,
+ iir_inp_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(rx_int0_1_interp_enum, SND_SOC_NOPM, 0,
+ rx_int0_1_interp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_1_interp_enum, SND_SOC_NOPM, 0,
+ rx_int1_1_interp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_1_interp_enum, SND_SOC_NOPM, 0,
+ rx_int2_1_interp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int0_2_interp_enum, SND_SOC_NOPM, 0,
+ rx_int0_2_interp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_2_interp_enum, SND_SOC_NOPM, 0,
+ rx_int1_2_interp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int2_2_interp_enum, SND_SOC_NOPM, 0,
+ rx_int2_2_interp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int0_dem_inp_enum, CDC_RX_RX0_RX_PATH_CFG1, 0,
+ rx_int_dem_inp_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_int1_dem_inp_enum, CDC_RX_RX1_RX_PATH_CFG1, 0,
+ rx_int_dem_inp_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(rx_macro_rx0_enum, SND_SOC_NOPM, 0, rx_macro_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_macro_rx1_enum, SND_SOC_NOPM, 0, rx_macro_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_macro_rx2_enum, SND_SOC_NOPM, 0, rx_macro_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_macro_rx3_enum, SND_SOC_NOPM, 0, rx_macro_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_macro_rx4_enum, SND_SOC_NOPM, 0, rx_macro_mux_text);
+static SOC_ENUM_SINGLE_DECL(rx_macro_rx5_enum, SND_SOC_NOPM, 0, rx_macro_mux_text);
+
+static const struct snd_kcontrol_new rx_mix_tx1_mux =
+ SOC_DAPM_ENUM("RX MIX TX1_MUX Mux", rx_mix_tx1_mux_enum);
+static const struct snd_kcontrol_new rx_mix_tx2_mux =
+ SOC_DAPM_ENUM("RX MIX TX2_MUX Mux", rx_mix_tx2_mux_enum);
+static const struct snd_kcontrol_new rx_int0_2_mux =
+ SOC_DAPM_ENUM("rx_int0_2", rx_int0_2_enum);
+static const struct snd_kcontrol_new rx_int1_2_mux =
+ SOC_DAPM_ENUM("rx_int1_2", rx_int1_2_enum);
+static const struct snd_kcontrol_new rx_int2_2_mux =
+ SOC_DAPM_ENUM("rx_int2_2", rx_int2_2_enum);
+static const struct snd_kcontrol_new rx_int0_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("rx_int0_1_mix_inp0", rx_int0_1_mix_inp0_enum);
+static const struct snd_kcontrol_new rx_int0_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("rx_int0_1_mix_inp1", rx_int0_1_mix_inp1_enum);
+static const struct snd_kcontrol_new rx_int0_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("rx_int0_1_mix_inp2", rx_int0_1_mix_inp2_enum);
+static const struct snd_kcontrol_new rx_int1_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("rx_int1_1_mix_inp0", rx_int1_1_mix_inp0_enum);
+static const struct snd_kcontrol_new rx_int1_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("rx_int1_1_mix_inp1", rx_int1_1_mix_inp1_enum);
+static const struct snd_kcontrol_new rx_int1_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("rx_int1_1_mix_inp2", rx_int1_1_mix_inp2_enum);
+static const struct snd_kcontrol_new rx_int2_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("rx_int2_1_mix_inp0", rx_int2_1_mix_inp0_enum);
+static const struct snd_kcontrol_new rx_int2_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("rx_int2_1_mix_inp1", rx_int2_1_mix_inp1_enum);
+static const struct snd_kcontrol_new rx_int2_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("rx_int2_1_mix_inp2", rx_int2_1_mix_inp2_enum);
+static const struct snd_kcontrol_new rx_int0_mix2_inp_mux =
+ SOC_DAPM_ENUM("rx_int0_mix2_inp", rx_int0_mix2_inp_enum);
+static const struct snd_kcontrol_new rx_int1_mix2_inp_mux =
+ SOC_DAPM_ENUM("rx_int1_mix2_inp", rx_int1_mix2_inp_enum);
+static const struct snd_kcontrol_new rx_int2_mix2_inp_mux =
+ SOC_DAPM_ENUM("rx_int2_mix2_inp", rx_int2_mix2_inp_enum);
+static const struct snd_kcontrol_new iir0_inp0_mux =
+ SOC_DAPM_ENUM("iir0_inp0", iir0_inp0_enum);
+static const struct snd_kcontrol_new iir0_inp1_mux =
+ SOC_DAPM_ENUM("iir0_inp1", iir0_inp1_enum);
+static const struct snd_kcontrol_new iir0_inp2_mux =
+ SOC_DAPM_ENUM("iir0_inp2", iir0_inp2_enum);
+static const struct snd_kcontrol_new iir0_inp3_mux =
+ SOC_DAPM_ENUM("iir0_inp3", iir0_inp3_enum);
+static const struct snd_kcontrol_new iir1_inp0_mux =
+ SOC_DAPM_ENUM("iir1_inp0", iir1_inp0_enum);
+static const struct snd_kcontrol_new iir1_inp1_mux =
+ SOC_DAPM_ENUM("iir1_inp1", iir1_inp1_enum);
+static const struct snd_kcontrol_new iir1_inp2_mux =
+ SOC_DAPM_ENUM("iir1_inp2", iir1_inp2_enum);
+static const struct snd_kcontrol_new iir1_inp3_mux =
+ SOC_DAPM_ENUM("iir1_inp3", iir1_inp3_enum);
+static const struct snd_kcontrol_new rx_int0_1_interp_mux =
+ SOC_DAPM_ENUM("rx_int0_1_interp", rx_int0_1_interp_enum);
+static const struct snd_kcontrol_new rx_int1_1_interp_mux =
+ SOC_DAPM_ENUM("rx_int1_1_interp", rx_int1_1_interp_enum);
+static const struct snd_kcontrol_new rx_int2_1_interp_mux =
+ SOC_DAPM_ENUM("rx_int2_1_interp", rx_int2_1_interp_enum);
+static const struct snd_kcontrol_new rx_int0_2_interp_mux =
+ SOC_DAPM_ENUM("rx_int0_2_interp", rx_int0_2_interp_enum);
+static const struct snd_kcontrol_new rx_int1_2_interp_mux =
+ SOC_DAPM_ENUM("rx_int1_2_interp", rx_int1_2_interp_enum);
+static const struct snd_kcontrol_new rx_int2_2_interp_mux =
+ SOC_DAPM_ENUM("rx_int2_2_interp", rx_int2_2_interp_enum);
+static const struct snd_kcontrol_new rx_mix_tx0_mux =
+ SOC_DAPM_ENUM("RX MIX TX0_MUX Mux", rx_mix_tx0_mux_enum);
+
+static const struct reg_default rx_defaults[] = {
+ /* RX Macro */
+ { CDC_RX_TOP_TOP_CFG0, 0x00 },
+ { CDC_RX_TOP_SWR_CTRL, 0x00 },
+ { CDC_RX_TOP_DEBUG, 0x00 },
+ { CDC_RX_TOP_DEBUG_BUS, 0x00 },
+ { CDC_RX_TOP_DEBUG_EN0, 0x00 },
+ { CDC_RX_TOP_DEBUG_EN1, 0x00 },
+ { CDC_RX_TOP_DEBUG_EN2, 0x00 },
+ { CDC_RX_TOP_HPHL_COMP_WR_LSB, 0x00 },
+ { CDC_RX_TOP_HPHL_COMP_WR_MSB, 0x00 },
+ { CDC_RX_TOP_HPHL_COMP_LUT, 0x00 },
+ { CDC_RX_TOP_HPHL_COMP_RD_LSB, 0x00 },
+ { CDC_RX_TOP_HPHL_COMP_RD_MSB, 0x00 },
+ { CDC_RX_TOP_HPHR_COMP_WR_LSB, 0x00 },
+ { CDC_RX_TOP_HPHR_COMP_WR_MSB, 0x00 },
+ { CDC_RX_TOP_HPHR_COMP_LUT, 0x00 },
+ { CDC_RX_TOP_HPHR_COMP_RD_LSB, 0x00 },
+ { CDC_RX_TOP_HPHR_COMP_RD_MSB, 0x00 },
+ { CDC_RX_TOP_DSD0_DEBUG_CFG0, 0x11 },
+ { CDC_RX_TOP_DSD0_DEBUG_CFG1, 0x20 },
+ { CDC_RX_TOP_DSD0_DEBUG_CFG2, 0x00 },
+ { CDC_RX_TOP_DSD0_DEBUG_CFG3, 0x00 },
+ { CDC_RX_TOP_DSD1_DEBUG_CFG0, 0x11 },
+ { CDC_RX_TOP_DSD1_DEBUG_CFG1, 0x20 },
+ { CDC_RX_TOP_DSD1_DEBUG_CFG2, 0x00 },
+ { CDC_RX_TOP_DSD1_DEBUG_CFG3, 0x00 },
+ { CDC_RX_TOP_RX_I2S_CTL, 0x0C },
+ { CDC_RX_TOP_TX_I2S2_CTL, 0x0C },
+ { CDC_RX_TOP_I2S_CLK, 0x0C },
+ { CDC_RX_TOP_I2S_RESET, 0x00 },
+ { CDC_RX_TOP_I2S_MUX, 0x00 },
+ { CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, 0x00 },
+ { CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00 },
+ { CDC_RX_CLK_RST_CTRL_SWR_CONTROL, 0x00 },
+ { CDC_RX_CLK_RST_CTRL_DSD_CONTROL, 0x00 },
+ { CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL, 0x08 },
+ { CDC_RX_SOFTCLIP_CRC, 0x00 },
+ { CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x38 },
+ { CDC_RX_INP_MUX_RX_INT0_CFG0, 0x00 },
+ { CDC_RX_INP_MUX_RX_INT0_CFG1, 0x00 },
+ { CDC_RX_INP_MUX_RX_INT1_CFG0, 0x00 },
+ { CDC_RX_INP_MUX_RX_INT1_CFG1, 0x00 },
+ { CDC_RX_INP_MUX_RX_INT2_CFG0, 0x00 },
+ { CDC_RX_INP_MUX_RX_INT2_CFG1, 0x00 },
+ { CDC_RX_INP_MUX_RX_MIX_CFG4, 0x00 },
+ { CDC_RX_INP_MUX_RX_MIX_CFG5, 0x00 },
+ { CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 0x00 },
+ { CDC_RX_CLSH_CRC, 0x00 },
+ { CDC_RX_CLSH_DLY_CTRL, 0x03 },
+ { CDC_RX_CLSH_DECAY_CTRL, 0x02 },
+ { CDC_RX_CLSH_HPH_V_PA, 0x1C },
+ { CDC_RX_CLSH_EAR_V_PA, 0x39 },
+ { CDC_RX_CLSH_HPH_V_HD, 0x0C },
+ { CDC_RX_CLSH_EAR_V_HD, 0x0C },
+ { CDC_RX_CLSH_K1_MSB, 0x01 },
+ { CDC_RX_CLSH_K1_LSB, 0x00 },
+ { CDC_RX_CLSH_K2_MSB, 0x00 },
+ { CDC_RX_CLSH_K2_LSB, 0x80 },
+ { CDC_RX_CLSH_IDLE_CTRL, 0x00 },
+ { CDC_RX_CLSH_IDLE_HPH, 0x00 },
+ { CDC_RX_CLSH_IDLE_EAR, 0x00 },
+ { CDC_RX_CLSH_TEST0, 0x07 },
+ { CDC_RX_CLSH_TEST1, 0x00 },
+ { CDC_RX_CLSH_OVR_VREF, 0x00 },
+ { CDC_RX_CLSH_CLSG_CTL, 0x02 },
+ { CDC_RX_CLSH_CLSG_CFG1, 0x9A },
+ { CDC_RX_CLSH_CLSG_CFG2, 0x10 },
+ { CDC_RX_BCL_VBAT_PATH_CTL, 0x00 },
+ { CDC_RX_BCL_VBAT_CFG, 0x10 },
+ { CDC_RX_BCL_VBAT_ADC_CAL1, 0x00 },
+ { CDC_RX_BCL_VBAT_ADC_CAL2, 0x00 },
+ { CDC_RX_BCL_VBAT_ADC_CAL3, 0x04 },
+ { CDC_RX_BCL_VBAT_PK_EST1, 0xE0 },
+ { 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_TAC1, 0x00 },
+ { CDC_RX_BCL_VBAT_TAC2, 0x18 },
+ { CDC_RX_BCL_VBAT_TAC3, 0x18 },
+ { CDC_RX_BCL_VBAT_TAC4, 0x03 },
+ { CDC_RX_BCL_VBAT_GAIN_UPD1, 0x01 },
+ { CDC_RX_BCL_VBAT_GAIN_UPD2, 0x00 },
+ { CDC_RX_BCL_VBAT_GAIN_UPD3, 0x00 },
+ { CDC_RX_BCL_VBAT_GAIN_UPD4, 0x64 },
+ { CDC_RX_BCL_VBAT_GAIN_UPD5, 0x01 },
+ { CDC_RX_BCL_VBAT_DEBUG1, 0x00 },
+ { CDC_RX_BCL_VBAT_GAIN_UPD_MON, 0x00 },
+ { CDC_RX_BCL_VBAT_GAIN_MON_VAL, 0x00 },
+ { CDC_RX_BCL_VBAT_BAN, 0x0C },
+ { CDC_RX_BCL_VBAT_BCL_GAIN_UPD1, 0x00 },
+ { CDC_RX_BCL_VBAT_BCL_GAIN_UPD2, 0x77 },
+ { CDC_RX_BCL_VBAT_BCL_GAIN_UPD3, 0x01 },
+ { CDC_RX_BCL_VBAT_BCL_GAIN_UPD4, 0x00 },
+ { CDC_RX_BCL_VBAT_BCL_GAIN_UPD5, 0x4B },
+ { CDC_RX_BCL_VBAT_BCL_GAIN_UPD6, 0x00 },
+ { CDC_RX_BCL_VBAT_BCL_GAIN_UPD7, 0x01 },
+ { CDC_RX_BCL_VBAT_BCL_GAIN_UPD8, 0x00 },
+ { CDC_RX_BCL_VBAT_BCL_GAIN_UPD9, 0x00 },
+ { CDC_RX_BCL_VBAT_ATTN1, 0x04 },
+ { CDC_RX_BCL_VBAT_ATTN2, 0x08 },
+ { CDC_RX_BCL_VBAT_ATTN3, 0x0C },
+ { CDC_RX_BCL_VBAT_DECODE_CTL1, 0xE0 },
+ { CDC_RX_BCL_VBAT_DECODE_CTL2, 0x00 },
+ { CDC_RX_BCL_VBAT_DECODE_CFG1, 0x00 },
+ { CDC_RX_BCL_VBAT_DECODE_CFG2, 0x00 },
+ { CDC_RX_BCL_VBAT_DECODE_CFG3, 0x00 },
+ { CDC_RX_BCL_VBAT_DECODE_CFG4, 0x00 },
+ { CDC_RX_BCL_VBAT_DECODE_ST, 0x00 },
+ { CDC_RX_INTR_CTRL_CFG, 0x00 },
+ { CDC_RX_INTR_CTRL_CLR_COMMIT, 0x00 },
+ { CDC_RX_INTR_CTRL_PIN1_MASK0, 0xFF },
+ { CDC_RX_INTR_CTRL_PIN1_STATUS0, 0x00 },
+ { CDC_RX_INTR_CTRL_PIN1_CLEAR0, 0x00 },
+ { CDC_RX_INTR_CTRL_PIN2_MASK0, 0xFF },
+ { CDC_RX_INTR_CTRL_PIN2_STATUS0, 0x00 },
+ { CDC_RX_INTR_CTRL_PIN2_CLEAR0, 0x00 },
+ { CDC_RX_INTR_CTRL_LEVEL0, 0x00 },
+ { CDC_RX_INTR_CTRL_BYPASS0, 0x00 },
+ { CDC_RX_INTR_CTRL_SET0, 0x00 },
+ { CDC_RX_RX0_RX_PATH_CTL, 0x04 },
+ { CDC_RX_RX0_RX_PATH_CFG0, 0x00 },
+ { CDC_RX_RX0_RX_PATH_CFG1, 0x64 },
+ { CDC_RX_RX0_RX_PATH_CFG2, 0x8F },
+ { CDC_RX_RX0_RX_PATH_CFG3, 0x00 },
+ { CDC_RX_RX0_RX_VOL_CTL, 0x00 },
+ { CDC_RX_RX0_RX_PATH_MIX_CTL, 0x04 },
+ { CDC_RX_RX0_RX_PATH_MIX_CFG, 0x7E },
+ { CDC_RX_RX0_RX_VOL_MIX_CTL, 0x00 },
+ { CDC_RX_RX0_RX_PATH_SEC1, 0x08 },
+ { CDC_RX_RX0_RX_PATH_SEC2, 0x00 },
+ { CDC_RX_RX0_RX_PATH_SEC3, 0x00 },
+ { CDC_RX_RX0_RX_PATH_SEC4, 0x00 },
+ { CDC_RX_RX0_RX_PATH_SEC7, 0x00 },
+ { CDC_RX_RX0_RX_PATH_MIX_SEC0, 0x08 },
+ { CDC_RX_RX0_RX_PATH_MIX_SEC1, 0x00 },
+ { CDC_RX_RX0_RX_PATH_DSM_CTL, 0x08 },
+ { CDC_RX_RX0_RX_PATH_DSM_DATA1, 0x00 },
+ { CDC_RX_RX0_RX_PATH_DSM_DATA2, 0x00 },
+ { CDC_RX_RX0_RX_PATH_DSM_DATA3, 0x00 },
+ { CDC_RX_RX0_RX_PATH_DSM_DATA4, 0x55 },
+ { CDC_RX_RX0_RX_PATH_DSM_DATA5, 0x55 },
+ { CDC_RX_RX0_RX_PATH_DSM_DATA6, 0x55 },
+ { CDC_RX_RX1_RX_PATH_CTL, 0x04 },
+ { CDC_RX_RX1_RX_PATH_CFG0, 0x00 },
+ { CDC_RX_RX1_RX_PATH_CFG1, 0x64 },
+ { CDC_RX_RX1_RX_PATH_CFG2, 0x8F },
+ { CDC_RX_RX1_RX_PATH_CFG3, 0x00 },
+ { CDC_RX_RX1_RX_VOL_CTL, 0x00 },
+ { CDC_RX_RX1_RX_PATH_MIX_CTL, 0x04 },
+ { CDC_RX_RX1_RX_PATH_MIX_CFG, 0x7E },
+ { CDC_RX_RX1_RX_VOL_MIX_CTL, 0x00 },
+ { CDC_RX_RX1_RX_PATH_SEC1, 0x08 },
+ { CDC_RX_RX1_RX_PATH_SEC2, 0x00 },
+ { CDC_RX_RX1_RX_PATH_SEC3, 0x00 },
+ { CDC_RX_RX1_RX_PATH_SEC4, 0x00 },
+ { CDC_RX_RX1_RX_PATH_SEC7, 0x00 },
+ { CDC_RX_RX1_RX_PATH_MIX_SEC0, 0x08 },
+ { CDC_RX_RX1_RX_PATH_MIX_SEC1, 0x00 },
+ { CDC_RX_RX1_RX_PATH_DSM_CTL, 0x08 },
+ { CDC_RX_RX1_RX_PATH_DSM_DATA1, 0x00 },
+ { CDC_RX_RX1_RX_PATH_DSM_DATA2, 0x00 },
+ { CDC_RX_RX1_RX_PATH_DSM_DATA3, 0x00 },
+ { CDC_RX_RX1_RX_PATH_DSM_DATA4, 0x55 },
+ { CDC_RX_RX1_RX_PATH_DSM_DATA5, 0x55 },
+ { CDC_RX_RX1_RX_PATH_DSM_DATA6, 0x55 },
+ { CDC_RX_RX2_RX_PATH_CTL, 0x04 },
+ { CDC_RX_RX2_RX_PATH_CFG0, 0x00 },
+ { CDC_RX_RX2_RX_PATH_CFG1, 0x64 },
+ { CDC_RX_RX2_RX_PATH_CFG2, 0x8F },
+ { CDC_RX_RX2_RX_PATH_CFG3, 0x00 },
+ { CDC_RX_RX2_RX_VOL_CTL, 0x00 },
+ { CDC_RX_RX2_RX_PATH_MIX_CTL, 0x04 },
+ { CDC_RX_RX2_RX_PATH_MIX_CFG, 0x7E },
+ { CDC_RX_RX2_RX_VOL_MIX_CTL, 0x00 },
+ { CDC_RX_RX2_RX_PATH_SEC0, 0x04 },
+ { CDC_RX_RX2_RX_PATH_SEC1, 0x08 },
+ { CDC_RX_RX2_RX_PATH_SEC2, 0x00 },
+ { CDC_RX_RX2_RX_PATH_SEC3, 0x00 },
+ { CDC_RX_RX2_RX_PATH_SEC4, 0x00 },
+ { CDC_RX_RX2_RX_PATH_SEC5, 0x00 },
+ { CDC_RX_RX2_RX_PATH_SEC6, 0x00 },
+ { CDC_RX_RX2_RX_PATH_SEC7, 0x00 },
+ { CDC_RX_RX2_RX_PATH_MIX_SEC0, 0x08 },
+ { CDC_RX_RX2_RX_PATH_MIX_SEC1, 0x00 },
+ { CDC_RX_RX2_RX_PATH_DSM_CTL, 0x00 },
+ { CDC_RX_IDLE_DETECT_PATH_CTL, 0x00 },
+ { CDC_RX_IDLE_DETECT_CFG0, 0x07 },
+ { CDC_RX_IDLE_DETECT_CFG1, 0x3C },
+ { CDC_RX_IDLE_DETECT_CFG2, 0x00 },
+ { CDC_RX_IDLE_DETECT_CFG3, 0x00 },
+ { CDC_RX_COMPANDER0_CTL0, 0x60 },
+ { CDC_RX_COMPANDER0_CTL1, 0xDB },
+ { CDC_RX_COMPANDER0_CTL2, 0xFF },
+ { CDC_RX_COMPANDER0_CTL3, 0x35 },
+ { CDC_RX_COMPANDER0_CTL4, 0xFF },
+ { CDC_RX_COMPANDER0_CTL5, 0x00 },
+ { CDC_RX_COMPANDER0_CTL6, 0x01 },
+ { CDC_RX_COMPANDER0_CTL7, 0x28 },
+ { CDC_RX_COMPANDER1_CTL0, 0x60 },
+ { CDC_RX_COMPANDER1_CTL1, 0xDB },
+ { CDC_RX_COMPANDER1_CTL2, 0xFF },
+ { CDC_RX_COMPANDER1_CTL3, 0x35 },
+ { CDC_RX_COMPANDER1_CTL4, 0xFF },
+ { CDC_RX_COMPANDER1_CTL5, 0x00 },
+ { CDC_RX_COMPANDER1_CTL6, 0x01 },
+ { CDC_RX_COMPANDER1_CTL7, 0x28 },
+ { CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR0_IIR_CTL, 0x40 },
+ { CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR1_IIR_CTL, 0x40 },
+ { CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL, 0x00 },
+ { CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL, 0x00 },
+ { CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0, 0x00 },
+ { CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1, 0x00 },
+ { CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2, 0x00 },
+ { CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3, 0x00 },
+ { CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0, 0x00 },
+ { CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1, 0x00 },
+ { CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2, 0x00 },
+ { CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3, 0x00 },
+ { CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL, 0x04 },
+ { CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1, 0x00 },
+ { CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL, 0x04 },
+ { CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1, 0x00 },
+ { CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL, 0x00 },
+ { CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0, 0x01 },
+ { CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL, 0x00 },
+ { CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0, 0x01 },
+ { CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL, 0x00 },
+ { CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0, 0x01 },
+ { CDC_RX_EC_ASRC0_CLK_RST_CTL, 0x00 },
+ { CDC_RX_EC_ASRC0_CTL0, 0x00 },
+ { CDC_RX_EC_ASRC0_CTL1, 0x00 },
+ { CDC_RX_EC_ASRC0_FIFO_CTL, 0xA8 },
+ { CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB, 0x00 },
+ { CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB, 0x00 },
+ { CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB, 0x00 },
+ { CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB, 0x00 },
+ { CDC_RX_EC_ASRC0_STATUS_FIFO, 0x00 },
+ { CDC_RX_EC_ASRC1_CLK_RST_CTL, 0x00 },
+ { CDC_RX_EC_ASRC1_CTL0, 0x00 },
+ { CDC_RX_EC_ASRC1_CTL1, 0x00 },
+ { CDC_RX_EC_ASRC1_FIFO_CTL, 0xA8 },
+ { CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB, 0x00 },
+ { CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB, 0x00 },
+ { CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB, 0x00 },
+ { CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB, 0x00 },
+ { CDC_RX_EC_ASRC1_STATUS_FIFO, 0x00 },
+ { CDC_RX_EC_ASRC2_CLK_RST_CTL, 0x00 },
+ { CDC_RX_EC_ASRC2_CTL0, 0x00 },
+ { CDC_RX_EC_ASRC2_CTL1, 0x00 },
+ { CDC_RX_EC_ASRC2_FIFO_CTL, 0xA8 },
+ { CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB, 0x00 },
+ { CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB, 0x00 },
+ { CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB, 0x00 },
+ { CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB, 0x00 },
+ { CDC_RX_EC_ASRC2_STATUS_FIFO, 0x00 },
+ { CDC_RX_DSD0_PATH_CTL, 0x00 },
+ { CDC_RX_DSD0_CFG0, 0x00 },
+ { CDC_RX_DSD0_CFG1, 0x62 },
+ { CDC_RX_DSD0_CFG2, 0x96 },
+ { CDC_RX_DSD1_PATH_CTL, 0x00 },
+ { CDC_RX_DSD1_CFG0, 0x00 },
+ { CDC_RX_DSD1_CFG1, 0x62 },
+ { CDC_RX_DSD1_CFG2, 0x96 },
+};
+
+static bool rx_is_wronly_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case CDC_RX_BCL_VBAT_GAIN_UPD_MON:
+ case CDC_RX_INTR_CTRL_CLR_COMMIT:
+ case CDC_RX_INTR_CTRL_PIN1_CLEAR0:
+ case CDC_RX_INTR_CTRL_PIN2_CLEAR0:
+ return true;
+ }
+
+ return false;
+}
+
+static bool rx_is_volatile_register(struct device *dev, unsigned int reg)
+{
+ /* Update volatile list for rx/tx macros */
+ switch (reg) {
+ case CDC_RX_TOP_HPHL_COMP_RD_LSB:
+ case CDC_RX_TOP_HPHL_COMP_WR_LSB:
+ case CDC_RX_TOP_HPHL_COMP_RD_MSB:
+ case CDC_RX_TOP_HPHL_COMP_WR_MSB:
+ case CDC_RX_TOP_HPHR_COMP_RD_LSB:
+ case CDC_RX_TOP_HPHR_COMP_WR_LSB:
+ case CDC_RX_TOP_HPHR_COMP_RD_MSB:
+ case CDC_RX_TOP_HPHR_COMP_WR_MSB:
+ case CDC_RX_TOP_DSD0_DEBUG_CFG2:
+ case CDC_RX_TOP_DSD1_DEBUG_CFG2:
+ case CDC_RX_BCL_VBAT_GAIN_MON_VAL:
+ case CDC_RX_BCL_VBAT_DECODE_ST:
+ case CDC_RX_INTR_CTRL_PIN1_STATUS0:
+ case CDC_RX_INTR_CTRL_PIN2_STATUS0:
+ case CDC_RX_COMPANDER0_CTL6:
+ case CDC_RX_COMPANDER1_CTL6:
+ case CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB:
+ case CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB:
+ case CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB:
+ case CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB:
+ case CDC_RX_EC_ASRC0_STATUS_FIFO:
+ case CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB:
+ case CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB:
+ case CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB:
+ case CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB:
+ case CDC_RX_EC_ASRC1_STATUS_FIFO:
+ case CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB:
+ case CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB:
+ case CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB:
+ case CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB:
+ case CDC_RX_EC_ASRC2_STATUS_FIFO:
+ return true;
+ }
+ return false;
+}
+
+static bool rx_is_rw_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CDC_RX_TOP_TOP_CFG0:
+ case CDC_RX_TOP_SWR_CTRL:
+ case CDC_RX_TOP_DEBUG:
+ case CDC_RX_TOP_DEBUG_BUS:
+ case CDC_RX_TOP_DEBUG_EN0:
+ case CDC_RX_TOP_DEBUG_EN1:
+ case CDC_RX_TOP_DEBUG_EN2:
+ case CDC_RX_TOP_HPHL_COMP_WR_LSB:
+ case CDC_RX_TOP_HPHL_COMP_WR_MSB:
+ case CDC_RX_TOP_HPHL_COMP_LUT:
+ case CDC_RX_TOP_HPHR_COMP_WR_LSB:
+ case CDC_RX_TOP_HPHR_COMP_WR_MSB:
+ case CDC_RX_TOP_HPHR_COMP_LUT:
+ case CDC_RX_TOP_DSD0_DEBUG_CFG0:
+ case CDC_RX_TOP_DSD0_DEBUG_CFG1:
+ case CDC_RX_TOP_DSD0_DEBUG_CFG3:
+ case CDC_RX_TOP_DSD1_DEBUG_CFG0:
+ case CDC_RX_TOP_DSD1_DEBUG_CFG1:
+ case CDC_RX_TOP_DSD1_DEBUG_CFG3:
+ case CDC_RX_TOP_RX_I2S_CTL:
+ case CDC_RX_TOP_TX_I2S2_CTL:
+ case CDC_RX_TOP_I2S_CLK:
+ case CDC_RX_TOP_I2S_RESET:
+ case CDC_RX_TOP_I2S_MUX:
+ case CDC_RX_CLK_RST_CTRL_MCLK_CONTROL:
+ case CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL:
+ case CDC_RX_CLK_RST_CTRL_SWR_CONTROL:
+ case CDC_RX_CLK_RST_CTRL_DSD_CONTROL:
+ case CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL:
+ case CDC_RX_SOFTCLIP_CRC:
+ case CDC_RX_SOFTCLIP_SOFTCLIP_CTRL:
+ case CDC_RX_INP_MUX_RX_INT0_CFG0:
+ case CDC_RX_INP_MUX_RX_INT0_CFG1:
+ case CDC_RX_INP_MUX_RX_INT1_CFG0:
+ case CDC_RX_INP_MUX_RX_INT1_CFG1:
+ case CDC_RX_INP_MUX_RX_INT2_CFG0:
+ case CDC_RX_INP_MUX_RX_INT2_CFG1:
+ case CDC_RX_INP_MUX_RX_MIX_CFG4:
+ case CDC_RX_INP_MUX_RX_MIX_CFG5:
+ case CDC_RX_INP_MUX_SIDETONE_SRC_CFG0:
+ case CDC_RX_CLSH_CRC:
+ case CDC_RX_CLSH_DLY_CTRL:
+ case CDC_RX_CLSH_DECAY_CTRL:
+ case CDC_RX_CLSH_HPH_V_PA:
+ case CDC_RX_CLSH_EAR_V_PA:
+ case CDC_RX_CLSH_HPH_V_HD:
+ case CDC_RX_CLSH_EAR_V_HD:
+ case CDC_RX_CLSH_K1_MSB:
+ case CDC_RX_CLSH_K1_LSB:
+ case CDC_RX_CLSH_K2_MSB:
+ case CDC_RX_CLSH_K2_LSB:
+ case CDC_RX_CLSH_IDLE_CTRL:
+ case CDC_RX_CLSH_IDLE_HPH:
+ case CDC_RX_CLSH_IDLE_EAR:
+ case CDC_RX_CLSH_TEST0:
+ case CDC_RX_CLSH_TEST1:
+ case CDC_RX_CLSH_OVR_VREF:
+ case CDC_RX_CLSH_CLSG_CTL:
+ case CDC_RX_CLSH_CLSG_CFG1:
+ case CDC_RX_CLSH_CLSG_CFG2:
+ case CDC_RX_BCL_VBAT_PATH_CTL:
+ case CDC_RX_BCL_VBAT_CFG:
+ case CDC_RX_BCL_VBAT_ADC_CAL1:
+ case CDC_RX_BCL_VBAT_ADC_CAL2:
+ case CDC_RX_BCL_VBAT_ADC_CAL3:
+ case CDC_RX_BCL_VBAT_PK_EST1:
+ case CDC_RX_BCL_VBAT_PK_EST2:
+ case CDC_RX_BCL_VBAT_PK_EST3:
+ case CDC_RX_BCL_VBAT_RF_PROC1:
+ case CDC_RX_BCL_VBAT_RF_PROC2:
+ case CDC_RX_BCL_VBAT_TAC1:
+ case CDC_RX_BCL_VBAT_TAC2:
+ case CDC_RX_BCL_VBAT_TAC3:
+ case CDC_RX_BCL_VBAT_TAC4:
+ case CDC_RX_BCL_VBAT_GAIN_UPD1:
+ case CDC_RX_BCL_VBAT_GAIN_UPD2:
+ case CDC_RX_BCL_VBAT_GAIN_UPD3:
+ case CDC_RX_BCL_VBAT_GAIN_UPD4:
+ case CDC_RX_BCL_VBAT_GAIN_UPD5:
+ case CDC_RX_BCL_VBAT_DEBUG1:
+ case CDC_RX_BCL_VBAT_BAN:
+ case CDC_RX_BCL_VBAT_BCL_GAIN_UPD1:
+ case CDC_RX_BCL_VBAT_BCL_GAIN_UPD2:
+ case CDC_RX_BCL_VBAT_BCL_GAIN_UPD3:
+ case CDC_RX_BCL_VBAT_BCL_GAIN_UPD4:
+ case CDC_RX_BCL_VBAT_BCL_GAIN_UPD5:
+ case CDC_RX_BCL_VBAT_BCL_GAIN_UPD6:
+ case CDC_RX_BCL_VBAT_BCL_GAIN_UPD7:
+ case CDC_RX_BCL_VBAT_BCL_GAIN_UPD8:
+ case CDC_RX_BCL_VBAT_BCL_GAIN_UPD9:
+ case CDC_RX_BCL_VBAT_ATTN1:
+ case CDC_RX_BCL_VBAT_ATTN2:
+ case CDC_RX_BCL_VBAT_ATTN3:
+ case CDC_RX_BCL_VBAT_DECODE_CTL1:
+ case CDC_RX_BCL_VBAT_DECODE_CTL2:
+ case CDC_RX_BCL_VBAT_DECODE_CFG1:
+ case CDC_RX_BCL_VBAT_DECODE_CFG2:
+ case CDC_RX_BCL_VBAT_DECODE_CFG3:
+ case CDC_RX_BCL_VBAT_DECODE_CFG4:
+ case CDC_RX_INTR_CTRL_CFG:
+ case CDC_RX_INTR_CTRL_PIN1_MASK0:
+ case CDC_RX_INTR_CTRL_PIN2_MASK0:
+ case CDC_RX_INTR_CTRL_LEVEL0:
+ case CDC_RX_INTR_CTRL_BYPASS0:
+ case CDC_RX_INTR_CTRL_SET0:
+ case CDC_RX_RX0_RX_PATH_CTL:
+ case CDC_RX_RX0_RX_PATH_CFG0:
+ case CDC_RX_RX0_RX_PATH_CFG1:
+ case CDC_RX_RX0_RX_PATH_CFG2:
+ case CDC_RX_RX0_RX_PATH_CFG3:
+ case CDC_RX_RX0_RX_VOL_CTL:
+ case CDC_RX_RX0_RX_PATH_MIX_CTL:
+ case CDC_RX_RX0_RX_PATH_MIX_CFG:
+ case CDC_RX_RX0_RX_VOL_MIX_CTL:
+ case CDC_RX_RX0_RX_PATH_SEC1:
+ case CDC_RX_RX0_RX_PATH_SEC2:
+ case CDC_RX_RX0_RX_PATH_SEC3:
+ case CDC_RX_RX0_RX_PATH_SEC4:
+ case CDC_RX_RX0_RX_PATH_SEC7:
+ case CDC_RX_RX0_RX_PATH_MIX_SEC0:
+ case CDC_RX_RX0_RX_PATH_MIX_SEC1:
+ case CDC_RX_RX0_RX_PATH_DSM_CTL:
+ case CDC_RX_RX0_RX_PATH_DSM_DATA1:
+ case CDC_RX_RX0_RX_PATH_DSM_DATA2:
+ case CDC_RX_RX0_RX_PATH_DSM_DATA3:
+ case CDC_RX_RX0_RX_PATH_DSM_DATA4:
+ case CDC_RX_RX0_RX_PATH_DSM_DATA5:
+ case CDC_RX_RX0_RX_PATH_DSM_DATA6:
+ case CDC_RX_RX1_RX_PATH_CTL:
+ case CDC_RX_RX1_RX_PATH_CFG0:
+ case CDC_RX_RX1_RX_PATH_CFG1:
+ case CDC_RX_RX1_RX_PATH_CFG2:
+ case CDC_RX_RX1_RX_PATH_CFG3:
+ case CDC_RX_RX1_RX_VOL_CTL:
+ case CDC_RX_RX1_RX_PATH_MIX_CTL:
+ case CDC_RX_RX1_RX_PATH_MIX_CFG:
+ case CDC_RX_RX1_RX_VOL_MIX_CTL:
+ case CDC_RX_RX1_RX_PATH_SEC1:
+ case CDC_RX_RX1_RX_PATH_SEC2:
+ case CDC_RX_RX1_RX_PATH_SEC3:
+ case CDC_RX_RX1_RX_PATH_SEC4:
+ case CDC_RX_RX1_RX_PATH_SEC7:
+ case CDC_RX_RX1_RX_PATH_MIX_SEC0:
+ case CDC_RX_RX1_RX_PATH_MIX_SEC1:
+ case CDC_RX_RX1_RX_PATH_DSM_CTL:
+ case CDC_RX_RX1_RX_PATH_DSM_DATA1:
+ case CDC_RX_RX1_RX_PATH_DSM_DATA2:
+ case CDC_RX_RX1_RX_PATH_DSM_DATA3:
+ case CDC_RX_RX1_RX_PATH_DSM_DATA4:
+ case CDC_RX_RX1_RX_PATH_DSM_DATA5:
+ case CDC_RX_RX1_RX_PATH_DSM_DATA6:
+ case CDC_RX_RX2_RX_PATH_CTL:
+ case CDC_RX_RX2_RX_PATH_CFG0:
+ case CDC_RX_RX2_RX_PATH_CFG1:
+ case CDC_RX_RX2_RX_PATH_CFG2:
+ case CDC_RX_RX2_RX_PATH_CFG3:
+ case CDC_RX_RX2_RX_VOL_CTL:
+ case CDC_RX_RX2_RX_PATH_MIX_CTL:
+ case CDC_RX_RX2_RX_PATH_MIX_CFG:
+ case CDC_RX_RX2_RX_VOL_MIX_CTL:
+ case CDC_RX_RX2_RX_PATH_SEC0:
+ case CDC_RX_RX2_RX_PATH_SEC1:
+ case CDC_RX_RX2_RX_PATH_SEC2:
+ case CDC_RX_RX2_RX_PATH_SEC3:
+ case CDC_RX_RX2_RX_PATH_SEC4:
+ case CDC_RX_RX2_RX_PATH_SEC5:
+ case CDC_RX_RX2_RX_PATH_SEC6:
+ case CDC_RX_RX2_RX_PATH_SEC7:
+ case CDC_RX_RX2_RX_PATH_MIX_SEC0:
+ case CDC_RX_RX2_RX_PATH_MIX_SEC1:
+ case CDC_RX_RX2_RX_PATH_DSM_CTL:
+ case CDC_RX_IDLE_DETECT_PATH_CTL:
+ case CDC_RX_IDLE_DETECT_CFG0:
+ case CDC_RX_IDLE_DETECT_CFG1:
+ case CDC_RX_IDLE_DETECT_CFG2:
+ case CDC_RX_IDLE_DETECT_CFG3:
+ case CDC_RX_COMPANDER0_CTL0:
+ case CDC_RX_COMPANDER0_CTL1:
+ case CDC_RX_COMPANDER0_CTL2:
+ case CDC_RX_COMPANDER0_CTL3:
+ case CDC_RX_COMPANDER0_CTL4:
+ case CDC_RX_COMPANDER0_CTL5:
+ case CDC_RX_COMPANDER0_CTL7:
+ case CDC_RX_COMPANDER1_CTL0:
+ case CDC_RX_COMPANDER1_CTL1:
+ case CDC_RX_COMPANDER1_CTL2:
+ case CDC_RX_COMPANDER1_CTL3:
+ case CDC_RX_COMPANDER1_CTL4:
+ case CDC_RX_COMPANDER1_CTL5:
+ case CDC_RX_COMPANDER1_CTL7:
+ case CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL:
+ case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL:
+ case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL:
+ case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL:
+ case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL:
+ case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL:
+ case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL:
+ case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL:
+ case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL:
+ case CDC_RX_SIDETONE_IIR0_IIR_CTL:
+ case CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL:
+ case CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL:
+ case CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL:
+ case CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL:
+ case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL:
+ case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL:
+ case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL:
+ case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL:
+ case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL:
+ case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL:
+ case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL:
+ case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL:
+ case CDC_RX_SIDETONE_IIR1_IIR_CTL:
+ case CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL:
+ case CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL:
+ case CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL:
+ case CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0:
+ case CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1:
+ case CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2:
+ case CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3:
+ case CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0:
+ case CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1:
+ case CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2:
+ case CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3:
+ case CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL:
+ case CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1:
+ case CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL:
+ case CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1:
+ case CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL:
+ case CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0:
+ case CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL:
+ case CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0:
+ case CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL:
+ case CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0:
+ case CDC_RX_EC_ASRC0_CLK_RST_CTL:
+ case CDC_RX_EC_ASRC0_CTL0:
+ case CDC_RX_EC_ASRC0_CTL1:
+ case CDC_RX_EC_ASRC0_FIFO_CTL:
+ case CDC_RX_EC_ASRC1_CLK_RST_CTL:
+ case CDC_RX_EC_ASRC1_CTL0:
+ case CDC_RX_EC_ASRC1_CTL1:
+ case CDC_RX_EC_ASRC1_FIFO_CTL:
+ case CDC_RX_EC_ASRC2_CLK_RST_CTL:
+ case CDC_RX_EC_ASRC2_CTL0:
+ case CDC_RX_EC_ASRC2_CTL1:
+ case CDC_RX_EC_ASRC2_FIFO_CTL:
+ case CDC_RX_DSD0_PATH_CTL:
+ case CDC_RX_DSD0_CFG0:
+ case CDC_RX_DSD0_CFG1:
+ case CDC_RX_DSD0_CFG2:
+ case CDC_RX_DSD1_PATH_CTL:
+ case CDC_RX_DSD1_CFG0:
+ case CDC_RX_DSD1_CFG1:
+ case CDC_RX_DSD1_CFG2:
+ return true;
+ }
+
+ return false;
+}
+
+static bool rx_is_writeable_register(struct device *dev, unsigned int reg)
+{
+ bool ret;
+
+ ret = rx_is_rw_register(dev, reg);
+ if (!ret)
+ return rx_is_wronly_register(dev, reg);
+
+ return ret;
+}
+
+static bool rx_is_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CDC_RX_TOP_HPHL_COMP_RD_LSB:
+ case CDC_RX_TOP_HPHL_COMP_RD_MSB:
+ case CDC_RX_TOP_HPHR_COMP_RD_LSB:
+ case CDC_RX_TOP_HPHR_COMP_RD_MSB:
+ case CDC_RX_TOP_DSD0_DEBUG_CFG2:
+ case CDC_RX_TOP_DSD1_DEBUG_CFG2:
+ case CDC_RX_BCL_VBAT_GAIN_MON_VAL:
+ case CDC_RX_BCL_VBAT_DECODE_ST:
+ case CDC_RX_INTR_CTRL_PIN1_STATUS0:
+ case CDC_RX_INTR_CTRL_PIN2_STATUS0:
+ case CDC_RX_COMPANDER0_CTL6:
+ case CDC_RX_COMPANDER1_CTL6:
+ case CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB:
+ case CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB:
+ case CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB:
+ case CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB:
+ case CDC_RX_EC_ASRC0_STATUS_FIFO:
+ case CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB:
+ case CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB:
+ case CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB:
+ case CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB:
+ case CDC_RX_EC_ASRC1_STATUS_FIFO:
+ case CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB:
+ case CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB:
+ case CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB:
+ case CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB:
+ case CDC_RX_EC_ASRC2_STATUS_FIFO:
+ return true;
+ }
+
+ return rx_is_rw_register(dev, reg);
+}
+
+static const struct regmap_config rx_regmap_config = {
+ .name = "rx_macro",
+ .reg_bits = 16,
+ .val_bits = 32, /* 8 but with 32 bit read/write */
+ .reg_stride = 4,
+ .cache_type = REGCACHE_FLAT,
+ .reg_defaults = rx_defaults,
+ .num_reg_defaults = ARRAY_SIZE(rx_defaults),
+ .max_register = RX_MAX_OFFSET,
+ .writeable_reg = rx_is_writeable_register,
+ .volatile_reg = rx_is_volatile_register,
+ .readable_reg = rx_is_readable_register,
+};
+
+static int rx_macro_int_dem_inp_mux_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol);
+ struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned short look_ahead_dly_reg;
+ unsigned int val;
+
+ val = ucontrol->value.enumerated.item[0];
+
+ if (e->reg == CDC_RX_RX0_RX_PATH_CFG1)
+ look_ahead_dly_reg = CDC_RX_RX0_RX_PATH_CFG0;
+ else if (e->reg == CDC_RX_RX1_RX_PATH_CFG1)
+ look_ahead_dly_reg = CDC_RX_RX1_RX_PATH_CFG0;
+
+ /* Set Look Ahead Delay */
+ if (val)
+ snd_soc_component_update_bits(component, look_ahead_dly_reg,
+ CDC_RX_DLY_ZN_EN_MASK,
+ CDC_RX_DLY_ZN_ENABLE);
+ else
+ snd_soc_component_update_bits(component, look_ahead_dly_reg,
+ CDC_RX_DLY_ZN_EN_MASK, 0);
+ /* Set DEM INP Select */
+ return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
+static const struct snd_kcontrol_new rx_int0_dem_inp_mux =
+ SOC_DAPM_ENUM_EXT("rx_int0_dem_inp", rx_int0_dem_inp_enum,
+ snd_soc_dapm_get_enum_double, rx_macro_int_dem_inp_mux_put);
+static const struct snd_kcontrol_new rx_int1_dem_inp_mux =
+ SOC_DAPM_ENUM_EXT("rx_int1_dem_inp", rx_int1_dem_inp_enum,
+ snd_soc_dapm_get_enum_double, rx_macro_int_dem_inp_mux_put);
+
+static int rx_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
+ int rate_reg_val, u32 sample_rate)
+{
+
+ u8 int_1_mix1_inp;
+ u32 j, port;
+ u16 int_mux_cfg0, int_mux_cfg1;
+ u16 int_fs_reg;
+ u8 inp0_sel, inp1_sel, inp2_sel;
+ struct snd_soc_component *component = dai->component;
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ for_each_set_bit(port, &rx->active_ch_mask[dai->id], RX_MACRO_PORTS_MAX) {
+ int_1_mix1_inp = port;
+ int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0;
+ /*
+ * Loop through all interpolator MUX inputs and find out
+ * to which interpolator input, the rx port
+ * is connected
+ */
+ for (j = 0; j < INTERP_MAX; j++) {
+ int_mux_cfg1 = int_mux_cfg0 + 4;
+
+ inp0_sel = snd_soc_component_read_field(component, int_mux_cfg0,
+ CDC_RX_INTX_1_MIX_INP0_SEL_MASK);
+ inp1_sel = snd_soc_component_read_field(component, int_mux_cfg0,
+ CDC_RX_INTX_1_MIX_INP1_SEL_MASK);
+ inp2_sel = snd_soc_component_read_field(component, int_mux_cfg1,
+ CDC_RX_INTX_1_MIX_INP2_SEL_MASK);
+
+ if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) ||
+ (inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) ||
+ (inp2_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0)) {
+ int_fs_reg = CDC_RX_RXn_RX_PATH_CTL(j);
+ /* sample_rate is in Hz */
+ snd_soc_component_update_bits(component, int_fs_reg,
+ CDC_RX_PATH_PCM_RATE_MASK,
+ rate_reg_val);
+ }
+ int_mux_cfg0 += 8;
+ }
+ }
+
+ return 0;
+}
+
+static int rx_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai,
+ int rate_reg_val, u32 sample_rate)
+{
+
+ u8 int_2_inp;
+ u32 j, port;
+ u16 int_mux_cfg1, int_fs_reg;
+ u8 int_mux_cfg1_val;
+ struct snd_soc_component *component = dai->component;
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ for_each_set_bit(port, &rx->active_ch_mask[dai->id], RX_MACRO_PORTS_MAX) {
+ int_2_inp = port;
+
+ int_mux_cfg1 = CDC_RX_INP_MUX_RX_INT0_CFG1;
+ for (j = 0; j < INTERP_MAX; j++) {
+ int_mux_cfg1_val = snd_soc_component_read_field(component, int_mux_cfg1,
+ CDC_RX_INTX_2_SEL_MASK);
+
+ if (int_mux_cfg1_val == int_2_inp + INTn_2_INP_SEL_RX0) {
+ int_fs_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j);
+ snd_soc_component_update_bits(component, int_fs_reg,
+ CDC_RX_RXn_MIX_PCM_RATE_MASK,
+ rate_reg_val);
+ }
+ int_mux_cfg1 += 8;
+ }
+ }
+ return 0;
+}
+
+static int rx_macro_set_interpolator_rate(struct snd_soc_dai *dai,
+ u32 sample_rate)
+{
+ int rate_val = 0;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(sr_val_tbl); i++)
+ if (sample_rate == sr_val_tbl[i].sample_rate)
+ rate_val = sr_val_tbl[i].rate_val;
+
+ ret = rx_macro_set_prim_interpolator_rate(dai, rate_val, sample_rate);
+ if (ret)
+ return ret;
+
+ ret = rx_macro_set_mix_interpolator_rate(dai, rate_val, sample_rate);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+static int rx_macro_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 rx_macro *rx = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ switch (substream->stream) {
+ case SNDRV_PCM_STREAM_PLAYBACK:
+ ret = rx_macro_set_interpolator_rate(dai, params_rate(params));
+ if (ret) {
+ dev_err(component->dev, "%s: cannot set sample rate: %u\n",
+ __func__, params_rate(params));
+ return ret;
+ }
+ rx->bit_width[dai->id] = params_width(params);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int rx_macro_get_channel_map(struct snd_soc_dai *dai,
+ unsigned int *tx_num, unsigned int *tx_slot,
+ unsigned int *rx_num, unsigned int *rx_slot)
+{
+ struct snd_soc_component *component = dai->component;
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+ u16 val, mask = 0, cnt = 0, temp;
+
+ switch (dai->id) {
+ case RX_MACRO_AIF1_PB:
+ case RX_MACRO_AIF2_PB:
+ case RX_MACRO_AIF3_PB:
+ case RX_MACRO_AIF4_PB:
+ for_each_set_bit(temp, &rx->active_ch_mask[dai->id],
+ RX_MACRO_PORTS_MAX) {
+ mask |= (1 << temp);
+ if (++cnt == RX_MACRO_MAX_DMA_CH_PER_PORT)
+ break;
+ }
+ /*
+ * CDC_DMA_RX_0 port drives RX0/RX1 -- ch_mask 0x1/0x2/0x3
+ * CDC_DMA_RX_1 port drives RX2/RX3 -- ch_mask 0x1/0x2/0x3
+ * CDC_DMA_RX_2 port drives RX4 -- ch_mask 0x1
+ * CDC_DMA_RX_3 port drives RX5 -- ch_mask 0x1
+ * AIFn can pair to any CDC_DMA_RX_n port.
+ * In general, below convention is used::
+ * CDC_DMA_RX_0(AIF1)/CDC_DMA_RX_1(AIF2)/
+ * CDC_DMA_RX_2(AIF3)/CDC_DMA_RX_3(AIF4)
+ */
+ if (mask & 0x0C)
+ mask = mask >> 2;
+ if ((mask & 0x10) || (mask & 0x20))
+ mask = 0x1;
+ *rx_slot = mask;
+ *rx_num = rx->active_ch_cnt[dai->id];
+ break;
+ case RX_MACRO_AIF_ECHO:
+ val = snd_soc_component_read(component, CDC_RX_INP_MUX_RX_MIX_CFG4);
+ if (val & RX_MACRO_EC_MIX_TX0_MASK) {
+ mask |= 0x1;
+ cnt++;
+ }
+ if (val & RX_MACRO_EC_MIX_TX1_MASK) {
+ mask |= 0x2;
+ cnt++;
+ }
+ val = snd_soc_component_read(component,
+ CDC_RX_INP_MUX_RX_MIX_CFG5);
+ if (val & RX_MACRO_EC_MIX_TX2_MASK) {
+ mask |= 0x4;
+ cnt++;
+ }
+ *tx_slot = mask;
+ *tx_num = cnt;
+ break;
+ default:
+ dev_err(component->dev, "%s: Invalid AIF\n", __func__);
+ break;
+ }
+ return 0;
+}
+
+static int rx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+ struct snd_soc_component *component = dai->component;
+ uint16_t j, reg, mix_reg, dsm_reg;
+ u16 int_mux_cfg0, int_mux_cfg1;
+ u8 int_mux_cfg0_val, int_mux_cfg1_val;
+
+ switch (dai->id) {
+ case RX_MACRO_AIF1_PB:
+ case RX_MACRO_AIF2_PB:
+ case RX_MACRO_AIF3_PB:
+ case RX_MACRO_AIF4_PB:
+ for (j = 0; j < INTERP_MAX; j++) {
+ reg = CDC_RX_RXn_RX_PATH_CTL(j);
+ mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j);
+ dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(j);
+
+ if (mute) {
+ snd_soc_component_update_bits(component, reg,
+ CDC_RX_PATH_PGA_MUTE_MASK,
+ CDC_RX_PATH_PGA_MUTE_ENABLE);
+ snd_soc_component_update_bits(component, mix_reg,
+ CDC_RX_PATH_PGA_MUTE_MASK,
+ CDC_RX_PATH_PGA_MUTE_ENABLE);
+ } else {
+ snd_soc_component_update_bits(component, reg,
+ CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
+ snd_soc_component_update_bits(component, mix_reg,
+ CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
+ }
+
+ if (j == INTERP_AUX)
+ dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL;
+
+ int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8;
+ int_mux_cfg1 = int_mux_cfg0 + 4;
+ int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0);
+ int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1);
+
+ if (snd_soc_component_read(component, dsm_reg) & 0x01) {
+ if (int_mux_cfg0_val || (int_mux_cfg1_val & 0xF0))
+ snd_soc_component_update_bits(component, reg, 0x20, 0x20);
+ if (int_mux_cfg1_val & 0x0F) {
+ snd_soc_component_update_bits(component, reg, 0x20, 0x20);
+ snd_soc_component_update_bits(component, mix_reg, 0x20, 0x20);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static struct snd_soc_dai_ops rx_macro_dai_ops = {
+ .hw_params = rx_macro_hw_params,
+ .get_channel_map = rx_macro_get_channel_map,
+ .mute_stream = rx_macro_digital_mute,
+};
+
+static struct snd_soc_dai_driver rx_macro_dai[] = {
+ {
+ .name = "rx_macro_rx1",
+ .id = RX_MACRO_AIF1_PB,
+ .playback = {
+ .stream_name = "RX_MACRO_AIF1 Playback",
+ .rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES,
+ .formats = RX_MACRO_FORMATS,
+ .rate_max = 384000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &rx_macro_dai_ops,
+ },
+ {
+ .name = "rx_macro_rx2",
+ .id = RX_MACRO_AIF2_PB,
+ .playback = {
+ .stream_name = "RX_MACRO_AIF2 Playback",
+ .rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES,
+ .formats = RX_MACRO_FORMATS,
+ .rate_max = 384000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &rx_macro_dai_ops,
+ },
+ {
+ .name = "rx_macro_rx3",
+ .id = RX_MACRO_AIF3_PB,
+ .playback = {
+ .stream_name = "RX_MACRO_AIF3 Playback",
+ .rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES,
+ .formats = RX_MACRO_FORMATS,
+ .rate_max = 384000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &rx_macro_dai_ops,
+ },
+ {
+ .name = "rx_macro_rx4",
+ .id = RX_MACRO_AIF4_PB,
+ .playback = {
+ .stream_name = "RX_MACRO_AIF4 Playback",
+ .rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES,
+ .formats = RX_MACRO_FORMATS,
+ .rate_max = 384000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &rx_macro_dai_ops,
+ },
+ {
+ .name = "rx_macro_echo",
+ .id = RX_MACRO_AIF_ECHO,
+ .capture = {
+ .stream_name = "RX_AIF_ECHO Capture",
+ .rates = RX_MACRO_ECHO_RATES,
+ .formats = RX_MACRO_ECHO_FORMATS,
+ .rate_max = 48000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 3,
+ },
+ .ops = &rx_macro_dai_ops,
+ },
+};
+
+static void rx_macro_mclk_enable(struct rx_macro *rx, bool mclk_enable)
+{
+ struct regmap *regmap = rx->regmap;
+
+ if (mclk_enable) {
+ if (rx->rx_mclk_users == 0) {
+ regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_MCLK_CONTROL,
+ CDC_RX_CLK_MCLK_EN_MASK |
+ CDC_RX_CLK_MCLK2_EN_MASK,
+ CDC_RX_CLK_MCLK_ENABLE |
+ CDC_RX_CLK_MCLK2_ENABLE);
+ regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+ CDC_RX_FS_MCLK_CNT_CLR_MASK, 0x00);
+ regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+ CDC_RX_FS_MCLK_CNT_EN_MASK,
+ CDC_RX_FS_MCLK_CNT_ENABLE);
+ regcache_mark_dirty(regmap);
+ regcache_sync(regmap);
+ }
+ rx->rx_mclk_users++;
+ } else {
+ if (rx->rx_mclk_users <= 0) {
+ dev_err(rx->dev, "%s: clock already disabled\n", __func__);
+ rx->rx_mclk_users = 0;
+ return;
+ }
+ rx->rx_mclk_users--;
+ if (rx->rx_mclk_users == 0) {
+ regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+ CDC_RX_FS_MCLK_CNT_EN_MASK, 0x0);
+ regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL,
+ CDC_RX_FS_MCLK_CNT_CLR_MASK,
+ CDC_RX_FS_MCLK_CNT_CLR);
+ regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_MCLK_CONTROL,
+ CDC_RX_CLK_MCLK_EN_MASK |
+ CDC_RX_CLK_MCLK2_EN_MASK, 0x0);
+ }
+ }
+}
+
+static int rx_macro_mclk_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 rx_macro *rx = snd_soc_component_get_drvdata(component);
+ int ret = 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ rx_macro_mclk_enable(rx, true);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ rx_macro_mclk_enable(rx, false);
+ break;
+ default:
+ dev_err(component->dev, "%s: invalid DAPM event %d\n", __func__, event);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static bool rx_macro_adie_lb(struct snd_soc_component *component,
+ int interp_idx)
+{
+ u16 int_mux_cfg0, int_mux_cfg1;
+ u8 int_n_inp0, int_n_inp1, int_n_inp2;
+
+ int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + interp_idx * 8;
+ int_mux_cfg1 = int_mux_cfg0 + 4;
+
+ int_n_inp0 = snd_soc_component_read_field(component, int_mux_cfg0,
+ CDC_RX_INTX_1_MIX_INP0_SEL_MASK);
+ int_n_inp1 = snd_soc_component_read_field(component, int_mux_cfg0,
+ CDC_RX_INTX_1_MIX_INP1_SEL_MASK);
+ int_n_inp2 = snd_soc_component_read_field(component, int_mux_cfg1,
+ CDC_RX_INTX_1_MIX_INP2_SEL_MASK);
+
+ if (int_n_inp0 == INTn_1_INP_SEL_DEC0 ||
+ int_n_inp0 == INTn_1_INP_SEL_DEC1 ||
+ int_n_inp0 == INTn_1_INP_SEL_IIR0 ||
+ int_n_inp0 == INTn_1_INP_SEL_IIR1)
+ return true;
+
+ if (int_n_inp1 == INTn_1_INP_SEL_DEC0 ||
+ int_n_inp1 == INTn_1_INP_SEL_DEC1 ||
+ int_n_inp1 == INTn_1_INP_SEL_IIR0 ||
+ int_n_inp1 == INTn_1_INP_SEL_IIR1)
+ return true;
+
+ if (int_n_inp2 == INTn_1_INP_SEL_DEC0 ||
+ int_n_inp2 == INTn_1_INP_SEL_DEC1 ||
+ int_n_inp2 == INTn_1_INP_SEL_IIR0 ||
+ int_n_inp2 == INTn_1_INP_SEL_IIR1)
+ return true;
+
+ return false;
+}
+
+static int rx_macro_enable_interp_clk(struct snd_soc_component *component,
+ int event, int interp_idx);
+static int rx_macro_enable_main_path(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+ u16 gain_reg, reg;
+
+ reg = CDC_RX_RXn_RX_PATH_CTL(w->shift);
+ gain_reg = CDC_RX_RXn_RX_VOL_CTL(w->shift);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ rx_macro_enable_interp_clk(component, event, w->shift);
+ if (rx_macro_adie_lb(component, w->shift))
+ snd_soc_component_update_bits(component, reg,
+ CDC_RX_PATH_CLK_EN_MASK,
+ CDC_RX_PATH_CLK_ENABLE);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_component_write(component, gain_reg,
+ snd_soc_component_read(component, gain_reg));
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ rx_macro_enable_interp_clk(component, event, w->shift);
+ break;
+ }
+
+ return 0;
+}
+
+static int rx_macro_config_compander(struct snd_soc_component *component,
+ struct rx_macro *rx,
+ int comp, int event)
+{
+ u8 pcm_rate, val;
+
+ /* AUX does not have compander */
+ if (comp == INTERP_AUX)
+ return 0;
+
+ pcm_rate = snd_soc_component_read(component, CDC_RX_RXn_RX_PATH_CTL(comp)) & 0x0F;
+ if (pcm_rate < 0x06)
+ val = 0x03;
+ else if (pcm_rate < 0x08)
+ val = 0x01;
+ else if (pcm_rate < 0x0B)
+ val = 0x02;
+ else
+ val = 0x00;
+
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(comp),
+ CDC_RX_DC_COEFF_SEL_MASK, val);
+
+ if (SND_SOC_DAPM_EVENT_OFF(event))
+ snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(comp),
+ CDC_RX_DC_COEFF_SEL_MASK, 0x3);
+ if (!rx->comp_enabled[comp])
+ return 0;
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ /* Enable Compander Clock */
+ snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp),
+ CDC_RX_COMPANDERn_CLK_EN_MASK, 0x1);
+ snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp),
+ CDC_RX_COMPANDERn_SOFT_RST_MASK, 0x1);
+ snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp),
+ CDC_RX_COMPANDERn_SOFT_RST_MASK, 0x0);
+ snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG0(comp),
+ CDC_RX_RXn_COMP_EN_MASK, 0x1);
+ }
+
+ if (SND_SOC_DAPM_EVENT_OFF(event)) {
+ snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp),
+ CDC_RX_COMPANDERn_HALT_MASK, 0x1);
+ snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG0(comp),
+ CDC_RX_RXn_COMP_EN_MASK, 0x0);
+ snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp),
+ CDC_RX_COMPANDERn_CLK_EN_MASK, 0x0);
+ snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp),
+ CDC_RX_COMPANDERn_HALT_MASK, 0x0);
+ }
+
+ return 0;
+}
+
+static int rx_macro_load_compander_coeff(struct snd_soc_component *component,
+ struct rx_macro *rx,
+ int comp, int event)
+{
+ u16 comp_coeff_lsb_reg, comp_coeff_msb_reg;
+ int i;
+ int hph_pwr_mode = HPH_LOHIFI;
+
+ if (!rx->comp_enabled[comp])
+ return 0;
+
+ if (comp == INTERP_HPHL) {
+ comp_coeff_lsb_reg = CDC_RX_TOP_HPHL_COMP_WR_LSB;
+ comp_coeff_msb_reg = CDC_RX_TOP_HPHL_COMP_WR_MSB;
+ } else if (comp == INTERP_HPHR) {
+ comp_coeff_lsb_reg = CDC_RX_TOP_HPHR_COMP_WR_LSB;
+ comp_coeff_msb_reg = CDC_RX_TOP_HPHR_COMP_WR_MSB;
+ } else {
+ /* compander coefficients are loaded only for hph path */
+ return 0;
+ }
+
+ hph_pwr_mode = rx->hph_pwr_mode;
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ /* Load Compander Coeff */
+ for (i = 0; i < COMP_MAX_COEFF; i++) {
+ snd_soc_component_write(component, comp_coeff_lsb_reg,
+ comp_coeff_table[hph_pwr_mode][i].lsb);
+ snd_soc_component_write(component, comp_coeff_msb_reg,
+ comp_coeff_table[hph_pwr_mode][i].msb);
+ }
+ }
+
+ return 0;
+}
+
+static void rx_macro_enable_softclip_clk(struct snd_soc_component *component,
+ struct rx_macro *rx, bool enable)
+{
+ if (enable) {
+ if (rx->softclip_clk_users == 0)
+ snd_soc_component_write_field(component, CDC_RX_SOFTCLIP_CRC,
+ CDC_RX_SOFTCLIP_CLK_EN_MASK, 1);
+ rx->softclip_clk_users++;
+ } else {
+ rx->softclip_clk_users--;
+ if (rx->softclip_clk_users == 0)
+ snd_soc_component_write_field(component, CDC_RX_SOFTCLIP_CRC,
+ CDC_RX_SOFTCLIP_CLK_EN_MASK, 0);
+ }
+}
+
+static int rx_macro_config_softclip(struct snd_soc_component *component,
+ struct rx_macro *rx, int event)
+{
+
+ if (!rx->is_softclip_on)
+ return 0;
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ /* Enable Softclip clock */
+ rx_macro_enable_softclip_clk(component, rx, true);
+ /* Enable Softclip control */
+ snd_soc_component_write_field(component, CDC_RX_SOFTCLIP_SOFTCLIP_CTRL,
+ CDC_RX_SOFTCLIP_EN_MASK, 0x01);
+ }
+
+ if (SND_SOC_DAPM_EVENT_OFF(event)) {
+ snd_soc_component_write_field(component, CDC_RX_SOFTCLIP_SOFTCLIP_CTRL,
+ CDC_RX_SOFTCLIP_EN_MASK, 0x0);
+ rx_macro_enable_softclip_clk(component, rx, false);
+ }
+
+ return 0;
+}
+
+static int rx_macro_config_aux_hpf(struct snd_soc_component *component,
+ struct rx_macro *rx, int event)
+{
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ /* Update Aux HPF control */
+ if (!rx->is_aux_hpf_on)
+ snd_soc_component_update_bits(component,
+ CDC_RX_RX2_RX_PATH_CFG1, 0x04, 0x00);
+ }
+
+ if (SND_SOC_DAPM_EVENT_OFF(event)) {
+ /* Reset to default (HPF=ON) */
+ snd_soc_component_update_bits(component,
+ CDC_RX_RX2_RX_PATH_CFG1, 0x04, 0x04);
+ }
+
+ return 0;
+}
+
+static inline void rx_macro_enable_clsh_block(struct rx_macro *rx, bool enable)
+{
+ if ((enable && ++rx->clsh_users == 1) || (!enable && --rx->clsh_users == 0))
+ snd_soc_component_update_bits(rx->component, CDC_RX_CLSH_CRC,
+ CDC_RX_CLSH_CLK_EN_MASK, enable);
+ if (rx->clsh_users < 0)
+ rx->clsh_users = 0;
+}
+
+static int rx_macro_config_classh(struct snd_soc_component *component,
+ struct rx_macro *rx,
+ int interp_n, int event)
+{
+ if (SND_SOC_DAPM_EVENT_OFF(event)) {
+ rx_macro_enable_clsh_block(rx, false);
+ return 0;
+ }
+
+ if (!SND_SOC_DAPM_EVENT_ON(event))
+ return 0;
+
+ rx_macro_enable_clsh_block(rx, true);
+ if (interp_n == INTERP_HPHL ||
+ interp_n == INTERP_HPHR) {
+ /*
+ * These K1 values depend on the Headphone Impedance
+ * For now it is assumed to be 16 ohm
+ */
+ snd_soc_component_write(component, CDC_RX_CLSH_K1_LSB, 0xc0);
+ snd_soc_component_write_field(component, CDC_RX_CLSH_K1_MSB,
+ CDC_RX_CLSH_K1_MSB_COEFF_MASK, 0);
+ }
+ switch (interp_n) {
+ case INTERP_HPHL:
+ if (rx->is_ear_mode_on)
+ snd_soc_component_update_bits(component,
+ CDC_RX_CLSH_HPH_V_PA,
+ CDC_RX_CLSH_HPH_V_PA_MIN_MASK, 0x39);
+ else
+ snd_soc_component_update_bits(component,
+ CDC_RX_CLSH_HPH_V_PA,
+ CDC_RX_CLSH_HPH_V_PA_MIN_MASK, 0x1c);
+ snd_soc_component_update_bits(component,
+ CDC_RX_CLSH_DECAY_CTRL,
+ CDC_RX_CLSH_DECAY_RATE_MASK, 0x0);
+ snd_soc_component_write_field(component,
+ CDC_RX_RX0_RX_PATH_CFG0,
+ CDC_RX_RXn_CLSH_EN_MASK, 0x1);
+ break;
+ case INTERP_HPHR:
+ if (rx->is_ear_mode_on)
+ snd_soc_component_update_bits(component,
+ CDC_RX_CLSH_HPH_V_PA,
+ CDC_RX_CLSH_HPH_V_PA_MIN_MASK, 0x39);
+ else
+ snd_soc_component_update_bits(component,
+ CDC_RX_CLSH_HPH_V_PA,
+ CDC_RX_CLSH_HPH_V_PA_MIN_MASK, 0x1c);
+ snd_soc_component_update_bits(component,
+ CDC_RX_CLSH_DECAY_CTRL,
+ CDC_RX_CLSH_DECAY_RATE_MASK, 0x0);
+ snd_soc_component_update_bits(component,
+ CDC_RX_RX1_RX_PATH_CFG0,
+ CDC_RX_RXn_CLSH_EN_MASK, 0x1);
+ break;
+ case INTERP_AUX:
+ snd_soc_component_update_bits(component,
+ CDC_RX_RX2_RX_PATH_CFG0,
+ CDC_RX_RX2_DLY_Z_EN_MASK, 1);
+ snd_soc_component_write_field(component,
+ CDC_RX_RX2_RX_PATH_CFG0,
+ CDC_RX_RX2_CLSH_EN_MASK, 1);
+ break;
+ }
+
+ return 0;
+}
+
+static void rx_macro_hd2_control(struct snd_soc_component *component,
+ u16 interp_idx, int event)
+{
+ u16 hd2_scale_reg, hd2_enable_reg;
+
+ switch (interp_idx) {
+ case INTERP_HPHL:
+ hd2_scale_reg = CDC_RX_RX0_RX_PATH_SEC3;
+ hd2_enable_reg = CDC_RX_RX0_RX_PATH_CFG0;
+ break;
+ case INTERP_HPHR:
+ hd2_scale_reg = CDC_RX_RX1_RX_PATH_SEC3;
+ hd2_enable_reg = CDC_RX_RX1_RX_PATH_CFG0;
+ break;
+ }
+
+ if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
+ snd_soc_component_update_bits(component, hd2_scale_reg,
+ CDC_RX_RXn_HD2_ALPHA_MASK, 0x14);
+ snd_soc_component_write_field(component, hd2_enable_reg,
+ CDC_RX_RXn_HD2_EN_MASK, 1);
+ }
+
+ if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+ snd_soc_component_write_field(component, hd2_enable_reg,
+ CDC_RX_RXn_HD2_EN_MASK, 0);
+ snd_soc_component_update_bits(component, hd2_scale_reg,
+ CDC_RX_RXn_HD2_ALPHA_MASK, 0x0);
+ }
+}
+
+static int rx_macro_get_compander(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ int comp = ((struct soc_mixer_control *) kcontrol->private_value)->shift;
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = rx->comp_enabled[comp];
+ return 0;
+}
+
+static int rx_macro_set_compander(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ int comp = ((struct soc_mixer_control *) kcontrol->private_value)->shift;
+ int value = ucontrol->value.integer.value[0];
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ rx->comp_enabled[comp] = value;
+
+ return 0;
+}
+
+static int rx_macro_mux_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol);
+ struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] =
+ rx->rx_port_value[widget->shift];
+ return 0;
+}
+
+static int rx_macro_mux_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol);
+ struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ struct snd_soc_dapm_update *update = NULL;
+ u32 rx_port_value = ucontrol->value.integer.value[0];
+ u32 aif_rst;
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ aif_rst = rx->rx_port_value[widget->shift];
+ if (!rx_port_value) {
+ if (aif_rst == 0) {
+ dev_err(component->dev, "%s:AIF reset already\n", __func__);
+ return 0;
+ }
+ if (aif_rst > RX_MACRO_AIF4_PB) {
+ dev_err(component->dev, "%s: Invalid AIF reset\n", __func__);
+ return 0;
+ }
+ }
+ rx->rx_port_value[widget->shift] = rx_port_value;
+
+ switch (rx_port_value) {
+ case 0:
+ if (rx->active_ch_cnt[aif_rst]) {
+ clear_bit(widget->shift,
+ &rx->active_ch_mask[aif_rst]);
+ rx->active_ch_cnt[aif_rst]--;
+ }
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ set_bit(widget->shift,
+ &rx->active_ch_mask[rx_port_value]);
+ rx->active_ch_cnt[rx_port_value]++;
+ break;
+ default:
+ dev_err(component->dev,
+ "%s:Invalid AIF_ID for RX_MACRO MUX %d\n",
+ __func__, rx_port_value);
+ goto err;
+ }
+
+ snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
+ rx_port_value, e, update);
+ return 0;
+err:
+ return -EINVAL;
+}
+
+static const struct snd_kcontrol_new rx_macro_rx0_mux =
+ SOC_DAPM_ENUM_EXT("rx_macro_rx0", rx_macro_rx0_enum,
+ rx_macro_mux_get, rx_macro_mux_put);
+static const struct snd_kcontrol_new rx_macro_rx1_mux =
+ SOC_DAPM_ENUM_EXT("rx_macro_rx1", rx_macro_rx1_enum,
+ rx_macro_mux_get, rx_macro_mux_put);
+static const struct snd_kcontrol_new rx_macro_rx2_mux =
+ SOC_DAPM_ENUM_EXT("rx_macro_rx2", rx_macro_rx2_enum,
+ rx_macro_mux_get, rx_macro_mux_put);
+static const struct snd_kcontrol_new rx_macro_rx3_mux =
+ SOC_DAPM_ENUM_EXT("rx_macro_rx3", rx_macro_rx3_enum,
+ rx_macro_mux_get, rx_macro_mux_put);
+static const struct snd_kcontrol_new rx_macro_rx4_mux =
+ SOC_DAPM_ENUM_EXT("rx_macro_rx4", rx_macro_rx4_enum,
+ rx_macro_mux_get, rx_macro_mux_put);
+static const struct snd_kcontrol_new rx_macro_rx5_mux =
+ SOC_DAPM_ENUM_EXT("rx_macro_rx5", rx_macro_rx5_enum,
+ rx_macro_mux_get, rx_macro_mux_put);
+
+static int rx_macro_get_ear_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = rx->is_ear_mode_on;
+ return 0;
+}
+
+static int rx_macro_put_ear_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ rx->is_ear_mode_on = (!ucontrol->value.integer.value[0] ? false : true);
+ return 0;
+}
+
+static int rx_macro_get_hph_hd2_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = rx->hph_hd2_mode;
+ return 0;
+}
+
+static int rx_macro_put_hph_hd2_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ rx->hph_hd2_mode = ucontrol->value.integer.value[0];
+ return 0;
+}
+
+static int rx_macro_get_hph_pwr_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = rx->hph_pwr_mode;
+ return 0;
+}
+
+static int rx_macro_put_hph_pwr_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ rx->hph_pwr_mode = ucontrol->value.integer.value[0];
+ return 0;
+}
+
+static int rx_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = rx->is_softclip_on;
+
+ return 0;
+}
+
+static int rx_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ rx->is_softclip_on = ucontrol->value.integer.value[0];
+
+ return 0;
+}
+
+static int rx_macro_aux_hpf_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = rx->is_aux_hpf_on;
+
+ return 0;
+}
+
+static int rx_macro_aux_hpf_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ rx->is_aux_hpf_on = ucontrol->value.integer.value[0];
+
+ return 0;
+}
+
+static int rx_macro_hphdelay_lutbypass(struct snd_soc_component *component,
+ struct rx_macro *rx,
+ u16 interp_idx, int event)
+{
+ u16 hph_lut_bypass_reg;
+ u16 hph_comp_ctrl7;
+
+ switch (interp_idx) {
+ case INTERP_HPHL:
+ hph_lut_bypass_reg = CDC_RX_TOP_HPHL_COMP_LUT;
+ hph_comp_ctrl7 = CDC_RX_COMPANDER0_CTL7;
+ break;
+ case INTERP_HPHR:
+ hph_lut_bypass_reg = CDC_RX_TOP_HPHR_COMP_LUT;
+ hph_comp_ctrl7 = CDC_RX_COMPANDER1_CTL7;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_ON(event)) {
+ if (interp_idx == INTERP_HPHL) {
+ if (rx->is_ear_mode_on)
+ snd_soc_component_write_field(component,
+ CDC_RX_RX0_RX_PATH_CFG1,
+ CDC_RX_RX0_HPH_L_EAR_SEL_MASK, 0x1);
+ else
+ snd_soc_component_write_field(component,
+ hph_lut_bypass_reg,
+ CDC_RX_TOP_HPH_LUT_BYPASS_MASK, 1);
+ } else {
+ snd_soc_component_write_field(component, hph_lut_bypass_reg,
+ CDC_RX_TOP_HPH_LUT_BYPASS_MASK, 1);
+ }
+ if (rx->hph_pwr_mode)
+ snd_soc_component_write_field(component, hph_comp_ctrl7,
+ CDC_RX_COMPANDER1_HPH_LOW_PWR_MODE_MASK, 0x0);
+ }
+
+ if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+ snd_soc_component_write_field(component,
+ CDC_RX_RX0_RX_PATH_CFG1,
+ CDC_RX_RX0_HPH_L_EAR_SEL_MASK, 0x0);
+ snd_soc_component_update_bits(component, hph_lut_bypass_reg,
+ CDC_RX_TOP_HPH_LUT_BYPASS_MASK, 0);
+ snd_soc_component_write_field(component, hph_comp_ctrl7,
+ CDC_RX_COMPANDER1_HPH_LOW_PWR_MODE_MASK, 0x1);
+ }
+
+ return 0;
+}
+
+static int rx_macro_enable_interp_clk(struct snd_soc_component *component,
+ int event, int interp_idx)
+{
+ u16 main_reg, dsm_reg, rx_cfg2_reg;
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ main_reg = CDC_RX_RXn_RX_PATH_CTL(interp_idx);
+ dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(interp_idx);
+ if (interp_idx == INTERP_AUX)
+ dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL;
+ rx_cfg2_reg = CDC_RX_RXn_RX_PATH_CFG2(interp_idx);
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ if (rx->main_clk_users[interp_idx] == 0) {
+ /* Main path PGA mute enable */
+ snd_soc_component_write_field(component, main_reg,
+ CDC_RX_PATH_PGA_MUTE_MASK, 0x1);
+ snd_soc_component_write_field(component, dsm_reg,
+ CDC_RX_RXn_DSM_CLK_EN_MASK, 0x1);
+ snd_soc_component_update_bits(component, rx_cfg2_reg,
+ CDC_RX_RXn_HPF_CUT_FREQ_MASK, 0x03);
+ rx_macro_load_compander_coeff(component, rx, interp_idx, event);
+ if (rx->hph_hd2_mode)
+ rx_macro_hd2_control(component, interp_idx, event);
+ rx_macro_hphdelay_lutbypass(component, rx, interp_idx, event);
+ rx_macro_config_compander(component, rx, interp_idx, event);
+ if (interp_idx == INTERP_AUX) {
+ rx_macro_config_softclip(component, rx, event);
+ rx_macro_config_aux_hpf(component, rx, event);
+ }
+ rx_macro_config_classh(component, rx, interp_idx, event);
+ }
+ rx->main_clk_users[interp_idx]++;
+ }
+
+ if (SND_SOC_DAPM_EVENT_OFF(event)) {
+ rx->main_clk_users[interp_idx]--;
+ if (rx->main_clk_users[interp_idx] <= 0) {
+ rx->main_clk_users[interp_idx] = 0;
+ /* Main path PGA mute enable */
+ snd_soc_component_write_field(component, main_reg,
+ CDC_RX_PATH_PGA_MUTE_MASK, 0x1);
+ /* Clk Disable */
+ snd_soc_component_write_field(component, dsm_reg,
+ CDC_RX_RXn_DSM_CLK_EN_MASK, 0);
+ snd_soc_component_write_field(component, main_reg,
+ CDC_RX_PATH_CLK_EN_MASK, 0);
+ /* Reset enable and disable */
+ snd_soc_component_write_field(component, main_reg,
+ CDC_RX_PATH_RESET_EN_MASK, 1);
+ snd_soc_component_write_field(component, main_reg,
+ CDC_RX_PATH_RESET_EN_MASK, 0);
+ /* Reset rate to 48K*/
+ snd_soc_component_update_bits(component, main_reg,
+ CDC_RX_PATH_PCM_RATE_MASK,
+ 0x04);
+ snd_soc_component_update_bits(component, rx_cfg2_reg,
+ CDC_RX_RXn_HPF_CUT_FREQ_MASK, 0x00);
+ rx_macro_config_classh(component, rx, interp_idx, event);
+ rx_macro_config_compander(component, rx, interp_idx, event);
+ if (interp_idx == INTERP_AUX) {
+ rx_macro_config_softclip(component, rx, event);
+ rx_macro_config_aux_hpf(component, rx, event);
+ }
+ rx_macro_hphdelay_lutbypass(component, rx, interp_idx, event);
+ if (rx->hph_hd2_mode)
+ rx_macro_hd2_control(component, interp_idx, event);
+ }
+ }
+
+ return rx->main_clk_users[interp_idx];
+}
+
+static int rx_macro_enable_mix_path(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+ u16 gain_reg, mix_reg;
+
+ gain_reg = CDC_RX_RXn_RX_VOL_MIX_CTL(w->shift);
+ mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(w->shift);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ rx_macro_enable_interp_clk(component, event, w->shift);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_component_write(component, gain_reg,
+ snd_soc_component_read(component, gain_reg));
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /* Clk Disable */
+ snd_soc_component_update_bits(component, mix_reg,
+ CDC_RX_RXn_MIX_CLK_EN_MASK, 0x00);
+ rx_macro_enable_interp_clk(component, event, w->shift);
+ /* Reset enable and disable */
+ snd_soc_component_update_bits(component, mix_reg,
+ CDC_RX_RXn_MIX_RESET_MASK,
+ CDC_RX_RXn_MIX_RESET);
+ snd_soc_component_update_bits(component, mix_reg,
+ CDC_RX_RXn_MIX_RESET_MASK, 0x00);
+ break;
+ }
+
+ return 0;
+}
+
+static int rx_macro_enable_rx_path_clk(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_PRE_PMU:
+ rx_macro_enable_interp_clk(component, event, w->shift);
+ snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG1(w->shift),
+ CDC_RX_RXn_SIDETONE_EN_MASK, 1);
+ snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CTL(w->shift),
+ CDC_RX_PATH_CLK_EN_MASK, 1);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG1(w->shift),
+ CDC_RX_RXn_SIDETONE_EN_MASK, 0);
+ rx_macro_enable_interp_clk(component, event, w->shift);
+ break;
+ default:
+ break;
+ };
+ return 0;
+}
+
+static int rx_macro_set_iir_gain(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: /* fall through */
+ case SND_SOC_DAPM_PRE_PMD:
+ if (strnstr(w->name, "IIR0", sizeof("IIR0"))) {
+ snd_soc_component_write(component,
+ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL,
+ snd_soc_component_read(component,
+ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL));
+ snd_soc_component_write(component,
+ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL,
+ snd_soc_component_read(component,
+ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL));
+ snd_soc_component_write(component,
+ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL,
+ snd_soc_component_read(component,
+ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL));
+ snd_soc_component_write(component,
+ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL,
+ snd_soc_component_read(component,
+ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL));
+ } else {
+ snd_soc_component_write(component,
+ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL,
+ snd_soc_component_read(component,
+ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL));
+ snd_soc_component_write(component,
+ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL,
+ snd_soc_component_read(component,
+ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL));
+ snd_soc_component_write(component,
+ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL,
+ snd_soc_component_read(component,
+ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL));
+ snd_soc_component_write(component,
+ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL,
+ snd_soc_component_read(component,
+ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL));
+ }
+ break;
+ }
+ return 0;
+}
+
+static uint32_t get_iir_band_coeff(struct snd_soc_component *component,
+ int iir_idx, int band_idx, int coeff_idx)
+{
+ u32 value;
+ int reg, b2_reg;
+
+ /* Address does not automatically update if reading */
+ reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx;
+ b2_reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx;
+
+ snd_soc_component_write(component, reg,
+ ((band_idx * BAND_MAX + coeff_idx) *
+ sizeof(uint32_t)) & 0x7F);
+
+ value = snd_soc_component_read(component, b2_reg);
+ snd_soc_component_write(component, reg,
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 1) & 0x7F);
+
+ value |= (snd_soc_component_read(component, b2_reg) << 8);
+ snd_soc_component_write(component, reg,
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 2) & 0x7F);
+
+ value |= (snd_soc_component_read(component, b2_reg) << 16);
+ snd_soc_component_write(component, reg,
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 3) & 0x7F);
+
+ /* Mask bits top 2 bits since they are reserved */
+ value |= (snd_soc_component_read(component, b2_reg) << 24);
+ return value;
+}
+
+static void set_iir_band_coeff(struct snd_soc_component *component,
+ int iir_idx, int band_idx, uint32_t value)
+{
+ int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx;
+
+ snd_soc_component_write(component, reg, (value & 0xFF));
+ snd_soc_component_write(component, reg, (value >> 8) & 0xFF);
+ snd_soc_component_write(component, reg, (value >> 16) & 0xFF);
+ /* Mask top 2 bits, 7-8 are reserved */
+ snd_soc_component_write(component, reg, (value >> 24) & 0x3F);
+}
+
+static int rx_macro_put_iir_band_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct wcd_iir_filter_ctl *ctl =
+ (struct wcd_iir_filter_ctl *)kcontrol->private_value;
+ struct soc_bytes_ext *params = &ctl->bytes_ext;
+ int iir_idx = ctl->iir_idx;
+ int band_idx = ctl->band_idx;
+ u32 coeff[BAND_MAX];
+ int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx;
+
+ memcpy(&coeff[0], ucontrol->value.bytes.data, params->max);
+
+ /* Mask top bit it is reserved */
+ /* Updates addr automatically for each B2 write */
+ snd_soc_component_write(component, reg, (band_idx * BAND_MAX *
+ sizeof(uint32_t)) & 0x7F);
+
+ set_iir_band_coeff(component, iir_idx, band_idx, coeff[0]);
+ set_iir_band_coeff(component, iir_idx, band_idx, coeff[1]);
+ set_iir_band_coeff(component, iir_idx, band_idx, coeff[2]);
+ set_iir_band_coeff(component, iir_idx, band_idx, coeff[3]);
+ set_iir_band_coeff(component, iir_idx, band_idx, coeff[4]);
+
+ return 0;
+}
+
+static int rx_macro_get_iir_band_audio_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct wcd_iir_filter_ctl *ctl =
+ (struct wcd_iir_filter_ctl *)kcontrol->private_value;
+ struct soc_bytes_ext *params = &ctl->bytes_ext;
+ int iir_idx = ctl->iir_idx;
+ int band_idx = ctl->band_idx;
+ u32 coeff[BAND_MAX];
+
+ coeff[0] = get_iir_band_coeff(component, iir_idx, band_idx, 0);
+ coeff[1] = get_iir_band_coeff(component, iir_idx, band_idx, 1);
+ coeff[2] = get_iir_band_coeff(component, iir_idx, band_idx, 2);
+ coeff[3] = get_iir_band_coeff(component, iir_idx, band_idx, 3);
+ coeff[4] = get_iir_band_coeff(component, iir_idx, band_idx, 4);
+
+ memcpy(ucontrol->value.bytes.data, &coeff[0], params->max);
+
+ return 0;
+}
+
+static int rx_macro_iir_filter_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *ucontrol)
+{
+ struct wcd_iir_filter_ctl *ctl =
+ (struct wcd_iir_filter_ctl *)kcontrol->private_value;
+ struct soc_bytes_ext *params = &ctl->bytes_ext;
+
+ ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ ucontrol->count = params->max;
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new rx_macro_snd_controls[] = {
+ SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume", CDC_RX_RX0_RX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX_RX1 Digital Volume", CDC_RX_RX1_RX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX_RX2 Digital Volume", CDC_RX_RX2_RX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX_RX0 Mix Digital Volume", CDC_RX_RX0_RX_VOL_MIX_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX_RX1 Mix Digital Volume", CDC_RX_RX1_RX_VOL_MIX_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX_RX2 Mix Digital Volume", CDC_RX_RX2_RX_VOL_MIX_CTL,
+ -84, 40, digital_gain),
+
+ SOC_SINGLE_EXT("RX_COMP1 Switch", SND_SOC_NOPM, RX_MACRO_COMP1, 1, 0,
+ rx_macro_get_compander, rx_macro_set_compander),
+ SOC_SINGLE_EXT("RX_COMP2 Switch", SND_SOC_NOPM, RX_MACRO_COMP2, 1, 0,
+ rx_macro_get_compander, rx_macro_set_compander),
+
+ SOC_SINGLE_EXT("RX_EAR Mode Switch", SND_SOC_NOPM, 0, 1, 0,
+ rx_macro_get_ear_mode, rx_macro_put_ear_mode),
+
+ SOC_SINGLE_EXT("RX_HPH HD2 Mode Switch", SND_SOC_NOPM, 0, 1, 0,
+ rx_macro_get_hph_hd2_mode, rx_macro_put_hph_hd2_mode),
+
+ SOC_ENUM_EXT("RX_HPH PWR Mode", rx_macro_hph_pwr_mode_enum,
+ rx_macro_get_hph_pwr_mode, rx_macro_put_hph_pwr_mode),
+
+ SOC_SINGLE_EXT("RX_Softclip Switch", SND_SOC_NOPM, 0, 1, 0,
+ rx_macro_soft_clip_enable_get,
+ rx_macro_soft_clip_enable_put),
+ SOC_SINGLE_EXT("AUX_HPF Switch", SND_SOC_NOPM, 0, 1, 0,
+ rx_macro_aux_hpf_mode_get,
+ rx_macro_aux_hpf_mode_put),
+
+ SOC_SINGLE_S8_TLV("IIR0 INP0 Volume",
+ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR0 INP1 Volume",
+ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR0 INP2 Volume",
+ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR0 INP3 Volume",
+ CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP0 Volume",
+ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP1 Volume",
+ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP2 Volume",
+ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP3 Volume",
+ CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, -84, 40,
+ digital_gain),
+
+ SOC_SINGLE("IIR1 Band1 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL,
+ 0, 1, 0),
+ SOC_SINGLE("IIR1 Band2 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL,
+ 1, 1, 0),
+ SOC_SINGLE("IIR1 Band3 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL,
+ 2, 1, 0),
+ SOC_SINGLE("IIR1 Band4 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL,
+ 3, 1, 0),
+ SOC_SINGLE("IIR1 Band5 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL,
+ 4, 1, 0),
+ SOC_SINGLE("IIR2 Band1 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL,
+ 0, 1, 0),
+ SOC_SINGLE("IIR2 Band2 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL,
+ 1, 1, 0),
+ SOC_SINGLE("IIR2 Band3 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL,
+ 2, 1, 0),
+ SOC_SINGLE("IIR2 Band4 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL,
+ 3, 1, 0),
+ SOC_SINGLE("IIR2 Band5 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL,
+ 4, 1, 0),
+
+ RX_MACRO_IIR_FILTER_CTL("IIR0 Band1", IIR0, BAND1),
+ RX_MACRO_IIR_FILTER_CTL("IIR0 Band2", IIR0, BAND2),
+ RX_MACRO_IIR_FILTER_CTL("IIR0 Band3", IIR0, BAND3),
+ RX_MACRO_IIR_FILTER_CTL("IIR0 Band4", IIR0, BAND4),
+ RX_MACRO_IIR_FILTER_CTL("IIR0 Band5", IIR0, BAND5),
+
+ RX_MACRO_IIR_FILTER_CTL("IIR1 Band1", IIR1, BAND1),
+ RX_MACRO_IIR_FILTER_CTL("IIR1 Band2", IIR1, BAND2),
+ RX_MACRO_IIR_FILTER_CTL("IIR1 Band3", IIR1, BAND3),
+ RX_MACRO_IIR_FILTER_CTL("IIR1 Band4", IIR1, BAND4),
+ RX_MACRO_IIR_FILTER_CTL("IIR1 Band5", IIR1, BAND5),
+
+};
+
+static int rx_macro_enable_echo(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+ u16 val, ec_hq_reg;
+ int ec_tx;
+
+ val = snd_soc_component_read(component,
+ CDC_RX_INP_MUX_RX_MIX_CFG4);
+ if (!(strcmp(w->name, "RX MIX TX0 MUX")))
+ ec_tx = ((val & 0xf0) >> 0x4) - 1;
+ else if (!(strcmp(w->name, "RX MIX TX1 MUX")))
+ ec_tx = (val & 0x0f) - 1;
+
+ val = snd_soc_component_read(component,
+ CDC_RX_INP_MUX_RX_MIX_CFG5);
+ if (!(strcmp(w->name, "RX MIX TX2 MUX")))
+ ec_tx = (val & 0x0f) - 1;
+
+ if (ec_tx < 0 || (ec_tx >= RX_MACRO_EC_MUX_MAX)) {
+ dev_err(component->dev, "%s: EC mix control not set correctly\n",
+ __func__);
+ return -EINVAL;
+ }
+ ec_hq_reg = CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL +
+ 0x40 * ec_tx;
+ snd_soc_component_update_bits(component, ec_hq_reg, 0x01, 0x01);
+ ec_hq_reg = CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0 +
+ 0x40 * ec_tx;
+ /* default set to 48k */
+ snd_soc_component_update_bits(component, ec_hq_reg, 0x1E, 0x08);
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget rx_macro_dapm_widgets[] = {
+ SND_SOC_DAPM_AIF_IN("RX AIF1 PB", "RX_MACRO_AIF1 Playback", 0,
+ SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_AIF_IN("RX AIF2 PB", "RX_MACRO_AIF2 Playback", 0,
+ SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_AIF_IN("RX AIF3 PB", "RX_MACRO_AIF3 Playback", 0,
+ SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_AIF_IN("RX AIF4 PB", "RX_MACRO_AIF4 Playback", 0,
+ SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_AIF_OUT("RX AIF_ECHO", "RX_AIF_ECHO Capture", 0,
+ SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_MUX("RX_MACRO RX0 MUX", SND_SOC_NOPM, RX_MACRO_RX0, 0,
+ &rx_macro_rx0_mux),
+ SND_SOC_DAPM_MUX("RX_MACRO RX1 MUX", SND_SOC_NOPM, RX_MACRO_RX1, 0,
+ &rx_macro_rx1_mux),
+ SND_SOC_DAPM_MUX("RX_MACRO RX2 MUX", SND_SOC_NOPM, RX_MACRO_RX2, 0,
+ &rx_macro_rx2_mux),
+ SND_SOC_DAPM_MUX("RX_MACRO RX3 MUX", SND_SOC_NOPM, RX_MACRO_RX3, 0,
+ &rx_macro_rx3_mux),
+ SND_SOC_DAPM_MUX("RX_MACRO RX4 MUX", SND_SOC_NOPM, RX_MACRO_RX4, 0,
+ &rx_macro_rx4_mux),
+ SND_SOC_DAPM_MUX("RX_MACRO RX5 MUX", SND_SOC_NOPM, RX_MACRO_RX5, 0,
+ &rx_macro_rx5_mux),
+
+ SND_SOC_DAPM_MIXER("RX_RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX_RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX_RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX_RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX_RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX_RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("IIR0 INP0 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp0_mux),
+ SND_SOC_DAPM_MUX("IIR0 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp1_mux),
+ SND_SOC_DAPM_MUX("IIR0 INP2 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp2_mux),
+ SND_SOC_DAPM_MUX("IIR0 INP3 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp3_mux),
+ SND_SOC_DAPM_MUX("IIR1 INP0 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp0_mux),
+ SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
+ SND_SOC_DAPM_MUX("IIR1 INP2 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp2_mux),
+ SND_SOC_DAPM_MUX("IIR1 INP3 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp3_mux),
+
+ SND_SOC_DAPM_MUX_E("RX MIX TX0 MUX", SND_SOC_NOPM,
+ RX_MACRO_EC0_MUX, 0,
+ &rx_mix_tx0_mux, rx_macro_enable_echo,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX MIX TX1 MUX", SND_SOC_NOPM,
+ RX_MACRO_EC1_MUX, 0,
+ &rx_mix_tx1_mux, rx_macro_enable_echo,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX MIX TX2 MUX", SND_SOC_NOPM,
+ RX_MACRO_EC2_MUX, 0,
+ &rx_mix_tx2_mux, rx_macro_enable_echo,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MIXER_E("IIR0", CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL,
+ 4, 0, NULL, 0, rx_macro_set_iir_gain,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_MIXER_E("IIR1", CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL,
+ 4, 0, NULL, 0, rx_macro_set_iir_gain,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_MIXER("SRC0", CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL,
+ 4, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SRC1", CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL,
+ 4, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("RX INT0 DEM MUX", SND_SOC_NOPM, 0, 0,
+ &rx_int0_dem_inp_mux),
+ SND_SOC_DAPM_MUX("RX INT1 DEM MUX", SND_SOC_NOPM, 0, 0,
+ &rx_int1_dem_inp_mux),
+
+ SND_SOC_DAPM_MUX_E("RX INT0_2 MUX", SND_SOC_NOPM, INTERP_HPHL, 0,
+ &rx_int0_2_mux, rx_macro_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT1_2 MUX", SND_SOC_NOPM, INTERP_HPHR, 0,
+ &rx_int1_2_mux, rx_macro_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT2_2 MUX", SND_SOC_NOPM, INTERP_AUX, 0,
+ &rx_int2_2_mux, rx_macro_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP0", SND_SOC_NOPM, 0, 0, &rx_int0_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP1", SND_SOC_NOPM, 0, 0, &rx_int0_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP2", SND_SOC_NOPM, 0, 0, &rx_int0_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP0", SND_SOC_NOPM, 0, 0, &rx_int1_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP1", SND_SOC_NOPM, 0, 0, &rx_int1_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP2", SND_SOC_NOPM, 0, 0, &rx_int1_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP0", SND_SOC_NOPM, 0, 0, &rx_int2_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP1", SND_SOC_NOPM, 0, 0, &rx_int2_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP2", SND_SOC_NOPM, 0, 0, &rx_int2_1_mix_inp2_mux),
+
+ SND_SOC_DAPM_MUX_E("RX INT0_1 INTERP", SND_SOC_NOPM, INTERP_HPHL, 0,
+ &rx_int0_1_interp_mux, rx_macro_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT1_1 INTERP", SND_SOC_NOPM, INTERP_HPHR, 0,
+ &rx_int1_1_interp_mux, rx_macro_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT2_1 INTERP", SND_SOC_NOPM, INTERP_AUX, 0,
+ &rx_int2_1_interp_mux, rx_macro_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("RX INT0_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int0_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT1_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int1_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT2_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int2_2_interp_mux),
+
+ SND_SOC_DAPM_MIXER("RX INT0_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT1_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT2_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT2 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX_E("RX INT0 MIX2 INP", SND_SOC_NOPM, INTERP_HPHL,
+ 0, &rx_int0_mix2_inp_mux, rx_macro_enable_rx_path_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT1 MIX2 INP", SND_SOC_NOPM, INTERP_HPHR,
+ 0, &rx_int1_mix2_inp_mux, rx_macro_enable_rx_path_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT2 MIX2 INP", SND_SOC_NOPM, INTERP_AUX,
+ 0, &rx_int2_mix2_inp_mux, rx_macro_enable_rx_path_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MIXER("RX INT0 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT1 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT2 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_OUTPUT("HPHL_OUT"),
+ SND_SOC_DAPM_OUTPUT("HPHR_OUT"),
+ SND_SOC_DAPM_OUTPUT("AUX_OUT"),
+
+ SND_SOC_DAPM_INPUT("RX_TX DEC0_INP"),
+ SND_SOC_DAPM_INPUT("RX_TX DEC1_INP"),
+ SND_SOC_DAPM_INPUT("RX_TX DEC2_INP"),
+ SND_SOC_DAPM_INPUT("RX_TX DEC3_INP"),
+
+ SND_SOC_DAPM_SUPPLY_S("RX_MCLK", 0, SND_SOC_NOPM, 0, 0,
+ rx_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route rx_audio_map[] = {
+ {"RX AIF1 PB", NULL, "RX_MCLK"},
+ {"RX AIF2 PB", NULL, "RX_MCLK"},
+ {"RX AIF3 PB", NULL, "RX_MCLK"},
+ {"RX AIF4 PB", NULL, "RX_MCLK"},
+
+ {"RX_MACRO RX0 MUX", "AIF1_PB", "RX AIF1 PB"},
+ {"RX_MACRO RX1 MUX", "AIF1_PB", "RX AIF1 PB"},
+ {"RX_MACRO RX2 MUX", "AIF1_PB", "RX AIF1 PB"},
+ {"RX_MACRO RX3 MUX", "AIF1_PB", "RX AIF1 PB"},
+ {"RX_MACRO RX4 MUX", "AIF1_PB", "RX AIF1 PB"},
+ {"RX_MACRO RX5 MUX", "AIF1_PB", "RX AIF1 PB"},
+
+ {"RX_MACRO RX0 MUX", "AIF2_PB", "RX AIF2 PB"},
+ {"RX_MACRO RX1 MUX", "AIF2_PB", "RX AIF2 PB"},
+ {"RX_MACRO RX2 MUX", "AIF2_PB", "RX AIF2 PB"},
+ {"RX_MACRO RX3 MUX", "AIF2_PB", "RX AIF2 PB"},
+ {"RX_MACRO RX4 MUX", "AIF2_PB", "RX AIF2 PB"},
+ {"RX_MACRO RX5 MUX", "AIF2_PB", "RX AIF2 PB"},
+
+ {"RX_MACRO RX0 MUX", "AIF3_PB", "RX AIF3 PB"},
+ {"RX_MACRO RX1 MUX", "AIF3_PB", "RX AIF3 PB"},
+ {"RX_MACRO RX2 MUX", "AIF3_PB", "RX AIF3 PB"},
+ {"RX_MACRO RX3 MUX", "AIF3_PB", "RX AIF3 PB"},
+ {"RX_MACRO RX4 MUX", "AIF3_PB", "RX AIF3 PB"},
+ {"RX_MACRO RX5 MUX", "AIF3_PB", "RX AIF3 PB"},
+
+ {"RX_MACRO RX0 MUX", "AIF4_PB", "RX AIF4 PB"},
+ {"RX_MACRO RX1 MUX", "AIF4_PB", "RX AIF4 PB"},
+ {"RX_MACRO RX2 MUX", "AIF4_PB", "RX AIF4 PB"},
+ {"RX_MACRO RX3 MUX", "AIF4_PB", "RX AIF4 PB"},
+ {"RX_MACRO RX4 MUX", "AIF4_PB", "RX AIF4 PB"},
+ {"RX_MACRO RX5 MUX", "AIF4_PB", "RX AIF4 PB"},
+
+ {"RX_RX0", NULL, "RX_MACRO RX0 MUX"},
+ {"RX_RX1", NULL, "RX_MACRO RX1 MUX"},
+ {"RX_RX2", NULL, "RX_MACRO RX2 MUX"},
+ {"RX_RX3", NULL, "RX_MACRO RX3 MUX"},
+ {"RX_RX4", NULL, "RX_MACRO RX4 MUX"},
+ {"RX_RX5", NULL, "RX_MACRO RX5 MUX"},
+
+ {"RX INT0_1 MIX1 INP0", "RX0", "RX_RX0"},
+ {"RX INT0_1 MIX1 INP0", "RX1", "RX_RX1"},
+ {"RX INT0_1 MIX1 INP0", "RX2", "RX_RX2"},
+ {"RX INT0_1 MIX1 INP0", "RX3", "RX_RX3"},
+ {"RX INT0_1 MIX1 INP0", "RX4", "RX_RX4"},
+ {"RX INT0_1 MIX1 INP0", "RX5", "RX_RX5"},
+ {"RX INT0_1 MIX1 INP0", "IIR0", "IIR0"},
+ {"RX INT0_1 MIX1 INP0", "IIR1", "IIR1"},
+ {"RX INT0_1 MIX1 INP0", "DEC0", "RX_TX DEC0_INP"},
+ {"RX INT0_1 MIX1 INP0", "DEC1", "RX_TX DEC1_INP"},
+ {"RX INT0_1 MIX1 INP1", "RX0", "RX_RX0"},
+ {"RX INT0_1 MIX1 INP1", "RX1", "RX_RX1"},
+ {"RX INT0_1 MIX1 INP1", "RX2", "RX_RX2"},
+ {"RX INT0_1 MIX1 INP1", "RX3", "RX_RX3"},
+ {"RX INT0_1 MIX1 INP1", "RX4", "RX_RX4"},
+ {"RX INT0_1 MIX1 INP1", "RX5", "RX_RX5"},
+ {"RX INT0_1 MIX1 INP1", "IIR0", "IIR0"},
+ {"RX INT0_1 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX INT0_1 MIX1 INP1", "DEC0", "RX_TX DEC0_INP"},
+ {"RX INT0_1 MIX1 INP1", "DEC1", "RX_TX DEC1_INP"},
+ {"RX INT0_1 MIX1 INP2", "RX0", "RX_RX0"},
+ {"RX INT0_1 MIX1 INP2", "RX1", "RX_RX1"},
+ {"RX INT0_1 MIX1 INP2", "RX2", "RX_RX2"},
+ {"RX INT0_1 MIX1 INP2", "RX3", "RX_RX3"},
+ {"RX INT0_1 MIX1 INP2", "RX4", "RX_RX4"},
+ {"RX INT0_1 MIX1 INP2", "RX5", "RX_RX5"},
+ {"RX INT0_1 MIX1 INP2", "IIR0", "IIR0"},
+ {"RX INT0_1 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX INT0_1 MIX1 INP2", "DEC0", "RX_TX DEC0_INP"},
+ {"RX INT0_1 MIX1 INP2", "DEC1", "RX_TX DEC1_INP"},
+
+ {"RX INT1_1 MIX1 INP0", "RX0", "RX_RX0"},
+ {"RX INT1_1 MIX1 INP0", "RX1", "RX_RX1"},
+ {"RX INT1_1 MIX1 INP0", "RX2", "RX_RX2"},
+ {"RX INT1_1 MIX1 INP0", "RX3", "RX_RX3"},
+ {"RX INT1_1 MIX1 INP0", "RX4", "RX_RX4"},
+ {"RX INT1_1 MIX1 INP0", "RX5", "RX_RX5"},
+ {"RX INT1_1 MIX1 INP0", "IIR0", "IIR0"},
+ {"RX INT1_1 MIX1 INP0", "IIR1", "IIR1"},
+ {"RX INT1_1 MIX1 INP0", "DEC0", "RX_TX DEC0_INP"},
+ {"RX INT1_1 MIX1 INP0", "DEC1", "RX_TX DEC1_INP"},
+ {"RX INT1_1 MIX1 INP1", "RX0", "RX_RX0"},
+ {"RX INT1_1 MIX1 INP1", "RX1", "RX_RX1"},
+ {"RX INT1_1 MIX1 INP1", "RX2", "RX_RX2"},
+ {"RX INT1_1 MIX1 INP1", "RX3", "RX_RX3"},
+ {"RX INT1_1 MIX1 INP1", "RX4", "RX_RX4"},
+ {"RX INT1_1 MIX1 INP1", "RX5", "RX_RX5"},
+ {"RX INT1_1 MIX1 INP1", "IIR0", "IIR0"},
+ {"RX INT1_1 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX INT1_1 MIX1 INP1", "DEC0", "RX_TX DEC0_INP"},
+ {"RX INT1_1 MIX1 INP1", "DEC1", "RX_TX DEC1_INP"},
+ {"RX INT1_1 MIX1 INP2", "RX0", "RX_RX0"},
+ {"RX INT1_1 MIX1 INP2", "RX1", "RX_RX1"},
+ {"RX INT1_1 MIX1 INP2", "RX2", "RX_RX2"},
+ {"RX INT1_1 MIX1 INP2", "RX3", "RX_RX3"},
+ {"RX INT1_1 MIX1 INP2", "RX4", "RX_RX4"},
+ {"RX INT1_1 MIX1 INP2", "RX5", "RX_RX5"},
+ {"RX INT1_1 MIX1 INP2", "IIR0", "IIR0"},
+ {"RX INT1_1 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX INT1_1 MIX1 INP2", "DEC0", "RX_TX DEC0_INP"},
+ {"RX INT1_1 MIX1 INP2", "DEC1", "RX_TX DEC1_INP"},
+
+ {"RX INT2_1 MIX1 INP0", "RX0", "RX_RX0"},
+ {"RX INT2_1 MIX1 INP0", "RX1", "RX_RX1"},
+ {"RX INT2_1 MIX1 INP0", "RX2", "RX_RX2"},
+ {"RX INT2_1 MIX1 INP0", "RX3", "RX_RX3"},
+ {"RX INT2_1 MIX1 INP0", "RX4", "RX_RX4"},
+ {"RX INT2_1 MIX1 INP0", "RX5", "RX_RX5"},
+ {"RX INT2_1 MIX1 INP0", "IIR0", "IIR0"},
+ {"RX INT2_1 MIX1 INP0", "IIR1", "IIR1"},
+ {"RX INT2_1 MIX1 INP0", "DEC0", "RX_TX DEC0_INP"},
+ {"RX INT2_1 MIX1 INP0", "DEC1", "RX_TX DEC1_INP"},
+ {"RX INT2_1 MIX1 INP1", "RX0", "RX_RX0"},
+ {"RX INT2_1 MIX1 INP1", "RX1", "RX_RX1"},
+ {"RX INT2_1 MIX1 INP1", "RX2", "RX_RX2"},
+ {"RX INT2_1 MIX1 INP1", "RX3", "RX_RX3"},
+ {"RX INT2_1 MIX1 INP1", "RX4", "RX_RX4"},
+ {"RX INT2_1 MIX1 INP1", "RX5", "RX_RX5"},
+ {"RX INT2_1 MIX1 INP1", "IIR0", "IIR0"},
+ {"RX INT2_1 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX INT2_1 MIX1 INP1", "DEC0", "RX_TX DEC0_INP"},
+ {"RX INT2_1 MIX1 INP1", "DEC1", "RX_TX DEC1_INP"},
+ {"RX INT2_1 MIX1 INP2", "RX0", "RX_RX0"},
+ {"RX INT2_1 MIX1 INP2", "RX1", "RX_RX1"},
+ {"RX INT2_1 MIX1 INP2", "RX2", "RX_RX2"},
+ {"RX INT2_1 MIX1 INP2", "RX3", "RX_RX3"},
+ {"RX INT2_1 MIX1 INP2", "RX4", "RX_RX4"},
+ {"RX INT2_1 MIX1 INP2", "RX5", "RX_RX5"},
+ {"RX INT2_1 MIX1 INP2", "IIR0", "IIR0"},
+ {"RX INT2_1 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX INT2_1 MIX1 INP2", "DEC0", "RX_TX DEC0_INP"},
+ {"RX INT2_1 MIX1 INP2", "DEC1", "RX_TX DEC1_INP"},
+
+ {"RX INT0_1 MIX1", NULL, "RX INT0_1 MIX1 INP0"},
+ {"RX INT0_1 MIX1", NULL, "RX INT0_1 MIX1 INP1"},
+ {"RX INT0_1 MIX1", NULL, "RX INT0_1 MIX1 INP2"},
+ {"RX INT1_1 MIX1", NULL, "RX INT1_1 MIX1 INP0"},
+ {"RX INT1_1 MIX1", NULL, "RX INT1_1 MIX1 INP1"},
+ {"RX INT1_1 MIX1", NULL, "RX INT1_1 MIX1 INP2"},
+ {"RX INT2_1 MIX1", NULL, "RX INT2_1 MIX1 INP0"},
+ {"RX INT2_1 MIX1", NULL, "RX INT2_1 MIX1 INP1"},
+ {"RX INT2_1 MIX1", NULL, "RX INT2_1 MIX1 INP2"},
+
+ {"RX MIX TX0 MUX", "RX_MIX0", "RX INT0 SEC MIX"},
+ {"RX MIX TX0 MUX", "RX_MIX1", "RX INT1 SEC MIX"},
+ {"RX MIX TX0 MUX", "RX_MIX2", "RX INT2 SEC MIX"},
+ {"RX MIX TX1 MUX", "RX_MIX0", "RX INT0 SEC MIX"},
+ {"RX MIX TX1 MUX", "RX_MIX1", "RX INT1 SEC MIX"},
+ {"RX MIX TX1 MUX", "RX_MIX2", "RX INT2 SEC MIX"},
+ {"RX MIX TX2 MUX", "RX_MIX0", "RX INT0 SEC MIX"},
+ {"RX MIX TX2 MUX", "RX_MIX1", "RX INT1 SEC MIX"},
+ {"RX MIX TX2 MUX", "RX_MIX2", "RX INT2 SEC MIX"},
+ {"RX AIF_ECHO", NULL, "RX MIX TX0 MUX"},
+ {"RX AIF_ECHO", NULL, "RX MIX TX1 MUX"},
+ {"RX AIF_ECHO", NULL, "RX MIX TX2 MUX"},
+ {"RX AIF_ECHO", NULL, "RX_MCLK"},
+
+ /* Mixing path INT0 */
+ {"RX INT0_2 MUX", "RX0", "RX_RX0"},
+ {"RX INT0_2 MUX", "RX1", "RX_RX1"},
+ {"RX INT0_2 MUX", "RX2", "RX_RX2"},
+ {"RX INT0_2 MUX", "RX3", "RX_RX3"},
+ {"RX INT0_2 MUX", "RX4", "RX_RX4"},
+ {"RX INT0_2 MUX", "RX5", "RX_RX5"},
+ {"RX INT0_2 INTERP", NULL, "RX INT0_2 MUX"},
+ {"RX INT0 SEC MIX", NULL, "RX INT0_2 INTERP"},
+
+ /* Mixing path INT1 */
+ {"RX INT1_2 MUX", "RX0", "RX_RX0"},
+ {"RX INT1_2 MUX", "RX1", "RX_RX1"},
+ {"RX INT1_2 MUX", "RX2", "RX_RX2"},
+ {"RX INT1_2 MUX", "RX3", "RX_RX3"},
+ {"RX INT1_2 MUX", "RX4", "RX_RX4"},
+ {"RX INT1_2 MUX", "RX5", "RX_RX5"},
+ {"RX INT1_2 INTERP", NULL, "RX INT1_2 MUX"},
+ {"RX INT1 SEC MIX", NULL, "RX INT1_2 INTERP"},
+
+ /* Mixing path INT2 */
+ {"RX INT2_2 MUX", "RX0", "RX_RX0"},
+ {"RX INT2_2 MUX", "RX1", "RX_RX1"},
+ {"RX INT2_2 MUX", "RX2", "RX_RX2"},
+ {"RX INT2_2 MUX", "RX3", "RX_RX3"},
+ {"RX INT2_2 MUX", "RX4", "RX_RX4"},
+ {"RX INT2_2 MUX", "RX5", "RX_RX5"},
+ {"RX INT2_2 INTERP", NULL, "RX INT2_2 MUX"},
+ {"RX INT2 SEC MIX", NULL, "RX INT2_2 INTERP"},
+
+ {"RX INT0_1 INTERP", NULL, "RX INT0_1 MIX1"},
+ {"RX INT0 SEC MIX", NULL, "RX INT0_1 INTERP"},
+ {"RX INT0 MIX2", NULL, "RX INT0 SEC MIX"},
+ {"RX INT0 MIX2", NULL, "RX INT0 MIX2 INP"},
+ {"RX INT0 DEM MUX", "CLSH_DSM_OUT", "RX INT0 MIX2"},
+ {"HPHL_OUT", NULL, "RX INT0 DEM MUX"},
+ {"HPHL_OUT", NULL, "RX_MCLK"},
+
+ {"RX INT1_1 INTERP", NULL, "RX INT1_1 MIX1"},
+ {"RX INT1 SEC MIX", NULL, "RX INT1_1 INTERP"},
+ {"RX INT1 MIX2", NULL, "RX INT1 SEC MIX"},
+ {"RX INT1 MIX2", NULL, "RX INT1 MIX2 INP"},
+ {"RX INT1 DEM MUX", "CLSH_DSM_OUT", "RX INT1 MIX2"},
+ {"HPHR_OUT", NULL, "RX INT1 DEM MUX"},
+ {"HPHR_OUT", NULL, "RX_MCLK"},
+
+ {"RX INT2_1 INTERP", NULL, "RX INT2_1 MIX1"},
+
+ {"RX INT2 SEC MIX", NULL, "RX INT2_1 INTERP"},
+ {"RX INT2 MIX2", NULL, "RX INT2 SEC MIX"},
+ {"RX INT2 MIX2", NULL, "RX INT2 MIX2 INP"},
+ {"AUX_OUT", NULL, "RX INT2 MIX2"},
+ {"AUX_OUT", NULL, "RX_MCLK"},
+
+ {"IIR0", NULL, "RX_MCLK"},
+ {"IIR0", NULL, "IIR0 INP0 MUX"},
+ {"IIR0 INP0 MUX", "DEC0", "RX_TX DEC0_INP"},
+ {"IIR0 INP0 MUX", "DEC1", "RX_TX DEC1_INP"},
+ {"IIR0 INP0 MUX", "DEC2", "RX_TX DEC2_INP"},
+ {"IIR0 INP0 MUX", "DEC3", "RX_TX DEC3_INP"},
+ {"IIR0 INP0 MUX", "RX0", "RX_RX0"},
+ {"IIR0 INP0 MUX", "RX1", "RX_RX1"},
+ {"IIR0 INP0 MUX", "RX2", "RX_RX2"},
+ {"IIR0 INP0 MUX", "RX3", "RX_RX3"},
+ {"IIR0 INP0 MUX", "RX4", "RX_RX4"},
+ {"IIR0 INP0 MUX", "RX5", "RX_RX5"},
+ {"IIR0", NULL, "IIR0 INP1 MUX"},
+ {"IIR0 INP1 MUX", "DEC0", "RX_TX DEC0_INP"},
+ {"IIR0 INP1 MUX", "DEC1", "RX_TX DEC1_INP"},
+ {"IIR0 INP1 MUX", "DEC2", "RX_TX DEC2_INP"},
+ {"IIR0 INP1 MUX", "DEC3", "RX_TX DEC3_INP"},
+ {"IIR0 INP1 MUX", "RX0", "RX_RX0"},
+ {"IIR0 INP1 MUX", "RX1", "RX_RX1"},
+ {"IIR0 INP1 MUX", "RX2", "RX_RX2"},
+ {"IIR0 INP1 MUX", "RX3", "RX_RX3"},
+ {"IIR0 INP1 MUX", "RX4", "RX_RX4"},
+ {"IIR0 INP1 MUX", "RX5", "RX_RX5"},
+ {"IIR0", NULL, "IIR0 INP2 MUX"},
+ {"IIR0 INP2 MUX", "DEC0", "RX_TX DEC0_INP"},
+ {"IIR0 INP2 MUX", "DEC1", "RX_TX DEC1_INP"},
+ {"IIR0 INP2 MUX", "DEC2", "RX_TX DEC2_INP"},
+ {"IIR0 INP2 MUX", "DEC3", "RX_TX DEC3_INP"},
+ {"IIR0 INP2 MUX", "RX0", "RX_RX0"},
+ {"IIR0 INP2 MUX", "RX1", "RX_RX1"},
+ {"IIR0 INP2 MUX", "RX2", "RX_RX2"},
+ {"IIR0 INP2 MUX", "RX3", "RX_RX3"},
+ {"IIR0 INP2 MUX", "RX4", "RX_RX4"},
+ {"IIR0 INP2 MUX", "RX5", "RX_RX5"},
+ {"IIR0", NULL, "IIR0 INP3 MUX"},
+ {"IIR0 INP3 MUX", "DEC0", "RX_TX DEC0_INP"},
+ {"IIR0 INP3 MUX", "DEC1", "RX_TX DEC1_INP"},
+ {"IIR0 INP3 MUX", "DEC2", "RX_TX DEC2_INP"},
+ {"IIR0 INP3 MUX", "DEC3", "RX_TX DEC3_INP"},
+ {"IIR0 INP3 MUX", "RX0", "RX_RX0"},
+ {"IIR0 INP3 MUX", "RX1", "RX_RX1"},
+ {"IIR0 INP3 MUX", "RX2", "RX_RX2"},
+ {"IIR0 INP3 MUX", "RX3", "RX_RX3"},
+ {"IIR0 INP3 MUX", "RX4", "RX_RX4"},
+ {"IIR0 INP3 MUX", "RX5", "RX_RX5"},
+
+ {"IIR1", NULL, "RX_MCLK"},
+ {"IIR1", NULL, "IIR1 INP0 MUX"},
+ {"IIR1 INP0 MUX", "DEC0", "RX_TX DEC0_INP"},
+ {"IIR1 INP0 MUX", "DEC1", "RX_TX DEC1_INP"},
+ {"IIR1 INP0 MUX", "DEC2", "RX_TX DEC2_INP"},
+ {"IIR1 INP0 MUX", "DEC3", "RX_TX DEC3_INP"},
+ {"IIR1 INP0 MUX", "RX0", "RX_RX0"},
+ {"IIR1 INP0 MUX", "RX1", "RX_RX1"},
+ {"IIR1 INP0 MUX", "RX2", "RX_RX2"},
+ {"IIR1 INP0 MUX", "RX3", "RX_RX3"},
+ {"IIR1 INP0 MUX", "RX4", "RX_RX4"},
+ {"IIR1 INP0 MUX", "RX5", "RX_RX5"},
+ {"IIR1", NULL, "IIR1 INP1 MUX"},
+ {"IIR1 INP1 MUX", "DEC0", "RX_TX DEC0_INP"},
+ {"IIR1 INP1 MUX", "DEC1", "RX_TX DEC1_INP"},
+ {"IIR1 INP1 MUX", "DEC2", "RX_TX DEC2_INP"},
+ {"IIR1 INP1 MUX", "DEC3", "RX_TX DEC3_INP"},
+ {"IIR1 INP1 MUX", "RX0", "RX_RX0"},
+ {"IIR1 INP1 MUX", "RX1", "RX_RX1"},
+ {"IIR1 INP1 MUX", "RX2", "RX_RX2"},
+ {"IIR1 INP1 MUX", "RX3", "RX_RX3"},
+ {"IIR1 INP1 MUX", "RX4", "RX_RX4"},
+ {"IIR1 INP1 MUX", "RX5", "RX_RX5"},
+ {"IIR1", NULL, "IIR1 INP2 MUX"},
+ {"IIR1 INP2 MUX", "DEC0", "RX_TX DEC0_INP"},
+ {"IIR1 INP2 MUX", "DEC1", "RX_TX DEC1_INP"},
+ {"IIR1 INP2 MUX", "DEC2", "RX_TX DEC2_INP"},
+ {"IIR1 INP2 MUX", "DEC3", "RX_TX DEC3_INP"},
+ {"IIR1 INP2 MUX", "RX0", "RX_RX0"},
+ {"IIR1 INP2 MUX", "RX1", "RX_RX1"},
+ {"IIR1 INP2 MUX", "RX2", "RX_RX2"},
+ {"IIR1 INP2 MUX", "RX3", "RX_RX3"},
+ {"IIR1 INP2 MUX", "RX4", "RX_RX4"},
+ {"IIR1 INP2 MUX", "RX5", "RX_RX5"},
+ {"IIR1", NULL, "IIR1 INP3 MUX"},
+ {"IIR1 INP3 MUX", "DEC0", "RX_TX DEC0_INP"},
+ {"IIR1 INP3 MUX", "DEC1", "RX_TX DEC1_INP"},
+ {"IIR1 INP3 MUX", "DEC2", "RX_TX DEC2_INP"},
+ {"IIR1 INP3 MUX", "DEC3", "RX_TX DEC3_INP"},
+ {"IIR1 INP3 MUX", "RX0", "RX_RX0"},
+ {"IIR1 INP3 MUX", "RX1", "RX_RX1"},
+ {"IIR1 INP3 MUX", "RX2", "RX_RX2"},
+ {"IIR1 INP3 MUX", "RX3", "RX_RX3"},
+ {"IIR1 INP3 MUX", "RX4", "RX_RX4"},
+ {"IIR1 INP3 MUX", "RX5", "RX_RX5"},
+
+ {"SRC0", NULL, "IIR0"},
+ {"SRC1", NULL, "IIR1"},
+ {"RX INT0 MIX2 INP", "SRC0", "SRC0"},
+ {"RX INT0 MIX2 INP", "SRC1", "SRC1"},
+ {"RX INT1 MIX2 INP", "SRC0", "SRC0"},
+ {"RX INT1 MIX2 INP", "SRC1", "SRC1"},
+ {"RX INT2 MIX2 INP", "SRC0", "SRC0"},
+ {"RX INT2 MIX2 INP", "SRC1", "SRC1"},
+};
+
+static int rx_macro_component_probe(struct snd_soc_component *component)
+{
+ struct rx_macro *rx = snd_soc_component_get_drvdata(component);
+
+ snd_soc_component_init_regmap(component, rx->regmap);
+
+ snd_soc_component_update_bits(component, CDC_RX_RX0_RX_PATH_SEC7,
+ CDC_RX_DSM_OUT_DELAY_SEL_MASK,
+ CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE);
+ snd_soc_component_update_bits(component, CDC_RX_RX1_RX_PATH_SEC7,
+ CDC_RX_DSM_OUT_DELAY_SEL_MASK,
+ CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE);
+ snd_soc_component_update_bits(component, CDC_RX_RX2_RX_PATH_SEC7,
+ CDC_RX_DSM_OUT_DELAY_SEL_MASK,
+ CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE);
+ snd_soc_component_update_bits(component, CDC_RX_RX0_RX_PATH_CFG3,
+ CDC_RX_DC_COEFF_SEL_MASK,
+ CDC_RX_DC_COEFF_SEL_TWO);
+ snd_soc_component_update_bits(component, CDC_RX_RX1_RX_PATH_CFG3,
+ CDC_RX_DC_COEFF_SEL_MASK,
+ CDC_RX_DC_COEFF_SEL_TWO);
+ snd_soc_component_update_bits(component, CDC_RX_RX2_RX_PATH_CFG3,
+ CDC_RX_DC_COEFF_SEL_MASK,
+ CDC_RX_DC_COEFF_SEL_TWO);
+
+ rx->component = component;
+
+ return 0;
+}
+
+static int swclk_gate_enable(struct clk_hw *hw)
+{
+ struct rx_macro *rx = to_rx_macro(hw);
+
+ rx_macro_mclk_enable(rx, true);
+ if (rx->reset_swr)
+ regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+ CDC_RX_SWR_RESET_MASK,
+ CDC_RX_SWR_RESET);
+
+ regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+ CDC_RX_SWR_CLK_EN_MASK, 1);
+
+ if (rx->reset_swr)
+ regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+ CDC_RX_SWR_RESET_MASK, 0);
+ rx->reset_swr = false;
+
+ return 0;
+}
+
+static void swclk_gate_disable(struct clk_hw *hw)
+{
+ struct rx_macro *rx = to_rx_macro(hw);
+
+ regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL,
+ CDC_RX_SWR_CLK_EN_MASK, 0);
+
+ rx_macro_mclk_enable(rx, false);
+}
+
+static int swclk_gate_is_enabled(struct clk_hw *hw)
+{
+ struct rx_macro *rx = to_rx_macro(hw);
+ int ret, val;
+
+ regmap_read(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, &val);
+ ret = val & BIT(0);
+
+ return ret;
+}
+
+static unsigned long swclk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return parent_rate / 2;
+}
+
+static const struct clk_ops swclk_gate_ops = {
+ .prepare = swclk_gate_enable,
+ .unprepare = swclk_gate_disable,
+ .is_enabled = swclk_gate_is_enabled,
+ .recalc_rate = swclk_recalc_rate,
+
+};
+
+static struct clk *rx_macro_register_mclk_output(struct rx_macro *rx)
+{
+ struct device *dev = rx->dev;
+ struct device_node *np = dev->of_node;
+ const char *parent_clk_name = NULL;
+ const char *clk_name = "lpass-rx-mclk";
+ struct clk_hw *hw;
+ struct clk_init_data init;
+ int ret;
+
+ parent_clk_name = __clk_get_name(rx->clks[2].clk);
+
+ init.name = clk_name;
+ init.ops = &swclk_gate_ops;
+ init.flags = 0;
+ init.parent_names = &parent_clk_name;
+ init.num_parents = 1;
+ rx->hw.init = &init;
+ hw = &rx->hw;
+ ret = clk_hw_register(rx->dev, hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ of_clk_add_provider(np, of_clk_src_simple_get, hw->clk);
+
+ return NULL;
+}
+
+static const struct snd_soc_component_driver rx_macro_component_drv = {
+ .name = "RX-MACRO",
+ .probe = rx_macro_component_probe,
+ .controls = rx_macro_snd_controls,
+ .num_controls = ARRAY_SIZE(rx_macro_snd_controls),
+ .dapm_widgets = rx_macro_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(rx_macro_dapm_widgets),
+ .dapm_routes = rx_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(rx_audio_map),
+};
+
+static int rx_macro_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rx_macro *rx;
+ void __iomem *base;
+ int ret;
+
+ rx = devm_kzalloc(dev, sizeof(*rx), GFP_KERNEL);
+ if (!rx)
+ return -ENOMEM;
+
+ rx->clks[0].id = "macro";
+ rx->clks[1].id = "dcodec";
+ rx->clks[2].id = "mclk";
+ rx->clks[3].id = "npl";
+ rx->clks[4].id = "fsgen";
+
+ ret = devm_clk_bulk_get(dev, RX_NUM_CLKS_MAX, rx->clks);
+ if (ret) {
+ dev_err(dev, "Error getting RX Clocks (%d)\n", ret);
+ return ret;
+ }
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ rx->regmap = devm_regmap_init_mmio(dev, base, &rx_regmap_config);
+
+ dev_set_drvdata(dev, rx);
+
+ rx->reset_swr = true;
+ rx->dev = dev;
+
+ /* set MCLK and NPL rates */
+ clk_set_rate(rx->clks[2].clk, MCLK_FREQ);
+ clk_set_rate(rx->clks[3].clk, MCLK_FREQ);
+
+ ret = clk_bulk_prepare_enable(RX_NUM_CLKS_MAX, rx->clks);
+ if (ret)
+ return ret;
+
+ rx_macro_register_mclk_output(rx);
+
+ ret = devm_snd_soc_register_component(dev, &rx_macro_component_drv,
+ rx_macro_dai,
+ ARRAY_SIZE(rx_macro_dai));
+ if (ret)
+ clk_bulk_disable_unprepare(RX_NUM_CLKS_MAX, rx->clks);
+
+ return ret;
+}
+
+static int rx_macro_remove(struct platform_device *pdev)
+{
+ struct rx_macro *rx = dev_get_drvdata(&pdev->dev);
+
+ of_clk_del_provider(pdev->dev.of_node);
+ clk_bulk_disable_unprepare(RX_NUM_CLKS_MAX, rx->clks);
+ return 0;
+}
+
+static const struct of_device_id rx_macro_dt_match[] = {
+ { .compatible = "qcom,sm8250-lpass-rx-macro" },
+ { }
+};
+
+static struct platform_driver rx_macro_driver = {
+ .driver = {
+ .name = "rx_macro",
+ .owner = THIS_MODULE,
+ .of_match_table = rx_macro_dt_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = rx_macro_probe,
+ .remove = rx_macro_remove,
+};
+
+module_platform_driver(rx_macro_driver);
+
+MODULE_DESCRIPTION("RX macro driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c
new file mode 100644
index 000000000000..36d7a6442cdb
--- /dev/null
+++ b/sound/soc/codecs/lpass-tx-macro.c
@@ -0,0 +1,1862 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <linux/of_clk.h>
+#include <linux/clk-provider.h>
+
+#define CDC_TX_CLK_RST_CTRL_MCLK_CONTROL (0x0000)
+#define CDC_TX_MCLK_EN_MASK BIT(0)
+#define CDC_TX_MCLK_ENABLE BIT(0)
+#define CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL (0x0004)
+#define CDC_TX_FS_CNT_EN_MASK BIT(0)
+#define CDC_TX_FS_CNT_ENABLE BIT(0)
+#define CDC_TX_CLK_RST_CTRL_SWR_CONTROL (0x0008)
+#define CDC_TX_SWR_RESET_MASK BIT(1)
+#define CDC_TX_SWR_RESET_ENABLE BIT(1)
+#define CDC_TX_SWR_CLK_EN_MASK BIT(0)
+#define CDC_TX_SWR_CLK_ENABLE BIT(0)
+#define CDC_TX_TOP_CSR_TOP_CFG0 (0x0080)
+#define CDC_TX_TOP_CSR_ANC_CFG (0x0084)
+#define CDC_TX_TOP_CSR_SWR_CTRL (0x0088)
+#define CDC_TX_TOP_CSR_FREQ_MCLK (0x0090)
+#define CDC_TX_TOP_CSR_DEBUG_BUS (0x0094)
+#define CDC_TX_TOP_CSR_DEBUG_EN (0x0098)
+#define CDC_TX_TOP_CSR_TX_I2S_CTL (0x00A4)
+#define CDC_TX_TOP_CSR_I2S_CLK (0x00A8)
+#define CDC_TX_TOP_CSR_I2S_RESET (0x00AC)
+#define CDC_TX_TOP_CSR_SWR_DMICn_CTL(n) (0x00C0 + n * 0x4)
+#define CDC_TX_TOP_CSR_SWR_DMIC0_CTL (0x00C0)
+#define CDC_TX_SWR_DMIC_CLK_SEL_MASK GENMASK(3, 1)
+#define CDC_TX_TOP_CSR_SWR_DMIC1_CTL (0x00C4)
+#define CDC_TX_TOP_CSR_SWR_DMIC2_CTL (0x00C8)
+#define CDC_TX_TOP_CSR_SWR_DMIC3_CTL (0x00CC)
+#define CDC_TX_TOP_CSR_SWR_AMIC0_CTL (0x00D0)
+#define CDC_TX_TOP_CSR_SWR_AMIC1_CTL (0x00D4)
+#define CDC_TX_INP_MUX_ADC_MUXn_CFG0(n) (0x0100 + 0x8 * n)
+#define CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK GENMASK(3, 0)
+#define CDC_TX_INP_MUX_ADC_MUX0_CFG0 (0x0100)
+#define CDC_TX_INP_MUX_ADC_MUXn_CFG1(n) (0x0104 + 0x8 * n)
+#define CDC_TX_INP_MUX_ADC_MUX0_CFG1 (0x0104)
+#define CDC_TX_INP_MUX_ADC_MUX1_CFG0 (0x0108)
+#define CDC_TX_INP_MUX_ADC_MUX1_CFG1 (0x010C)
+#define CDC_TX_INP_MUX_ADC_MUX2_CFG0 (0x0110)
+#define CDC_TX_INP_MUX_ADC_MUX2_CFG1 (0x0114)
+#define CDC_TX_INP_MUX_ADC_MUX3_CFG0 (0x0118)
+#define CDC_TX_INP_MUX_ADC_MUX3_CFG1 (0x011C)
+#define CDC_TX_INP_MUX_ADC_MUX4_CFG0 (0x0120)
+#define CDC_TX_INP_MUX_ADC_MUX4_CFG1 (0x0124)
+#define CDC_TX_INP_MUX_ADC_MUX5_CFG0 (0x0128)
+#define CDC_TX_INP_MUX_ADC_MUX5_CFG1 (0x012C)
+#define CDC_TX_INP_MUX_ADC_MUX6_CFG0 (0x0130)
+#define CDC_TX_INP_MUX_ADC_MUX6_CFG1 (0x0134)
+#define CDC_TX_INP_MUX_ADC_MUX7_CFG0 (0x0138)
+#define CDC_TX_INP_MUX_ADC_MUX7_CFG1 (0x013C)
+#define CDC_TX_ANC0_CLK_RESET_CTL (0x0200)
+#define CDC_TX_ANC0_MODE_1_CTL (0x0204)
+#define CDC_TX_ANC0_MODE_2_CTL (0x0208)
+#define CDC_TX_ANC0_FF_SHIFT (0x020C)
+#define CDC_TX_ANC0_FB_SHIFT (0x0210)
+#define CDC_TX_ANC0_LPF_FF_A_CTL (0x0214)
+#define CDC_TX_ANC0_LPF_FF_B_CTL (0x0218)
+#define CDC_TX_ANC0_LPF_FB_CTL (0x021C)
+#define CDC_TX_ANC0_SMLPF_CTL (0x0220)
+#define CDC_TX_ANC0_DCFLT_SHIFT_CTL (0x0224)
+#define CDC_TX_ANC0_IIR_ADAPT_CTL (0x0228)
+#define CDC_TX_ANC0_IIR_COEFF_1_CTL (0x022C)
+#define CDC_TX_ANC0_IIR_COEFF_2_CTL (0x0230)
+#define CDC_TX_ANC0_FF_A_GAIN_CTL (0x0234)
+#define CDC_TX_ANC0_FF_B_GAIN_CTL (0x0238)
+#define CDC_TX_ANC0_FB_GAIN_CTL (0x023C)
+#define CDC_TXn_TX_PATH_CTL(n) (0x0400 + 0x80 * n)
+#define CDC_TXn_PCM_RATE_MASK GENMASK(3, 0)
+#define CDC_TXn_PGA_MUTE_MASK BIT(4)
+#define CDC_TXn_CLK_EN_MASK BIT(5)
+#define CDC_TX0_TX_PATH_CTL (0x0400)
+#define CDC_TXn_TX_PATH_CFG0(n) (0x0404 + 0x80 * n)
+#define CDC_TX0_TX_PATH_CFG0 (0x0404)
+#define CDC_TXn_PH_EN_MASK BIT(0)
+#define CDC_TXn_ADC_MODE_MASK GENMASK(2, 1)
+#define CDC_TXn_HPF_CUT_FREQ_MASK GENMASK(6, 5)
+#define CDC_TXn_ADC_DMIC_SEL_MASK BIT(7)
+#define CDC_TX0_TX_PATH_CFG1 (0x0408)
+#define CDC_TXn_TX_VOL_CTL(n) (0x040C + 0x80 * n)
+#define CDC_TX0_TX_VOL_CTL (0x040C)
+#define CDC_TX0_TX_PATH_SEC0 (0x0410)
+#define CDC_TX0_TX_PATH_SEC1 (0x0414)
+#define CDC_TXn_TX_PATH_SEC2(n) (0x0418 + 0x80 * n)
+#define CDC_TXn_HPF_F_CHANGE_MASK BIT(1)
+#define CDC_TXn_HPF_ZERO_GATE_MASK BIT(0)
+#define CDC_TX0_TX_PATH_SEC2 (0x0418)
+#define CDC_TX0_TX_PATH_SEC3 (0x041C)
+#define CDC_TX0_TX_PATH_SEC4 (0x0420)
+#define CDC_TX0_TX_PATH_SEC5 (0x0424)
+#define CDC_TX0_TX_PATH_SEC6 (0x0428)
+#define CDC_TX0_TX_PATH_SEC7 (0x042C)
+#define CDC_TX0_MBHC_CTL_EN_MASK BIT(6)
+#define CDC_TX1_TX_PATH_CTL (0x0480)
+#define CDC_TX1_TX_PATH_CFG0 (0x0484)
+#define CDC_TX1_TX_PATH_CFG1 (0x0488)
+#define CDC_TX1_TX_VOL_CTL (0x048C)
+#define CDC_TX1_TX_PATH_SEC0 (0x0490)
+#define CDC_TX1_TX_PATH_SEC1 (0x0494)
+#define CDC_TX1_TX_PATH_SEC2 (0x0498)
+#define CDC_TX1_TX_PATH_SEC3 (0x049C)
+#define CDC_TX1_TX_PATH_SEC4 (0x04A0)
+#define CDC_TX1_TX_PATH_SEC5 (0x04A4)
+#define CDC_TX1_TX_PATH_SEC6 (0x04A8)
+#define CDC_TX2_TX_PATH_CTL (0x0500)
+#define CDC_TX2_TX_PATH_CFG0 (0x0504)
+#define CDC_TX2_TX_PATH_CFG1 (0x0508)
+#define CDC_TX2_TX_VOL_CTL (0x050C)
+#define CDC_TX2_TX_PATH_SEC0 (0x0510)
+#define CDC_TX2_TX_PATH_SEC1 (0x0514)
+#define CDC_TX2_TX_PATH_SEC2 (0x0518)
+#define CDC_TX2_TX_PATH_SEC3 (0x051C)
+#define CDC_TX2_TX_PATH_SEC4 (0x0520)
+#define CDC_TX2_TX_PATH_SEC5 (0x0524)
+#define CDC_TX2_TX_PATH_SEC6 (0x0528)
+#define CDC_TX3_TX_PATH_CTL (0x0580)
+#define CDC_TX3_TX_PATH_CFG0 (0x0584)
+#define CDC_TX3_TX_PATH_CFG1 (0x0588)
+#define CDC_TX3_TX_VOL_CTL (0x058C)
+#define CDC_TX3_TX_PATH_SEC0 (0x0590)
+#define CDC_TX3_TX_PATH_SEC1 (0x0594)
+#define CDC_TX3_TX_PATH_SEC2 (0x0598)
+#define CDC_TX3_TX_PATH_SEC3 (0x059C)
+#define CDC_TX3_TX_PATH_SEC4 (0x05A0)
+#define CDC_TX3_TX_PATH_SEC5 (0x05A4)
+#define CDC_TX3_TX_PATH_SEC6 (0x05A8)
+#define CDC_TX4_TX_PATH_CTL (0x0600)
+#define CDC_TX4_TX_PATH_CFG0 (0x0604)
+#define CDC_TX4_TX_PATH_CFG1 (0x0608)
+#define CDC_TX4_TX_VOL_CTL (0x060C)
+#define CDC_TX4_TX_PATH_SEC0 (0x0610)
+#define CDC_TX4_TX_PATH_SEC1 (0x0614)
+#define CDC_TX4_TX_PATH_SEC2 (0x0618)
+#define CDC_TX4_TX_PATH_SEC3 (0x061C)
+#define CDC_TX4_TX_PATH_SEC4 (0x0620)
+#define CDC_TX4_TX_PATH_SEC5 (0x0624)
+#define CDC_TX4_TX_PATH_SEC6 (0x0628)
+#define CDC_TX5_TX_PATH_CTL (0x0680)
+#define CDC_TX5_TX_PATH_CFG0 (0x0684)
+#define CDC_TX5_TX_PATH_CFG1 (0x0688)
+#define CDC_TX5_TX_VOL_CTL (0x068C)
+#define CDC_TX5_TX_PATH_SEC0 (0x0690)
+#define CDC_TX5_TX_PATH_SEC1 (0x0694)
+#define CDC_TX5_TX_PATH_SEC2 (0x0698)
+#define CDC_TX5_TX_PATH_SEC3 (0x069C)
+#define CDC_TX5_TX_PATH_SEC4 (0x06A0)
+#define CDC_TX5_TX_PATH_SEC5 (0x06A4)
+#define CDC_TX5_TX_PATH_SEC6 (0x06A8)
+#define CDC_TX6_TX_PATH_CTL (0x0700)
+#define CDC_TX6_TX_PATH_CFG0 (0x0704)
+#define CDC_TX6_TX_PATH_CFG1 (0x0708)
+#define CDC_TX6_TX_VOL_CTL (0x070C)
+#define CDC_TX6_TX_PATH_SEC0 (0x0710)
+#define CDC_TX6_TX_PATH_SEC1 (0x0714)
+#define CDC_TX6_TX_PATH_SEC2 (0x0718)
+#define CDC_TX6_TX_PATH_SEC3 (0x071C)
+#define CDC_TX6_TX_PATH_SEC4 (0x0720)
+#define CDC_TX6_TX_PATH_SEC5 (0x0724)
+#define CDC_TX6_TX_PATH_SEC6 (0x0728)
+#define CDC_TX7_TX_PATH_CTL (0x0780)
+#define CDC_TX7_TX_PATH_CFG0 (0x0784)
+#define CDC_TX7_TX_PATH_CFG1 (0x0788)
+#define CDC_TX7_TX_VOL_CTL (0x078C)
+#define CDC_TX7_TX_PATH_SEC0 (0x0790)
+#define CDC_TX7_TX_PATH_SEC1 (0x0794)
+#define CDC_TX7_TX_PATH_SEC2 (0x0798)
+#define CDC_TX7_TX_PATH_SEC3 (0x079C)
+#define CDC_TX7_TX_PATH_SEC4 (0x07A0)
+#define CDC_TX7_TX_PATH_SEC5 (0x07A4)
+#define CDC_TX7_TX_PATH_SEC6 (0x07A8)
+#define TX_MAX_OFFSET (0x07A8)
+
+#define TX_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
+ SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+#define TX_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S24_3LE)
+
+#define CF_MIN_3DB_4HZ 0x0
+#define CF_MIN_3DB_75HZ 0x1
+#define CF_MIN_3DB_150HZ 0x2
+#define TX_ADC_MAX 5
+#define TX_ADC_TO_DMIC(n) ((n - TX_ADC_MAX)/2)
+#define NUM_DECIMATORS 8
+#define TX_NUM_CLKS_MAX 5
+#define TX_MACRO_DMIC_UNMUTE_DELAY_MS 40
+#define TX_MACRO_AMIC_UNMUTE_DELAY_MS 100
+#define TX_MACRO_DMIC_HPF_DELAY_MS 300
+#define TX_MACRO_AMIC_HPF_DELAY_MS 300
+#define MCLK_FREQ 9600000
+
+enum {
+ TX_MACRO_AIF_INVALID = 0,
+ TX_MACRO_AIF1_CAP,
+ TX_MACRO_AIF2_CAP,
+ TX_MACRO_AIF3_CAP,
+ TX_MACRO_MAX_DAIS
+};
+
+enum {
+ TX_MACRO_DEC0,
+ TX_MACRO_DEC1,
+ TX_MACRO_DEC2,
+ TX_MACRO_DEC3,
+ TX_MACRO_DEC4,
+ TX_MACRO_DEC5,
+ TX_MACRO_DEC6,
+ TX_MACRO_DEC7,
+ TX_MACRO_DEC_MAX,
+};
+
+enum {
+ TX_MACRO_CLK_DIV_2,
+ TX_MACRO_CLK_DIV_3,
+ TX_MACRO_CLK_DIV_4,
+ TX_MACRO_CLK_DIV_6,
+ TX_MACRO_CLK_DIV_8,
+ TX_MACRO_CLK_DIV_16,
+};
+
+enum {
+ MSM_DMIC,
+ SWR_MIC,
+ ANC_FB_TUNE1
+};
+
+struct tx_mute_work {
+ struct tx_macro *tx;
+ u32 decimator;
+ struct delayed_work dwork;
+};
+
+struct hpf_work {
+ struct tx_macro *tx;
+ u8 decimator;
+ u8 hpf_cut_off_freq;
+ struct delayed_work dwork;
+};
+
+struct tx_macro {
+ struct device *dev;
+ struct snd_soc_component *component;
+ struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+ struct tx_mute_work tx_mute_dwork[NUM_DECIMATORS];
+ unsigned long active_ch_mask[TX_MACRO_MAX_DAIS];
+ unsigned long active_ch_cnt[TX_MACRO_MAX_DAIS];
+ unsigned long active_decimator[TX_MACRO_MAX_DAIS];
+ struct regmap *regmap;
+ struct clk_bulk_data clks[TX_NUM_CLKS_MAX];
+ struct clk_hw hw;
+ bool dec_active[NUM_DECIMATORS];
+ bool reset_swr;
+ int tx_mclk_users;
+ u16 dmic_clk_div;
+ bool bcs_enable;
+ int dec_mode[NUM_DECIMATORS];
+ bool bcs_clk_en;
+};
+#define to_tx_macro(_hw) container_of(_hw, struct tx_macro, hw)
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400);
+
+static const struct reg_default tx_defaults[] = {
+ /* TX Macro */
+ { CDC_TX_CLK_RST_CTRL_MCLK_CONTROL, 0x00 },
+ { CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00 },
+ { CDC_TX_CLK_RST_CTRL_SWR_CONTROL, 0x00},
+ { CDC_TX_TOP_CSR_TOP_CFG0, 0x00},
+ { CDC_TX_TOP_CSR_ANC_CFG, 0x00},
+ { CDC_TX_TOP_CSR_SWR_CTRL, 0x00},
+ { CDC_TX_TOP_CSR_FREQ_MCLK, 0x00},
+ { CDC_TX_TOP_CSR_DEBUG_BUS, 0x00},
+ { CDC_TX_TOP_CSR_DEBUG_EN, 0x00},
+ { CDC_TX_TOP_CSR_TX_I2S_CTL, 0x0C},
+ { CDC_TX_TOP_CSR_I2S_CLK, 0x00},
+ { CDC_TX_TOP_CSR_I2S_RESET, 0x00},
+ { CDC_TX_TOP_CSR_SWR_DMIC0_CTL, 0x00},
+ { CDC_TX_TOP_CSR_SWR_DMIC1_CTL, 0x00},
+ { CDC_TX_TOP_CSR_SWR_DMIC2_CTL, 0x00},
+ { CDC_TX_TOP_CSR_SWR_DMIC3_CTL, 0x00},
+ { CDC_TX_TOP_CSR_SWR_AMIC0_CTL, 0x00},
+ { CDC_TX_TOP_CSR_SWR_AMIC1_CTL, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX3_CFG0, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX3_CFG1, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX4_CFG0, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX4_CFG1, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX5_CFG0, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX5_CFG1, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX6_CFG0, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX6_CFG1, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0x00},
+ { CDC_TX_INP_MUX_ADC_MUX7_CFG1, 0x00},
+ { CDC_TX_ANC0_CLK_RESET_CTL, 0x00},
+ { CDC_TX_ANC0_MODE_1_CTL, 0x00},
+ { CDC_TX_ANC0_MODE_2_CTL, 0x00},
+ { CDC_TX_ANC0_FF_SHIFT, 0x00},
+ { CDC_TX_ANC0_FB_SHIFT, 0x00},
+ { CDC_TX_ANC0_LPF_FF_A_CTL, 0x00},
+ { CDC_TX_ANC0_LPF_FF_B_CTL, 0x00},
+ { CDC_TX_ANC0_LPF_FB_CTL, 0x00},
+ { CDC_TX_ANC0_SMLPF_CTL, 0x00},
+ { CDC_TX_ANC0_DCFLT_SHIFT_CTL, 0x00},
+ { CDC_TX_ANC0_IIR_ADAPT_CTL, 0x00},
+ { CDC_TX_ANC0_IIR_COEFF_1_CTL, 0x00},
+ { CDC_TX_ANC0_IIR_COEFF_2_CTL, 0x00},
+ { CDC_TX_ANC0_FF_A_GAIN_CTL, 0x00},
+ { CDC_TX_ANC0_FF_B_GAIN_CTL, 0x00},
+ { CDC_TX_ANC0_FB_GAIN_CTL, 0x00},
+ { CDC_TX0_TX_PATH_CTL, 0x04},
+ { CDC_TX0_TX_PATH_CFG0, 0x10},
+ { CDC_TX0_TX_PATH_CFG1, 0x0B},
+ { CDC_TX0_TX_VOL_CTL, 0x00},
+ { CDC_TX0_TX_PATH_SEC0, 0x00},
+ { CDC_TX0_TX_PATH_SEC1, 0x00},
+ { CDC_TX0_TX_PATH_SEC2, 0x01},
+ { CDC_TX0_TX_PATH_SEC3, 0x3C},
+ { CDC_TX0_TX_PATH_SEC4, 0x20},
+ { CDC_TX0_TX_PATH_SEC5, 0x00},
+ { CDC_TX0_TX_PATH_SEC6, 0x00},
+ { CDC_TX0_TX_PATH_SEC7, 0x25},
+ { CDC_TX1_TX_PATH_CTL, 0x04},
+ { CDC_TX1_TX_PATH_CFG0, 0x10},
+ { CDC_TX1_TX_PATH_CFG1, 0x0B},
+ { CDC_TX1_TX_VOL_CTL, 0x00},
+ { CDC_TX1_TX_PATH_SEC0, 0x00},
+ { CDC_TX1_TX_PATH_SEC1, 0x00},
+ { CDC_TX1_TX_PATH_SEC2, 0x01},
+ { CDC_TX1_TX_PATH_SEC3, 0x3C},
+ { CDC_TX1_TX_PATH_SEC4, 0x20},
+ { CDC_TX1_TX_PATH_SEC5, 0x00},
+ { CDC_TX1_TX_PATH_SEC6, 0x00},
+ { CDC_TX2_TX_PATH_CTL, 0x04},
+ { CDC_TX2_TX_PATH_CFG0, 0x10},
+ { CDC_TX2_TX_PATH_CFG1, 0x0B},
+ { CDC_TX2_TX_VOL_CTL, 0x00},
+ { CDC_TX2_TX_PATH_SEC0, 0x00},
+ { CDC_TX2_TX_PATH_SEC1, 0x00},
+ { CDC_TX2_TX_PATH_SEC2, 0x01},
+ { CDC_TX2_TX_PATH_SEC3, 0x3C},
+ { CDC_TX2_TX_PATH_SEC4, 0x20},
+ { CDC_TX2_TX_PATH_SEC5, 0x00},
+ { CDC_TX2_TX_PATH_SEC6, 0x00},
+ { CDC_TX3_TX_PATH_CTL, 0x04},
+ { CDC_TX3_TX_PATH_CFG0, 0x10},
+ { CDC_TX3_TX_PATH_CFG1, 0x0B},
+ { CDC_TX3_TX_VOL_CTL, 0x00},
+ { CDC_TX3_TX_PATH_SEC0, 0x00},
+ { CDC_TX3_TX_PATH_SEC1, 0x00},
+ { CDC_TX3_TX_PATH_SEC2, 0x01},
+ { CDC_TX3_TX_PATH_SEC3, 0x3C},
+ { CDC_TX3_TX_PATH_SEC4, 0x20},
+ { CDC_TX3_TX_PATH_SEC5, 0x00},
+ { CDC_TX3_TX_PATH_SEC6, 0x00},
+ { CDC_TX4_TX_PATH_CTL, 0x04},
+ { CDC_TX4_TX_PATH_CFG0, 0x10},
+ { CDC_TX4_TX_PATH_CFG1, 0x0B},
+ { CDC_TX4_TX_VOL_CTL, 0x00},
+ { CDC_TX4_TX_PATH_SEC0, 0x00},
+ { CDC_TX4_TX_PATH_SEC1, 0x00},
+ { CDC_TX4_TX_PATH_SEC2, 0x01},
+ { CDC_TX4_TX_PATH_SEC3, 0x3C},
+ { CDC_TX4_TX_PATH_SEC4, 0x20},
+ { CDC_TX4_TX_PATH_SEC5, 0x00},
+ { CDC_TX4_TX_PATH_SEC6, 0x00},
+ { CDC_TX5_TX_PATH_CTL, 0x04},
+ { CDC_TX5_TX_PATH_CFG0, 0x10},
+ { CDC_TX5_TX_PATH_CFG1, 0x0B},
+ { CDC_TX5_TX_VOL_CTL, 0x00},
+ { CDC_TX5_TX_PATH_SEC0, 0x00},
+ { CDC_TX5_TX_PATH_SEC1, 0x00},
+ { CDC_TX5_TX_PATH_SEC2, 0x01},
+ { CDC_TX5_TX_PATH_SEC3, 0x3C},
+ { CDC_TX5_TX_PATH_SEC4, 0x20},
+ { CDC_TX5_TX_PATH_SEC5, 0x00},
+ { CDC_TX5_TX_PATH_SEC6, 0x00},
+ { CDC_TX6_TX_PATH_CTL, 0x04},
+ { CDC_TX6_TX_PATH_CFG0, 0x10},
+ { CDC_TX6_TX_PATH_CFG1, 0x0B},
+ { CDC_TX6_TX_VOL_CTL, 0x00},
+ { CDC_TX6_TX_PATH_SEC0, 0x00},
+ { CDC_TX6_TX_PATH_SEC1, 0x00},
+ { CDC_TX6_TX_PATH_SEC2, 0x01},
+ { CDC_TX6_TX_PATH_SEC3, 0x3C},
+ { CDC_TX6_TX_PATH_SEC4, 0x20},
+ { CDC_TX6_TX_PATH_SEC5, 0x00},
+ { CDC_TX6_TX_PATH_SEC6, 0x00},
+ { CDC_TX7_TX_PATH_CTL, 0x04},
+ { CDC_TX7_TX_PATH_CFG0, 0x10},
+ { CDC_TX7_TX_PATH_CFG1, 0x0B},
+ { CDC_TX7_TX_VOL_CTL, 0x00},
+ { CDC_TX7_TX_PATH_SEC0, 0x00},
+ { CDC_TX7_TX_PATH_SEC1, 0x00},
+ { CDC_TX7_TX_PATH_SEC2, 0x01},
+ { CDC_TX7_TX_PATH_SEC3, 0x3C},
+ { CDC_TX7_TX_PATH_SEC4, 0x20},
+ { CDC_TX7_TX_PATH_SEC5, 0x00},
+ { CDC_TX7_TX_PATH_SEC6, 0x00},
+};
+
+static bool tx_is_volatile_register(struct device *dev, unsigned int reg)
+{
+ /* Update volatile list for tx/tx macros */
+ switch (reg) {
+ case CDC_TX_TOP_CSR_SWR_DMIC0_CTL:
+ case CDC_TX_TOP_CSR_SWR_DMIC1_CTL:
+ case CDC_TX_TOP_CSR_SWR_DMIC2_CTL:
+ case CDC_TX_TOP_CSR_SWR_DMIC3_CTL:
+ return true;
+ }
+ return false;
+}
+
+static bool tx_is_rw_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CDC_TX_CLK_RST_CTRL_MCLK_CONTROL:
+ case CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL:
+ case CDC_TX_CLK_RST_CTRL_SWR_CONTROL:
+ case CDC_TX_TOP_CSR_TOP_CFG0:
+ case CDC_TX_TOP_CSR_ANC_CFG:
+ case CDC_TX_TOP_CSR_SWR_CTRL:
+ case CDC_TX_TOP_CSR_FREQ_MCLK:
+ case CDC_TX_TOP_CSR_DEBUG_BUS:
+ case CDC_TX_TOP_CSR_DEBUG_EN:
+ case CDC_TX_TOP_CSR_TX_I2S_CTL:
+ case CDC_TX_TOP_CSR_I2S_CLK:
+ case CDC_TX_TOP_CSR_I2S_RESET:
+ case CDC_TX_TOP_CSR_SWR_DMIC0_CTL:
+ case CDC_TX_TOP_CSR_SWR_DMIC1_CTL:
+ case CDC_TX_TOP_CSR_SWR_DMIC2_CTL:
+ case CDC_TX_TOP_CSR_SWR_DMIC3_CTL:
+ case CDC_TX_TOP_CSR_SWR_AMIC0_CTL:
+ case CDC_TX_TOP_CSR_SWR_AMIC1_CTL:
+ case CDC_TX_ANC0_CLK_RESET_CTL:
+ case CDC_TX_ANC0_MODE_1_CTL:
+ case CDC_TX_ANC0_MODE_2_CTL:
+ case CDC_TX_ANC0_FF_SHIFT:
+ case CDC_TX_ANC0_FB_SHIFT:
+ case CDC_TX_ANC0_LPF_FF_A_CTL:
+ case CDC_TX_ANC0_LPF_FF_B_CTL:
+ case CDC_TX_ANC0_LPF_FB_CTL:
+ case CDC_TX_ANC0_SMLPF_CTL:
+ case CDC_TX_ANC0_DCFLT_SHIFT_CTL:
+ case CDC_TX_ANC0_IIR_ADAPT_CTL:
+ case CDC_TX_ANC0_IIR_COEFF_1_CTL:
+ case CDC_TX_ANC0_IIR_COEFF_2_CTL:
+ case CDC_TX_ANC0_FF_A_GAIN_CTL:
+ case CDC_TX_ANC0_FF_B_GAIN_CTL:
+ case CDC_TX_ANC0_FB_GAIN_CTL:
+ case CDC_TX_INP_MUX_ADC_MUX0_CFG0:
+ case CDC_TX_INP_MUX_ADC_MUX0_CFG1:
+ case CDC_TX_INP_MUX_ADC_MUX1_CFG0:
+ case CDC_TX_INP_MUX_ADC_MUX1_CFG1:
+ case CDC_TX_INP_MUX_ADC_MUX2_CFG0:
+ case CDC_TX_INP_MUX_ADC_MUX2_CFG1:
+ case CDC_TX_INP_MUX_ADC_MUX3_CFG0:
+ case CDC_TX_INP_MUX_ADC_MUX3_CFG1:
+ case CDC_TX_INP_MUX_ADC_MUX4_CFG0:
+ case CDC_TX_INP_MUX_ADC_MUX4_CFG1:
+ case CDC_TX_INP_MUX_ADC_MUX5_CFG0:
+ case CDC_TX_INP_MUX_ADC_MUX5_CFG1:
+ case CDC_TX_INP_MUX_ADC_MUX6_CFG0:
+ case CDC_TX_INP_MUX_ADC_MUX6_CFG1:
+ case CDC_TX_INP_MUX_ADC_MUX7_CFG0:
+ case CDC_TX_INP_MUX_ADC_MUX7_CFG1:
+ case CDC_TX0_TX_PATH_CTL:
+ case CDC_TX0_TX_PATH_CFG0:
+ case CDC_TX0_TX_PATH_CFG1:
+ case CDC_TX0_TX_VOL_CTL:
+ case CDC_TX0_TX_PATH_SEC0:
+ case CDC_TX0_TX_PATH_SEC1:
+ case CDC_TX0_TX_PATH_SEC2:
+ case CDC_TX0_TX_PATH_SEC3:
+ case CDC_TX0_TX_PATH_SEC4:
+ case CDC_TX0_TX_PATH_SEC5:
+ case CDC_TX0_TX_PATH_SEC6:
+ case CDC_TX0_TX_PATH_SEC7:
+ case CDC_TX1_TX_PATH_CTL:
+ case CDC_TX1_TX_PATH_CFG0:
+ case CDC_TX1_TX_PATH_CFG1:
+ case CDC_TX1_TX_VOL_CTL:
+ case CDC_TX1_TX_PATH_SEC0:
+ case CDC_TX1_TX_PATH_SEC1:
+ case CDC_TX1_TX_PATH_SEC2:
+ case CDC_TX1_TX_PATH_SEC3:
+ case CDC_TX1_TX_PATH_SEC4:
+ case CDC_TX1_TX_PATH_SEC5:
+ case CDC_TX1_TX_PATH_SEC6:
+ case CDC_TX2_TX_PATH_CTL:
+ case CDC_TX2_TX_PATH_CFG0:
+ case CDC_TX2_TX_PATH_CFG1:
+ case CDC_TX2_TX_VOL_CTL:
+ case CDC_TX2_TX_PATH_SEC0:
+ case CDC_TX2_TX_PATH_SEC1:
+ case CDC_TX2_TX_PATH_SEC2:
+ case CDC_TX2_TX_PATH_SEC3:
+ case CDC_TX2_TX_PATH_SEC4:
+ case CDC_TX2_TX_PATH_SEC5:
+ case CDC_TX2_TX_PATH_SEC6:
+ case CDC_TX3_TX_PATH_CTL:
+ case CDC_TX3_TX_PATH_CFG0:
+ case CDC_TX3_TX_PATH_CFG1:
+ case CDC_TX3_TX_VOL_CTL:
+ case CDC_TX3_TX_PATH_SEC0:
+ case CDC_TX3_TX_PATH_SEC1:
+ case CDC_TX3_TX_PATH_SEC2:
+ case CDC_TX3_TX_PATH_SEC3:
+ case CDC_TX3_TX_PATH_SEC4:
+ case CDC_TX3_TX_PATH_SEC5:
+ case CDC_TX3_TX_PATH_SEC6:
+ case CDC_TX4_TX_PATH_CTL:
+ case CDC_TX4_TX_PATH_CFG0:
+ case CDC_TX4_TX_PATH_CFG1:
+ case CDC_TX4_TX_VOL_CTL:
+ case CDC_TX4_TX_PATH_SEC0:
+ case CDC_TX4_TX_PATH_SEC1:
+ case CDC_TX4_TX_PATH_SEC2:
+ case CDC_TX4_TX_PATH_SEC3:
+ case CDC_TX4_TX_PATH_SEC4:
+ case CDC_TX4_TX_PATH_SEC5:
+ case CDC_TX4_TX_PATH_SEC6:
+ case CDC_TX5_TX_PATH_CTL:
+ case CDC_TX5_TX_PATH_CFG0:
+ case CDC_TX5_TX_PATH_CFG1:
+ case CDC_TX5_TX_VOL_CTL:
+ case CDC_TX5_TX_PATH_SEC0:
+ case CDC_TX5_TX_PATH_SEC1:
+ case CDC_TX5_TX_PATH_SEC2:
+ case CDC_TX5_TX_PATH_SEC3:
+ case CDC_TX5_TX_PATH_SEC4:
+ case CDC_TX5_TX_PATH_SEC5:
+ case CDC_TX5_TX_PATH_SEC6:
+ case CDC_TX6_TX_PATH_CTL:
+ case CDC_TX6_TX_PATH_CFG0:
+ case CDC_TX6_TX_PATH_CFG1:
+ case CDC_TX6_TX_VOL_CTL:
+ case CDC_TX6_TX_PATH_SEC0:
+ case CDC_TX6_TX_PATH_SEC1:
+ case CDC_TX6_TX_PATH_SEC2:
+ case CDC_TX6_TX_PATH_SEC3:
+ case CDC_TX6_TX_PATH_SEC4:
+ case CDC_TX6_TX_PATH_SEC5:
+ case CDC_TX6_TX_PATH_SEC6:
+ case CDC_TX7_TX_PATH_CTL:
+ case CDC_TX7_TX_PATH_CFG0:
+ case CDC_TX7_TX_PATH_CFG1:
+ case CDC_TX7_TX_VOL_CTL:
+ case CDC_TX7_TX_PATH_SEC0:
+ case CDC_TX7_TX_PATH_SEC1:
+ case CDC_TX7_TX_PATH_SEC2:
+ case CDC_TX7_TX_PATH_SEC3:
+ case CDC_TX7_TX_PATH_SEC4:
+ case CDC_TX7_TX_PATH_SEC5:
+ case CDC_TX7_TX_PATH_SEC6:
+ return true;
+ }
+
+ return false;
+}
+
+static const struct regmap_config tx_regmap_config = {
+ .name = "tx_macro",
+ .reg_bits = 16,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .cache_type = REGCACHE_FLAT,
+ .max_register = TX_MAX_OFFSET,
+ .reg_defaults = tx_defaults,
+ .num_reg_defaults = ARRAY_SIZE(tx_defaults),
+ .writeable_reg = tx_is_rw_register,
+ .volatile_reg = tx_is_volatile_register,
+ .readable_reg = tx_is_rw_register,
+};
+
+static int tx_macro_mclk_enable(struct tx_macro *tx,
+ bool mclk_enable)
+{
+ struct regmap *regmap = tx->regmap;
+
+ if (mclk_enable) {
+ if (tx->tx_mclk_users == 0) {
+ /* 9.6MHz MCLK, set value 0x00 if other frequency */
+ regmap_update_bits(regmap, CDC_TX_TOP_CSR_FREQ_MCLK, 0x01, 0x01);
+ regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+ CDC_TX_MCLK_EN_MASK,
+ CDC_TX_MCLK_ENABLE);
+ regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+ CDC_TX_FS_CNT_EN_MASK,
+ CDC_TX_FS_CNT_ENABLE);
+ regcache_mark_dirty(regmap);
+ regcache_sync(regmap);
+ }
+ tx->tx_mclk_users++;
+ } else {
+ if (tx->tx_mclk_users <= 0) {
+ dev_err(tx->dev, "clock already disabled\n");
+ tx->tx_mclk_users = 0;
+ goto exit;
+ }
+ tx->tx_mclk_users--;
+ if (tx->tx_mclk_users == 0) {
+ regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+ CDC_TX_FS_CNT_EN_MASK, 0x0);
+ regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+ CDC_TX_MCLK_EN_MASK, 0x0);
+ }
+ }
+exit:
+ return 0;
+}
+
+static bool is_amic_enabled(struct snd_soc_component *component, int decimator)
+{
+ u16 adc_mux_reg, adc_reg, adc_n;
+
+ adc_mux_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG1(decimator);
+
+ if (snd_soc_component_read(component, adc_mux_reg) & SWR_MIC) {
+ adc_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG0(decimator);
+ adc_n = snd_soc_component_read_field(component, adc_reg,
+ CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK);
+ if (adc_n < TX_ADC_MAX)
+ return true;
+ }
+
+ return false;
+}
+
+static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+ struct delayed_work *hpf_delayed_work;
+ struct hpf_work *hpf_work;
+ struct tx_macro *tx;
+ struct snd_soc_component *component;
+ u16 dec_cfg_reg, hpf_gate_reg;
+ u8 hpf_cut_off_freq;
+
+ hpf_delayed_work = to_delayed_work(work);
+ hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+ tx = hpf_work->tx;
+ component = tx->component;
+ hpf_cut_off_freq = hpf_work->hpf_cut_off_freq;
+
+ dec_cfg_reg = CDC_TXn_TX_PATH_CFG0(hpf_work->decimator);
+ hpf_gate_reg = CDC_TXn_TX_PATH_SEC2(hpf_work->decimator);
+
+ if (is_amic_enabled(component, hpf_work->decimator)) {
+ snd_soc_component_write_field(component,
+ dec_cfg_reg,
+ CDC_TXn_HPF_CUT_FREQ_MASK,
+ hpf_cut_off_freq);
+ snd_soc_component_update_bits(component, hpf_gate_reg,
+ CDC_TXn_HPF_F_CHANGE_MASK |
+ CDC_TXn_HPF_ZERO_GATE_MASK,
+ 0x02);
+ snd_soc_component_update_bits(component, hpf_gate_reg,
+ CDC_TXn_HPF_F_CHANGE_MASK |
+ CDC_TXn_HPF_ZERO_GATE_MASK,
+ 0x01);
+ } else {
+ snd_soc_component_write_field(component, dec_cfg_reg,
+ CDC_TXn_HPF_CUT_FREQ_MASK,
+ hpf_cut_off_freq);
+ snd_soc_component_write_field(component, hpf_gate_reg,
+ CDC_TXn_HPF_F_CHANGE_MASK, 0x1);
+ /* Minimum 1 clk cycle delay is required as per HW spec */
+ usleep_range(1000, 1010);
+ snd_soc_component_write_field(component, hpf_gate_reg,
+ CDC_TXn_HPF_F_CHANGE_MASK, 0x0);
+ }
+}
+
+static void tx_macro_mute_update_callback(struct work_struct *work)
+{
+ struct tx_mute_work *tx_mute_dwork;
+ struct snd_soc_component *component;
+ struct tx_macro *tx;
+ struct delayed_work *delayed_work;
+ u8 decimator;
+
+ delayed_work = to_delayed_work(work);
+ tx_mute_dwork = container_of(delayed_work, struct tx_mute_work, dwork);
+ tx = tx_mute_dwork->tx;
+ component = tx->component;
+ decimator = tx_mute_dwork->decimator;
+
+ snd_soc_component_write_field(component, CDC_TXn_TX_PATH_CTL(decimator),
+ CDC_TXn_PGA_MUTE_MASK, 0x0);
+}
+
+static int tx_macro_mclk_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 tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ tx_macro_mclk_enable(tx, true);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ tx_macro_mclk_enable(tx, false);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol);
+ struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int val, dmic;
+ u16 mic_sel_reg;
+ u16 dmic_clk_reg;
+ struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+ val = ucontrol->value.enumerated.item[0];
+
+ switch (e->reg) {
+ case CDC_TX_INP_MUX_ADC_MUX0_CFG0:
+ mic_sel_reg = CDC_TX0_TX_PATH_CFG0;
+ break;
+ case CDC_TX_INP_MUX_ADC_MUX1_CFG0:
+ mic_sel_reg = CDC_TX1_TX_PATH_CFG0;
+ break;
+ case CDC_TX_INP_MUX_ADC_MUX2_CFG0:
+ mic_sel_reg = CDC_TX2_TX_PATH_CFG0;
+ break;
+ case CDC_TX_INP_MUX_ADC_MUX3_CFG0:
+ mic_sel_reg = CDC_TX3_TX_PATH_CFG0;
+ break;
+ case CDC_TX_INP_MUX_ADC_MUX4_CFG0:
+ mic_sel_reg = CDC_TX4_TX_PATH_CFG0;
+ break;
+ case CDC_TX_INP_MUX_ADC_MUX5_CFG0:
+ mic_sel_reg = CDC_TX5_TX_PATH_CFG0;
+ break;
+ case CDC_TX_INP_MUX_ADC_MUX6_CFG0:
+ mic_sel_reg = CDC_TX6_TX_PATH_CFG0;
+ break;
+ case CDC_TX_INP_MUX_ADC_MUX7_CFG0:
+ mic_sel_reg = CDC_TX7_TX_PATH_CFG0;
+ break;
+ }
+
+ if (val != 0) {
+ if (val < 5) {
+ snd_soc_component_write_field(component, mic_sel_reg,
+ CDC_TXn_ADC_DMIC_SEL_MASK, 0);
+ } else {
+ snd_soc_component_write_field(component, mic_sel_reg,
+ CDC_TXn_ADC_DMIC_SEL_MASK, 1);
+ dmic = TX_ADC_TO_DMIC(val);
+ dmic_clk_reg = CDC_TX_TOP_CSR_SWR_DMICn_CTL(dmic);
+ snd_soc_component_write_field(component, dmic_clk_reg,
+ CDC_TX_SWR_DMIC_CLK_SEL_MASK,
+ tx->dmic_clk_div);
+ }
+ }
+
+ return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
+static int tx_macro_tx_mixer_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol);
+ struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+ struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
+ u32 dai_id = widget->shift;
+ u32 dec_id = mc->shift;
+ struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+ if (test_bit(dec_id, &tx->active_ch_mask[dai_id]))
+ ucontrol->value.integer.value[0] = 1;
+ else
+ ucontrol->value.integer.value[0] = 0;
+
+ return 0;
+}
+
+static int tx_macro_tx_mixer_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol);
+ struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
+ struct snd_soc_dapm_update *update = NULL;
+ struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
+ u32 dai_id = widget->shift;
+ u32 dec_id = mc->shift;
+ u32 enable = ucontrol->value.integer.value[0];
+ struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+ if (enable) {
+ set_bit(dec_id, &tx->active_ch_mask[dai_id]);
+ tx->active_ch_cnt[dai_id]++;
+ tx->active_decimator[dai_id] = dec_id;
+ } else {
+ tx->active_ch_cnt[dai_id]--;
+ clear_bit(dec_id, &tx->active_ch_mask[dai_id]);
+ tx->active_decimator[dai_id] = -1;
+ }
+ snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update);
+
+ return 0;
+}
+
+static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+ unsigned int decimator;
+ u16 tx_vol_ctl_reg, dec_cfg_reg, hpf_gate_reg, tx_gain_ctl_reg;
+ u8 hpf_cut_off_freq;
+ int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS;
+ int unmute_delay = TX_MACRO_DMIC_UNMUTE_DELAY_MS;
+ u16 adc_mux_reg, adc_reg, adc_n, dmic;
+ u16 dmic_clk_reg;
+ struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+ decimator = w->shift;
+ tx_vol_ctl_reg = CDC_TXn_TX_PATH_CTL(decimator);
+ hpf_gate_reg = CDC_TXn_TX_PATH_SEC2(decimator);
+ dec_cfg_reg = CDC_TXn_TX_PATH_CFG0(decimator);
+ tx_gain_ctl_reg = CDC_TXn_TX_VOL_CTL(decimator);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ adc_mux_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG1(decimator);
+ if (snd_soc_component_read(component, adc_mux_reg) & SWR_MIC) {
+ adc_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG0(decimator);
+ adc_n = snd_soc_component_read(component, adc_reg) &
+ CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK;
+ if (adc_n >= TX_ADC_MAX) {
+ dmic = TX_ADC_TO_DMIC(adc_n);
+ dmic_clk_reg = CDC_TX_TOP_CSR_SWR_DMICn_CTL(dmic);
+
+ snd_soc_component_write_field(component, dmic_clk_reg,
+ CDC_TX_SWR_DMIC_CLK_SEL_MASK,
+ tx->dmic_clk_div);
+ }
+ }
+ snd_soc_component_write_field(component, dec_cfg_reg,
+ CDC_TXn_ADC_MODE_MASK,
+ tx->dec_mode[decimator]);
+ /* Enable TX PGA Mute */
+ snd_soc_component_write_field(component, tx_vol_ctl_reg,
+ CDC_TXn_PGA_MUTE_MASK, 0x1);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_component_write_field(component, tx_vol_ctl_reg,
+ CDC_TXn_CLK_EN_MASK, 0x1);
+ if (!is_amic_enabled(component, decimator)) {
+ snd_soc_component_update_bits(component, hpf_gate_reg, 0x01, 0x00);
+ /* Minimum 1 clk cycle delay is required as per HW spec */
+ usleep_range(1000, 1010);
+ }
+ hpf_cut_off_freq = snd_soc_component_read_field(component, dec_cfg_reg,
+ CDC_TXn_HPF_CUT_FREQ_MASK);
+
+ tx->tx_hpf_work[decimator].hpf_cut_off_freq =
+ hpf_cut_off_freq;
+
+ if (hpf_cut_off_freq != CF_MIN_3DB_150HZ)
+ snd_soc_component_write_field(component, dec_cfg_reg,
+ CDC_TXn_HPF_CUT_FREQ_MASK,
+ CF_MIN_3DB_150HZ);
+
+ if (is_amic_enabled(component, decimator)) {
+ hpf_delay = TX_MACRO_AMIC_HPF_DELAY_MS;
+ unmute_delay = TX_MACRO_AMIC_UNMUTE_DELAY_MS;
+ }
+ /* schedule work queue to Remove Mute */
+ queue_delayed_work(system_freezable_wq,
+ &tx->tx_mute_dwork[decimator].dwork,
+ msecs_to_jiffies(unmute_delay));
+ if (tx->tx_hpf_work[decimator].hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
+ queue_delayed_work(system_freezable_wq,
+ &tx->tx_hpf_work[decimator].dwork,
+ msecs_to_jiffies(hpf_delay));
+ snd_soc_component_update_bits(component, hpf_gate_reg,
+ CDC_TXn_HPF_F_CHANGE_MASK |
+ CDC_TXn_HPF_ZERO_GATE_MASK,
+ 0x02);
+ if (!is_amic_enabled(component, decimator))
+ snd_soc_component_update_bits(component, hpf_gate_reg,
+ CDC_TXn_HPF_F_CHANGE_MASK |
+ CDC_TXn_HPF_ZERO_GATE_MASK,
+ 0x00);
+ snd_soc_component_update_bits(component, hpf_gate_reg,
+ CDC_TXn_HPF_F_CHANGE_MASK |
+ CDC_TXn_HPF_ZERO_GATE_MASK,
+ 0x01);
+
+ /*
+ * 6ms delay is required as per HW spec
+ */
+ usleep_range(6000, 6010);
+ }
+ /* apply gain after decimator is enabled */
+ snd_soc_component_write(component, tx_gain_ctl_reg,
+ snd_soc_component_read(component,
+ tx_gain_ctl_reg));
+ if (tx->bcs_enable) {
+ snd_soc_component_update_bits(component, dec_cfg_reg,
+ 0x01, 0x01);
+ tx->bcs_clk_en = true;
+ }
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ hpf_cut_off_freq =
+ tx->tx_hpf_work[decimator].hpf_cut_off_freq;
+ snd_soc_component_write_field(component, tx_vol_ctl_reg,
+ CDC_TXn_PGA_MUTE_MASK, 0x1);
+ if (cancel_delayed_work_sync(
+ &tx->tx_hpf_work[decimator].dwork)) {
+ if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
+ snd_soc_component_write_field(
+ component, dec_cfg_reg,
+ CDC_TXn_HPF_CUT_FREQ_MASK,
+ hpf_cut_off_freq);
+ if (is_amic_enabled(component, decimator))
+ snd_soc_component_update_bits(component,
+ hpf_gate_reg,
+ CDC_TXn_HPF_F_CHANGE_MASK |
+ CDC_TXn_HPF_ZERO_GATE_MASK,
+ 0x02);
+ else
+ snd_soc_component_update_bits(component,
+ hpf_gate_reg,
+ CDC_TXn_HPF_F_CHANGE_MASK |
+ CDC_TXn_HPF_ZERO_GATE_MASK,
+ 0x03);
+
+ /*
+ * Minimum 1 clk cycle delay is required
+ * as per HW spec
+ */
+ usleep_range(1000, 1010);
+ snd_soc_component_update_bits(component, hpf_gate_reg,
+ CDC_TXn_HPF_F_CHANGE_MASK |
+ CDC_TXn_HPF_ZERO_GATE_MASK,
+ 0x1);
+ }
+ }
+ cancel_delayed_work_sync(&tx->tx_mute_dwork[decimator].dwork);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_component_write_field(component, tx_vol_ctl_reg,
+ CDC_TXn_CLK_EN_MASK, 0x0);
+ snd_soc_component_write_field(component, dec_cfg_reg,
+ CDC_TXn_ADC_MODE_MASK, 0x0);
+ snd_soc_component_write_field(component, tx_vol_ctl_reg,
+ CDC_TXn_PGA_MUTE_MASK, 0x0);
+ if (tx->bcs_enable) {
+ snd_soc_component_write_field(component, dec_cfg_reg,
+ CDC_TXn_PH_EN_MASK, 0x0);
+ snd_soc_component_write_field(component,
+ CDC_TX0_TX_PATH_SEC7,
+ CDC_TX0_MBHC_CTL_EN_MASK,
+ 0x0);
+ tx->bcs_clk_en = false;
+ }
+ break;
+ }
+ return 0;
+}
+
+static int tx_macro_dec_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ int path = e->shift_l;
+
+ ucontrol->value.integer.value[0] = tx->dec_mode[path];
+
+ return 0;
+}
+
+static int tx_macro_dec_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ int value = ucontrol->value.integer.value[0];
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ int path = e->shift_l;
+ struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+ tx->dec_mode[path] = value;
+
+ return 0;
+}
+
+static int tx_macro_get_bcs(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = tx->bcs_enable;
+
+ return 0;
+}
+
+static int tx_macro_set_bcs(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ int value = ucontrol->value.integer.value[0];
+ struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+ tx->bcs_enable = value;
+
+ return 0;
+}
+
+static int tx_macro_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;
+ u32 decimator, sample_rate;
+ int tx_fs_rate;
+ struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+ sample_rate = params_rate(params);
+ switch (sample_rate) {
+ case 8000:
+ tx_fs_rate = 0;
+ break;
+ case 16000:
+ tx_fs_rate = 1;
+ break;
+ case 32000:
+ tx_fs_rate = 3;
+ break;
+ case 48000:
+ tx_fs_rate = 4;
+ break;
+ case 96000:
+ tx_fs_rate = 5;
+ break;
+ case 192000:
+ tx_fs_rate = 6;
+ break;
+ case 384000:
+ tx_fs_rate = 7;
+ break;
+ default:
+ dev_err(component->dev, "%s: Invalid TX sample rate: %d\n",
+ __func__, params_rate(params));
+ return -EINVAL;
+ }
+
+ for_each_set_bit(decimator, &tx->active_ch_mask[dai->id], TX_MACRO_DEC_MAX)
+ snd_soc_component_update_bits(component, CDC_TXn_TX_PATH_CTL(decimator),
+ CDC_TXn_PCM_RATE_MASK,
+ tx_fs_rate);
+ return 0;
+}
+
+static int tx_macro_get_channel_map(struct snd_soc_dai *dai,
+ unsigned int *tx_num, unsigned int *tx_slot,
+ unsigned int *rx_num, unsigned int *rx_slot)
+{
+ struct snd_soc_component *component = dai->component;
+ struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+
+ switch (dai->id) {
+ case TX_MACRO_AIF1_CAP:
+ case TX_MACRO_AIF2_CAP:
+ case TX_MACRO_AIF3_CAP:
+ *tx_slot = tx->active_ch_mask[dai->id];
+ *tx_num = tx->active_ch_cnt[dai->id];
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int tx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+ struct snd_soc_component *component = dai->component;
+ struct tx_macro *tx = snd_soc_component_get_drvdata(component);
+ u16 decimator;
+
+ decimator = tx->active_decimator[dai->id];
+
+ if (mute)
+ snd_soc_component_write_field(component,
+ CDC_TXn_TX_PATH_CTL(decimator),
+ CDC_TXn_PGA_MUTE_MASK, 0x1);
+ else
+ snd_soc_component_update_bits(component,
+ CDC_TXn_TX_PATH_CTL(decimator),
+ CDC_TXn_PGA_MUTE_MASK, 0x0);
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops tx_macro_dai_ops = {
+ .hw_params = tx_macro_hw_params,
+ .get_channel_map = tx_macro_get_channel_map,
+ .mute_stream = tx_macro_digital_mute,
+};
+
+static struct snd_soc_dai_driver tx_macro_dai[] = {
+ {
+ .name = "tx_macro_tx1",
+ .id = TX_MACRO_AIF1_CAP,
+ .capture = {
+ .stream_name = "TX_AIF1 Capture",
+ .rates = TX_MACRO_RATES,
+ .formats = TX_MACRO_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+ .ops = &tx_macro_dai_ops,
+ },
+ {
+ .name = "tx_macro_tx2",
+ .id = TX_MACRO_AIF2_CAP,
+ .capture = {
+ .stream_name = "TX_AIF2 Capture",
+ .rates = TX_MACRO_RATES,
+ .formats = TX_MACRO_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+ .ops = &tx_macro_dai_ops,
+ },
+ {
+ .name = "tx_macro_tx3",
+ .id = TX_MACRO_AIF3_CAP,
+ .capture = {
+ .stream_name = "TX_AIF3 Capture",
+ .rates = TX_MACRO_RATES,
+ .formats = TX_MACRO_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+ .ops = &tx_macro_dai_ops,
+ },
+};
+
+static const char * const adc_mux_text[] = {
+ "MSM_DMIC", "SWR_MIC", "ANC_FB_TUNE1"
+};
+
+static SOC_ENUM_SINGLE_DECL(tx_dec0_enum, CDC_TX_INP_MUX_ADC_MUX0_CFG1,
+ 0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec1_enum, CDC_TX_INP_MUX_ADC_MUX1_CFG1,
+ 0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec2_enum, CDC_TX_INP_MUX_ADC_MUX2_CFG1,
+ 0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec3_enum, CDC_TX_INP_MUX_ADC_MUX3_CFG1,
+ 0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec4_enum, CDC_TX_INP_MUX_ADC_MUX4_CFG1,
+ 0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec5_enum, CDC_TX_INP_MUX_ADC_MUX5_CFG1,
+ 0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec6_enum, CDC_TX_INP_MUX_ADC_MUX6_CFG1,
+ 0, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(tx_dec7_enum, CDC_TX_INP_MUX_ADC_MUX7_CFG1,
+ 0, adc_mux_text);
+
+static const struct snd_kcontrol_new tx_dec0_mux = SOC_DAPM_ENUM("tx_dec0", tx_dec0_enum);
+static const struct snd_kcontrol_new tx_dec1_mux = SOC_DAPM_ENUM("tx_dec1", tx_dec1_enum);
+static const struct snd_kcontrol_new tx_dec2_mux = SOC_DAPM_ENUM("tx_dec2", tx_dec2_enum);
+static const struct snd_kcontrol_new tx_dec3_mux = SOC_DAPM_ENUM("tx_dec3", tx_dec3_enum);
+static const struct snd_kcontrol_new tx_dec4_mux = SOC_DAPM_ENUM("tx_dec4", tx_dec4_enum);
+static const struct snd_kcontrol_new tx_dec5_mux = SOC_DAPM_ENUM("tx_dec5", tx_dec5_enum);
+static const struct snd_kcontrol_new tx_dec6_mux = SOC_DAPM_ENUM("tx_dec6", tx_dec6_enum);
+static const struct snd_kcontrol_new tx_dec7_mux = SOC_DAPM_ENUM("tx_dec7", tx_dec7_enum);
+
+static const char * const smic_mux_text[] = {
+ "ZERO", "ADC0", "ADC1", "ADC2", "ADC3", "SWR_DMIC0",
+ "SWR_DMIC1", "SWR_DMIC2", "SWR_DMIC3", "SWR_DMIC4",
+ "SWR_DMIC5", "SWR_DMIC6", "SWR_DMIC7"
+};
+
+static SOC_ENUM_SINGLE_DECL(tx_smic0_enum, CDC_TX_INP_MUX_ADC_MUX0_CFG0,
+ 0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic1_enum, CDC_TX_INP_MUX_ADC_MUX1_CFG0,
+ 0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic2_enum, CDC_TX_INP_MUX_ADC_MUX2_CFG0,
+ 0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic3_enum, CDC_TX_INP_MUX_ADC_MUX3_CFG0,
+ 0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic4_enum, CDC_TX_INP_MUX_ADC_MUX4_CFG0,
+ 0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic5_enum, CDC_TX_INP_MUX_ADC_MUX5_CFG0,
+ 0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic6_enum, CDC_TX_INP_MUX_ADC_MUX6_CFG0,
+ 0, smic_mux_text);
+
+static SOC_ENUM_SINGLE_DECL(tx_smic7_enum, CDC_TX_INP_MUX_ADC_MUX7_CFG0,
+ 0, smic_mux_text);
+
+static const struct snd_kcontrol_new tx_smic0_mux = SOC_DAPM_ENUM_EXT("tx_smic0", tx_smic0_enum,
+ snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic1_mux = SOC_DAPM_ENUM_EXT("tx_smic1", tx_smic1_enum,
+ snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic2_mux = SOC_DAPM_ENUM_EXT("tx_smic2", tx_smic2_enum,
+ snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic3_mux = SOC_DAPM_ENUM_EXT("tx_smic3", tx_smic3_enum,
+ snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic4_mux = SOC_DAPM_ENUM_EXT("tx_smic4", tx_smic4_enum,
+ snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic5_mux = SOC_DAPM_ENUM_EXT("tx_smic5", tx_smic5_enum,
+ snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic6_mux = SOC_DAPM_ENUM_EXT("tx_smic6", tx_smic6_enum,
+ snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+static const struct snd_kcontrol_new tx_smic7_mux = SOC_DAPM_ENUM_EXT("tx_smic7", tx_smic7_enum,
+ snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum);
+
+static const char * const dec_mode_mux_text[] = {
+ "ADC_DEFAULT", "ADC_LOW_PWR", "ADC_HIGH_PERF",
+};
+
+static const struct soc_enum dec_mode_mux_enum[] = {
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(dec_mode_mux_text),
+ dec_mode_mux_text),
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 1, ARRAY_SIZE(dec_mode_mux_text),
+ dec_mode_mux_text),
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 2, ARRAY_SIZE(dec_mode_mux_text),
+ dec_mode_mux_text),
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 3, ARRAY_SIZE(dec_mode_mux_text),
+ dec_mode_mux_text),
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 4, ARRAY_SIZE(dec_mode_mux_text),
+ dec_mode_mux_text),
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 5, ARRAY_SIZE(dec_mode_mux_text),
+ dec_mode_mux_text),
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 6, ARRAY_SIZE(dec_mode_mux_text),
+ dec_mode_mux_text),
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 7, ARRAY_SIZE(dec_mode_mux_text),
+ dec_mode_mux_text),
+};
+
+static const struct snd_kcontrol_new tx_aif1_cap_mixer[] = {
+ SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, TX_MACRO_DEC4, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, TX_MACRO_DEC5, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, TX_MACRO_DEC6, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, TX_MACRO_DEC7, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new tx_aif2_cap_mixer[] = {
+ SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, TX_MACRO_DEC4, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, TX_MACRO_DEC5, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, TX_MACRO_DEC6, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, TX_MACRO_DEC7, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new tx_aif3_cap_mixer[] = {
+ SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, TX_MACRO_DEC4, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, TX_MACRO_DEC5, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, TX_MACRO_DEC6, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+ SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, TX_MACRO_DEC7, 1, 0,
+ tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+};
+
+static const struct snd_soc_dapm_widget tx_macro_dapm_widgets[] = {
+ SND_SOC_DAPM_AIF_OUT("TX_AIF1 CAP", "TX_AIF1 Capture", 0,
+ SND_SOC_NOPM, TX_MACRO_AIF1_CAP, 0),
+
+ SND_SOC_DAPM_AIF_OUT("TX_AIF2 CAP", "TX_AIF2 Capture", 0,
+ SND_SOC_NOPM, TX_MACRO_AIF2_CAP, 0),
+
+ SND_SOC_DAPM_AIF_OUT("TX_AIF3 CAP", "TX_AIF3 Capture", 0,
+ SND_SOC_NOPM, TX_MACRO_AIF3_CAP, 0),
+
+ SND_SOC_DAPM_MIXER("TX_AIF1_CAP Mixer", SND_SOC_NOPM, TX_MACRO_AIF1_CAP, 0,
+ tx_aif1_cap_mixer, ARRAY_SIZE(tx_aif1_cap_mixer)),
+
+ SND_SOC_DAPM_MIXER("TX_AIF2_CAP Mixer", SND_SOC_NOPM, TX_MACRO_AIF2_CAP, 0,
+ tx_aif2_cap_mixer, ARRAY_SIZE(tx_aif2_cap_mixer)),
+
+ SND_SOC_DAPM_MIXER("TX_AIF3_CAP Mixer", SND_SOC_NOPM, TX_MACRO_AIF3_CAP, 0,
+ tx_aif3_cap_mixer, ARRAY_SIZE(tx_aif3_cap_mixer)),
+
+ SND_SOC_DAPM_MUX("TX SMIC MUX0", SND_SOC_NOPM, 0, 0, &tx_smic0_mux),
+ SND_SOC_DAPM_MUX("TX SMIC MUX1", SND_SOC_NOPM, 0, 0, &tx_smic1_mux),
+ SND_SOC_DAPM_MUX("TX SMIC MUX2", SND_SOC_NOPM, 0, 0, &tx_smic2_mux),
+ SND_SOC_DAPM_MUX("TX SMIC MUX3", SND_SOC_NOPM, 0, 0, &tx_smic3_mux),
+ SND_SOC_DAPM_MUX("TX SMIC MUX4", SND_SOC_NOPM, 0, 0, &tx_smic4_mux),
+ SND_SOC_DAPM_MUX("TX SMIC MUX5", SND_SOC_NOPM, 0, 0, &tx_smic5_mux),
+ SND_SOC_DAPM_MUX("TX SMIC MUX6", SND_SOC_NOPM, 0, 0, &tx_smic6_mux),
+ SND_SOC_DAPM_MUX("TX SMIC MUX7", SND_SOC_NOPM, 0, 0, &tx_smic7_mux),
+
+ SND_SOC_DAPM_INPUT("TX SWR_ADC0"),
+ SND_SOC_DAPM_INPUT("TX SWR_ADC1"),
+ SND_SOC_DAPM_INPUT("TX SWR_ADC2"),
+ SND_SOC_DAPM_INPUT("TX SWR_ADC3"),
+ SND_SOC_DAPM_INPUT("TX SWR_DMIC0"),
+ SND_SOC_DAPM_INPUT("TX SWR_DMIC1"),
+ SND_SOC_DAPM_INPUT("TX SWR_DMIC2"),
+ SND_SOC_DAPM_INPUT("TX SWR_DMIC3"),
+ SND_SOC_DAPM_INPUT("TX SWR_DMIC4"),
+ SND_SOC_DAPM_INPUT("TX SWR_DMIC5"),
+ SND_SOC_DAPM_INPUT("TX SWR_DMIC6"),
+ SND_SOC_DAPM_INPUT("TX SWR_DMIC7"),
+
+ SND_SOC_DAPM_MUX_E("TX DEC0 MUX", SND_SOC_NOPM,
+ TX_MACRO_DEC0, 0,
+ &tx_dec0_mux, tx_macro_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("TX DEC1 MUX", SND_SOC_NOPM,
+ TX_MACRO_DEC1, 0,
+ &tx_dec1_mux, tx_macro_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("TX DEC2 MUX", SND_SOC_NOPM,
+ TX_MACRO_DEC2, 0,
+ &tx_dec2_mux, tx_macro_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("TX DEC3 MUX", SND_SOC_NOPM,
+ TX_MACRO_DEC3, 0,
+ &tx_dec3_mux, tx_macro_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("TX DEC4 MUX", SND_SOC_NOPM,
+ TX_MACRO_DEC4, 0,
+ &tx_dec4_mux, tx_macro_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("TX DEC5 MUX", SND_SOC_NOPM,
+ TX_MACRO_DEC5, 0,
+ &tx_dec5_mux, tx_macro_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("TX DEC6 MUX", SND_SOC_NOPM,
+ TX_MACRO_DEC6, 0,
+ &tx_dec6_mux, tx_macro_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("TX DEC7 MUX", SND_SOC_NOPM,
+ TX_MACRO_DEC7, 0,
+ &tx_dec7_mux, tx_macro_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("TX_MCLK", 0, SND_SOC_NOPM, 0, 0,
+ tx_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("TX_SWR_CLK", 0, SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY_S("VA_SWR_CLK", 0, SND_SOC_NOPM, 0, 0,
+ NULL, 0),
+};
+
+static const struct snd_soc_dapm_route tx_audio_map[] = {
+ {"TX_AIF1 CAP", NULL, "TX_MCLK"},
+ {"TX_AIF2 CAP", NULL, "TX_MCLK"},
+ {"TX_AIF3 CAP", NULL, "TX_MCLK"},
+
+ {"TX_AIF1 CAP", NULL, "TX_AIF1_CAP Mixer"},
+ {"TX_AIF2 CAP", NULL, "TX_AIF2_CAP Mixer"},
+ {"TX_AIF3 CAP", NULL, "TX_AIF3_CAP Mixer"},
+
+ {"TX_AIF1_CAP Mixer", "DEC0", "TX DEC0 MUX"},
+ {"TX_AIF1_CAP Mixer", "DEC1", "TX DEC1 MUX"},
+ {"TX_AIF1_CAP Mixer", "DEC2", "TX DEC2 MUX"},
+ {"TX_AIF1_CAP Mixer", "DEC3", "TX DEC3 MUX"},
+ {"TX_AIF1_CAP Mixer", "DEC4", "TX DEC4 MUX"},
+ {"TX_AIF1_CAP Mixer", "DEC5", "TX DEC5 MUX"},
+ {"TX_AIF1_CAP Mixer", "DEC6", "TX DEC6 MUX"},
+ {"TX_AIF1_CAP Mixer", "DEC7", "TX DEC7 MUX"},
+
+ {"TX_AIF2_CAP Mixer", "DEC0", "TX DEC0 MUX"},
+ {"TX_AIF2_CAP Mixer", "DEC1", "TX DEC1 MUX"},
+ {"TX_AIF2_CAP Mixer", "DEC2", "TX DEC2 MUX"},
+ {"TX_AIF2_CAP Mixer", "DEC3", "TX DEC3 MUX"},
+ {"TX_AIF2_CAP Mixer", "DEC4", "TX DEC4 MUX"},
+ {"TX_AIF2_CAP Mixer", "DEC5", "TX DEC5 MUX"},
+ {"TX_AIF2_CAP Mixer", "DEC6", "TX DEC6 MUX"},
+ {"TX_AIF2_CAP Mixer", "DEC7", "TX DEC7 MUX"},
+
+ {"TX_AIF3_CAP Mixer", "DEC0", "TX DEC0 MUX"},
+ {"TX_AIF3_CAP Mixer", "DEC1", "TX DEC1 MUX"},
+ {"TX_AIF3_CAP Mixer", "DEC2", "TX DEC2 MUX"},
+ {"TX_AIF3_CAP Mixer", "DEC3", "TX DEC3 MUX"},
+ {"TX_AIF3_CAP Mixer", "DEC4", "TX DEC4 MUX"},
+ {"TX_AIF3_CAP Mixer", "DEC5", "TX DEC5 MUX"},
+ {"TX_AIF3_CAP Mixer", "DEC6", "TX DEC6 MUX"},
+ {"TX_AIF3_CAP Mixer", "DEC7", "TX DEC7 MUX"},
+
+ {"TX DEC0 MUX", NULL, "TX_MCLK"},
+ {"TX DEC1 MUX", NULL, "TX_MCLK"},
+ {"TX DEC2 MUX", NULL, "TX_MCLK"},
+ {"TX DEC3 MUX", NULL, "TX_MCLK"},
+ {"TX DEC4 MUX", NULL, "TX_MCLK"},
+ {"TX DEC5 MUX", NULL, "TX_MCLK"},
+ {"TX DEC6 MUX", NULL, "TX_MCLK"},
+ {"TX DEC7 MUX", NULL, "TX_MCLK"},
+
+ {"TX DEC0 MUX", "SWR_MIC", "TX SMIC MUX0"},
+ {"TX SMIC MUX0", NULL, "TX_SWR_CLK"},
+ {"TX SMIC MUX0", "ADC0", "TX SWR_ADC0"},
+ {"TX SMIC MUX0", "ADC1", "TX SWR_ADC1"},
+ {"TX SMIC MUX0", "ADC2", "TX SWR_ADC2"},
+ {"TX SMIC MUX0", "ADC3", "TX SWR_ADC3"},
+ {"TX SMIC MUX0", "SWR_DMIC0", "TX SWR_DMIC0"},
+ {"TX SMIC MUX0", "SWR_DMIC1", "TX SWR_DMIC1"},
+ {"TX SMIC MUX0", "SWR_DMIC2", "TX SWR_DMIC2"},
+ {"TX SMIC MUX0", "SWR_DMIC3", "TX SWR_DMIC3"},
+ {"TX SMIC MUX0", "SWR_DMIC4", "TX SWR_DMIC4"},
+ {"TX SMIC MUX0", "SWR_DMIC5", "TX SWR_DMIC5"},
+ {"TX SMIC MUX0", "SWR_DMIC6", "TX SWR_DMIC6"},
+ {"TX SMIC MUX0", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+ {"TX DEC1 MUX", "SWR_MIC", "TX SMIC MUX1"},
+ {"TX SMIC MUX1", NULL, "TX_SWR_CLK"},
+ {"TX SMIC MUX1", "ADC0", "TX SWR_ADC0"},
+ {"TX SMIC MUX1", "ADC1", "TX SWR_ADC1"},
+ {"TX SMIC MUX1", "ADC2", "TX SWR_ADC2"},
+ {"TX SMIC MUX1", "ADC3", "TX SWR_ADC3"},
+ {"TX SMIC MUX1", "SWR_DMIC0", "TX SWR_DMIC0"},
+ {"TX SMIC MUX1", "SWR_DMIC1", "TX SWR_DMIC1"},
+ {"TX SMIC MUX1", "SWR_DMIC2", "TX SWR_DMIC2"},
+ {"TX SMIC MUX1", "SWR_DMIC3", "TX SWR_DMIC3"},
+ {"TX SMIC MUX1", "SWR_DMIC4", "TX SWR_DMIC4"},
+ {"TX SMIC MUX1", "SWR_DMIC5", "TX SWR_DMIC5"},
+ {"TX SMIC MUX1", "SWR_DMIC6", "TX SWR_DMIC6"},
+ {"TX SMIC MUX1", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+ {"TX DEC2 MUX", "SWR_MIC", "TX SMIC MUX2"},
+ {"TX SMIC MUX2", NULL, "TX_SWR_CLK"},
+ {"TX SMIC MUX2", "ADC0", "TX SWR_ADC0"},
+ {"TX SMIC MUX2", "ADC1", "TX SWR_ADC1"},
+ {"TX SMIC MUX2", "ADC2", "TX SWR_ADC2"},
+ {"TX SMIC MUX2", "ADC3", "TX SWR_ADC3"},
+ {"TX SMIC MUX2", "SWR_DMIC0", "TX SWR_DMIC0"},
+ {"TX SMIC MUX2", "SWR_DMIC1", "TX SWR_DMIC1"},
+ {"TX SMIC MUX2", "SWR_DMIC2", "TX SWR_DMIC2"},
+ {"TX SMIC MUX2", "SWR_DMIC3", "TX SWR_DMIC3"},
+ {"TX SMIC MUX2", "SWR_DMIC4", "TX SWR_DMIC4"},
+ {"TX SMIC MUX2", "SWR_DMIC5", "TX SWR_DMIC5"},
+ {"TX SMIC MUX2", "SWR_DMIC6", "TX SWR_DMIC6"},
+ {"TX SMIC MUX2", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+ {"TX DEC3 MUX", "SWR_MIC", "TX SMIC MUX3"},
+ {"TX SMIC MUX3", NULL, "TX_SWR_CLK"},
+ {"TX SMIC MUX3", "ADC0", "TX SWR_ADC0"},
+ {"TX SMIC MUX3", "ADC1", "TX SWR_ADC1"},
+ {"TX SMIC MUX3", "ADC2", "TX SWR_ADC2"},
+ {"TX SMIC MUX3", "ADC3", "TX SWR_ADC3"},
+ {"TX SMIC MUX3", "SWR_DMIC0", "TX SWR_DMIC0"},
+ {"TX SMIC MUX3", "SWR_DMIC1", "TX SWR_DMIC1"},
+ {"TX SMIC MUX3", "SWR_DMIC2", "TX SWR_DMIC2"},
+ {"TX SMIC MUX3", "SWR_DMIC3", "TX SWR_DMIC3"},
+ {"TX SMIC MUX3", "SWR_DMIC4", "TX SWR_DMIC4"},
+ {"TX SMIC MUX3", "SWR_DMIC5", "TX SWR_DMIC5"},
+ {"TX SMIC MUX3", "SWR_DMIC6", "TX SWR_DMIC6"},
+ {"TX SMIC MUX3", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+ {"TX DEC4 MUX", "SWR_MIC", "TX SMIC MUX4"},
+ {"TX SMIC MUX4", NULL, "TX_SWR_CLK"},
+ {"TX SMIC MUX4", "ADC0", "TX SWR_ADC0"},
+ {"TX SMIC MUX4", "ADC1", "TX SWR_ADC1"},
+ {"TX SMIC MUX4", "ADC2", "TX SWR_ADC2"},
+ {"TX SMIC MUX4", "ADC3", "TX SWR_ADC3"},
+ {"TX SMIC MUX4", "SWR_DMIC0", "TX SWR_DMIC0"},
+ {"TX SMIC MUX4", "SWR_DMIC1", "TX SWR_DMIC1"},
+ {"TX SMIC MUX4", "SWR_DMIC2", "TX SWR_DMIC2"},
+ {"TX SMIC MUX4", "SWR_DMIC3", "TX SWR_DMIC3"},
+ {"TX SMIC MUX4", "SWR_DMIC4", "TX SWR_DMIC4"},
+ {"TX SMIC MUX4", "SWR_DMIC5", "TX SWR_DMIC5"},
+ {"TX SMIC MUX4", "SWR_DMIC6", "TX SWR_DMIC6"},
+ {"TX SMIC MUX4", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+ {"TX DEC5 MUX", "SWR_MIC", "TX SMIC MUX5"},
+ {"TX SMIC MUX5", NULL, "TX_SWR_CLK"},
+ {"TX SMIC MUX5", "ADC0", "TX SWR_ADC0"},
+ {"TX SMIC MUX5", "ADC1", "TX SWR_ADC1"},
+ {"TX SMIC MUX5", "ADC2", "TX SWR_ADC2"},
+ {"TX SMIC MUX5", "ADC3", "TX SWR_ADC3"},
+ {"TX SMIC MUX5", "SWR_DMIC0", "TX SWR_DMIC0"},
+ {"TX SMIC MUX5", "SWR_DMIC1", "TX SWR_DMIC1"},
+ {"TX SMIC MUX5", "SWR_DMIC2", "TX SWR_DMIC2"},
+ {"TX SMIC MUX5", "SWR_DMIC3", "TX SWR_DMIC3"},
+ {"TX SMIC MUX5", "SWR_DMIC4", "TX SWR_DMIC4"},
+ {"TX SMIC MUX5", "SWR_DMIC5", "TX SWR_DMIC5"},
+ {"TX SMIC MUX5", "SWR_DMIC6", "TX SWR_DMIC6"},
+ {"TX SMIC MUX5", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+ {"TX DEC6 MUX", "SWR_MIC", "TX SMIC MUX6"},
+ {"TX SMIC MUX6", NULL, "TX_SWR_CLK"},
+ {"TX SMIC MUX6", "ADC0", "TX SWR_ADC0"},
+ {"TX SMIC MUX6", "ADC1", "TX SWR_ADC1"},
+ {"TX SMIC MUX6", "ADC2", "TX SWR_ADC2"},
+ {"TX SMIC MUX6", "ADC3", "TX SWR_ADC3"},
+ {"TX SMIC MUX6", "SWR_DMIC0", "TX SWR_DMIC0"},
+ {"TX SMIC MUX6", "SWR_DMIC1", "TX SWR_DMIC1"},
+ {"TX SMIC MUX6", "SWR_DMIC2", "TX SWR_DMIC2"},
+ {"TX SMIC MUX6", "SWR_DMIC3", "TX SWR_DMIC3"},
+ {"TX SMIC MUX6", "SWR_DMIC4", "TX SWR_DMIC4"},
+ {"TX SMIC MUX6", "SWR_DMIC5", "TX SWR_DMIC5"},
+ {"TX SMIC MUX6", "SWR_DMIC6", "TX SWR_DMIC6"},
+ {"TX SMIC MUX6", "SWR_DMIC7", "TX SWR_DMIC7"},
+
+ {"TX DEC7 MUX", "SWR_MIC", "TX SMIC MUX7"},
+ {"TX SMIC MUX7", NULL, "TX_SWR_CLK"},
+ {"TX SMIC MUX7", "ADC0", "TX SWR_ADC0"},
+ {"TX SMIC MUX7", "ADC1", "TX SWR_ADC1"},
+ {"TX SMIC MUX7", "ADC2", "TX SWR_ADC2"},
+ {"TX SMIC MUX7", "ADC3", "TX SWR_ADC3"},
+ {"TX SMIC MUX7", "SWR_DMIC0", "TX SWR_DMIC0"},
+ {"TX SMIC MUX7", "SWR_DMIC1", "TX SWR_DMIC1"},
+ {"TX SMIC MUX7", "SWR_DMIC2", "TX SWR_DMIC2"},
+ {"TX SMIC MUX7", "SWR_DMIC3", "TX SWR_DMIC3"},
+ {"TX SMIC MUX7", "SWR_DMIC4", "TX SWR_DMIC4"},
+ {"TX SMIC MUX7", "SWR_DMIC5", "TX SWR_DMIC5"},
+ {"TX SMIC MUX7", "SWR_DMIC6", "TX SWR_DMIC6"},
+ {"TX SMIC MUX7", "SWR_DMIC7", "TX SWR_DMIC7"},
+};
+
+static const struct snd_kcontrol_new tx_macro_snd_controls[] = {
+ SOC_SINGLE_S8_TLV("TX_DEC0 Volume",
+ CDC_TX0_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("TX_DEC1 Volume",
+ CDC_TX1_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("TX_DEC2 Volume",
+ CDC_TX2_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("TX_DEC3 Volume",
+ CDC_TX3_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("TX_DEC4 Volume",
+ CDC_TX4_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("TX_DEC5 Volume",
+ CDC_TX5_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("TX_DEC6 Volume",
+ CDC_TX6_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("TX_DEC7 Volume",
+ CDC_TX7_TX_VOL_CTL,
+ -84, 40, digital_gain),
+
+ SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum[0],
+ tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+ SOC_ENUM_EXT("DEC1 MODE", dec_mode_mux_enum[1],
+ tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+ SOC_ENUM_EXT("DEC2 MODE", dec_mode_mux_enum[2],
+ tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+ SOC_ENUM_EXT("DEC3 MODE", dec_mode_mux_enum[3],
+ tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+ SOC_ENUM_EXT("DEC4 MODE", dec_mode_mux_enum[4],
+ tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+ SOC_ENUM_EXT("DEC5 MODE", dec_mode_mux_enum[5],
+ tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+ SOC_ENUM_EXT("DEC6 MODE", dec_mode_mux_enum[6],
+ tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+ SOC_ENUM_EXT("DEC7 MODE", dec_mode_mux_enum[7],
+ tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+ SOC_SINGLE_EXT("DEC0_BCS Switch", SND_SOC_NOPM, 0, 1, 0,
+ tx_macro_get_bcs, tx_macro_set_bcs),
+};
+
+static int tx_macro_component_probe(struct snd_soc_component *comp)
+{
+ struct tx_macro *tx = snd_soc_component_get_drvdata(comp);
+ int i;
+
+ snd_soc_component_init_regmap(comp, tx->regmap);
+
+ for (i = 0; i < NUM_DECIMATORS; i++) {
+ tx->tx_hpf_work[i].tx = tx;
+ tx->tx_hpf_work[i].decimator = i;
+ INIT_DELAYED_WORK(&tx->tx_hpf_work[i].dwork,
+ tx_macro_tx_hpf_corner_freq_callback);
+ }
+
+ for (i = 0; i < NUM_DECIMATORS; i++) {
+ tx->tx_mute_dwork[i].tx = tx;
+ tx->tx_mute_dwork[i].decimator = i;
+ INIT_DELAYED_WORK(&tx->tx_mute_dwork[i].dwork,
+ tx_macro_mute_update_callback);
+ }
+ tx->component = comp;
+
+ snd_soc_component_update_bits(comp, CDC_TX0_TX_PATH_SEC7, 0x3F,
+ 0x0A);
+
+ return 0;
+}
+
+static int swclk_gate_enable(struct clk_hw *hw)
+{
+ struct tx_macro *tx = to_tx_macro(hw);
+ struct regmap *regmap = tx->regmap;
+
+ tx_macro_mclk_enable(tx, true);
+ if (tx->reset_swr)
+ regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
+ CDC_TX_SWR_RESET_MASK,
+ CDC_TX_SWR_RESET_ENABLE);
+
+ regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
+ CDC_TX_SWR_CLK_EN_MASK,
+ CDC_TX_SWR_CLK_ENABLE);
+ if (tx->reset_swr)
+ regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
+ CDC_TX_SWR_RESET_MASK, 0x0);
+ tx->reset_swr = false;
+
+ return 0;
+}
+
+static void swclk_gate_disable(struct clk_hw *hw)
+{
+ struct tx_macro *tx = to_tx_macro(hw);
+ struct regmap *regmap = tx->regmap;
+
+ regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
+ CDC_TX_SWR_CLK_EN_MASK, 0x0);
+
+ tx_macro_mclk_enable(tx, false);
+}
+
+static int swclk_gate_is_enabled(struct clk_hw *hw)
+{
+ struct tx_macro *tx = to_tx_macro(hw);
+ int ret, val;
+
+ regmap_read(tx->regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, &val);
+ ret = val & BIT(0);
+
+ return ret;
+}
+
+static unsigned long swclk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return parent_rate / 2;
+}
+
+static const struct clk_ops swclk_gate_ops = {
+ .prepare = swclk_gate_enable,
+ .unprepare = swclk_gate_disable,
+ .is_enabled = swclk_gate_is_enabled,
+ .recalc_rate = swclk_recalc_rate,
+
+};
+
+static struct clk *tx_macro_register_mclk_output(struct tx_macro *tx)
+{
+ struct device *dev = tx->dev;
+ struct device_node *np = dev->of_node;
+ const char *parent_clk_name = NULL;
+ const char *clk_name = "lpass-tx-mclk";
+ struct clk_hw *hw;
+ struct clk_init_data init;
+ int ret;
+
+ parent_clk_name = __clk_get_name(tx->clks[2].clk);
+
+ init.name = clk_name;
+ init.ops = &swclk_gate_ops;
+ init.flags = 0;
+ init.parent_names = &parent_clk_name;
+ init.num_parents = 1;
+ tx->hw.init = &init;
+ hw = &tx->hw;
+ ret = clk_hw_register(tx->dev, hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ of_clk_add_provider(np, of_clk_src_simple_get, hw->clk);
+
+ return NULL;
+}
+
+static const struct snd_soc_component_driver tx_macro_component_drv = {
+ .name = "RX-MACRO",
+ .probe = tx_macro_component_probe,
+ .controls = tx_macro_snd_controls,
+ .num_controls = ARRAY_SIZE(tx_macro_snd_controls),
+ .dapm_widgets = tx_macro_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tx_macro_dapm_widgets),
+ .dapm_routes = tx_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(tx_audio_map),
+};
+
+static int tx_macro_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct tx_macro *tx;
+ void __iomem *base;
+ int ret;
+
+ tx = devm_kzalloc(dev, sizeof(*tx), GFP_KERNEL);
+ if (!tx)
+ return -ENOMEM;
+
+ tx->clks[0].id = "macro";
+ tx->clks[1].id = "dcodec";
+ tx->clks[2].id = "mclk";
+ tx->clks[3].id = "npl";
+ tx->clks[4].id = "fsgen";
+
+ ret = devm_clk_bulk_get(dev, TX_NUM_CLKS_MAX, tx->clks);
+ if (ret) {
+ dev_err(dev, "Error getting RX Clocks (%d)\n", ret);
+ return ret;
+ }
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ tx->regmap = devm_regmap_init_mmio(dev, base, &tx_regmap_config);
+
+ dev_set_drvdata(dev, tx);
+
+ tx->reset_swr = true;
+ tx->dev = dev;
+
+ /* set MCLK and NPL rates */
+ clk_set_rate(tx->clks[2].clk, MCLK_FREQ);
+ clk_set_rate(tx->clks[3].clk, MCLK_FREQ);
+
+ ret = clk_bulk_prepare_enable(TX_NUM_CLKS_MAX, tx->clks);
+ if (ret)
+ return ret;
+
+ tx_macro_register_mclk_output(tx);
+
+ ret = devm_snd_soc_register_component(dev, &tx_macro_component_drv,
+ tx_macro_dai,
+ ARRAY_SIZE(tx_macro_dai));
+ if (ret)
+ goto err;
+ return ret;
+err:
+ clk_bulk_disable_unprepare(TX_NUM_CLKS_MAX, tx->clks);
+
+ return ret;
+}
+
+static int tx_macro_remove(struct platform_device *pdev)
+{
+ struct tx_macro *tx = dev_get_drvdata(&pdev->dev);
+
+ of_clk_del_provider(pdev->dev.of_node);
+
+ clk_bulk_disable_unprepare(TX_NUM_CLKS_MAX, tx->clks);
+
+ return 0;
+}
+
+static const struct of_device_id tx_macro_dt_match[] = {
+ { .compatible = "qcom,sm8250-lpass-tx-macro" },
+ { }
+};
+static struct platform_driver tx_macro_driver = {
+ .driver = {
+ .name = "tx_macro",
+ .of_match_table = tx_macro_dt_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = tx_macro_probe,
+ .remove = tx_macro_remove,
+};
+
+module_platform_driver(tx_macro_driver);
+
+MODULE_DESCRIPTION("TX macro driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c
index 25f1df214ca5..5ebcd935ba89 100644
--- a/sound/soc/codecs/lpass-wsa-macro.c
+++ b/sound/soc/codecs/lpass-wsa-macro.c
@@ -40,9 +40,11 @@
#define CDC_WSA_TOP_I2S_CLK (0x00A4)
#define CDC_WSA_TOP_I2S_RESET (0x00A8)
#define CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 (0x0100)
-#define CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK GENMASK(5, 3)
-#define CDC_WSA_RX_INTX_2_SEL_MASK GENMASK(2, 0)
+#define CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK GENMASK(2, 0)
+#define CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK GENMASK(5, 3)
#define CDC_WSA_RX_INP_MUX_RX_INT0_CFG1 (0x0104)
+#define CDC_WSA_RX_INTX_2_SEL_MASK GENMASK(2, 0)
+#define CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK GENMASK(5, 3)
#define CDC_WSA_RX_INP_MUX_RX_INT1_CFG0 (0x0108)
#define CDC_WSA_RX_INP_MUX_RX_INT1_CFG1 (0x010C)
#define CDC_WSA_RX_INP_MUX_RX_MIX_CFG0 (0x0110)
@@ -229,8 +231,6 @@
#define NUM_INTERPOLATORS 2
#define WSA_NUM_CLKS_MAX 5
#define WSA_MACRO_MCLK_FREQ 19200000
-#define WSA_MACRO_MUX_INP_SHFT 0x3
-#define WSA_MACRO_MUX_INP_MASK1 0x07
#define WSA_MACRO_MUX_INP_MASK2 0x38
#define WSA_MACRO_MUX_CFG_OFFSET 0x8
#define WSA_MACRO_MUX_CFG1_OFFSET 0x4
@@ -843,7 +843,6 @@ static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
u32 j, port;
u16 int_mux_cfg0, int_mux_cfg1;
u16 int_fs_reg;
- u8 int_mux_cfg0_val, int_mux_cfg1_val;
u8 inp0_sel, inp1_sel, inp2_sel;
struct snd_soc_component *component = dai->component;
struct wsa_macro *wsa = snd_soc_component_get_drvdata(component);
@@ -865,15 +864,13 @@ static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
*/
for (j = 0; j < NUM_INTERPOLATORS; j++) {
int_mux_cfg1 = int_mux_cfg0 + WSA_MACRO_MUX_CFG1_OFFSET;
- int_mux_cfg0_val = snd_soc_component_read(component,
- int_mux_cfg0);
- int_mux_cfg1_val = snd_soc_component_read(component,
- int_mux_cfg1);
- inp0_sel = int_mux_cfg0_val & WSA_MACRO_MUX_INP_MASK1;
- inp1_sel = (int_mux_cfg0_val >> WSA_MACRO_MUX_INP_SHFT) &
- WSA_MACRO_MUX_INP_MASK1;
- inp2_sel = (int_mux_cfg1_val >> WSA_MACRO_MUX_INP_SHFT) &
- WSA_MACRO_MUX_INP_MASK1;
+ inp0_sel = snd_soc_component_read_field(component, int_mux_cfg0,
+ CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK);
+ inp1_sel = snd_soc_component_read_field(component, int_mux_cfg0,
+ CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK);
+ inp2_sel = snd_soc_component_read_field(component, int_mux_cfg1,
+ CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK);
+
if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) ||
(inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) ||
(inp2_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0)) {
@@ -912,9 +909,9 @@ static int wsa_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai,
int_mux_cfg1 = CDC_WSA_RX_INP_MUX_RX_INT0_CFG1;
for (j = 0; j < NUM_INTERPOLATORS; j++) {
- int_mux_cfg1_val = snd_soc_component_read(component,
- int_mux_cfg1) &
- WSA_MACRO_MUX_INP_MASK1;
+ int_mux_cfg1_val = snd_soc_component_read_field(component, int_mux_cfg1,
+ CDC_WSA_RX_INTX_2_SEL_MASK);
+
if (int_mux_cfg1_val == int_2_inp + INTn_2_INP_SEL_RX0) {
int_fs_reg = CDC_WSA_RX0_RX_PATH_MIX_CTL +
WSA_MACRO_RX_PATH_OFFSET * j;
@@ -1410,25 +1407,25 @@ static bool wsa_macro_adie_lb(struct snd_soc_component *component,
int interp_idx)
{
u16 int_mux_cfg0, int_mux_cfg1;
- u8 int_mux_cfg0_val, int_mux_cfg1_val;
u8 int_n_inp0, int_n_inp1, int_n_inp2;
int_mux_cfg0 = CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 + interp_idx * 8;
int_mux_cfg1 = int_mux_cfg0 + 4;
- int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0);
- int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1);
- int_n_inp0 = int_mux_cfg0_val & 0x0F;
+ int_n_inp0 = snd_soc_component_read_field(component, int_mux_cfg0,
+ CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK);
if (int_n_inp0 == INTn_1_INP_SEL_DEC0 ||
int_n_inp0 == INTn_1_INP_SEL_DEC1)
return true;
- int_n_inp1 = int_mux_cfg0_val >> 4;
+ int_n_inp1 = snd_soc_component_read_field(component, int_mux_cfg0,
+ CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK);
if (int_n_inp1 == INTn_1_INP_SEL_DEC0 ||
int_n_inp1 == INTn_1_INP_SEL_DEC1)
return true;
- int_n_inp2 = int_mux_cfg1_val >> 4;
+ int_n_inp2 = snd_soc_component_read_field(component, int_mux_cfg1,
+ CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK);
if (int_n_inp2 == INTn_1_INP_SEL_DEC0 ||
int_n_inp2 == INTn_1_INP_SEL_DEC1)
return true;
diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c
index b8d471d79e93..d8c47667a9ea 100644
--- a/sound/soc/codecs/max98373-sdw.c
+++ b/sound/soc/codecs/max98373-sdw.c
@@ -262,6 +262,8 @@ static __maybe_unused int max98373_suspend(struct device *dev)
return 0;
}
+#define MAX98373_PROBE_TIMEOUT 5000
+
static __maybe_unused int max98373_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
@@ -275,7 +277,7 @@ static __maybe_unused int max98373_resume(struct device *dev)
goto regmap_sync;
time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(2000));
+ msecs_to_jiffies(MAX98373_PROBE_TIMEOUT));
if (!time) {
dev_err(dev, "Initialization not complete, timed out\n");
return -ETIMEDOUT;
diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c
index 31d571d4fac1..746c829312b8 100644
--- a/sound/soc/codecs/max98373.c
+++ b/sound/soc/codecs/max98373.c
@@ -190,7 +190,7 @@ static int max98373_feedback_get(struct snd_kcontrol *kcontrol,
}
}
- return snd_soc_put_volsw(kcontrol, ucontrol);
+ return snd_soc_get_volsw(kcontrol, ucontrol);
}
static const struct snd_kcontrol_new max98373_snd_controls[] = {
diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c
index d5925c42b4b5..dd29b183ecd6 100644
--- a/sound/soc/codecs/max9860.c
+++ b/sound/soc/codecs/max9860.c
@@ -489,7 +489,7 @@ static struct snd_soc_dai_driver max9860_dai = {
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &max9860_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int max9860_set_bias_level(struct snd_soc_component *component,
diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c
index 512e6f2513d3..09b2d730e9fd 100644
--- a/sound/soc/codecs/max9867.c
+++ b/sound/soc/codecs/max9867.c
@@ -520,7 +520,7 @@ static struct snd_soc_dai_driver max9867_dai[] = {
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.ops = &max9867_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
}
};
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index 9e6a0cda43d0..a21072503cb9 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -712,7 +712,7 @@ static struct snd_soc_dai_driver mc13783_dai_sync[] = {
.formats = MC13783_FORMATS,
},
.ops = &mc13783_ops_sync,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
}
};
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
index 70c17be455ca..4d7c0be2a4aa 100644
--- a/sound/soc/codecs/ml26124.c
+++ b/sound/soc/codecs/ml26124.c
@@ -513,7 +513,7 @@ static struct snd_soc_dai_driver ml26124_dai = {
.rates = ML26124_RATES,
.formats = ML26124_FORMATS,},
.ops = &ml26124_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int ml26124_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/mt6359.c b/sound/soc/codecs/mt6359.c
index 6de0d744fa9e..6f4b1da52082 100644
--- a/sound/soc/codecs/mt6359.c
+++ b/sound/soc/codecs/mt6359.c
@@ -2754,7 +2754,8 @@ static int mt6359_parse_dt(struct mt6359_priv *priv)
ret = of_property_read_u32(np, "mediatek,dmic-mode",
&priv->dmic_one_wire_mode);
if (ret) {
- dev_warn(priv->dev, "%s() failed to read dmic-mode\n",
+ dev_info(priv->dev,
+ "%s() failed to read dmic-mode, use default (0)\n",
__func__);
priv->dmic_one_wire_mode = 0;
}
@@ -2762,24 +2763,27 @@ static int mt6359_parse_dt(struct mt6359_priv *priv)
ret = of_property_read_u32(np, "mediatek,mic-type-0",
&priv->mux_select[MUX_MIC_TYPE_0]);
if (ret) {
- dev_warn(priv->dev, "%s() failed to read mic-type-0\n",
- __func__);
+ dev_info(priv->dev,
+ "%s() failed to read mic-type-0, use default (%d)\n",
+ __func__, MIC_TYPE_MUX_IDLE);
priv->mux_select[MUX_MIC_TYPE_0] = MIC_TYPE_MUX_IDLE;
}
ret = of_property_read_u32(np, "mediatek,mic-type-1",
&priv->mux_select[MUX_MIC_TYPE_1]);
if (ret) {
- dev_warn(priv->dev, "%s() failed to read mic-type-1\n",
- __func__);
+ dev_info(priv->dev,
+ "%s() failed to read mic-type-1, use default (%d)\n",
+ __func__, MIC_TYPE_MUX_IDLE);
priv->mux_select[MUX_MIC_TYPE_1] = MIC_TYPE_MUX_IDLE;
}
ret = of_property_read_u32(np, "mediatek,mic-type-2",
&priv->mux_select[MUX_MIC_TYPE_2]);
if (ret) {
- dev_warn(priv->dev, "%s() failed to read mic-type-2\n",
- __func__);
+ dev_info(priv->dev,
+ "%s() failed to read mic-type-2, use default (%d)\n",
+ __func__, MIC_TYPE_MUX_IDLE);
priv->mux_select[MUX_MIC_TYPE_2] = MIC_TYPE_MUX_IDLE;
}
diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c
index d1797003c83d..358c500377df 100644
--- a/sound/soc/codecs/mt6660.c
+++ b/sound/soc/codecs/mt6660.c
@@ -404,9 +404,9 @@ static struct snd_soc_dai_driver mt6660_codec_dai = {
.formats = STUB_FORMATS,
},
/* dai properties */
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
.symmetric_channels = 1,
- .symmetric_samplebits = 1,
+ .symmetric_sample_bits = 1,
/* dai operations */
.ops = &mt6660_component_aif_ops,
};
diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c
index 33ebc6398426..13676b544f58 100644
--- a/sound/soc/codecs/nau8810.c
+++ b/sound/soc/codecs/nau8810.c
@@ -837,7 +837,7 @@ static struct snd_soc_dai_driver nau8810_dai = {
.formats = NAU8810_FORMATS,
},
.ops = &nau8810_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static const struct regmap_config nau8810_regmap_config = {
diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c
index 609aeeb27818..58123390c7a3 100644
--- a/sound/soc/codecs/nau8822.c
+++ b/sound/soc/codecs/nau8822.c
@@ -991,7 +991,7 @@ static struct snd_soc_dai_driver nau8822_dai = {
.formats = NAU8822_FORMATS,
},
.ops = &nau8822_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int nau8822_suspend(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c
index 32e6bcf763d1..37b5795b00d1 100644
--- a/sound/soc/codecs/rt1015.c
+++ b/sound/soc/codecs/rt1015.c
@@ -24,10 +24,10 @@
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
+#include <sound/rt1015.h>
#include <sound/soc-dapm.h>
#include <sound/soc.h>
#include <sound/tlv.h>
-#include <sound/rt1015.h>
#include "rl6231.h"
#include "rt1015.h"
@@ -444,10 +444,9 @@ static int rt1015_boost_mode_put(struct snd_kcontrol *kcontrol,
snd_soc_kcontrol_component(kcontrol);
struct rt1015_priv *rt1015 =
snd_soc_component_get_drvdata(component);
+ int boost_mode = ucontrol->value.integer.value[0];
- rt1015->boost_mode = ucontrol->value.integer.value[0];
-
- switch (rt1015->boost_mode) {
+ switch (boost_mode) {
case BYPASS:
snd_soc_component_update_bits(component,
RT1015_SMART_BST_CTRL1, RT1015_ABST_AUTO_EN_MASK |
@@ -471,8 +470,11 @@ static int rt1015_boost_mode_put(struct snd_kcontrol *kcontrol,
break;
default:
dev_err(component->dev, "Unknown boost control.\n");
+ return -EINVAL;
}
+ rt1015->boost_mode = boost_mode;
+
return 0;
}
@@ -497,40 +499,20 @@ static void rt1015_calibrate(struct rt1015_priv *rt1015)
snd_soc_dapm_mutex_lock(&component->dapm);
regcache_cache_bypass(regmap, true);
- regmap_write(regmap, RT1015_PWR9, 0xAA60);
- regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0089);
- regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008A);
- regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008C);
- regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008D);
- regmap_write(regmap, RT1015_PWR4, 0x80B2);
- regmap_write(regmap, RT1015_CLASSD_SEQ, 0x5797);
- regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2100);
- regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0100);
- regmap_write(regmap, RT1015_PWR5, 0x2175);
- regmap_write(regmap, RT1015_MIXER1, 0x005D);
- regmap_write(regmap, RT1015_CLSD_INTERNAL1, 0x00A1);
- regmap_write(regmap, RT1015_CLSD_INTERNAL2, 0x12F7);
- regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x1205);
- msleep(200);
- regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2000);
- regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0180);
- regmap_write(regmap, RT1015_CLSD_INTERNAL1, 0x00A1);
- regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x0A05);
- msleep(200);
+ regmap_write(regmap, RT1015_CLK_DET, 0x0000);
regmap_write(regmap, RT1015_PWR4, 0x00B2);
+ regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0009);
+ msleep(100);
+ regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000A);
+ msleep(100);
+ regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000C);
+ msleep(100);
regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2028);
regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0140);
- regmap_write(regmap, RT1015_PWR5, 0x0175);
- regmap_write(regmap, RT1015_CLSD_INTERNAL1, 0x1721);
- regmap_write(regmap, RT1015_CLASSD_SEQ, 0x570E);
- regmap_write(regmap, RT1015_MIXER1, 0x203D);
- regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x5A01);
- regmap_write(regmap, RT1015_CLSD_INTERNAL2, 0x12FF);
- regmap_write(regmap, RT1015_GAT_BOOST, 0x0eFE);
- regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008E);
- regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0088);
+ regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000D);
+ msleep(300);
+ regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0008);
regmap_write(regmap, RT1015_SYS_RST1, 0x05F5);
- regmap_write(regmap, RT1015_SYS_RST2, 0x0b9a);
regcache_cache_bypass(regmap, false);
regcache_mark_dirty(regmap);
@@ -546,17 +528,19 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol,
struct rt1015_priv *rt1015 =
snd_soc_component_get_drvdata(component);
- if (!rt1015->dac_is_used) {
- rt1015->bypass_boost = ucontrol->value.integer.value[0];
- if (rt1015->bypass_boost == RT1015_Bypass_Boost &&
+ if (rt1015->dac_is_used) {
+ dev_err(component->dev, "DAC is being used!\n");
+ return -EBUSY;
+ }
+
+ rt1015->bypass_boost = ucontrol->value.integer.value[0];
+ if (rt1015->bypass_boost == RT1015_Bypass_Boost &&
!rt1015->cali_done) {
- rt1015_calibrate(rt1015);
- rt1015->cali_done = 1;
+ rt1015_calibrate(rt1015);
+ rt1015->cali_done = 1;
- regmap_write(rt1015->regmap, RT1015_MONO_DYNA_CTRL, 0x0010);
- }
- } else
- dev_err(component->dev, "DAC is being used!\n");
+ regmap_write(rt1015->regmap, RT1015_MONO_DYNA_CTRL, 0x0010);
+ }
return 0;
}
@@ -566,15 +550,14 @@ static void rt1015_flush_work(struct work_struct *work)
struct rt1015_priv *rt1015 = container_of(work, struct rt1015_priv,
flush_work.work);
struct snd_soc_component *component = rt1015->component;
- unsigned int val, i = 0, count = 200;
+ unsigned int val, i;
- while (i < count) {
+ for (i = 0; i < 200; ++i) {
usleep_range(1000, 1500);
dev_dbg(component->dev, "Flush DAC (retry:%u)\n", i);
regmap_read(rt1015->regmap, RT1015_CLK_DET, &val);
if (val & 0x800)
break;
- i++;
}
regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597);
@@ -721,11 +704,11 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_component *component = dai->component;
struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component);
- int pre_div, bclk_ms, frame_size;
+ int pre_div, bclk_ms, frame_size, lrck;
unsigned int val_len = 0;
- rt1015->lrck = params_rate(params);
- pre_div = rl6231_get_clk_info(rt1015->sysclk, rt1015->lrck);
+ lrck = params_rate(params);
+ pre_div = rl6231_get_clk_info(rt1015->sysclk, lrck);
if (pre_div < 0) {
dev_err(component->dev, "Unsupported clock rate\n");
return -EINVAL;
@@ -739,13 +722,12 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream,
}
bclk_ms = frame_size > 32;
- rt1015->bclk = rt1015->lrck * (32 << bclk_ms);
dev_dbg(component->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
bclk_ms, pre_div, dai->id);
dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n",
- rt1015->lrck, pre_div, dai->id);
+ lrck, pre_div, dai->id);
switch (params_width(params)) {
case 16:
@@ -882,14 +864,6 @@ static int rt1015_set_component_pll(struct snd_soc_component *component,
freq_out == rt1015->pll_out)
return 0;
- if (source == RT1015_PLL_S_BCLK) {
- if (rt1015->bclk_ratio == 0) {
- dev_err(component->dev,
- "Can not support bclk ratio as 0.\n");
- return -EINVAL;
- }
- }
-
switch (source) {
case RT1015_PLL_S_MCLK:
snd_soc_component_update_bits(component, RT1015_CLK2,
@@ -929,23 +903,6 @@ static int rt1015_set_component_pll(struct snd_soc_component *component,
return 0;
}
-static int rt1015_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
-{
- struct snd_soc_component *component = dai->component;
- struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component);
-
- dev_dbg(component->dev, "%s ratio=%d\n", __func__, ratio);
-
- rt1015->bclk_ratio = ratio;
-
- if (ratio == 50) {
- dev_dbg(component->dev, "Unsupport bclk ratio\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
static int rt1015_set_tdm_slot(struct snd_soc_dai *dai,
unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
{
@@ -1052,9 +1009,6 @@ static int rt1015_probe(struct snd_soc_component *component)
snd_soc_component_get_drvdata(component);
rt1015->component = component;
- rt1015->bclk_ratio = 0;
- rt1015->cali_done = 0;
-
INIT_DELAYED_WORK(&rt1015->flush_work, rt1015_flush_work);
return 0;
@@ -1075,7 +1029,6 @@ static void rt1015_remove(struct snd_soc_component *component)
static struct snd_soc_dai_ops rt1015_aif_dai_ops = {
.hw_params = rt1015_hw_params,
.set_fmt = rt1015_set_dai_fmt,
- .set_bclk_ratio = rt1015_set_bclk_ratio,
.set_tdm_slot = rt1015_set_tdm_slot,
};
@@ -1111,6 +1064,10 @@ static int rt1015_resume(struct snd_soc_component *component)
regcache_cache_only(rt1015->regmap, false);
regcache_sync(rt1015->regmap);
+
+ if (rt1015->cali_done)
+ rt1015_calibrate(rt1015);
+
return 0;
}
#else
@@ -1183,9 +1140,8 @@ static int rt1015_i2c_probe(struct i2c_client *i2c,
int ret;
unsigned int val;
- rt1015 = devm_kzalloc(&i2c->dev, sizeof(struct rt1015_priv),
- GFP_KERNEL);
- if (rt1015 == NULL)
+ rt1015 = devm_kzalloc(&i2c->dev, sizeof(*rt1015), GFP_KERNEL);
+ if (!rt1015)
return -ENOMEM;
i2c_set_clientdata(i2c, rt1015);
diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h
index b6ea753014e1..2aeaf65ba793 100644
--- a/sound/soc/codecs/rt1015.h
+++ b/sound/soc/codecs/rt1015.h
@@ -427,16 +427,11 @@ struct rt1015_priv {
struct regmap *regmap;
int sysclk;
int sysclk_src;
- int lrck;
- int bclk;
- int bclk_ratio;
- int id;
int pll_src;
int pll_in;
int pll_out;
int boost_mode;
int bypass_boost;
- int amp_ver;
int dac_is_used;
int cali_done;
int hw_config;
diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c
index ec5564f780e8..afd2c3b687cc 100644
--- a/sound/soc/codecs/rt1308-sdw.c
+++ b/sound/soc/codecs/rt1308-sdw.c
@@ -701,7 +701,7 @@ static int __maybe_unused rt1308_dev_suspend(struct device *dev)
return 0;
}
-#define RT1308_PROBE_TIMEOUT 2000
+#define RT1308_PROBE_TIMEOUT 5000
static int __maybe_unused rt1308_dev_resume(struct device *dev)
{
diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c
index 70cf17c0aa99..0d3773c576f8 100644
--- a/sound/soc/codecs/rt274.c
+++ b/sound/soc/codecs/rt274.c
@@ -1056,7 +1056,7 @@ static struct snd_soc_dai_driver rt274_dai[] = {
.formats = RT274_FORMATS,
},
.ops = &rt274_aif_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
index 5fb9653d9131..8abe232ca4a4 100644
--- a/sound/soc/codecs/rt286.c
+++ b/sound/soc/codecs/rt286.c
@@ -1017,7 +1017,7 @@ static struct snd_soc_dai_driver rt286_dai[] = {
.formats = RT286_FORMATS,
},
.ops = &rt286_aif_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "rt286-aif2",
@@ -1037,7 +1037,7 @@ static struct snd_soc_dai_driver rt286_dai[] = {
.formats = RT286_FORMATS,
},
.ops = &rt286_aif_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c
index dc0273a5a11f..32cc9b6287d2 100644
--- a/sound/soc/codecs/rt298.c
+++ b/sound/soc/codecs/rt298.c
@@ -1084,7 +1084,7 @@ static struct snd_soc_dai_driver rt298_dai[] = {
.formats = RT298_FORMATS,
},
.ops = &rt298_aif_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "rt298-aif2",
@@ -1104,7 +1104,7 @@ static struct snd_soc_dai_driver rt298_dai[] = {
.formats = RT298_FORMATS,
},
.ops = &rt298_aif_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 420003d062c7..63a7e052eaa0 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -34,6 +34,7 @@
#define QUIRK_INV_JD1_1(q) ((q) & 1)
#define QUIRK_LEVEL_IRQ(q) (((q) >> 1) & 1)
#define QUIRK_IN2_DIFF(q) (((q) >> 2) & 1)
+#define QUIRK_INV_HP_POL(q) (((q) >> 3) & 1)
#define QUIRK_JD_MODE(q) (((q) >> 4) & 7)
#define QUIRK_DMIC1_DATA_PIN(q) (((q) >> 8) & 3)
#define QUIRK_DMIC2_DATA_PIN(q) (((q) >> 12) & 3)
@@ -42,6 +43,8 @@ static unsigned int quirk = -1;
module_param(quirk, uint, 0444);
MODULE_PARM_DESC(quirk, "RT5645 pdata quirk override");
+static const struct acpi_gpio_mapping *cht_rt5645_gpios;
+
#define RT5645_DEVICE_ID 0x6308
#define RT5650_DEVICE_ID 0x6419
@@ -435,7 +438,6 @@ struct rt5645_priv {
int jack_type;
bool en_button_func;
- bool hp_on;
int v_id;
};
@@ -1645,6 +1647,7 @@ static void hp_amp_power(struct snd_soc_component *component, int on)
{
static int hp_amp_power_count;
struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component);
+ int i, val;
if (on) {
if (hp_amp_power_count <= 0) {
@@ -1655,7 +1658,13 @@ static void hp_amp_power(struct snd_soc_component *component, int on)
snd_soc_component_write(component, RT5645_DEPOP_M1, 0x000d);
regmap_write(rt5645->regmap, RT5645_PR_BASE +
RT5645_HP_DCC_INT1, 0x9f01);
- msleep(20);
+ for (i = 0; i < 20; i++) {
+ usleep_range(1000, 1500);
+ regmap_read(rt5645->regmap, RT5645_PR_BASE +
+ RT5645_HP_DCC_INT1, &val);
+ if (!(val & 0x8000))
+ break;
+ }
snd_soc_component_update_bits(component, RT5645_DEPOP_M1,
RT5645_HP_CO_MASK, RT5645_HP_CO_EN);
regmap_write(rt5645->regmap, RT5645_PR_BASE +
@@ -1665,7 +1674,6 @@ static void hp_amp_power(struct snd_soc_component *component, int on)
RT5645_MAMP_INT_REG2, 0xfc00);
snd_soc_component_write(component, RT5645_DEPOP_M2, 0x1140);
msleep(90);
- rt5645->hp_on = true;
} else {
/* depop parameters */
snd_soc_component_update_bits(component, RT5645_DEPOP_M2,
@@ -1885,27 +1893,6 @@ static int rt5645_bst2_event(struct snd_soc_dapm_widget *w,
return 0;
}
-static int rt5650_hp_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 rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component);
-
- switch (event) {
- case SND_SOC_DAPM_POST_PMU:
- if (rt5645->hp_on) {
- msleep(100);
- rt5645->hp_on = false;
- }
- break;
-
- default:
- return 0;
- }
-
- return 0;
-}
-
static int rt5645_set_micbias1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
@@ -2242,7 +2229,6 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("PDM1R"),
SND_SOC_DAPM_OUTPUT("SPOL"),
SND_SOC_DAPM_OUTPUT("SPOR"),
- SND_SOC_DAPM_POST("DAPM_POST", rt5650_hp_event),
};
static const struct snd_soc_dapm_widget rt5645_specific_dapm_widgets[] = {
@@ -3261,6 +3247,8 @@ static void rt5645_jack_detect_work(struct work_struct *work)
case 0: /* Not using rt5645 JD */
if (rt5645->gpiod_hp_det) {
gpio_state = gpiod_get_value(rt5645->gpiod_hp_det);
+ if (rt5645->pdata.inv_hp_pol)
+ gpio_state ^= 1;
dev_dbg(rt5645->component->dev, "gpio_state = %d\n",
gpio_state);
report = rt5645_jack_detect(rt5645->component, gpio_state);
@@ -3651,6 +3639,25 @@ static const struct rt5645_platform_data kahlee_platform_data = {
.jd_mode = 3,
};
+static const struct rt5645_platform_data ecs_ef20_platform_data = {
+ .dmic1_data_pin = RT5645_DMIC1_DISABLE,
+ .dmic2_data_pin = RT5645_DMIC_DATA_IN2P,
+ .inv_hp_pol = 1,
+};
+
+static const struct acpi_gpio_params ef20_hp_detect = { 1, 0, false };
+
+static const struct acpi_gpio_mapping cht_rt5645_ef20_gpios[] = {
+ { "hp-detect-gpios", &ef20_hp_detect, 1 },
+ { },
+};
+
+static int cht_rt5645_ef20_quirk_cb(const struct dmi_system_id *id)
+{
+ cht_rt5645_gpios = cht_rt5645_ef20_gpios;
+ return 1;
+}
+
static const struct dmi_system_id dmi_platform_data[] = {
{
.ident = "Chrome Buddy",
@@ -3780,6 +3787,22 @@ static const struct dmi_system_id dmi_platform_data[] = {
},
.driver_data = (void *)&intel_braswell_platform_data,
},
+ {
+ .ident = "EF20",
+ .callback = cht_rt5645_ef20_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "EF20"),
+ },
+ .driver_data = (void *)&ecs_ef20_platform_data,
+ },
+ {
+ .ident = "EF20EA",
+ .callback = cht_rt5645_ef20_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
+ },
+ .driver_data = (void *)&ecs_ef20_platform_data,
+ },
{ }
};
@@ -3843,11 +3866,16 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
rt5645->pdata.in2_diff = QUIRK_IN2_DIFF(quirk);
rt5645->pdata.level_trigger_irq = QUIRK_LEVEL_IRQ(quirk);
rt5645->pdata.inv_jd1_1 = QUIRK_INV_JD1_1(quirk);
+ rt5645->pdata.inv_hp_pol = QUIRK_INV_HP_POL(quirk);
rt5645->pdata.jd_mode = QUIRK_JD_MODE(quirk);
rt5645->pdata.dmic1_data_pin = QUIRK_DMIC1_DATA_PIN(quirk);
rt5645->pdata.dmic2_data_pin = QUIRK_DMIC2_DATA_PIN(quirk);
}
+ if (cht_rt5645_gpios && has_acpi_companion(&i2c->dev))
+ if (devm_acpi_dev_add_driver_gpios(&i2c->dev, cht_rt5645_gpios))
+ dev_dbg(&i2c->dev, "Failed to add driver gpios\n");
+
rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect",
GPIOD_IN);
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
index a0c8f58d729b..c29317ea5df2 100644
--- a/sound/soc/codecs/rt5670.c
+++ b/sound/soc/codecs/rt5670.c
@@ -2741,7 +2741,7 @@ static struct snd_soc_dai_driver rt5670_dai[] = {
.formats = RT5670_FORMATS,
},
.ops = &rt5670_aif_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "rt5670-aif2",
@@ -2761,7 +2761,7 @@ static struct snd_soc_dai_driver rt5670_dai[] = {
.formats = RT5670_FORMATS,
},
.ops = &rt5670_aif_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c
index 37d13120f5ba..93c1603b42f1 100644
--- a/sound/soc/codecs/rt5682-i2c.c
+++ b/sound/soc/codecs/rt5682-i2c.c
@@ -273,6 +273,9 @@ static void rt5682_i2c_shutdown(struct i2c_client *client)
{
struct rt5682_priv *rt5682 = i2c_get_clientdata(client);
+ cancel_delayed_work_sync(&rt5682->jack_detect_work);
+ cancel_delayed_work_sync(&rt5682->jd_check_work);
+
rt5682_reset(rt5682);
}
diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c
index 4d707e854875..b49f1e16125d 100644
--- a/sound/soc/codecs/rt5682-sdw.c
+++ b/sound/soc/codecs/rt5682-sdw.c
@@ -375,18 +375,12 @@ static int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
static int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
{
struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
- int ret = 0;
+ int ret = 0, loop = 10;
unsigned int val;
if (rt5682->hw_init)
return 0;
- regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
- if (val != DEVICE_ID) {
- dev_err(dev, "Device with ID register %x is not rt5682\n", val);
- return -ENODEV;
- }
-
/*
* PM runtime is only enabled when a Slave reports as Attached
*/
@@ -406,6 +400,19 @@ static int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
pm_runtime_get_noresume(&slave->dev);
+ while (loop > 0) {
+ regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
+ if (val == DEVICE_ID)
+ break;
+ dev_warn(dev, "Device with ID register %x is not rt5682\n", val);
+ usleep_range(30000, 30005);
+ loop--;
+ }
+ if (val != DEVICE_ID) {
+ dev_err(dev, "Device with ID register %x is not rt5682\n", val);
+ return -ENODEV;
+ }
+
if (rt5682->first_hw_init) {
regcache_cache_only(rt5682->regmap, false);
regcache_cache_bypass(rt5682->regmap, true);
@@ -703,7 +710,7 @@ static int rt5682_sdw_remove(struct sdw_slave *slave)
struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev);
if (rt5682 && rt5682->hw_init)
- cancel_delayed_work(&rt5682->jack_detect_work);
+ cancel_delayed_work_sync(&rt5682->jack_detect_work);
return 0;
}
@@ -721,6 +728,8 @@ static int __maybe_unused rt5682_dev_suspend(struct device *dev)
if (!rt5682->hw_init)
return 0;
+ cancel_delayed_work_sync(&rt5682->jack_detect_work);
+
regcache_cache_only(rt5682->regmap, true);
regcache_mark_dirty(rt5682->regmap);
diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c
index 4d865edadd7e..b306ac4b9b2e 100644
--- a/sound/soc/codecs/rt5682.c
+++ b/sound/soc/codecs/rt5682.c
@@ -953,6 +953,8 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
case 0x1:
case 0x2:
rt5682->jack_type = SND_JACK_HEADSET;
+ snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
+ RT5682_FAST_OFF_MASK, RT5682_FAST_OFF_EN);
rt5682_enable_push_button_irq(component, true);
break;
default:
@@ -982,6 +984,8 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
snd_soc_component_update_bits(component, RT5682_MICBIAS_2,
RT5682_PWR_CLK25M_MASK | RT5682_PWR_CLK1M_MASK,
RT5682_PWR_CLK25M_PD | RT5682_PWR_CLK1M_PD);
+ snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
+ RT5682_FAST_OFF_MASK, RT5682_FAST_OFF_DIS);
rt5682->jack_type = 0;
}
@@ -1012,10 +1016,12 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component,
switch (rt5682->pdata.jd_src) {
case RT5682_JD1:
snd_soc_component_update_bits(component,
+ RT5682_CBJ_CTRL_5, 0x0700, 0x0600);
+ snd_soc_component_update_bits(component,
RT5682_CBJ_CTRL_2, RT5682_EXT_JD_SRC,
RT5682_EXT_JD_SRC_MANUAL);
snd_soc_component_write(component, RT5682_CBJ_CTRL_1,
- 0xd042);
+ 0xd142);
snd_soc_component_update_bits(component,
RT5682_CBJ_CTRL_3, RT5682_CBJ_IN_BUF_EN,
RT5682_CBJ_IN_BUF_EN);
@@ -1848,8 +1854,6 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
{"CLKDET SYS", NULL, "CLKDET"},
- {"IN1P", NULL, "LDO2"},
-
{"BST1 CBJ", NULL, "IN1P"},
{"RECMIX1L", "CBJ Switch", "BST1 CBJ"},
@@ -2906,6 +2910,9 @@ static int rt5682_suspend(struct snd_soc_component *component)
{
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ if (rt5682->is_sdw)
+ return 0;
+
regcache_cache_only(rt5682->regmap, true);
regcache_mark_dirty(rt5682->regmap);
return 0;
@@ -2915,6 +2922,9 @@ static int rt5682_resume(struct snd_soc_component *component)
{
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ if (rt5682->is_sdw)
+ return 0;
+
regcache_cache_only(rt5682->regmap, false);
regcache_sync(rt5682->regmap);
diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h
index 99b85cfe6248..1f9c51a5b9bf 100644
--- a/sound/soc/codecs/rt5682.h
+++ b/sound/soc/codecs/rt5682.h
@@ -1356,7 +1356,7 @@
#define RT5682_SAR_SOUR_TYPE (0x0)
/* soundwire timeout */
-#define RT5682_PROBE_TIMEOUT 2000
+#define RT5682_PROBE_TIMEOUT 5000
#define RT5682_STEREO_RATES SNDRV_PCM_RATE_8000_192000
diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c
index fb77e77a4ebd..4001612dfd73 100644
--- a/sound/soc/codecs/rt700-sdw.c
+++ b/sound/soc/codecs/rt700-sdw.c
@@ -462,8 +462,8 @@ static int rt700_sdw_remove(struct sdw_slave *slave)
struct rt700_priv *rt700 = dev_get_drvdata(&slave->dev);
if (rt700 && rt700->hw_init) {
- cancel_delayed_work(&rt700->jack_detect_work);
- cancel_delayed_work(&rt700->jack_btn_check_work);
+ cancel_delayed_work_sync(&rt700->jack_detect_work);
+ cancel_delayed_work_sync(&rt700->jack_btn_check_work);
}
return 0;
@@ -490,7 +490,7 @@ static int __maybe_unused rt700_dev_suspend(struct device *dev)
return 0;
}
-#define RT700_PROBE_TIMEOUT 2000
+#define RT700_PROBE_TIMEOUT 5000
static int __maybe_unused rt700_dev_resume(struct device *dev)
{
diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c
index fc7df79c3b91..2beb4286d997 100644
--- a/sound/soc/codecs/rt711-sdw.c
+++ b/sound/soc/codecs/rt711-sdw.c
@@ -463,8 +463,8 @@ static int rt711_sdw_remove(struct sdw_slave *slave)
struct rt711_priv *rt711 = dev_get_drvdata(&slave->dev);
if (rt711 && rt711->hw_init) {
- cancel_delayed_work(&rt711->jack_detect_work);
- cancel_delayed_work(&rt711->jack_btn_check_work);
+ cancel_delayed_work_sync(&rt711->jack_detect_work);
+ cancel_delayed_work_sync(&rt711->jack_btn_check_work);
cancel_work_sync(&rt711->calibration_work);
}
@@ -493,7 +493,7 @@ static int __maybe_unused rt711_dev_suspend(struct device *dev)
return 0;
}
-#define RT711_PROBE_TIMEOUT 2000
+#define RT711_PROBE_TIMEOUT 5000
static int __maybe_unused rt711_dev_resume(struct device *dev)
{
diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c
index 8f0aa1e8a273..71dd3b97a459 100644
--- a/sound/soc/codecs/rt715-sdw.c
+++ b/sound/soc/codecs/rt715-sdw.c
@@ -533,7 +533,7 @@ static int __maybe_unused rt715_dev_suspend(struct device *dev)
return 0;
}
-#define RT715_PROBE_TIMEOUT 2000
+#define RT715_PROBE_TIMEOUT 5000
static int __maybe_unused rt715_dev_resume(struct device *dev)
{
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 4d6ff8114622..73551e36695e 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -1187,7 +1187,7 @@ static struct snd_soc_dai_driver sgtl5000_dai = {
.formats = SGTL5000_FORMATS,
},
.ops = &sgtl5000_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static bool sgtl5000_volatile(struct device *dev, unsigned int reg)
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c
deleted file mode 100644
index a061d78473ac..000000000000
--- a/sound/soc/codecs/sirf-audio-codec.c
+++ /dev/null
@@ -1,575 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SiRF audio codec driver
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/regmap.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/tlv.h>
-#include <sound/soc.h>
-#include <sound/dmaengine_pcm.h>
-
-#include "sirf-audio-codec.h"
-
-struct sirf_audio_codec {
- struct clk *clk;
- struct regmap *regmap;
- u32 reg_ctrl0, reg_ctrl1;
-};
-
-static const char * const input_mode_mux[] = {"Single-ended",
- "Differential"};
-
-static const struct soc_enum input_mode_mux_enum =
- SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux);
-
-static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control =
- SOC_DAPM_ENUM("Route", input_mode_mux_enum);
-
-static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0);
-static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0);
-static const DECLARE_TLV_DB_RANGE(capture_vol_tlv_atlas6,
- 0, 7, TLV_DB_SCALE_ITEM(-100, 100, 0),
- 0x22, 0x3F, TLV_DB_SCALE_ITEM(700, 100, 0),
-);
-
-static struct snd_kcontrol_new volume_controls_atlas6[] = {
- SOC_DOUBLE_TLV("Playback Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
- 0x7F, 0, playback_vol_tlv),
- SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 16, 10,
- 0x3F, 0, capture_vol_tlv_atlas6),
-};
-
-static struct snd_kcontrol_new volume_controls_prima2[] = {
- SOC_DOUBLE_TLV("Speaker Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
- 0x7F, 0, playback_vol_tlv),
- SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 15, 10,
- 0x1F, 0, capture_vol_tlv_prima2),
-};
-
-static struct snd_kcontrol_new left_input_path_controls[] = {
- SOC_DAPM_SINGLE("Line Left Switch", AUDIO_IC_CODEC_CTRL1, 6, 1, 0),
- SOC_DAPM_SINGLE("Mic Left Switch", AUDIO_IC_CODEC_CTRL1, 3, 1, 0),
-};
-
-static struct snd_kcontrol_new right_input_path_controls[] = {
- SOC_DAPM_SINGLE("Line Right Switch", AUDIO_IC_CODEC_CTRL1, 5, 1, 0),
- SOC_DAPM_SINGLE("Mic Right Switch", AUDIO_IC_CODEC_CTRL1, 2, 1, 0),
-};
-
-static struct snd_kcontrol_new left_dac_to_hp_left_amp_switch_control =
- SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 9, 1, 0);
-
-static struct snd_kcontrol_new left_dac_to_hp_right_amp_switch_control =
- SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 8, 1, 0);
-
-static struct snd_kcontrol_new right_dac_to_hp_left_amp_switch_control =
- SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 7, 1, 0);
-
-static struct snd_kcontrol_new right_dac_to_hp_right_amp_switch_control =
- SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 6, 1, 0);
-
-static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control =
- SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0);
-
-static struct snd_kcontrol_new right_dac_to_speaker_lineout_switch_control =
- SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 10, 1, 0);
-
-/* After enable adc, Delay 200ms to avoid pop noise */
-static int adc_enable_delay_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- switch (event) {
- case SND_SOC_DAPM_POST_PMU:
- msleep(200);
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static void enable_and_reset_codec(struct regmap *regmap,
- u32 codec_enable_bits, u32 codec_reset_bits)
-{
- regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
- codec_enable_bits | codec_reset_bits,
- codec_enable_bits);
- msleep(20);
- regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
- codec_reset_bits, codec_reset_bits);
-}
-
-static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
-#define ATLAS6_CODEC_ENABLE_BITS (1 << 29)
-#define ATLAS6_CODEC_RESET_BITS (1 << 28)
- struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
- struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- enable_and_reset_codec(sirf_audio_codec->regmap,
- ATLAS6_CODEC_ENABLE_BITS, ATLAS6_CODEC_RESET_BITS);
- break;
- case SND_SOC_DAPM_POST_PMD:
- regmap_update_bits(sirf_audio_codec->regmap,
- AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, 0);
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
-#define PRIMA2_CODEC_ENABLE_BITS (1 << 27)
-#define PRIMA2_CODEC_RESET_BITS (1 << 26)
- struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
- struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
- switch (event) {
- case SND_SOC_DAPM_POST_PMU:
- enable_and_reset_codec(sirf_audio_codec->regmap,
- PRIMA2_CODEC_ENABLE_BITS, PRIMA2_CODEC_RESET_BITS);
- break;
- case SND_SOC_DAPM_POST_PMD:
- regmap_update_bits(sirf_audio_codec->regmap,
- AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, 0);
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static const struct snd_soc_dapm_widget atlas6_output_driver_dapm_widgets[] = {
- SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
- 25, 0, NULL, 0),
- SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
- 26, 0, NULL, 0),
- SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
- 27, 0, NULL, 0),
-};
-
-static const struct snd_soc_dapm_widget prima2_output_driver_dapm_widgets[] = {
- SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
- 23, 0, NULL, 0),
- SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
- 24, 0, NULL, 0),
- SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
- 25, 0, NULL, 0),
-};
-
-static const struct snd_soc_dapm_widget atlas6_codec_clock_dapm_widget =
- SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
- atlas6_codec_enable_and_reset_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
-
-static const struct snd_soc_dapm_widget prima2_codec_clock_dapm_widget =
- SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
- prima2_codec_enable_and_reset_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
-
-static const struct snd_soc_dapm_widget sirf_audio_codec_dapm_widgets[] = {
- SND_SOC_DAPM_DAC("DAC left", NULL, AUDIO_IC_CODEC_CTRL0, 1, 0),
- SND_SOC_DAPM_DAC("DAC right", NULL, AUDIO_IC_CODEC_CTRL0, 0, 0),
- SND_SOC_DAPM_SWITCH("Left dac to hp left amp", SND_SOC_NOPM, 0, 0,
- &left_dac_to_hp_left_amp_switch_control),
- SND_SOC_DAPM_SWITCH("Left dac to hp right amp", SND_SOC_NOPM, 0, 0,
- &left_dac_to_hp_right_amp_switch_control),
- SND_SOC_DAPM_SWITCH("Right dac to hp left amp", SND_SOC_NOPM, 0, 0,
- &right_dac_to_hp_left_amp_switch_control),
- SND_SOC_DAPM_SWITCH("Right dac to hp right amp", SND_SOC_NOPM, 0, 0,
- &right_dac_to_hp_right_amp_switch_control),
- SND_SOC_DAPM_OUT_DRV("HP amp left driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
- NULL, 0),
- SND_SOC_DAPM_OUT_DRV("HP amp right driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
- NULL, 0),
-
- SND_SOC_DAPM_SWITCH("Left dac to speaker lineout", SND_SOC_NOPM, 0, 0,
- &left_dac_to_speaker_lineout_switch_control),
- SND_SOC_DAPM_SWITCH("Right dac to speaker lineout", SND_SOC_NOPM, 0, 0,
- &right_dac_to_speaker_lineout_switch_control),
- SND_SOC_DAPM_OUT_DRV("Speaker amp driver", AUDIO_IC_CODEC_CTRL0, 4, 0,
- NULL, 0),
-
- SND_SOC_DAPM_OUTPUT("HPOUTL"),
- SND_SOC_DAPM_OUTPUT("HPOUTR"),
- SND_SOC_DAPM_OUTPUT("SPKOUT"),
-
- SND_SOC_DAPM_ADC_E("ADC left", NULL, AUDIO_IC_CODEC_CTRL1, 8, 0,
- adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_ADC_E("ADC right", NULL, AUDIO_IC_CODEC_CTRL1, 7, 0,
- adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_MIXER("Left PGA mixer", AUDIO_IC_CODEC_CTRL1, 1, 0,
- &left_input_path_controls[0],
- ARRAY_SIZE(left_input_path_controls)),
- SND_SOC_DAPM_MIXER("Right PGA mixer", AUDIO_IC_CODEC_CTRL1, 0, 0,
- &right_input_path_controls[0],
- ARRAY_SIZE(right_input_path_controls)),
-
- SND_SOC_DAPM_MUX("Mic input mode mux", SND_SOC_NOPM, 0, 0,
- &sirf_audio_codec_input_mode_control),
- SND_SOC_DAPM_MICBIAS("Mic Bias", AUDIO_IC_CODEC_PWR, 3, 0),
- SND_SOC_DAPM_INPUT("MICIN1"),
- SND_SOC_DAPM_INPUT("MICIN2"),
- SND_SOC_DAPM_INPUT("LINEIN1"),
- SND_SOC_DAPM_INPUT("LINEIN2"),
-
- SND_SOC_DAPM_SUPPLY("HSL Phase Opposite", AUDIO_IC_CODEC_CTRL0,
- 30, 0, NULL, 0),
-};
-
-static const struct snd_soc_dapm_route sirf_audio_codec_map[] = {
- {"SPKOUT", NULL, "Speaker Driver"},
- {"Speaker Driver", NULL, "Speaker amp driver"},
- {"Speaker amp driver", NULL, "Left dac to speaker lineout"},
- {"Speaker amp driver", NULL, "Right dac to speaker lineout"},
- {"Left dac to speaker lineout", "Switch", "DAC left"},
- {"Right dac to speaker lineout", "Switch", "DAC right"},
- {"HPOUTL", NULL, "HP Left Driver"},
- {"HPOUTR", NULL, "HP Right Driver"},
- {"HP Left Driver", NULL, "HP amp left driver"},
- {"HP Right Driver", NULL, "HP amp right driver"},
- {"HP amp left driver", NULL, "Right dac to hp left amp"},
- {"HP amp right driver", NULL , "Right dac to hp right amp"},
- {"HP amp left driver", NULL, "Left dac to hp left amp"},
- {"HP amp right driver", NULL , "Right dac to hp right amp"},
- {"Right dac to hp left amp", "Switch", "DAC left"},
- {"Right dac to hp right amp", "Switch", "DAC right"},
- {"Left dac to hp left amp", "Switch", "DAC left"},
- {"Left dac to hp right amp", "Switch", "DAC right"},
- {"DAC left", NULL, "codecclk"},
- {"DAC right", NULL, "codecclk"},
- {"DAC left", NULL, "Playback"},
- {"DAC right", NULL, "Playback"},
- {"DAC left", NULL, "HSL Phase Opposite"},
- {"DAC right", NULL, "HSL Phase Opposite"},
-
- {"Capture", NULL, "ADC left"},
- {"Capture", NULL, "ADC right"},
- {"ADC left", NULL, "codecclk"},
- {"ADC right", NULL, "codecclk"},
- {"ADC left", NULL, "Left PGA mixer"},
- {"ADC right", NULL, "Right PGA mixer"},
- {"Left PGA mixer", "Line Left Switch", "LINEIN2"},
- {"Right PGA mixer", "Line Right Switch", "LINEIN1"},
- {"Left PGA mixer", "Mic Left Switch", "MICIN2"},
- {"Right PGA mixer", "Mic Right Switch", "Mic input mode mux"},
- {"Mic input mode mux", "Single-ended", "MICIN1"},
- {"Mic input mode mux", "Differential", "MICIN1"},
-};
-
-static void sirf_audio_codec_tx_enable(struct sirf_audio_codec *sirf_audio_codec)
-{
- regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
- AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
- regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
- AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
- regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0);
- regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
- regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
- AUDIO_FIFO_START, AUDIO_FIFO_START);
- regmap_update_bits(sirf_audio_codec->regmap,
- AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, IC_TX_ENABLE);
-}
-
-static void sirf_audio_codec_tx_disable(struct sirf_audio_codec *sirf_audio_codec)
-{
- regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
- regmap_update_bits(sirf_audio_codec->regmap,
- AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, ~IC_TX_ENABLE);
-}
-
-static void sirf_audio_codec_rx_enable(struct sirf_audio_codec *sirf_audio_codec,
- int channels)
-{
- regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
- AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
- regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
- AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
- regmap_write(sirf_audio_codec->regmap,
- AUDIO_PORT_IC_RXFIFO_INT_MSK, 0);
- regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0);
- regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
- AUDIO_FIFO_START, AUDIO_FIFO_START);
- if (channels == 1)
- regmap_update_bits(sirf_audio_codec->regmap,
- AUDIO_PORT_IC_CODEC_RX_CTRL,
- IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO);
- else
- regmap_update_bits(sirf_audio_codec->regmap,
- AUDIO_PORT_IC_CODEC_RX_CTRL,
- IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO);
-}
-
-static void sirf_audio_codec_rx_disable(struct sirf_audio_codec *sirf_audio_codec)
-{
- regmap_update_bits(sirf_audio_codec->regmap,
- AUDIO_PORT_IC_CODEC_RX_CTRL,
- IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO);
-}
-
-static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream,
- int cmd,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_component *component = dai->component;
- struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
- int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-
- /*
- * This is a workaround, When stop playback,
- * need disable HP amp, avoid the current noise.
- */
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- if (playback) {
- snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0,
- IC_HSLEN | IC_HSREN, 0);
- sirf_audio_codec_tx_disable(sirf_audio_codec);
- } else
- sirf_audio_codec_rx_disable(sirf_audio_codec);
- break;
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- if (playback) {
- sirf_audio_codec_tx_enable(sirf_audio_codec);
- snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0,
- IC_HSLEN | IC_HSREN, IC_HSLEN | IC_HSREN);
- } else
- sirf_audio_codec_rx_enable(sirf_audio_codec,
- substream->runtime->channels);
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static const struct snd_soc_dai_ops sirf_audio_codec_dai_ops = {
- .trigger = sirf_audio_codec_trigger,
-};
-
-static struct snd_soc_dai_driver sirf_audio_codec_dai = {
- .name = "sirf-audio-codec",
- .playback = {
- .stream_name = "Playback",
- .channels_min = 2,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- .capture = {
- .stream_name = "Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- .ops = &sirf_audio_codec_dai_ops,
-};
-
-static int sirf_audio_codec_probe(struct snd_soc_component *component)
-{
- struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
-
- pm_runtime_enable(component->dev);
-
- if (of_device_is_compatible(component->dev->of_node, "sirf,prima2-audio-codec")) {
- snd_soc_dapm_new_controls(dapm,
- prima2_output_driver_dapm_widgets,
- ARRAY_SIZE(prima2_output_driver_dapm_widgets));
- snd_soc_dapm_new_controls(dapm,
- &prima2_codec_clock_dapm_widget, 1);
- return snd_soc_add_component_controls(component,
- volume_controls_prima2,
- ARRAY_SIZE(volume_controls_prima2));
- }
- if (of_device_is_compatible(component->dev->of_node, "sirf,atlas6-audio-codec")) {
- snd_soc_dapm_new_controls(dapm,
- atlas6_output_driver_dapm_widgets,
- ARRAY_SIZE(atlas6_output_driver_dapm_widgets));
- snd_soc_dapm_new_controls(dapm,
- &atlas6_codec_clock_dapm_widget, 1);
- return snd_soc_add_component_controls(component,
- volume_controls_atlas6,
- ARRAY_SIZE(volume_controls_atlas6));
- }
-
- return -EINVAL;
-}
-
-static void sirf_audio_codec_remove(struct snd_soc_component *component)
-{
- pm_runtime_disable(component->dev);
-}
-
-static const struct snd_soc_component_driver soc_codec_device_sirf_audio_codec = {
- .probe = sirf_audio_codec_probe,
- .remove = sirf_audio_codec_remove,
- .dapm_widgets = sirf_audio_codec_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(sirf_audio_codec_dapm_widgets),
- .dapm_routes = sirf_audio_codec_map,
- .num_dapm_routes = ARRAY_SIZE(sirf_audio_codec_map),
- .use_pmdown_time = 1,
- .endianness = 1,
- .non_legacy_dai_naming = 1,
-};
-
-static const struct of_device_id sirf_audio_codec_of_match[] = {
- { .compatible = "sirf,prima2-audio-codec" },
- { .compatible = "sirf,atlas6-audio-codec" },
- {}
-};
-MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match);
-
-static const struct regmap_config sirf_audio_codec_regmap_config = {
- .reg_bits = 32,
- .reg_stride = 4,
- .val_bits = 32,
- .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK,
- .cache_type = REGCACHE_NONE,
-};
-
-static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
-{
- int ret;
- struct sirf_audio_codec *sirf_audio_codec;
- void __iomem *base;
-
- sirf_audio_codec = devm_kzalloc(&pdev->dev,
- sizeof(struct sirf_audio_codec), GFP_KERNEL);
- if (!sirf_audio_codec)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, sirf_audio_codec);
-
- base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(base))
- return PTR_ERR(base);
-
- sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
- &sirf_audio_codec_regmap_config);
- if (IS_ERR(sirf_audio_codec->regmap))
- return PTR_ERR(sirf_audio_codec->regmap);
-
- sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(sirf_audio_codec->clk)) {
- dev_err(&pdev->dev, "Get clock failed.\n");
- return PTR_ERR(sirf_audio_codec->clk);
- }
-
- ret = clk_prepare_enable(sirf_audio_codec->clk);
- if (ret) {
- dev_err(&pdev->dev, "Enable clock failed.\n");
- return ret;
- }
-
- ret = devm_snd_soc_register_component(&(pdev->dev),
- &soc_codec_device_sirf_audio_codec,
- &sirf_audio_codec_dai, 1);
- if (ret) {
- dev_err(&pdev->dev, "Register Audio Codec dai failed.\n");
- goto err_clk_put;
- }
-
- /*
- * Always open charge pump, if not, when the charge pump closed the
- * adc will not stable
- */
- regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
- IC_CPFREQ, IC_CPFREQ);
-
- if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec"))
- regmap_update_bits(sirf_audio_codec->regmap,
- AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN);
- return 0;
-
-err_clk_put:
- clk_disable_unprepare(sirf_audio_codec->clk);
- return ret;
-}
-
-static int sirf_audio_codec_driver_remove(struct platform_device *pdev)
-{
- struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(sirf_audio_codec->clk);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int sirf_audio_codec_suspend(struct device *dev)
-{
- struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
-
- regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
- &sirf_audio_codec->reg_ctrl0);
- regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
- &sirf_audio_codec->reg_ctrl1);
- clk_disable_unprepare(sirf_audio_codec->clk);
-
- return 0;
-}
-
-static int sirf_audio_codec_resume(struct device *dev)
-{
- struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
- int ret;
-
- ret = clk_prepare_enable(sirf_audio_codec->clk);
- if (ret)
- return ret;
-
- regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
- sirf_audio_codec->reg_ctrl0);
- regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
- sirf_audio_codec->reg_ctrl1);
-
- return 0;
-}
-#endif
-
-static const struct dev_pm_ops sirf_audio_codec_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume)
-};
-
-static struct platform_driver sirf_audio_codec_driver = {
- .driver = {
- .name = "sirf-audio-codec",
- .of_match_table = sirf_audio_codec_of_match,
- .pm = &sirf_audio_codec_pm_ops,
- },
- .probe = sirf_audio_codec_driver_probe,
- .remove = sirf_audio_codec_driver_remove,
-};
-
-module_platform_driver(sirf_audio_codec_driver);
-
-MODULE_DESCRIPTION("SiRF audio codec driver");
-MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 905160246614..7964e922b07f 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -526,8 +526,8 @@ static struct snd_soc_dai_driver ssm2602_dai = {
.rates = SSM2602_RATES,
.formats = SSM2602_FORMATS,},
.ops = &ssm2602_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
};
static int ssm2602_resume(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index 14a193e48dc7..8ff4d9e8d568 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -490,7 +490,7 @@ static struct snd_soc_dai_driver tas2764_dai_driver[] = {
.formats = TAS2764_FORMATS,
},
.ops = &tas2764_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
index a91a0a31e74d..15fca5109e14 100644
--- a/sound/soc/codecs/tas2770.c
+++ b/sound/soc/codecs/tas2770.c
@@ -499,7 +499,7 @@ static struct snd_soc_dai_driver tas2770_dai_driver[] = {
.formats = TAS2770_FORMATS,
},
.ops = &tas2770_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c
index 3f027c8234a6..32b120d624b2 100644
--- a/sound/soc/codecs/tlv320adcx140.c
+++ b/sound/soc/codecs/tlv320adcx140.c
@@ -1069,7 +1069,7 @@ static struct snd_soc_dai_driver adcx140_dai_driver[] = {
.formats = ADCX140_FORMATS,
},
.ops = &adcx140_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
}
};
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 5ac7ce264431..51870d50f419 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -1395,7 +1395,7 @@ static struct snd_soc_dai_driver dac31xx_dai_driver[] = {
.formats = AIC31XX_FORMATS,
},
.ops = &aic31xx_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
}
};
@@ -1417,7 +1417,7 @@ static struct snd_soc_dai_driver aic31xx_dai_driver[] = {
.formats = AIC31XX_FORMATS,
},
.ops = &aic31xx_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
}
};
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 9e3de9ded0ef..f04f88c8d425 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -916,7 +916,7 @@ static struct snd_soc_dai_driver aic32x4_dai = {
.rates = AIC32X4_RATES,
.formats = AIC32X4_FORMATS,},
.ops = &aic32x4_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static void aic32x4_setup_gpios(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 6d066bc58ac8..db1444127444 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1503,7 +1503,7 @@ static struct snd_soc_dai_driver aic3x_dai = {
.rates = AIC3X_RATES,
.formats = AIC3X_FORMATS,},
.ops = &aic3x_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static void aic3x_mono_init(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/tscs42xx.c b/sound/soc/codecs/tscs42xx.c
index 6200fab7896f..fb861baf50e8 100644
--- a/sound/soc/codecs/tscs42xx.c
+++ b/sound/soc/codecs/tscs42xx.c
@@ -1397,9 +1397,9 @@ static struct snd_soc_dai_driver tscs42xx_dai = {
.rates = TSCS42XX_RATES,
.formats = TSCS42XX_FORMATS,},
.ops = &tscs42xx_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
.symmetric_channels = 1,
- .symmetric_samplebits = 1,
+ .symmetric_sample_bits = 1,
};
static const struct reg_sequence tscs42xx_patch[] = {
diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c
index cd1f1a592386..1bafc9d1101c 100644
--- a/sound/soc/codecs/tscs454.c
+++ b/sound/soc/codecs/tscs454.c
@@ -3346,9 +3346,9 @@ static struct snd_soc_dai_driver tscs454_dais[] = {
.rates = TSCS454_RATES,
.formats = TSCS454_FORMATS,},
.ops = &tscs454_dai1_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
.symmetric_channels = 1,
- .symmetric_samplebits = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "tscs454-dai2",
@@ -3366,9 +3366,9 @@ static struct snd_soc_dai_driver tscs454_dais[] = {
.rates = TSCS454_RATES,
.formats = TSCS454_FORMATS,},
.ops = &tscs454_dai23_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
.symmetric_channels = 1,
- .symmetric_samplebits = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "tscs454-dai3",
@@ -3386,9 +3386,9 @@ static struct snd_soc_dai_driver tscs454_dais[] = {
.rates = TSCS454_RATES,
.formats = TSCS454_FORMATS,},
.ops = &tscs454_dai23_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
.symmetric_channels = 1,
- .symmetric_samplebits = 1,
+ .symmetric_sample_bits = 1,
},
};
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 70d353b63fe0..fe33f2d88f55 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -1780,8 +1780,8 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
.formats = WM5102_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "wm5102-aif2",
@@ -1802,8 +1802,8 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
.formats = WM5102_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "wm5102-aif3",
@@ -1824,8 +1824,8 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
.formats = WM5102_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "wm5102-slim1",
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 4238929b2375..52c0a575cc4f 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -2089,8 +2089,8 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
.formats = WM5110_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "wm5110-aif2",
@@ -2111,8 +2111,8 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
.formats = WM5110_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "wm5110-aif3",
@@ -2133,8 +2133,8 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
.formats = WM5110_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "wm5110-slim1",
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 73c4a8b9f59e..a18e2290b8c8 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -569,7 +569,7 @@ static struct snd_soc_dai_driver wm8510_dai = {
.rates = WM8510_RATES,
.formats = WM8510_FORMATS,},
.ops = &wm8510_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int wm8510_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 304bf725a613..dcee7b2bd3d7 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -567,7 +567,7 @@ static struct snd_soc_dai_driver wm8731_dai = {
.rates = WM8731_RATES,
.formats = WM8731_FORMATS,},
.ops = &wm8731_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int wm8731_request_supplies(struct device *dev,
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index 1176a6ad269d..5f394065030d 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -562,7 +562,7 @@ static struct snd_soc_dai_driver wm8770_dai = {
.formats = WM8770_FORMATS
},
.ops = &wm8770_dai_ops,
- .symmetric_rates = 1
+ .symmetric_rate = 1
};
static int wm8770_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index 4ddb5e32df5d..21bf0cfa1e7e 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -536,7 +536,7 @@ static struct snd_soc_dai_driver wm8804_dai = {
.formats = WM8804_FORMATS,
},
.ops = &wm8804_dai_ops,
- .symmetric_rates = 1
+ .symmetric_rate = 1
};
static const struct snd_soc_component_driver soc_component_dev_wm8804 = {
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 09f4980630c7..026603ae44ce 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -1760,7 +1760,7 @@ static struct snd_soc_dai_driver wm8903_dai = {
.formats = WM8903_FORMATS,
},
.ops = &wm8903_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int wm8903_resume(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 1c360bae5652..a02a77fef360 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -1983,7 +1983,7 @@ static struct snd_soc_dai_driver wm8904_dai = {
.formats = WM8904_FORMATS,
},
.ops = &wm8904_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static void wm8904_handle_retune_mobile_pdata(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 016cd8aeef37..440d048ef0c0 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -688,7 +688,7 @@ static struct snd_soc_dai_driver wm8940_dai = {
.formats = WM8940_FORMATS,
},
.ops = &wm8940_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int wm8940_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 660ec46eecf2..df351519a3a6 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -1338,7 +1338,7 @@ static struct snd_soc_dai_driver wm8960_dai = {
.rates = WM8960_RATES,
.formats = WM8960_FORMATS,},
.ops = &wm8960_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int wm8960_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 3af456010b9c..ce4666a74793 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2973,7 +2973,7 @@ static struct snd_soc_dai_driver wm8962_dai = {
.formats = WM8962_FORMATS,
},
.ops = &wm8962_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static void wm8962_mic_work(struct work_struct *work)
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index c86231dfcf4f..fdc68ab49742 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -643,7 +643,7 @@ static struct snd_soc_dai_driver wm8974_dai = {
.rates = WM8974_RATES,
.formats = WM8974_FORMATS,},
.ops = &wm8974_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static const struct regmap_config wm8974_regmap = {
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index a7acb8981715..4b5ecd142249 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -918,7 +918,7 @@ static struct snd_soc_dai_driver wm8978_dai = {
.formats = WM8978_FORMATS,
},
.ops = &wm8978_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int wm8978_suspend(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index d1d2d408ad95..d8ed22a9caac 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -971,7 +971,7 @@ static struct snd_soc_dai_driver wm8983_dai = {
.formats = WM8983_FORMATS,
},
.ops = &wm8983_dai_ops,
- .symmetric_rates = 1
+ .symmetric_rate = 1
};
static const struct snd_soc_component_driver soc_component_dev_wm8983 = {
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index 3f27482349b2..a7e01106fbc0 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -1100,7 +1100,7 @@ static struct snd_soc_dai_driver wm8985_dai = {
.formats = WM8985_FORMATS,
},
.ops = &wm8985_dai_ops,
- .symmetric_rates = 1
+ .symmetric_rate = 1
};
static const struct snd_soc_component_driver soc_component_dev_wm8985 = {
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index d2c2d0d943f0..1d2f881bbcae 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -787,7 +787,7 @@ static struct snd_soc_dai_driver wm8988_dai = {
.formats = WM8988_FORMATS,
},
.ops = &wm8988_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int wm8988_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 9f310082e3c1..c4f41692b806 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -1476,7 +1476,7 @@ static struct snd_soc_dai_driver wm8993_dai = {
.sig_bits = 24,
},
.ops = &wm8993_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static int wm8993_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index f57884113406..f117ec0c489f 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -4351,7 +4351,7 @@ static int wm8994_component_probe(struct snd_soc_component *component)
}
if ((reg & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
wm8994->lrclk_shared[0] = 1;
- wm8994_dai[0].symmetric_rates = 1;
+ wm8994_dai[0].symmetric_rate = 1;
} else {
wm8994->lrclk_shared[0] = 0;
}
@@ -4363,7 +4363,7 @@ static int wm8994_component_probe(struct snd_soc_component *component)
}
if ((reg & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
wm8994->lrclk_shared[1] = 1;
- wm8994_dai[1].symmetric_rates = 1;
+ wm8994_dai[1].symmetric_rate = 1;
} else {
wm8994->lrclk_shared[1] = 0;
}
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c
index 229f2986cd96..99c3ebae6ba6 100644
--- a/sound/soc/codecs/wm8997.c
+++ b/sound/soc/codecs/wm8997.c
@@ -969,8 +969,8 @@ static struct snd_soc_dai_driver wm8997_dai[] = {
.formats = WM8997_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "wm8997-aif2",
@@ -991,8 +991,8 @@ static struct snd_soc_dai_driver wm8997_dai[] = {
.formats = WM8997_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "wm8997-slim1",
diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c
index 5413254295b7..b6f717aa5478 100644
--- a/sound/soc/codecs/wm8998.c
+++ b/sound/soc/codecs/wm8998.c
@@ -1161,8 +1161,8 @@ static struct snd_soc_dai_driver wm8998_dai[] = {
.formats = WM8998_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "wm8998-aif2",
@@ -1183,8 +1183,8 @@ static struct snd_soc_dai_driver wm8998_dai[] = {
.formats = WM8998_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "wm8998-aif3",
@@ -1205,8 +1205,8 @@ static struct snd_soc_dai_driver wm8998_dai[] = {
.formats = WM8998_FORMATS,
},
.ops = &arizona_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "wm8998-slim1",
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index f333e2ff4a16..e0ce32dd4a81 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1134,7 +1134,7 @@ static struct snd_soc_dai_driver wm9713_dai[] = {
.rates = WM9713_PCM_RATES,
.formats = WM9713_PCM_FORMATS,},
.ops = &wm9713_dai_ops_voice,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 985b2dcecf13..070ca7d8c661 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -595,13 +595,6 @@ static const struct {
[WM_ADSP_FW_MISC] = { .file = "misc" },
};
-struct wm_coeff_ctl_ops {
- int (*xget)(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
- int (*xput)(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-};
-
struct wm_coeff_ctl {
const char *name;
const char *fw_name;
@@ -609,7 +602,6 @@ struct wm_coeff_ctl {
const char *subname;
unsigned int subname_len;
struct wm_adsp_alg_region alg_region;
- struct wm_coeff_ctl_ops ops;
struct wm_adsp *dsp;
unsigned int enabled:1;
struct list_head list;
@@ -619,7 +611,7 @@ struct wm_coeff_ctl {
unsigned int set:1;
struct soc_bytes_ext bytes_ext;
unsigned int flags;
- unsigned int type;
+ snd_ctl_elem_type_t type;
};
static const char *wm_adsp_mem_region_name(unsigned int type)
@@ -980,7 +972,7 @@ static int wm_coeff_write_acked_control(struct wm_coeff_ctl *ctl,
unsigned int event_id)
{
struct wm_adsp *dsp = ctl->dsp;
- u32 val = cpu_to_be32(event_id);
+ __be32 val = cpu_to_be32(event_id);
unsigned int reg;
int i, ret;
@@ -1420,7 +1412,7 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
const struct wm_adsp_alg_region *alg_region,
unsigned int offset, unsigned int len,
const char *subname, unsigned int subname_len,
- unsigned int flags, unsigned int type)
+ unsigned int flags, snd_ctl_elem_type_t type)
{
struct wm_coeff_ctl *ctl;
struct wmfw_ctl_work *ctl_work;
@@ -1497,8 +1489,6 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
}
ctl->enabled = 1;
ctl->set = 0;
- ctl->ops.xget = wm_coeff_get;
- ctl->ops.xput = wm_coeff_put;
ctl->dsp = dsp;
ctl->flags = flags;
@@ -1554,7 +1544,7 @@ struct wm_coeff_parsed_coeff {
int mem_type;
const u8 *name;
int name_len;
- int ctl_type;
+ snd_ctl_elem_type_t ctl_type;
int flags;
int len;
};
@@ -1649,7 +1639,7 @@ static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data,
blk->mem_type = le16_to_cpu(raw->hdr.type);
blk->name = raw->name;
blk->name_len = strlen(raw->name);
- blk->ctl_type = le16_to_cpu(raw->ctl_type);
+ blk->ctl_type = (__force snd_ctl_elem_type_t)le16_to_cpu(raw->ctl_type);
blk->flags = le16_to_cpu(raw->flags);
blk->len = le32_to_cpu(raw->len);
break;
@@ -1662,7 +1652,9 @@ static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data,
&blk->name);
wm_coeff_parse_string(sizeof(u8), &tmp, NULL);
wm_coeff_parse_string(sizeof(u16), &tmp, NULL);
- blk->ctl_type = wm_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
+ blk->ctl_type =
+ (__force snd_ctl_elem_type_t)wm_coeff_parse_int(sizeof(raw->ctl_type),
+ &tmp);
blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp);
blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp);
@@ -3667,12 +3659,12 @@ int wm_adsp_compr_get_caps(struct snd_soc_component *component,
}
EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps);
-static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type,
- unsigned int mem_addr,
- unsigned int num_words, u32 *data)
+static int wm_adsp_read_raw_data_block(struct wm_adsp *dsp, int mem_type,
+ unsigned int mem_addr,
+ unsigned int num_words, __be32 *data)
{
struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
- unsigned int i, reg;
+ unsigned int reg;
int ret;
if (!mem)
@@ -3685,22 +3677,29 @@ static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type,
if (ret < 0)
return ret;
- for (i = 0; i < num_words; ++i)
- data[i] = be32_to_cpu(data[i]) & 0x00ffffffu;
-
return 0;
}
static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type,
unsigned int mem_addr, u32 *data)
{
- return wm_adsp_read_data_block(dsp, mem_type, mem_addr, 1, data);
+ __be32 raw;
+ int ret;
+
+ ret = wm_adsp_read_raw_data_block(dsp, mem_type, mem_addr, 1, &raw);
+ if (ret < 0)
+ return ret;
+
+ *data = be32_to_cpu(raw) & 0x00ffffffu;
+
+ return 0;
}
static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type,
unsigned int mem_addr, u32 data)
{
struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
+ __be32 val = cpu_to_be32(data & 0x00ffffffu);
unsigned int reg;
if (!mem)
@@ -3708,9 +3707,7 @@ static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type,
reg = dsp->ops->region_to_reg(mem, mem_addr);
- data = cpu_to_be32(data & 0x00ffffffu);
-
- return regmap_raw_write(dsp->regmap, reg, &data, sizeof(data));
+ return regmap_raw_write(dsp->regmap, reg, &val, sizeof(val));
}
static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf,
@@ -3727,18 +3724,22 @@ static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf,
buf->host_buf_ptr + field_offset, data);
}
-static void wm_adsp_remove_padding(u32 *buf, int nwords, int data_word_size)
+static void wm_adsp_remove_padding(u32 *buf, int nwords)
{
- u8 *pack_in = (u8 *)buf;
+ const __be32 *pack_in = (__be32 *)buf;
u8 *pack_out = (u8 *)buf;
- int i, j;
+ int i;
- /* Remove the padding bytes from the data read from the DSP */
+ /*
+ * DSP words from the register map have pad bytes and the data bytes
+ * are in swapped order. This swaps back to the original little-endian
+ * order and strips the pad bytes.
+ */
for (i = 0; i < nwords; i++) {
- for (j = 0; j < data_word_size; j++)
- *pack_out++ = *pack_in++;
-
- pack_in += sizeof(*buf) - data_word_size;
+ u32 word = be32_to_cpu(*pack_in++);
+ *pack_out++ = (u8)word;
+ *pack_out++ = (u8)(word >> 8);
+ *pack_out++ = (u8)(word >> 16);
}
}
@@ -3863,7 +3864,8 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
{
struct wm_adsp_host_buf_coeff_v1 coeff_v1;
struct wm_adsp_compr_buf *buf;
- unsigned int val, reg;
+ unsigned int reg, version;
+ __be32 bufp;
int ret, i;
ret = wm_coeff_base_reg(ctl, &reg);
@@ -3871,17 +3873,17 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
return ret;
for (i = 0; i < 5; ++i) {
- ret = regmap_raw_read(ctl->dsp->regmap, reg, &val, sizeof(val));
+ ret = regmap_raw_read(ctl->dsp->regmap, reg, &bufp, sizeof(bufp));
if (ret < 0)
return ret;
- if (val)
+ if (bufp)
break;
usleep_range(1000, 2000);
}
- if (!val) {
+ if (!bufp) {
adsp_err(ctl->dsp, "Failed to acquire host buffer\n");
return -EIO;
}
@@ -3891,7 +3893,7 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
return -ENOMEM;
buf->host_buf_mem_type = ctl->alg_region.type;
- buf->host_buf_ptr = be32_to_cpu(val);
+ buf->host_buf_ptr = be32_to_cpu(bufp);
ret = wm_adsp_buffer_populate(buf);
if (ret < 0)
@@ -3911,31 +3913,25 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
if (ret < 0)
return ret;
- coeff_v1.versions = be32_to_cpu(coeff_v1.versions);
- val = coeff_v1.versions & HOST_BUF_COEFF_COMPAT_VER_MASK;
- val >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT;
+ version = be32_to_cpu(coeff_v1.versions) & HOST_BUF_COEFF_COMPAT_VER_MASK;
+ version >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT;
- if (val > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) {
+ if (version > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) {
adsp_err(ctl->dsp,
"Host buffer coeff ver %u > supported version %u\n",
- val, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER);
+ version, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER);
return -EINVAL;
}
- for (i = 0; i < ARRAY_SIZE(coeff_v1.name); i++)
- coeff_v1.name[i] = be32_to_cpu(coeff_v1.name[i]);
-
- wm_adsp_remove_padding((u32 *)&coeff_v1.name,
- ARRAY_SIZE(coeff_v1.name),
- WM_ADSP_DATA_WORD_SIZE);
+ wm_adsp_remove_padding((u32 *)&coeff_v1.name, ARRAY_SIZE(coeff_v1.name));
buf->name = kasprintf(GFP_KERNEL, "%s-dsp-%s", ctl->dsp->part,
(char *)&coeff_v1.name);
compr_dbg(buf, "host_buf_ptr=%x coeff version %u\n",
- buf->host_buf_ptr, val);
+ buf->host_buf_ptr, version);
- return val;
+ return version;
}
static int wm_adsp_buffer_init(struct wm_adsp *dsp)
@@ -4266,12 +4262,12 @@ static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target)
return 0;
/* Read data from DSP */
- ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr,
- nwords, compr->raw_buf);
+ ret = wm_adsp_read_raw_data_block(buf->dsp, mem_type, adsp_addr,
+ nwords, (__be32 *)compr->raw_buf);
if (ret < 0)
return ret;
- wm_adsp_remove_padding(compr->raw_buf, nwords, WM_ADSP_DATA_WORD_SIZE);
+ wm_adsp_remove_padding(compr->raw_buf, nwords);
/* update read index to account for words read */
buf->read_index += nwords;
diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h
index 7423272c30e9..f3d51602f85c 100644
--- a/sound/soc/codecs/wmfw.h
+++ b/sound/soc/codecs/wmfw.h
@@ -24,9 +24,9 @@
#define WMFW_CTL_FLAG_READABLE 0x0001
/* Non-ALSA coefficient types start at 0x1000 */
-#define WMFW_CTL_TYPE_ACKED 0x1000 /* acked control */
-#define WMFW_CTL_TYPE_HOSTEVENT 0x1001 /* event control */
-#define WMFW_CTL_TYPE_HOST_BUFFER 0x1002 /* host buffer pointer */
+#define WMFW_CTL_TYPE_ACKED ((__force snd_ctl_elem_type_t)0x1000) /* acked control */
+#define WMFW_CTL_TYPE_HOSTEVENT ((__force snd_ctl_elem_type_t)0x1001) /* event control */
+#define WMFW_CTL_TYPE_HOST_BUFFER ((__force snd_ctl_elem_type_t)0x1002) /* host buffer pointer */
struct wmfw_header {
char magic[4];
diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c
index 4530b74f5921..db87e07b11c9 100644
--- a/sound/soc/codecs/wsa881x.c
+++ b/sound/soc/codecs/wsa881x.c
@@ -640,6 +640,7 @@ static struct regmap_config wsa881x_regmap_config = {
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
.reg_defaults = wsa881x_defaults,
+ .max_register = WSA881X_SPKR_STATUS3,
.num_reg_defaults = ARRAY_SIZE(wsa881x_defaults),
.volatile_reg = wsa881x_volatile_register,
.readable_reg = wsa881x_readable_register,
diff --git a/sound/soc/codecs/zl38060.c b/sound/soc/codecs/zl38060.c
index 42726dc0ba39..d21a72314d37 100644
--- a/sound/soc/codecs/zl38060.c
+++ b/sound/soc/codecs/zl38060.c
@@ -360,8 +360,8 @@ static struct snd_soc_dai_driver zl38_dai = {
.formats = ZL38_FORMATS,
},
.ops = &zl38_dai_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
.symmetric_channels = 1,
};
diff --git a/sound/soc/codecs/zx_aud96p22.c b/sound/soc/codecs/zx_aud96p22.c
deleted file mode 100644
index 16d44efb132d..000000000000
--- a/sound/soc/codecs/zx_aud96p22.c
+++ /dev/null
@@ -1,401 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2017 Sanechips Technology Co., Ltd.
- * Copyright 2017 Linaro Ltd.
- *
- * Author: Baoyou Xie <baoyou.xie@linaro.org>
- */
-
-#include <linux/gpio/consumer.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/regmap.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dai.h>
-#include <sound/tlv.h>
-
-#define AUD96P22_RESET 0x00
-#define RST_DAC_DPZ BIT(0)
-#define RST_ADC_DPZ BIT(1)
-#define AUD96P22_I2S1_CONFIG_0 0x03
-#define I2S1_MS_MODE BIT(3)
-#define I2S1_MODE_MASK 0x7
-#define I2S1_MODE_RIGHT_J 0x0
-#define I2S1_MODE_I2S 0x1
-#define I2S1_MODE_LEFT_J 0x2
-#define AUD96P22_PD_0 0x15
-#define AUD96P22_PD_1 0x16
-#define AUD96P22_PD_3 0x18
-#define AUD96P22_PD_4 0x19
-#define AUD96P22_MUTE_0 0x1d
-#define AUD96P22_MUTE_2 0x1f
-#define AUD96P22_MUTE_4 0x21
-#define AUD96P22_RECVOL_0 0x24
-#define AUD96P22_RECVOL_1 0x25
-#define AUD96P22_PGA1VOL_0 0x26
-#define AUD96P22_PGA1VOL_1 0x27
-#define AUD96P22_LMVOL_0 0x34
-#define AUD96P22_LMVOL_1 0x35
-#define AUD96P22_HS1VOL_0 0x38
-#define AUD96P22_HS1VOL_1 0x39
-#define AUD96P22_PGA1SEL_0 0x47
-#define AUD96P22_PGA1SEL_1 0x48
-#define AUD96P22_LDR1SEL_0 0x59
-#define AUD96P22_LDR1SEL_1 0x60
-#define AUD96P22_LDR2SEL_0 0x5d
-#define AUD96P22_REG_MAX 0xfb
-
-struct aud96p22_priv {
- struct regmap *regmap;
-};
-
-static int aud96p22_adc_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 aud96p22_priv *priv = snd_soc_component_get_drvdata(component);
- struct regmap *regmap = priv->regmap;
-
- if (event != SND_SOC_DAPM_POST_PMU)
- return -EINVAL;
-
- /* Assert/de-assert the bit to reset ADC data path */
- regmap_update_bits(regmap, AUD96P22_RESET, RST_ADC_DPZ, 0);
- regmap_update_bits(regmap, AUD96P22_RESET, RST_ADC_DPZ, RST_ADC_DPZ);
-
- return 0;
-}
-
-static int aud96p22_dac_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 aud96p22_priv *priv = snd_soc_component_get_drvdata(component);
- struct regmap *regmap = priv->regmap;
-
- if (event != SND_SOC_DAPM_POST_PMU)
- return -EINVAL;
-
- /* Assert/de-assert the bit to reset DAC data path */
- regmap_update_bits(regmap, AUD96P22_RESET, RST_DAC_DPZ, 0);
- regmap_update_bits(regmap, AUD96P22_RESET, RST_DAC_DPZ, RST_DAC_DPZ);
-
- return 0;
-}
-
-static const DECLARE_TLV_DB_SCALE(lm_tlv, -11550, 50, 0);
-static const DECLARE_TLV_DB_SCALE(hs_tlv, -3900, 300, 0);
-static const DECLARE_TLV_DB_SCALE(rec_tlv, -9550, 50, 0);
-static const DECLARE_TLV_DB_SCALE(pga_tlv, -1800, 100, 0);
-
-static const struct snd_kcontrol_new aud96p22_snd_controls[] = {
- /* Volume control */
- SOC_DOUBLE_R_TLV("Master Playback Volume", AUD96P22_LMVOL_0,
- AUD96P22_LMVOL_1, 0, 0xff, 0, lm_tlv),
- SOC_DOUBLE_R_TLV("Headphone Volume", AUD96P22_HS1VOL_0,
- AUD96P22_HS1VOL_1, 0, 0xf, 0, hs_tlv),
- SOC_DOUBLE_R_TLV("Master Capture Volume", AUD96P22_RECVOL_0,
- AUD96P22_RECVOL_1, 0, 0xff, 0, rec_tlv),
- SOC_DOUBLE_R_TLV("Analogue Capture Volume", AUD96P22_PGA1VOL_0,
- AUD96P22_PGA1VOL_1, 0, 0x37, 0, pga_tlv),
-
- /* Mute control */
- SOC_DOUBLE("Master Playback Switch", AUD96P22_MUTE_2, 0, 1, 1, 1),
- SOC_DOUBLE("Headphone Switch", AUD96P22_MUTE_2, 4, 5, 1, 1),
- SOC_DOUBLE("Line Out Switch", AUD96P22_MUTE_4, 0, 1, 1, 1),
- SOC_DOUBLE("Speaker Switch", AUD96P22_MUTE_4, 2, 3, 1, 1),
- SOC_DOUBLE("Master Capture Switch", AUD96P22_MUTE_0, 0, 1, 1, 1),
- SOC_DOUBLE("Analogue Capture Switch", AUD96P22_MUTE_0, 2, 3, 1, 1),
-};
-
-/* Input mux kcontrols */
-static const unsigned int ain_mux_values[] = {
- 0, 1, 3, 4, 5,
-};
-
-static const char * const ainl_mux_texts[] = {
- "AINL1 differential",
- "AINL1 single-ended",
- "AINL3 single-ended",
- "AINL2 differential",
- "AINL2 single-ended",
-};
-
-static const char * const ainr_mux_texts[] = {
- "AINR1 differential",
- "AINR1 single-ended",
- "AINR3 single-ended",
- "AINR2 differential",
- "AINR2 single-ended",
-};
-
-static SOC_VALUE_ENUM_SINGLE_DECL(ainl_mux_enum, AUD96P22_PGA1SEL_0,
- 0, 0x7, ainl_mux_texts, ain_mux_values);
-static SOC_VALUE_ENUM_SINGLE_DECL(ainr_mux_enum, AUD96P22_PGA1SEL_1,
- 0, 0x7, ainr_mux_texts, ain_mux_values);
-
-static const struct snd_kcontrol_new ainl_mux_kcontrol =
- SOC_DAPM_ENUM("AINL Mux", ainl_mux_enum);
-static const struct snd_kcontrol_new ainr_mux_kcontrol =
- SOC_DAPM_ENUM("AINR Mux", ainr_mux_enum);
-
-/* Output mixer kcontrols */
-static const struct snd_kcontrol_new ld1_left_kcontrols[] = {
- SOC_DAPM_SINGLE("DACL LD1L Switch", AUD96P22_LDR1SEL_0, 0, 1, 0),
- SOC_DAPM_SINGLE("AINL LD1L Switch", AUD96P22_LDR1SEL_0, 1, 1, 0),
- SOC_DAPM_SINGLE("AINR LD1L Switch", AUD96P22_LDR1SEL_0, 2, 1, 0),
-};
-
-static const struct snd_kcontrol_new ld1_right_kcontrols[] = {
- SOC_DAPM_SINGLE("DACR LD1R Switch", AUD96P22_LDR1SEL_1, 8, 1, 0),
- SOC_DAPM_SINGLE("AINR LD1R Switch", AUD96P22_LDR1SEL_1, 9, 1, 0),
- SOC_DAPM_SINGLE("AINL LD1R Switch", AUD96P22_LDR1SEL_1, 10, 1, 0),
-};
-
-static const struct snd_kcontrol_new ld2_kcontrols[] = {
- SOC_DAPM_SINGLE("DACL LD2 Switch", AUD96P22_LDR2SEL_0, 0, 1, 0),
- SOC_DAPM_SINGLE("AINL LD2 Switch", AUD96P22_LDR2SEL_0, 1, 1, 0),
- SOC_DAPM_SINGLE("DACR LD2 Switch", AUD96P22_LDR2SEL_0, 2, 1, 0),
-};
-
-static const struct snd_soc_dapm_widget aud96p22_dapm_widgets[] = {
- /* Overall power bit */
- SND_SOC_DAPM_SUPPLY("POWER", AUD96P22_PD_0, 0, 0, NULL, 0),
-
- /* Input pins */
- SND_SOC_DAPM_INPUT("AINL1P"),
- SND_SOC_DAPM_INPUT("AINL2P"),
- SND_SOC_DAPM_INPUT("AINL3"),
- SND_SOC_DAPM_INPUT("AINL1N"),
- SND_SOC_DAPM_INPUT("AINL2N"),
- SND_SOC_DAPM_INPUT("AINR2N"),
- SND_SOC_DAPM_INPUT("AINR1N"),
- SND_SOC_DAPM_INPUT("AINR3"),
- SND_SOC_DAPM_INPUT("AINR2P"),
- SND_SOC_DAPM_INPUT("AINR1P"),
-
- /* Input muxes */
- SND_SOC_DAPM_MUX("AINLMUX", AUD96P22_PD_1, 2, 0, &ainl_mux_kcontrol),
- SND_SOC_DAPM_MUX("AINRMUX", AUD96P22_PD_1, 3, 0, &ainr_mux_kcontrol),
-
- /* ADCs */
- SND_SOC_DAPM_ADC_E("ADCL", "Capture Left", AUD96P22_PD_1, 0, 0,
- aud96p22_adc_event, SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_ADC_E("ADCR", "Capture Right", AUD96P22_PD_1, 1, 0,
- aud96p22_adc_event, SND_SOC_DAPM_POST_PMU),
-
- /* DACs */
- SND_SOC_DAPM_DAC_E("DACL", "Playback Left", AUD96P22_PD_3, 0, 0,
- aud96p22_dac_event, SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_DAC_E("DACR", "Playback Right", AUD96P22_PD_3, 1, 0,
- aud96p22_dac_event, SND_SOC_DAPM_POST_PMU),
-
- /* Output mixers */
- SND_SOC_DAPM_MIXER("LD1L", AUD96P22_PD_3, 6, 0, ld1_left_kcontrols,
- ARRAY_SIZE(ld1_left_kcontrols)),
- SND_SOC_DAPM_MIXER("LD1R", AUD96P22_PD_3, 7, 0, ld1_right_kcontrols,
- ARRAY_SIZE(ld1_right_kcontrols)),
- SND_SOC_DAPM_MIXER("LD2", AUD96P22_PD_4, 2, 0, ld2_kcontrols,
- ARRAY_SIZE(ld2_kcontrols)),
-
- /* Headset power switch */
- SND_SOC_DAPM_SUPPLY("HS1L", AUD96P22_PD_3, 4, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("HS1R", AUD96P22_PD_3, 5, 0, NULL, 0),
-
- /* Output pins */
- SND_SOC_DAPM_OUTPUT("HSOUTL"),
- SND_SOC_DAPM_OUTPUT("LINEOUTL"),
- SND_SOC_DAPM_OUTPUT("LINEOUTMP"),
- SND_SOC_DAPM_OUTPUT("LINEOUTMN"),
- SND_SOC_DAPM_OUTPUT("LINEOUTR"),
- SND_SOC_DAPM_OUTPUT("HSOUTR"),
-};
-
-static const struct snd_soc_dapm_route aud96p22_dapm_routes[] = {
- { "AINLMUX", "AINL1 differential", "AINL1N" },
- { "AINLMUX", "AINL1 single-ended", "AINL1P" },
- { "AINLMUX", "AINL3 single-ended", "AINL3" },
- { "AINLMUX", "AINL2 differential", "AINL2N" },
- { "AINLMUX", "AINL2 single-ended", "AINL2P" },
-
- { "AINRMUX", "AINR1 differential", "AINR1N" },
- { "AINRMUX", "AINR1 single-ended", "AINR1P" },
- { "AINRMUX", "AINR3 single-ended", "AINR3" },
- { "AINRMUX", "AINR2 differential", "AINR2N" },
- { "AINRMUX", "AINR2 single-ended", "AINR2P" },
-
- { "ADCL", NULL, "AINLMUX" },
- { "ADCR", NULL, "AINRMUX" },
-
- { "ADCL", NULL, "POWER" },
- { "ADCR", NULL, "POWER" },
- { "DACL", NULL, "POWER" },
- { "DACR", NULL, "POWER" },
-
- { "LD1L", "DACL LD1L Switch", "DACL" },
- { "LD1L", "AINL LD1L Switch", "AINLMUX" },
- { "LD1L", "AINR LD1L Switch", "AINRMUX" },
-
- { "LD1R", "DACR LD1R Switch", "DACR" },
- { "LD1R", "AINR LD1R Switch", "AINRMUX" },
- { "LD1R", "AINL LD1R Switch", "AINLMUX" },
-
- { "LD2", "DACL LD2 Switch", "DACL" },
- { "LD2", "AINL LD2 Switch", "AINLMUX" },
- { "LD2", "DACR LD2 Switch", "DACR" },
-
- { "HSOUTL", NULL, "LD1L" },
- { "HSOUTR", NULL, "LD1R" },
- { "HSOUTL", NULL, "HS1L" },
- { "HSOUTR", NULL, "HS1R" },
-
- { "LINEOUTL", NULL, "LD1L" },
- { "LINEOUTR", NULL, "LD1R" },
-
- { "LINEOUTMP", NULL, "LD2" },
- { "LINEOUTMN", NULL, "LD2" },
-};
-
-static const struct snd_soc_component_driver aud96p22_driver = {
- .controls = aud96p22_snd_controls,
- .num_controls = ARRAY_SIZE(aud96p22_snd_controls),
- .dapm_widgets = aud96p22_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(aud96p22_dapm_widgets),
- .dapm_routes = aud96p22_dapm_routes,
- .num_dapm_routes = ARRAY_SIZE(aud96p22_dapm_routes),
- .idle_bias_on = 1,
- .use_pmdown_time = 1,
- .endianness = 1,
- .non_legacy_dai_naming = 1,
-};
-
-static int aud96p22_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-{
- struct aud96p22_priv *priv = snd_soc_component_get_drvdata(dai->component);
- struct regmap *regmap = priv->regmap;
- unsigned int val;
-
- /* Master/slave mode */
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBS_CFS:
- val = 0;
- break;
- case SND_SOC_DAIFMT_CBM_CFM:
- val = I2S1_MS_MODE;
- break;
- default:
- return -EINVAL;
- }
-
- regmap_update_bits(regmap, AUD96P22_I2S1_CONFIG_0, I2S1_MS_MODE, val);
-
- /* Audio format */
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_RIGHT_J:
- val = I2S1_MODE_RIGHT_J;
- break;
- case SND_SOC_DAIFMT_I2S:
- val = I2S1_MODE_I2S;
- break;
- case SND_SOC_DAIFMT_LEFT_J:
- val = I2S1_MODE_LEFT_J;
- break;
- default:
- return -EINVAL;
- }
-
- regmap_update_bits(regmap, AUD96P22_I2S1_CONFIG_0, I2S1_MODE_MASK, val);
-
- return 0;
-}
-
-static const struct snd_soc_dai_ops aud96p22_dai_ops = {
- .set_fmt = aud96p22_set_fmt,
-};
-
-#define AUD96P22_RATES SNDRV_PCM_RATE_8000_192000
-#define AUD96P22_FORMATS (\
- SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \
- SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
-
-static struct snd_soc_dai_driver aud96p22_dai = {
- .name = "aud96p22-dai",
- .playback = {
- .stream_name = "Playback",
- .channels_min = 1,
- .channels_max = 2,
- .rates = AUD96P22_RATES,
- .formats = AUD96P22_FORMATS,
- },
- .capture = {
- .stream_name = "Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = AUD96P22_RATES,
- .formats = AUD96P22_FORMATS,
- },
- .ops = &aud96p22_dai_ops,
-};
-
-static const struct regmap_config aud96p22_regmap = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = AUD96P22_REG_MAX,
- .cache_type = REGCACHE_RBTREE,
-};
-
-static int aud96p22_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
-{
- struct device *dev = &i2c->dev;
- struct aud96p22_priv *priv;
- int ret;
-
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (priv == NULL)
- return -ENOMEM;
-
- priv->regmap = devm_regmap_init_i2c(i2c, &aud96p22_regmap);
- if (IS_ERR(priv->regmap)) {
- ret = PTR_ERR(priv->regmap);
- dev_err(dev, "failed to init i2c regmap: %d\n", ret);
- return ret;
- }
-
- i2c_set_clientdata(i2c, priv);
-
- ret = devm_snd_soc_register_component(dev, &aud96p22_driver, &aud96p22_dai, 1);
- if (ret) {
- dev_err(dev, "failed to register component: %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-static int aud96p22_i2c_remove(struct i2c_client *i2c)
-{
- return 0;
-}
-
-static const struct of_device_id aud96p22_dt_ids[] = {
- { .compatible = "zte,zx-aud96p22", },
- { }
-};
-MODULE_DEVICE_TABLE(of, aud96p22_dt_ids);
-
-static struct i2c_driver aud96p22_i2c_driver = {
- .driver = {
- .name = "zx_aud96p22",
- .of_match_table = aud96p22_dt_ids,
- },
- .probe = aud96p22_i2c_probe,
- .remove = aud96p22_i2c_remove,
-};
-module_i2c_driver(aud96p22_i2c_driver);
-
-MODULE_DESCRIPTION("ZTE ASoC AUD96P22 CODEC driver");
-MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 84db0b7b9d59..d7f30036d434 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -108,6 +108,7 @@ config SND_SOC_FSL_XCVR
config SND_SOC_FSL_AUD2HTX
tristate "AUDIO TO HDMI TX module support"
depends on ARCH_MXC || COMPILE_TEST
+ select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n
help
Say Y if you want to add AUDIO TO HDMI TX support for NXP.
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 02c81d2e34ad..c325c984d165 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -1083,11 +1083,6 @@ static int fsl_asrc_probe(struct platform_device *pdev)
}
asrc_priv->soc = of_device_get_match_data(&pdev->dev);
- if (!asrc_priv->soc) {
- dev_err(&pdev->dev, "failed to get soc data\n");
- return -ENODEV;
- }
-
asrc->use_edma = asrc_priv->soc->use_edma;
asrc->get_dma_channel = fsl_asrc_get_dma_channel;
asrc->request_pair = fsl_asrc_request_pair;
diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index 60951a8aabd3..636a702f37a6 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -1530,7 +1530,7 @@ static int fsl_easrc_hw_free(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_dai_ops fsl_easrc_dai_ops = {
+static const struct snd_soc_dai_ops fsl_easrc_dai_ops = {
.startup = fsl_easrc_startup,
.trigger = fsl_easrc_trigger,
.hw_params = fsl_easrc_hw_params,
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 39637ca78cdb..08056fa0a0fa 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -23,11 +23,9 @@
/**
* struct fsl_esai_soc_data - soc specific data
- * @imx: for imx platform
* @reset_at_xrun: flags for enable reset operaton
*/
struct fsl_esai_soc_data {
- bool imx;
bool reset_at_xrun;
};
@@ -86,17 +84,14 @@ struct fsl_esai {
};
static struct fsl_esai_soc_data fsl_esai_vf610 = {
- .imx = false,
.reset_at_xrun = true,
};
static struct fsl_esai_soc_data fsl_esai_imx35 = {
- .imx = true,
.reset_at_xrun = true,
};
static struct fsl_esai_soc_data fsl_esai_imx6ull = {
- .imx = true,
.reset_at_xrun = false,
};
@@ -967,10 +962,6 @@ static int fsl_esai_probe(struct platform_device *pdev)
snprintf(esai_priv->name, sizeof(esai_priv->name), "%pOFn", np);
esai_priv->soc = of_device_get_match_data(&pdev->dev);
- if (!esai_priv->soc) {
- dev_err(&pdev->dev, "failed to get soc data\n");
- return -ENODEV;
- }
/* Get the addresses and IRQ */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1042,9 +1033,9 @@ static int fsl_esai_probe(struct platform_device *pdev)
/* Implement full symmetry for synchronous mode */
if (esai_priv->synchronous) {
- fsl_esai_dai.symmetric_rates = 1;
+ fsl_esai_dai.symmetric_rate = 1;
fsl_esai_dai.symmetric_channels = 1;
- fsl_esai_dai.symmetric_samplebits = 1;
+ fsl_esai_dai.symmetric_sample_bits = 1;
}
dev_set_drvdata(&pdev->dev, esai_priv);
diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c
index efc5daf53bba..5935af2e5ff4 100644
--- a/sound/soc/fsl/fsl_micfil.c
+++ b/sound/soc/fsl/fsl_micfil.c
@@ -381,7 +381,7 @@ static int fsl_micfil_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
return ret;
}
-static struct snd_soc_dai_ops fsl_micfil_dai_ops = {
+static const struct snd_soc_dai_ops fsl_micfil_dai_ops = {
.startup = fsl_micfil_startup,
.trigger = fsl_micfil_trigger,
.hw_params = fsl_micfil_hw_params,
@@ -637,7 +637,6 @@ static irqreturn_t micfil_err_isr(int irq, void *devid)
static int fsl_micfil_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- const struct of_device_id *of_id;
struct fsl_micfil *micfil;
struct resource *res;
void __iomem *regs;
@@ -651,11 +650,7 @@ static int fsl_micfil_probe(struct platform_device *pdev)
micfil->pdev = pdev;
strncpy(micfil->name, np->name, sizeof(micfil->name) - 1);
- of_id = of_match_device(fsl_micfil_dt_ids, &pdev->dev);
- if (!of_id || !of_id->data)
- return -EINVAL;
-
- micfil->soc = of_id->data;
+ micfil->soc = of_device_get_match_data(&pdev->dev);
/* ipg_clk is used to control the registers
* ipg_clk_app is used to operate the filter
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index f3d3d20d35d7..5e65b456d3e2 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -1079,9 +1079,9 @@ static int fsl_sai_probe(struct platform_device *pdev)
/* Sync Tx with Rx as default by following old DT binding */
sai->synchronous[RX] = true;
sai->synchronous[TX] = false;
- sai->cpu_dai_drv.symmetric_rates = 1;
+ sai->cpu_dai_drv.symmetric_rate = 1;
sai->cpu_dai_drv.symmetric_channels = 1;
- sai->cpu_dai_drv.symmetric_samplebits = 1;
+ sai->cpu_dai_drv.symmetric_sample_bits = 1;
if (of_find_property(np, "fsl,sai-synchronous-rx", NULL) &&
of_find_property(np, "fsl,sai-asynchronous", NULL)) {
@@ -1098,9 +1098,9 @@ static int fsl_sai_probe(struct platform_device *pdev)
/* Discard all settings for asynchronous mode */
sai->synchronous[RX] = false;
sai->synchronous[TX] = false;
- sai->cpu_dai_drv.symmetric_rates = 0;
+ sai->cpu_dai_drv.symmetric_rate = 0;
sai->cpu_dai_drv.symmetric_channels = 0;
- sai->cpu_dai_drv.symmetric_samplebits = 0;
+ sai->cpu_dai_drv.symmetric_sample_bits = 0;
}
if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) &&
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 5fa178f3f497..174e558224d8 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -1255,7 +1255,7 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
for (i = 0; i < STC_TXCLK_SRC_MAX; i++) {
sprintf(tmp, "rxtx%d", i);
- clk = devm_clk_get(&pdev->dev, tmp);
+ clk = devm_clk_get(dev, tmp);
if (IS_ERR(clk)) {
dev_err(dev, "no rxtx%d clock in devicetree\n", i);
return PTR_ERR(clk);
@@ -1277,14 +1277,14 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
break;
}
- dev_dbg(&pdev->dev, "use rxtx%d as tx clock source for %dHz sample rate\n",
+ dev_dbg(dev, "use rxtx%d as tx clock source for %dHz sample rate\n",
spdif_priv->txclk_src[index], rate[index]);
- dev_dbg(&pdev->dev, "use txclk df %d for %dHz sample rate\n",
+ dev_dbg(dev, "use txclk df %d for %dHz sample rate\n",
spdif_priv->txclk_df[index], rate[index]);
if (clk_is_match(spdif_priv->txclk[index], spdif_priv->sysclk))
- dev_dbg(&pdev->dev, "use sysclk df %d for %dHz sample rate\n",
+ dev_dbg(dev, "use sysclk df %d for %dHz sample rate\n",
spdif_priv->sysclk_df[index], rate[index]);
- dev_dbg(&pdev->dev, "the best rate for %dHz sample rate is %dHz\n",
+ dev_dbg(dev, "the best rate for %dHz sample rate is %dHz\n",
rate[index], spdif_priv->txrate[index]);
return 0;
@@ -1305,10 +1305,6 @@ static int fsl_spdif_probe(struct platform_device *pdev)
spdif_priv->pdev = pdev;
spdif_priv->soc = of_device_get_match_data(&pdev->dev);
- if (!spdif_priv->soc) {
- dev_err(&pdev->dev, "failed to get soc data\n");
- return -ENODEV;
- }
/* Initialize this copy of the CPU DAI driver structure */
memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai));
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 404be27c15fe..57811743c294 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1397,18 +1397,11 @@ static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi)
{
struct device *dev = ssi->dev;
struct device_node *np = dev->of_node;
- const struct of_device_id *of_id;
const char *p, *sprop;
const __be32 *iprop;
u32 dmas[4];
int ret;
- of_id = of_match_device(fsl_ssi_ids, dev);
- if (!of_id || !of_id->data)
- return -EINVAL;
-
- ssi->soc = of_id->data;
-
ret = of_property_match_string(np, "clock-names", "ipg");
/* Get error code if not found */
ssi->has_ipg_clk_name = ret >= 0;
@@ -1492,6 +1485,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
return -ENOMEM;
ssi->dev = dev;
+ ssi->soc = of_device_get_match_data(&pdev->dev);
/* Probe from DT */
ret = fsl_ssi_probe_from_dt(ssi);
@@ -1537,9 +1531,9 @@ static int fsl_ssi_probe(struct platform_device *pdev)
/* Set software limitations for synchronous mode except AC97 */
if (ssi->synchronous && !fsl_ssi_is_ac97(ssi)) {
- ssi->cpu_dai_drv.symmetric_rates = 1;
+ ssi->cpu_dai_drv.symmetric_rate = 1;
ssi->cpu_dai_drv.symmetric_channels = 1;
- ssi->cpu_dai_drv.symmetric_samplebits = 1;
+ ssi->cpu_dai_drv.symmetric_sample_bits = 1;
}
/*
diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
index 3d58c88ea603..6dd0a5fcd455 100644
--- a/sound/soc/fsl/fsl_xcvr.c
+++ b/sound/soc/fsl/fsl_xcvr.c
@@ -857,7 +857,7 @@ static struct snd_kcontrol_new fsl_xcvr_tx_ctls[] = {
},
};
-static struct snd_soc_dai_ops fsl_xcvr_dai_ops = {
+static const struct snd_soc_dai_ops fsl_xcvr_dai_ops = {
.prepare = fsl_xcvr_prepare,
.startup = fsl_xcvr_startup,
.shutdown = fsl_xcvr_shutdown,
@@ -1130,16 +1130,11 @@ MODULE_DEVICE_TABLE(of, fsl_xcvr_dt_ids);
static int fsl_xcvr_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- const struct of_device_id *of_id;
struct fsl_xcvr *xcvr;
struct resource *ram_res, *regs_res, *rx_res, *tx_res;
void __iomem *regs;
int ret, irq;
- of_id = of_match_device(fsl_xcvr_dt_ids, dev);
- if (!of_id)
- return -EINVAL;
-
xcvr = devm_kzalloc(dev, sizeof(*xcvr), GFP_KERNEL);
if (!xcvr)
return -ENOMEM;
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c
index 16a04a678828..8c5cdcdc8713 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -532,7 +532,7 @@ static int graph_for_each_link(struct asoc_simple_priv *priv,
static void graph_get_dais_count(struct asoc_simple_priv *priv,
struct link_info *li);
-int graph_parse_of(struct asoc_simple_priv *priv, struct device *dev)
+int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev)
{
struct snd_soc_card *card = simple_priv_to_card(priv);
struct link_info li;
@@ -608,7 +608,7 @@ err:
return ret;
}
-EXPORT_SYMBOL_GPL(graph_parse_of);
+EXPORT_SYMBOL_GPL(audio_graph_parse_of);
static int graph_count_noml(struct asoc_simple_priv *priv,
struct device_node *cpu_ep,
@@ -705,7 +705,7 @@ static void graph_get_dais_count(struct asoc_simple_priv *priv,
li->link, li->dais, li->conf);
}
-int graph_card_probe(struct snd_soc_card *card)
+int audio_graph_card_probe(struct snd_soc_card *card)
{
struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card);
int ret;
@@ -720,7 +720,7 @@ int graph_card_probe(struct snd_soc_card *card)
return 0;
}
-EXPORT_SYMBOL_GPL(graph_card_probe);
+EXPORT_SYMBOL_GPL(audio_graph_card_probe);
static int graph_probe(struct platform_device *pdev)
{
@@ -736,20 +736,21 @@ static int graph_probe(struct platform_device *pdev)
card = simple_priv_to_card(priv);
card->dapm_widgets = graph_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(graph_dapm_widgets);
- card->probe = graph_card_probe;
+ card->probe = audio_graph_card_probe;
if (of_device_get_match_data(dev))
priv->dpcm_selectable = 1;
- return graph_parse_of(priv, dev);
+ return audio_graph_parse_of(priv, dev);
}
-static int graph_remove(struct platform_device *pdev)
+int audio_graph_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
return asoc_simple_clean_reference(card);
}
+EXPORT_SYMBOL_GPL(audio_graph_remove);
static const struct of_device_id graph_of_match[] = {
{ .compatible = "audio-graph-card", },
@@ -766,7 +767,7 @@ static struct platform_driver graph_card = {
.of_match_table = graph_of_match,
},
.probe = graph_probe,
- .remove = graph_remove,
+ .remove = audio_graph_remove,
};
module_platform_driver(graph_card);
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 6cada4c1e283..ab31045cfc95 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -172,16 +172,15 @@ int asoc_simple_parse_clk(struct device *dev,
* or device's module clock.
*/
clk = devm_get_clk_from_child(dev, node, NULL);
- if (!IS_ERR(clk)) {
- simple_dai->sysclk = clk_get_rate(clk);
+ if (IS_ERR(clk))
+ clk = devm_get_clk_from_child(dev, dlc->of_node, NULL);
+ if (!IS_ERR(clk)) {
simple_dai->clk = clk;
- } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) {
+ simple_dai->sysclk = clk_get_rate(clk);
+ } else if (!of_property_read_u32(node, "system-clock-frequency",
+ &val)) {
simple_dai->sysclk = val;
- } else {
- clk = devm_get_clk_from_child(dev, dlc->of_node, NULL);
- if (!IS_ERR(clk))
- simple_dai->sysclk = clk_get_rate(clk);
}
if (of_property_read_bool(node, "system-clock-direction-out"))
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index 0c6404fc12b3..f3a4a907b29d 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -203,6 +203,8 @@ config SND_SOC_INTEL_KEEMBAY
tristate "Keembay Platforms"
depends on ARCH_KEEMBAY || COMPILE_TEST
depends on COMMON_CLK
+ select SND_DMAENGINE_PCM
+ select SND_SOC_GENERIC_DMAENGINE_PCM
help
If you have a Intel Keembay platform then enable this option
by saying Y or m.
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index b58b9b60d37e..d1d28129a32b 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -111,6 +111,18 @@ config SND_SOC_INTEL_BYTCR_RT5651_MACH
Say Y or m if you have such a device. This is a recommended option.
If unsure select "N".
+config SND_SOC_INTEL_BYTCR_WM5102_MACH
+ tristate "Baytrail and Baytrail-CR with WM5102 codec"
+ depends on MFD_ARIZONA && MFD_WM5102 && SPI_MASTER && ACPI
+ depends on X86_INTEL_LPSS || COMPILE_TEST
+ select SND_SOC_ACPI
+ select SND_SOC_WM5102
+ help
+ This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
+ platforms with WM5102 audio codec.
+ Say Y if you have such a device.
+ If unsure select "N".
+
config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
tristate "Cherrytrail & Braswell with RT5672 codec"
depends on I2C && ACPI
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
index 5f03e484b215..616c5fbab7d5 100644
--- a/sound/soc/intel/boards/Makefile
+++ b/sound/soc/intel/boards/Makefile
@@ -10,6 +10,7 @@ snd-soc-sst-sof-wm8804-objs := sof_wm8804.o
snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o hda_dsp_common.o
snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o
+snd-soc-sst-bytcr-wm5102-objs := bytcr_wm5102.o
snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o
@@ -51,6 +52,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5650_MACH) += snd-soc-sst-bdw-rt5650-mach.o
obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH) += snd-soc-sst-bdw-rt5677-mach.o
obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o
obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH) += snd-soc-sst-bytcr-rt5651.o
+obj-$(CONFIG_SND_SOC_INTEL_BYTCR_WM5102_MACH) += snd-soc-sst-bytcr-wm5102.o
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
index 892cf684216e..06df2d46d910 100644
--- a/sound/soc/intel/boards/bytcht_es8316.c
+++ b/sound/soc/intel/boards/bytcht_es8316.c
@@ -331,9 +331,6 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
/* back ends */
{
- /* Only SSP2 has been tested here, so BYT-CR platforms that
- * require SSP0 will not work.
- */
.name = "SSP2-Codec",
.id = 0,
.no_pcm = 1,
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 5520d7c80019..782f2b4d72ad 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -35,6 +35,7 @@ enum {
BYT_RT5640_DMIC2_MAP,
BYT_RT5640_IN1_MAP,
BYT_RT5640_IN3_MAP,
+ BYT_RT5640_NO_INTERNAL_MIC_MAP,
};
enum {
@@ -71,6 +72,7 @@ enum {
#define BYT_RT5640_SSP0_AIF2 BIT(21)
#define BYT_RT5640_MCLK_EN BIT(22)
#define BYT_RT5640_MCLK_25MHZ BIT(23)
+#define BYT_RT5640_NO_SPEAKERS BIT(24)
#define BYTCR_INPUT_DEFAULTS \
(BYT_RT5640_IN3_MAP | \
@@ -116,6 +118,9 @@ static void log_quirks(struct device *dev)
case BYT_RT5640_IN3_MAP:
dev_info(dev, "quirk IN3_MAP enabled\n");
break;
+ case BYT_RT5640_NO_INTERNAL_MIC_MAP:
+ dev_info(dev, "quirk NO_INTERNAL_MIC_MAP enabled\n");
+ break;
default:
dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map);
break;
@@ -132,6 +137,8 @@ static void log_quirks(struct device *dev)
dev_info(dev, "quirk JD_NOT_INV enabled\n");
if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER)
dev_info(dev, "quirk MONO_SPEAKER enabled\n");
+ if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)
+ dev_info(dev, "quirk NO_SPEAKERS enabled\n");
if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
dev_info(dev, "quirk DIFF_MIC enabled\n");
if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {
@@ -399,6 +406,19 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
+ { /* Acer One 10 S1002 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "One S1002"),
+ },
+ .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),
+ },
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -524,6 +544,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_MONO_SPEAKER |
BYT_RT5640_MCLK_EN),
},
+ { /* Estar Beauty HD MID 7316R */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Estar"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"),
+ },
+ .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
+ BYT_RT5640_MONO_SPEAKER |
+ BYT_RT5640_SSP0_AIF1 |
+ BYT_RT5640_MCLK_EN),
+ },
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
@@ -613,6 +643,15 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
+ { /* Mele PCG03 Mini PC */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "Mini PC"),
+ },
+ .driver_data = (void *)(BYT_RT5640_NO_INTERNAL_MIC_MAP |
+ BYT_RT5640_NO_SPEAKERS |
+ BYT_RT5640_SSP0_AIF1),
+ },
{ /* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"),
@@ -798,6 +837,20 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF2 |
BYT_RT5640_MCLK_EN),
},
+ { /* Voyo Winpad A15 */
+ .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, "11/20/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_MCLK_EN),
+ },
{ /* Catch-all for generic Insyde tablets, must be last */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
@@ -873,8 +926,8 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
struct snd_soc_card *card = runtime->card;
struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component;
- const struct snd_soc_dapm_route *custom_map;
- int num_routes;
+ const struct snd_soc_dapm_route *custom_map = NULL;
+ int num_routes = 0;
int ret;
card->dapm.idle_bias_off = true;
@@ -909,13 +962,14 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
custom_map = byt_rt5640_intmic_in3_map;
num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map);
break;
+ case BYT_RT5640_DMIC1_MAP:
+ custom_map = byt_rt5640_intmic_dmic1_map;
+ num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);
+ break;
case BYT_RT5640_DMIC2_MAP:
custom_map = byt_rt5640_intmic_dmic2_map;
num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map);
break;
- default:
- custom_map = byt_rt5640_intmic_dmic1_map;
- num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);
}
ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
@@ -946,7 +1000,7 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
ret = snd_soc_dapm_add_routes(&card->dapm,
byt_rt5640_mono_spk_map,
ARRAY_SIZE(byt_rt5640_mono_spk_map));
- } else {
+ } else if (!(byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)) {
ret = snd_soc_dapm_add_routes(&card->dapm,
byt_rt5640_stereo_spk_map,
ARRAY_SIZE(byt_rt5640_stereo_spk_map));
@@ -1187,7 +1241,8 @@ struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */
static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" };
+ static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" };
+ __maybe_unused const char *spk_type;
const struct dmi_system_id *dmi_id;
struct byt_rt5640_private *priv;
struct snd_soc_acpi_mach *mach;
@@ -1196,7 +1251,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
bool sof_parent;
int ret_val = 0;
int dai_index = 0;
- int i;
+ int i, cfg_spk;
is_bytcr = false;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -1335,16 +1390,24 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
}
}
+ if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) {
+ cfg_spk = 0;
+ spk_type = "none";
+ } else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {
+ cfg_spk = 1;
+ spk_type = "mono";
+ } else {
+ cfg_spk = 2;
+ spk_type = "stereo";
+ }
+
snprintf(byt_rt5640_components, sizeof(byt_rt5640_components),
- "cfg-spk:%s cfg-mic:%s",
- (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) ? "1" : "2",
+ "cfg-spk:%d cfg-mic:%s", cfg_spk,
map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]);
byt_rt5640_card.components = byt_rt5640_components;
#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name),
- "bytcr-rt5640-%s-spk-%s-mic",
- (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) ?
- "mono" : "stereo",
+ "bytcr-rt5640-%s-spk-%s-mic", spk_type,
map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]);
byt_rt5640_card.long_name = byt_rt5640_long_name;
#endif
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index f289ec8563a1..148b7b1bd3e8 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -436,6 +436,19 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
BYT_RT5651_MONO_SPEAKER),
},
{
+ /* Jumper EZpad 7 */
+ .callback = byt_rt5651_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Jumper"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
+ /* Jumper12x.WJ2012.bsBKRCP05 with the version dropped */
+ DMI_MATCH(DMI_BIOS_VERSION, "Jumper12x.WJ2012.bsBKRCP"),
+ },
+ .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
+ BYT_RT5651_IN2_MAP |
+ BYT_RT5651_JD_NOT_INV),
+ },
+ {
/* KIANO SlimNote 14.2 */
.callback = byt_rt5651_quirk_cb,
.matches = {
diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c
new file mode 100644
index 000000000000..f38850eb2eaf
--- /dev/null
+++ b/sound/soc/intel/boards/bytcr_wm5102.c
@@ -0,0 +1,465 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * bytcr_wm5102.c - ASoc Machine driver for Intel Baytrail platforms with a
+ * Wolfson Microelectronics WM5102 codec
+ *
+ * Copyright (C) 2020 Hans de Goede <hdegoede@redhat.com>
+ * Loosely based on bytcr_rt5640.c which is:
+ * Copyright (C) 2014-2020 Intel Corp
+ * Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
+ */
+
+#include <linux/acpi.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+#include "../../codecs/wm5102.h"
+#include "../atom/sst-atom-controls.h"
+
+#define MCLK_FREQ 25000000
+
+#define WM5102_MAX_SYSCLK_4K 49152000 /* max sysclk for 4K family */
+#define WM5102_MAX_SYSCLK_11025 45158400 /* max sysclk for 11.025K family */
+
+struct byt_wm5102_private {
+ struct clk *mclk;
+ struct gpio_desc *spkvdd_en_gpio;
+};
+
+static int byt_wm5102_spkvdd_power_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_card *card = w->dapm->card;
+ struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
+
+ gpiod_set_value_cansleep(priv->spkvdd_en_gpio,
+ !!SND_SOC_DAPM_EVENT_ON(event));
+
+ return 0;
+}
+
+static int byt_wm5102_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai, int rate)
+{
+ struct snd_soc_component *codec_component = codec_dai->component;
+ int sr_mult = ((rate % 4000) == 0) ?
+ (WM5102_MAX_SYSCLK_4K / rate) :
+ (WM5102_MAX_SYSCLK_11025 / rate);
+ int ret;
+
+ /* Reset FLL1 */
+ snd_soc_dai_set_pll(codec_dai, WM5102_FLL1_REFCLK, ARIZONA_FLL_SRC_NONE, 0, 0);
+ snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0);
+
+ /* Configure the FLL1 PLL before selecting it */
+ ret = snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_CLK_SRC_MCLK1,
+ MCLK_FREQ, rate * sr_mult);
+ if (ret) {
+ dev_err(codec_component->dev, "Error setting PLL: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_component_set_sysclk(codec_component, ARIZONA_CLK_SYSCLK,
+ ARIZONA_CLK_SRC_FLL1, rate * sr_mult,
+ SND_SOC_CLOCK_IN);
+ if (ret) {
+ dev_err(codec_component->dev, "Error setting SYSCLK: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, ARIZONA_CLK_SYSCLK,
+ rate * 512, SND_SOC_CLOCK_IN);
+ if (ret) {
+ dev_err(codec_component->dev, "Error setting clock: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int platform_clock_control(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ struct snd_soc_dapm_context *dapm = w->dapm;
+ struct snd_soc_card *card = dapm->card;
+ struct snd_soc_dai *codec_dai;
+ struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
+ int ret;
+
+ codec_dai = snd_soc_card_get_codec_dai(card, "wm5102-aif1");
+ if (!codec_dai) {
+ dev_err(card->dev, "Error codec DAI not found\n");
+ return -EIO;
+ }
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ ret = clk_prepare_enable(priv->mclk);
+ if (ret) {
+ dev_err(card->dev, "Error enabling MCLK: %d\n", ret);
+ return ret;
+ }
+ ret = byt_wm5102_prepare_and_enable_pll1(codec_dai, 48000);
+ if (ret) {
+ dev_err(card->dev, "Error setting codec sysclk: %d\n", ret);
+ return ret;
+ }
+ } else {
+ /*
+ * The WM5102 has a separate 32KHz clock for jack-detect
+ * so we can disable the PLL, followed by disabling the
+ * platform clock which is the source-clock for the PLL.
+ */
+ snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0);
+ clk_disable_unprepare(priv->mclk);
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget byt_wm5102_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Internal Mic", NULL),
+ SND_SOC_DAPM_SPK("Speaker", NULL),
+ SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
+ platform_clock_control, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("Speaker VDD", SND_SOC_NOPM, 0, 0,
+ byt_wm5102_spkvdd_power_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+};
+
+static const struct snd_soc_dapm_route byt_wm5102_audio_map[] = {
+ {"Headphone", NULL, "Platform Clock"},
+ {"Headset Mic", NULL, "Platform Clock"},
+ {"Internal Mic", NULL, "Platform Clock"},
+ {"Speaker", NULL, "Platform Clock"},
+
+ {"Speaker", NULL, "SPKOUTLP"},
+ {"Speaker", NULL, "SPKOUTLN"},
+ {"Speaker", NULL, "SPKOUTRP"},
+ {"Speaker", NULL, "SPKOUTRN"},
+ {"Speaker", NULL, "Speaker VDD"},
+
+ {"Headphone", NULL, "HPOUT1L"},
+ {"Headphone", NULL, "HPOUT1R"},
+
+ {"Internal Mic", NULL, "MICBIAS3"},
+ {"IN3L", NULL, "Internal Mic"},
+
+ /*
+ * The Headset Mix uses MICBIAS1 or 2 depending on if a CTIA/OMTP Headset
+ * is connected, as the MICBIAS is applied after the CTIA/OMTP cross-switch.
+ */
+ {"Headset Mic", NULL, "MICBIAS1"},
+ {"Headset Mic", NULL, "MICBIAS2"},
+ {"IN1L", NULL, "Headset Mic"},
+
+ {"AIF1 Playback", NULL, "ssp0 Tx"},
+ {"ssp0 Tx", NULL, "modem_out"},
+
+ {"modem_in", NULL, "ssp0 Rx"},
+ {"ssp0 Rx", NULL, "AIF1 Capture"},
+};
+
+static const struct snd_kcontrol_new byt_wm5102_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Headphone"),
+ SOC_DAPM_PIN_SWITCH("Headset Mic"),
+ SOC_DAPM_PIN_SWITCH("Internal Mic"),
+ SOC_DAPM_PIN_SWITCH("Speaker"),
+};
+
+static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime)
+{
+ struct snd_soc_card *card = runtime->card;
+ struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
+ int ret;
+
+ card->dapm.idle_bias_off = true;
+
+ ret = snd_soc_add_card_controls(card, byt_wm5102_controls,
+ ARRAY_SIZE(byt_wm5102_controls));
+ if (ret) {
+ dev_err(card->dev, "Error adding card controls: %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * The firmware might enable the clock at boot (this information
+ * may or may not be reflected in the enable clock register).
+ * To change the rate we must disable the clock first to cover these
+ * cases. Due to common clock framework restrictions that do not allow
+ * to disable a clock that has not been enabled, we need to enable
+ * the clock first.
+ */
+ ret = clk_prepare_enable(priv->mclk);
+ if (!ret)
+ clk_disable_unprepare(priv->mclk);
+
+ ret = clk_set_rate(priv->mclk, MCLK_FREQ);
+ if (ret) {
+ dev_err(card->dev, "Error setting MCLK rate: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_pcm_stream byt_wm5102_dai_params = {
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+};
+
+static int byt_wm5102_codec_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ 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);
+ int ret;
+
+ /* The DSP will covert the FE rate to 48k, stereo */
+ rate->min = 48000;
+ rate->max = 48000;
+ channels->min = 2;
+ channels->max = 2;
+
+ /* set SSP0 to 16-bit */
+ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
+
+ /*
+ * Default mode for SSP configuration is TDM 4 slot, override config
+ * with explicit setting to I2S 2ch 16-bit. The word length is set with
+ * dai_set_tdm_slot() since there is no other API exposed
+ */
+ ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS);
+ if (ret) {
+ dev_err(rtd->dev, "Error setting format to I2S: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 16);
+ if (ret) {
+ dev_err(rtd->dev, "Error setting I2S config: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int byt_wm5102_aif1_startup(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_hw_constraint_single(substream->runtime,
+ SNDRV_PCM_HW_PARAM_RATE, 48000);
+}
+
+static const struct snd_soc_ops byt_wm5102_aif1_ops = {
+ .startup = byt_wm5102_aif1_startup,
+};
+
+SND_SOC_DAILINK_DEF(dummy,
+ DAILINK_COMP_ARRAY(COMP_DUMMY()));
+
+SND_SOC_DAILINK_DEF(media,
+ DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
+
+SND_SOC_DAILINK_DEF(deepbuffer,
+ DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
+
+SND_SOC_DAILINK_DEF(ssp0_port,
+ DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port")));
+
+SND_SOC_DAILINK_DEF(ssp0_codec,
+ DAILINK_COMP_ARRAY(COMP_CODEC(
+ /*
+ * Note there is no need to overwrite the codec-name as is done in
+ * other bytcr machine drivers, because the codec is a MFD child-dev.
+ */
+ "wm5102-codec",
+ "wm5102-aif1")));
+
+SND_SOC_DAILINK_DEF(platform,
+ DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
+
+static struct snd_soc_dai_link byt_wm5102_dais[] = {
+ [MERR_DPCM_AUDIO] = {
+ .name = "Baytrail Audio Port",
+ .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),
+
+ },
+ [MERR_DPCM_DEEP_BUFFER] = {
+ .name = "Deep-Buffer Audio Port",
+ .stream_name = "Deep-Buffer Audio",
+ .nonatomic = true,
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .ops = &byt_wm5102_aif1_ops,
+ SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
+ },
+ /* back ends */
+ {
+ /*
+ * This must be named SSP2-Codec even though this machine driver
+ * always uses SSP0. Most machine drivers support both and dynamically
+ * update the dailink to point to SSP0 or SSP2, while keeping the name
+ * as "SSP2-Codec". The SOF tplg files hardcode the "SSP2-Codec" even
+ * in the byt-foo-ssp0.tplg versions because the other machine-drivers
+ * use "SSP2-Codec" even when SSP0 is used.
+ */
+ .name = "SSP2-Codec",
+ .id = 0,
+ .no_pcm = 1,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBS_CFS,
+ .be_hw_params_fixup = byt_wm5102_codec_fixup,
+ .nonatomic = true,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .init = byt_wm5102_init,
+ SND_SOC_DAILINK_REG(ssp0_port, ssp0_codec, platform),
+ },
+};
+
+/* use space before codec name to simplify card ID, and simplify driver name */
+#define SOF_CARD_NAME "bytcht wm5102" /* card name will be 'sof-bytcht wm5102' */
+#define SOF_DRIVER_NAME "SOF"
+
+#define CARD_NAME "bytcr-wm5102"
+#define DRIVER_NAME NULL /* card name will be used for driver name */
+
+/* SoC card */
+static struct snd_soc_card byt_wm5102_card = {
+ .owner = THIS_MODULE,
+ .dai_link = byt_wm5102_dais,
+ .num_links = ARRAY_SIZE(byt_wm5102_dais),
+ .dapm_widgets = byt_wm5102_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(byt_wm5102_widgets),
+ .dapm_routes = byt_wm5102_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(byt_wm5102_audio_map),
+ .fully_routed = true,
+};
+
+static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
+{
+ char codec_name[SND_ACPI_I2C_ID_LEN];
+ struct device *dev = &pdev->dev;
+ struct byt_wm5102_private *priv;
+ struct snd_soc_acpi_mach *mach;
+ const char *platform_name;
+ struct acpi_device *adev;
+ struct device *codec_dev;
+ bool sof_parent;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_ATOMIC);
+ if (!priv)
+ return -ENOMEM;
+
+ /* Get MCLK */
+ priv->mclk = devm_clk_get(dev, "pmc_plt_clk_3");
+ if (IS_ERR(priv->mclk))
+ return dev_err_probe(dev, PTR_ERR(priv->mclk), "getting pmc_plt_clk_3\n");
+
+ /*
+ * Get speaker VDD enable GPIO:
+ * 1. Get codec-device-name
+ * 2. Get codec-device
+ * 3. Get GPIO from codec-device
+ */
+ mach = dev->platform_data;
+ adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
+ if (!adev) {
+ dev_err(dev, "Error cannot find acpi-dev for codec\n");
+ return -ENOENT;
+ }
+ snprintf(codec_name, sizeof(codec_name), "spi-%s", acpi_dev_name(adev));
+ put_device(&adev->dev);
+
+ codec_dev = bus_find_device_by_name(&spi_bus_type, NULL, codec_name);
+ if (!codec_dev)
+ return -EPROBE_DEFER;
+
+ /* Note no devm_ here since we call gpiod_get on codec_dev rather then dev */
+ priv->spkvdd_en_gpio = gpiod_get(codec_dev, "wlf,spkvdd-ena", GPIOD_OUT_LOW);
+ put_device(codec_dev);
+
+ if (IS_ERR(priv->spkvdd_en_gpio))
+ return dev_err_probe(dev, PTR_ERR(priv->spkvdd_en_gpio), "getting spkvdd-GPIO\n");
+
+ /* override platform name, if required */
+ byt_wm5102_card.dev = dev;
+ platform_name = mach->mach_params.platform;
+ ret = snd_soc_fixup_dai_links_platform_name(&byt_wm5102_card, platform_name);
+ if (ret)
+ goto out_put_gpio;
+
+ /* set card and driver name and pm-ops */
+ sof_parent = snd_soc_acpi_sof_parent(dev);
+ if (sof_parent) {
+ byt_wm5102_card.name = SOF_CARD_NAME;
+ byt_wm5102_card.driver_name = SOF_DRIVER_NAME;
+ dev->driver->pm = &snd_soc_pm_ops;
+ } else {
+ byt_wm5102_card.name = CARD_NAME;
+ byt_wm5102_card.driver_name = DRIVER_NAME;
+ }
+
+ snd_soc_card_set_drvdata(&byt_wm5102_card, priv);
+ ret = devm_snd_soc_register_card(dev, &byt_wm5102_card);
+ if (ret) {
+ dev_err_probe(dev, ret, "registering card\n");
+ goto out_put_gpio;
+ }
+
+ platform_set_drvdata(pdev, &byt_wm5102_card);
+ return 0;
+
+out_put_gpio:
+ gpiod_put(priv->spkvdd_en_gpio);
+ return ret;
+}
+
+static int snd_byt_wm5102_mc_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
+
+ gpiod_put(priv->spkvdd_en_gpio);
+ return 0;
+}
+
+static struct platform_driver snd_byt_wm5102_mc_driver = {
+ .driver = {
+ .name = "bytcr_wm5102",
+ },
+ .probe = snd_byt_wm5102_mc_probe,
+ .remove = snd_byt_wm5102_mc_remove,
+};
+
+module_platform_driver(snd_byt_wm5102_mc_driver);
+
+MODULE_DESCRIPTION("ASoC Baytrail with WM5102 codec machine driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:bytcr_wm5102");
diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c
index fd5e25ca05f7..da5a5cbc8759 100644
--- a/sound/soc/intel/boards/cht_bsw_nau8824.c
+++ b/sound/soc/intel/boards/cht_bsw_nau8824.c
@@ -100,13 +100,6 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
struct snd_soc_component *component = codec_dai->component;
int ret, jack_type;
- /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */
- ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xf, 0x1, 4, 24);
- if (ret < 0) {
- dev_err(runtime->dev, "can't set codec TDM slot %d\n", ret);
- return ret;
- }
-
/* NAU88L24 supports 4 butons headset detection
* KEY_PLAYPAUSE
* KEY_VOICECOMMAND
@@ -141,6 +134,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
SNDRV_PCM_HW_PARAM_CHANNELS);
struct snd_mask *fmt =
hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ int ret;
/* The DSP will covert the FE rate to 48k, stereo, 24bits */
rate->min = rate->max = 48000;
@@ -150,6 +144,13 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
snd_mask_none(fmt);
params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+ /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */
+ ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0xf, 0x1, 4, 24);
+ if (ret < 0) {
+ dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret);
+ return ret;
+ }
+
return 0;
}
diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c
index c2a9757181fe..437d20562753 100644
--- a/sound/soc/intel/boards/sof_maxim_common.c
+++ b/sound/soc/intel/boards/sof_maxim_common.c
@@ -63,6 +63,7 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai;
+ struct snd_soc_dai *cpu_dai;
int j;
int ret = 0;
@@ -70,10 +71,10 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd)
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
return 0;
+ cpu_dai = asoc_rtd_to_cpu(rtd, 0);
for_each_rtd_codec_dais(rtd, j, codec_dai) {
- struct snd_soc_component *component = codec_dai->component;
struct snd_soc_dapm_context *dapm =
- snd_soc_component_get_dapm(component);
+ snd_soc_component_get_dapm(cpu_dai->component);
char pin_name[MAX_98373_PIN_NAME];
snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk",
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c
index 8b1ca2da9bb9..55505e207bc0 100644
--- a/sound/soc/intel/boards/sof_rt5682.c
+++ b/sound/soc/intel/boards/sof_rt5682.c
@@ -323,13 +323,6 @@ static int sof_rt1015_hw_params(struct snd_pcm_substream *substream,
fs = 64;
for_each_rtd_codec_dais(rtd, i, codec_dai) {
- /* Set tdm/i2s1 master bclk ratio */
- ret = snd_soc_dai_set_bclk_ratio(codec_dai, fs);
- if (ret < 0) {
- dev_err(card->dev, "failed to set bclk ratio\n");
- return ret;
- }
-
ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
params_rate(params) * fs,
params_rate(params) * 256);
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index 6d0d6ef711e0..8adce6417b02 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -48,34 +48,14 @@ static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
}
static const struct dmi_system_id sof_sdw_quirk_table[] = {
+ /* CometLake devices */
{
.callback = sof_sdw_quirk_cb,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
- },
- .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
- SOF_RT715_DAI_ID_FIX |
- SOF_SDW_FOUR_SPK),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
- },
- .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
- SOF_RT715_DAI_ID_FIX),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
},
- .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
- SOF_RT715_DAI_ID_FIX |
- SOF_SDW_FOUR_SPK),
+ .driver_data = (void *)SOF_SDW_PCH_DMIC,
},
{
.callback = sof_sdw_quirk_cb,
@@ -106,7 +86,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
SOF_RT715_DAI_ID_FIX |
SOF_SDW_FOUR_SPK),
},
- {
+ {
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
@@ -116,6 +96,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
SOF_RT715_DAI_ID_FIX |
SOF_SDW_FOUR_SPK),
},
+ /* IceLake devices */
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
+ },
+ .driver_data = (void *)SOF_SDW_PCH_DMIC,
+ },
+ /* TigerLake devices */
{
.callback = sof_sdw_quirk_cb,
.matches = {
@@ -123,25 +113,31 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME,
"Tiger Lake Client Platform"),
},
- .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 |
- SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
- SOF_SSP_PORT(SOF_I2S_SSP2)),
+ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+ SOF_RT711_JD_SRC_JD1 |
+ SOF_SDW_PCH_DMIC |
+ SOF_SSP_PORT(SOF_I2S_SSP2)),
},
{
.callback = sof_sdw_quirk_cb,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
},
- .driver_data = (void *)SOF_SDW_PCH_DMIC,
+ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+ SOF_RT711_JD_SRC_JD2 |
+ SOF_RT715_DAI_ID_FIX),
},
{
.callback = sof_sdw_quirk_cb,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
},
- .driver_data = (void *)SOF_SDW_PCH_DMIC,
+ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+ SOF_RT711_JD_SRC_JD2 |
+ SOF_RT715_DAI_ID_FIX |
+ SOF_SDW_FOUR_SPK),
},
{
.callback = sof_sdw_quirk_cb,
@@ -149,7 +145,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"),
},
- .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
+ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+ SOF_SDW_PCH_DMIC |
SOF_SDW_FOUR_SPK),
},
{
@@ -158,10 +155,38 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"),
},
- .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
+ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+ SOF_SDW_PCH_DMIC |
+ SOF_SDW_FOUR_SPK),
+ },
+ {
+ /*
+ * this entry covers multiple HP SKUs. The family name
+ * does not seem robust enough, so we use a partial
+ * match that ignores the product name suffix
+ * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx)
+ */
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible"),
+ },
+ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+ SOF_SDW_PCH_DMIC |
+ SOF_RT711_JD_SRC_JD2),
+ },
+ /* TigerLake-SDCA devices */
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
+ },
+ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+ SOF_RT711_JD_SRC_JD2 |
+ SOF_RT715_DAI_ID_FIX |
SOF_SDW_FOUR_SPK),
},
-
{}
};
@@ -451,15 +476,14 @@ static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links,
return 0;
}
-static void init_dai_link(struct snd_soc_dai_link *dai_links, int be_id,
- char *name, int playback, int capture,
- struct snd_soc_dai_link_component *cpus,
- int cpus_num,
- struct snd_soc_dai_link_component *codecs,
- int codecs_num,
+static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
+ int be_id, char *name, int playback, int capture,
+ struct snd_soc_dai_link_component *cpus, int cpus_num,
+ struct snd_soc_dai_link_component *codecs, int codecs_num,
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->platforms = platform_component;
@@ -797,7 +821,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index,
playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
- init_dai_link(dai_links + *be_index, *be_index, name,
+ init_dai_link(dev, dai_links + *be_index, *be_index, name,
playback, capture,
cpus + *cpu_id, cpu_dai_num,
codecs, codec_num,
@@ -930,7 +954,7 @@ static int sof_card_dai_links_create(struct device *dev,
ctx->idisp_codec = true;
/* enable dmic01 & dmic16k */
- dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC) ? 2 : 0;
+ dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ? 2 : 0;
comp_num += dmic_num;
dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num,
@@ -1036,7 +1060,7 @@ SSP:
playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK];
capture = info->direction[SNDRV_PCM_STREAM_CAPTURE];
- init_dai_link(links + link_id, be_id, name,
+ init_dai_link(dev, links + link_id, be_id, name,
playback, capture,
cpus + cpu_id, 1,
ssp_components, 1,
@@ -1053,7 +1077,7 @@ DMIC:
/* dmic */
if (dmic_num > 0) {
cpus[cpu_id].dai_name = "DMIC01 Pin";
- init_dai_link(links + link_id, be_id, "dmic01",
+ init_dai_link(dev, links + link_id, be_id, "dmic01",
0, 1, // DMIC only supports capture
cpus + cpu_id, 1,
dmic_component, 1,
@@ -1061,7 +1085,7 @@ DMIC:
INC_ID(be_id, cpu_id, link_id);
cpus[cpu_id].dai_name = "DMIC16k Pin";
- init_dai_link(links + link_id, be_id, "dmic16k",
+ init_dai_link(dev, links + link_id, be_id, "dmic16k",
0, 1, // DMIC only supports capture
cpus + cpu_id, 1,
dmic_component, 1,
@@ -1104,7 +1128,7 @@ DMIC:
return -ENOMEM;
cpus[cpu_id].dai_name = cpu_name;
- init_dai_link(links + link_id, be_id, name,
+ init_dai_link(dev, links + link_id, be_id, name,
1, 0, // HDMI only supports playback
cpus + cpu_id, 1,
idisp_components + i, 1,
@@ -1197,6 +1221,15 @@ static int mc_probe(struct platform_device *pdev)
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;
+ }
+
card->long_name = sdw_card_long_name;
/* Register the card */
diff --git a/sound/soc/intel/catpt/pcm.c b/sound/soc/intel/catpt/pcm.c
index e5d54bb1c42a..ebb27daeb1c7 100644
--- a/sound/soc/intel/catpt/pcm.c
+++ b/sound/soc/intel/catpt/pcm.c
@@ -331,7 +331,7 @@ static int catpt_dai_apply_usettings(struct snd_soc_dai *dai,
{
struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
struct snd_soc_component *component = dai->component;
- struct snd_kcontrol *pos, *kctl = NULL;
+ struct snd_kcontrol *pos;
const char *name;
int ret;
u32 id = stream->info.stream_hw_id;
@@ -352,21 +352,19 @@ static int catpt_dai_apply_usettings(struct snd_soc_dai *dai,
break;
default:
return 0;
- };
+ }
list_for_each_entry(pos, &component->card->snd_card->controls, list) {
if (pos->private_data == component &&
- !strncmp(name, pos->id.name, sizeof(pos->id.name))) {
- kctl = pos;
+ !strncmp(name, pos->id.name, sizeof(pos->id.name)))
break;
- }
}
- if (!kctl)
+ if (list_entry_is_head(pos, &component->card->snd_card->controls, list))
return -ENOENT;
if (stream->template->type != CATPT_STRM_TYPE_LOOPBACK)
- return catpt_set_dspvol(cdev, id, (long *)kctl->private_value);
- ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)kctl->private_value);
+ return catpt_set_dspvol(cdev, id, (long *)pos->private_value);
+ ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)pos->private_value);
if (ret)
return CATPT_IPC_ERROR(ret);
return 0;
diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
index 06b233d63b73..0aca340ebc25 100644
--- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
@@ -44,7 +44,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = {
.link_mask = 0x1, /* link0 required */
.links = adl_rvp,
.drv_name = "sof_sdw",
- .sof_fw_filename = "sof-adl.ri",
.sof_tplg_filename = "sof-adl-rt711.tplg",
},
{},
diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
index 32f77e29c2ff..398cc771c835 100644
--- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
@@ -85,6 +85,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[] = {
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_bxt_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c
index c348607b49a5..d1febbb53b70 100644
--- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c
@@ -155,6 +155,22 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_baytrail_machines[] = {
.sof_tplg_filename = "sof-byt-rt5651.tplg",
},
{
+ .id = "WM510204",
+ .drv_name = "bytcr_wm5102",
+ .fw_filename = "intel/fw_sst_0f28.bin",
+ .board = "bytcr_wm5102",
+ .sof_fw_filename = "sof-byt.ri",
+ .sof_tplg_filename = "sof-byt-wm5102.tplg",
+ },
+ {
+ .id = "WM510205",
+ .drv_name = "bytcr_wm5102",
+ .fw_filename = "intel/fw_sst_0f28.bin",
+ .board = "bytcr_wm5102",
+ .sof_fw_filename = "sof-byt.ri",
+ .sof_tplg_filename = "sof-byt-wm5102.tplg",
+ },
+ {
.id = "DLGS7212",
.drv_name = "bytcht_da7213",
.fw_filename = "intel/fw_sst_0f28.bin",
@@ -233,6 +249,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_baytrail_machines[] = {
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_baytrail_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-cfl-match.c b/sound/soc/intel/common/soc-acpi-intel-cfl-match.c
index 27b4b73d94d4..1733dfb23e79 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cfl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cfl-match.c
@@ -18,6 +18,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[] = {
{}
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cfl_sdw_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
index 2752dc955733..227424236fd5 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
@@ -196,6 +196,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cherrytrail_machines[] = {
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cherrytrail_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
index adddc91918df..2161b3b85b4a 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
@@ -309,6 +309,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_sdw_machines[] = {
{}
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_sdw_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
index b80f032a8b76..ec77a57a07ba 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
@@ -63,6 +63,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[] = {
{}
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cnl_sdw_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c
index badafc1d54d2..6222708a98e7 100644
--- a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * soc-apci-intel-ehl-match.c - tables and support for EHL ACPI enumeration.
+ * soc-acpi-intel-ehl-match.c - tables and support for EHL ACPI enumeration.
*
* Copyright (c) 2019, Intel Corporation.
*
@@ -20,6 +20,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[] = {
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_ehl_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
index 26cb3b16cdd3..6ceaab19ccb6 100644
--- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
@@ -43,6 +43,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[] = {
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_glk_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
index 35958553652e..fe343a95b5ff 100644
--- a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
@@ -53,6 +53,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_broadwell_machines[] = {
{}
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_broadwell_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c b/sound/soc/intel/common/soc-acpi-intel-icl-match.c
index 9a529a785288..d38ff7d187c4 100644
--- a/sound/soc/intel/common/soc-acpi-intel-icl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-icl-match.c
@@ -185,6 +185,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_sdw_machines[] = {
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_icl_sdw_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
index 34f5fcad5701..52238db0bcb5 100644
--- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
@@ -63,6 +63,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
index a4fbe6707ca7..47dadc9d5d2a 100644
--- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
@@ -128,6 +128,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = {
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_kbl_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-skl-match.c b/sound/soc/intel/common/soc-acpi-intel-skl-match.c
index 26f9ce146523..961df8d6b5e4 100644
--- a/sound/soc/intel/common/soc-acpi-intel-skl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-skl-match.c
@@ -42,6 +42,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_skl_machines[] = {
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_skl_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
index 98196e9fad62..40f31c8a3aba 100644
--- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * soc-apci-intel-tgl-match.c - tables and support for ICL ACPI enumeration.
+ * soc-acpi-intel-tgl-match.c - tables and support for TGL ACPI enumeration.
*
* Copyright (c) 2019, Intel Corporation.
*
@@ -205,6 +205,20 @@ static const struct snd_soc_acpi_link_adr tgl_rvp[] = {
{}
};
+static const struct snd_soc_acpi_link_adr tgl_hp[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt711_0_adr),
+ .adr_d = rt711_0_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt1308_1_single_adr),
+ .adr_d = rt1308_1_single_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_link_adr tgl_chromebook_base[] = {
{
.mask = BIT(0),
@@ -358,14 +372,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
.link_mask = 0x7,
.links = tgl_sdw_rt711_link1_rt1308_link2_rt715_link0,
.drv_name = "sof_sdw",
- .sof_fw_filename = "sof-tgl.ri",
.sof_tplg_filename = "sof-tgl-rt715-rt711-rt1308-mono.tplg",
},
{
.link_mask = 0xF, /* 4 active links required */
.links = tgl_3_in_1_default,
.drv_name = "sof_sdw",
- .sof_fw_filename = "sof-tgl.ri",
.sof_tplg_filename = "sof-tgl-rt711-rt1308-rt715.tplg",
},
{
@@ -377,40 +389,38 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
.link_mask = 0xF,
.links = tgl_3_in_1_mono_amp,
.drv_name = "sof_sdw",
- .sof_fw_filename = "sof-tgl.ri",
.sof_tplg_filename = "sof-tgl-rt711-rt1308-mono-rt715.tplg",
},
{
.link_mask = 0xF, /* 4 active links required */
.links = tgl_3_in_1_sdca,
.drv_name = "sof_sdw",
- .sof_fw_filename = "sof-tgl.ri",
.sof_tplg_filename = "sof-tgl-rt711-rt1316-rt714.tplg",
},
{
+ .link_mask = 0x3, /* rt711 on link 0 and 1 rt1308 on link 1 */
+ .links = tgl_hp,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-tgl-rt711-rt1308.tplg",
+ },
+ {
.link_mask = 0x3, /* rt711 on link 0 and 2 rt1308s on link 1 */
.links = tgl_rvp,
.drv_name = "sof_sdw",
- .sof_fw_filename = "sof-tgl.ri",
.sof_tplg_filename = "sof-tgl-rt711-rt1308.tplg",
},
{
.link_mask = 0x3, /* rt5682 on link0 & 2xmax98373 on link 1 */
.links = tgl_chromebook_base,
.drv_name = "sof_sdw",
- .sof_fw_filename = "sof-tgl.ri",
.sof_tplg_filename = "sof-tgl-sdw-max98373-rt5682.tplg",
},
{
.link_mask = 0x1, /* this will only enable rt5682 for now */
.links = tgl_chromebook_base,
.drv_name = "sof_sdw",
- .sof_fw_filename = "sof-tgl.ri",
.sof_tplg_filename = "sof-tgl-rt5682.tplg",
},
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_sdw_machines);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Intel Common ACPI Match module");
diff --git a/sound/soc/intel/common/soc-intel-quirks.h b/sound/soc/intel/common/soc-intel-quirks.h
index b07df3059926..a93987ab7f4d 100644
--- a/sound/soc/intel/common/soc-intel-quirks.h
+++ b/sound/soc/intel/common/soc-intel-quirks.h
@@ -11,6 +11,7 @@
#if IS_ENABLED(CONFIG_X86)
+#include <linux/dmi.h>
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
#include <asm/iosf_mbi.h>
@@ -38,12 +39,36 @@ SOC_INTEL_IS_CPU(cml, KABYLAKE_L);
static inline bool soc_intel_is_byt_cr(struct platform_device *pdev)
{
+ /*
+ * List of systems which:
+ * 1. Use a non CR version of the Bay Trail SoC
+ * 2. Contain at least 6 interrupt resources so that the
+ * platform_get_resource(pdev, IORESOURCE_IRQ, 5) check below
+ * succeeds
+ * 3. Despite 1. and 2. still have their IPC IRQ at index 0 rather then 5
+ *
+ * This needs to be here so that it can be shared between the SST and
+ * SOF drivers. We rely on the compiler to optimize this out in files
+ * where soc_intel_is_byt_cr is not used.
+ */
+ static const struct dmi_system_id force_bytcr_table[] = {
+ { /* Lenovo Yoga Tablet 2 series */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_FAMILY, "YOGATablet2"),
+ },
+ },
+ {}
+ };
struct device *dev = &pdev->dev;
int status = 0;
if (!soc_intel_is_byt())
return false;
+ if (dmi_check_system(force_bytcr_table))
+ return true;
+
if (iosf_mbi_available()) {
u32 bios_status;
diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c
index 1c3748f33136..0fd1e8f62c89 100644
--- a/sound/soc/intel/keembay/kmb_platform.c
+++ b/sound/soc/intel/keembay/kmb_platform.c
@@ -5,11 +5,14 @@
// Intel KeemBay Platform driver.
//
+#include <linux/bitrev.h>
#include <linux/clk.h>
+#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <sound/dmaengine_pcm.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -37,7 +40,8 @@ static const struct snd_pcm_hardware kmb_pcm_hardware = {
.rate_max = 48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_S32_LE,
+ SNDRV_PCM_FMTBIT_S32_LE |
+ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
.channels_min = 2,
.channels_max = 2,
.buffer_bytes_max = BUFFER_BYTES_MAX,
@@ -48,6 +52,50 @@ static const struct snd_pcm_hardware kmb_pcm_hardware = {
.fifo_size = 16,
};
+/*
+ * Convert to ADV7511 HDMI hardware format.
+ * ADV7511 HDMI chip need parity bit replaced by block start bit and
+ * with the preamble bits left out.
+ * ALSA IEC958 subframe format:
+ * bit 0-3 = preamble (0x8 = block start)
+ * 4-7 = AUX (=0)
+ * 8-27 = audio data (without AUX if 24bit sample)
+ * 28 = validity
+ * 29 = user data
+ * 30 = channel status
+ * 31 = parity
+ *
+ * ADV7511 IEC958 subframe format:
+ * bit 0-23 = audio data
+ * 24 = validity
+ * 25 = user data
+ * 26 = channel status
+ * 27 = block start
+ * 28-31 = 0
+ * MSB to LSB bit reverse by software as hardware not supporting it.
+ */
+static void hdmi_reformat_iec958(struct snd_pcm_runtime *runtime,
+ struct kmb_i2s_info *kmb_i2s,
+ unsigned int tx_ptr)
+{
+ u32(*buf)[2] = (void *)runtime->dma_area;
+ unsigned long temp;
+ u32 i, j, sample;
+
+ for (i = 0; i < kmb_i2s->fifo_th; i++) {
+ j = 0;
+ do {
+ temp = buf[tx_ptr][j];
+ /* Replace parity with block start*/
+ assign_bit(31, &temp, (BIT(3) & temp));
+ sample = bitrev32(temp);
+ buf[tx_ptr][j] = sample << 4;
+ j++;
+ } while (j < 2);
+ tx_ptr++;
+ }
+}
+
static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s,
struct snd_pcm_runtime *runtime,
unsigned int tx_ptr, bool *period_elapsed)
@@ -63,6 +111,8 @@ static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s,
writel(((u16(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0));
writel(((u16(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0));
} else {
+ if (kmb_i2s->iec958_fmt)
+ hdmi_reformat_iec958(runtime, kmb_i2s, tx_ptr);
writel(((u32(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0));
writel(((u32(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0));
}
@@ -233,6 +283,7 @@ static int kmb_pcm_trigger(struct snd_soc_component *component,
kmb_i2s->tx_substream = NULL;
else
kmb_i2s->rx_substream = NULL;
+ kmb_i2s->iec958_fmt = false;
break;
default:
return -EINVAL;
@@ -343,6 +394,53 @@ static const struct snd_soc_component_driver kmb_component = {
.pointer = kmb_pcm_pointer,
};
+static const struct snd_soc_component_driver kmb_component_dma = {
+ .name = "kmb",
+};
+
+static int kmb_probe(struct snd_soc_dai *cpu_dai)
+{
+ struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
+
+ if (kmb_i2s->use_pio)
+ return 0;
+
+ snd_soc_dai_init_dma_data(cpu_dai, &kmb_i2s->play_dma_data,
+ &kmb_i2s->capture_dma_data);
+
+ return 0;
+}
+
+static inline void kmb_i2s_enable_dma(struct kmb_i2s_info *kmb_i2s, u32 stream)
+{
+ u32 dma_reg;
+
+ dma_reg = readl(kmb_i2s->i2s_base + I2S_DMACR);
+ /* Enable DMA handshake for stream */
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dma_reg |= I2S_DMAEN_TXBLOCK;
+ else
+ dma_reg |= I2S_DMAEN_RXBLOCK;
+
+ writel(dma_reg, kmb_i2s->i2s_base + I2S_DMACR);
+}
+
+static inline void kmb_i2s_disable_dma(struct kmb_i2s_info *kmb_i2s, u32 stream)
+{
+ u32 dma_reg;
+
+ dma_reg = readl(kmb_i2s->i2s_base + I2S_DMACR);
+ /* Disable DMA handshake for stream */
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ dma_reg &= ~I2S_DMAEN_TXBLOCK;
+ writel(1, kmb_i2s->i2s_base + I2S_RTXDMA);
+ } else {
+ dma_reg &= ~I2S_DMAEN_RXBLOCK;
+ writel(1, kmb_i2s->i2s_base + I2S_RRXDMA);
+ }
+ writel(dma_reg, kmb_i2s->i2s_base + I2S_DMACR);
+}
+
static void kmb_i2s_start(struct kmb_i2s_info *kmb_i2s,
struct snd_pcm_substream *substream)
{
@@ -356,7 +454,11 @@ static void kmb_i2s_start(struct kmb_i2s_info *kmb_i2s,
else
writel(1, kmb_i2s->i2s_base + IRER);
- kmb_i2s_irq_trigger(kmb_i2s, substream->stream, config->chan_nr, true);
+ if (kmb_i2s->use_pio)
+ kmb_i2s_irq_trigger(kmb_i2s, substream->stream,
+ config->chan_nr, true);
+ else
+ kmb_i2s_enable_dma(kmb_i2s, substream->stream);
if (kmb_i2s->clock_provider)
writel(1, kmb_i2s->i2s_base + CER);
@@ -434,7 +536,8 @@ static int kmb_dai_trigger(struct snd_pcm_substream *substream,
break;
case SNDRV_PCM_TRIGGER_STOP:
kmb_i2s->active--;
- kmb_i2s_stop(kmb_i2s, substream);
+ if (kmb_i2s->use_pio)
+ kmb_i2s_stop(kmb_i2s, substream);
break;
default:
return -EINVAL;
@@ -485,16 +588,25 @@ static int kmb_dai_hw_params(struct snd_pcm_substream *substream,
config->data_width = 16;
kmb_i2s->ccr = 0x00;
kmb_i2s->xfer_resolution = 0x02;
+ kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
case SNDRV_PCM_FORMAT_S24_LE:
config->data_width = 32;
kmb_i2s->ccr = 0x14;
kmb_i2s->xfer_resolution = 0x05;
+ kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
+ case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
+ kmb_i2s->iec958_fmt = true;
+ fallthrough;
case SNDRV_PCM_FORMAT_S32_LE:
config->data_width = 32;
kmb_i2s->ccr = 0x10;
kmb_i2s->xfer_resolution = 0x05;
+ kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
default:
dev_err(kmb_i2s->dev, "kmb: unsupported PCM fmt");
@@ -572,13 +684,78 @@ static int kmb_dai_prepare(struct snd_pcm_substream *substream,
return 0;
}
+static int kmb_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
+ struct snd_dmaengine_dai_dma_data *dma_data;
+
+ if (kmb_i2s->use_pio)
+ return 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dma_data = &kmb_i2s->play_dma_data;
+ else
+ dma_data = &kmb_i2s->capture_dma_data;
+
+ snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
+
+ return 0;
+}
+
+static int kmb_dai_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
+ /* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */
+ if (kmb_i2s->use_pio)
+ kmb_i2s_clear_irqs(kmb_i2s, substream->stream);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ writel(0, kmb_i2s->i2s_base + ITER);
+ else
+ writel(0, kmb_i2s->i2s_base + IRER);
+
+ if (kmb_i2s->use_pio)
+ kmb_i2s_irq_trigger(kmb_i2s, substream->stream, 8, false);
+ else
+ kmb_i2s_disable_dma(kmb_i2s, substream->stream);
+
+ if (!kmb_i2s->active) {
+ writel(0, kmb_i2s->i2s_base + CER);
+ writel(0, kmb_i2s->i2s_base + IER);
+ }
+
+ return 0;
+}
+
static struct snd_soc_dai_ops kmb_dai_ops = {
+ .startup = kmb_dai_startup,
.trigger = kmb_dai_trigger,
.hw_params = kmb_dai_hw_params,
+ .hw_free = kmb_dai_hw_free,
.prepare = kmb_dai_prepare,
.set_fmt = kmb_set_dai_fmt,
};
+static struct snd_soc_dai_driver intel_kmb_hdmi_dai[] = {
+ {
+ .name = "intel_kmb_hdmi_i2s",
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE),
+ },
+ .ops = &kmb_dai_ops,
+ .probe = kmb_probe,
+ },
+};
+
static struct snd_soc_dai_driver intel_kmb_i2s_dai[] = {
{
.name = "intel_kmb_i2s",
@@ -607,6 +784,7 @@ static struct snd_soc_dai_driver intel_kmb_i2s_dai[] = {
SNDRV_PCM_FMTBIT_S16_LE),
},
.ops = &kmb_dai_ops,
+ .probe = kmb_probe,
},
};
@@ -626,21 +804,25 @@ static struct snd_soc_dai_driver intel_kmb_tdm_dai[] = {
SNDRV_PCM_FMTBIT_S16_LE),
},
.ops = &kmb_dai_ops,
+ .probe = kmb_probe,
},
};
static const struct of_device_id kmb_plat_of_match[] = {
{ .compatible = "intel,keembay-i2s", .data = &intel_kmb_i2s_dai},
+ { .compatible = "intel,keembay-hdmi-i2s", .data = &intel_kmb_hdmi_dai},
{ .compatible = "intel,keembay-tdm", .data = &intel_kmb_tdm_dai},
{}
};
static int kmb_plat_dai_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
struct snd_soc_dai_driver *kmb_i2s_dai;
const struct of_device_id *match;
struct device *dev = &pdev->dev;
struct kmb_i2s_info *kmb_i2s;
+ struct resource *res;
int ret, irq;
u32 comp1_reg;
@@ -682,7 +864,7 @@ static int kmb_plat_dai_probe(struct platform_device *pdev)
return PTR_ERR(kmb_i2s->clk_i2s);
}
- kmb_i2s->i2s_base = devm_platform_ioremap_resource(pdev, 0);
+ kmb_i2s->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(kmb_i2s->i2s_base))
return PTR_ERR(kmb_i2s->i2s_base);
@@ -692,22 +874,38 @@ static int kmb_plat_dai_probe(struct platform_device *pdev)
kmb_i2s->dev = &pdev->dev;
- irq = platform_get_irq_optional(pdev, 0);
- if (irq > 0) {
- ret = devm_request_irq(dev, irq, kmb_i2s_irq_handler, 0,
- pdev->name, kmb_i2s);
- if (ret < 0) {
- dev_err(dev, "failed to request irq\n");
- return ret;
- }
- }
-
comp1_reg = readl(kmb_i2s->i2s_base + I2S_COMP_PARAM_1);
kmb_i2s->fifo_th = (1 << COMP1_FIFO_DEPTH(comp1_reg)) / 2;
- ret = devm_snd_soc_register_component(dev, &kmb_component,
- kmb_i2s_dai, 1);
+ kmb_i2s->use_pio = !(of_property_read_bool(np, "dmas"));
+
+ if (kmb_i2s->use_pio) {
+ irq = platform_get_irq_optional(pdev, 0);
+ if (irq > 0) {
+ ret = devm_request_irq(dev, irq, kmb_i2s_irq_handler, 0,
+ pdev->name, kmb_i2s);
+ if (ret < 0) {
+ dev_err(dev, "failed to request irq\n");
+ return ret;
+ }
+ }
+ ret = devm_snd_soc_register_component(dev, &kmb_component,
+ kmb_i2s_dai, 1);
+ } else {
+ kmb_i2s->play_dma_data.addr = res->start + I2S_TXDMA;
+ kmb_i2s->capture_dma_data.addr = res->start + I2S_RXDMA;
+ ret = snd_dmaengine_pcm_register(&pdev->dev,
+ NULL, 0);
+ if (ret) {
+ dev_err(&pdev->dev, "could not register dmaengine: %d\n",
+ ret);
+ return ret;
+ }
+ ret = devm_snd_soc_register_component(dev, &kmb_component_dma,
+ kmb_i2s_dai, 1);
+ }
+
if (ret) {
dev_err(dev, "not able to register dai\n");
return ret;
diff --git a/sound/soc/intel/keembay/kmb_platform.h b/sound/soc/intel/keembay/kmb_platform.h
index 0c393e5916b6..29be2cd84ddb 100644
--- a/sound/soc/intel/keembay/kmb_platform.h
+++ b/sound/soc/intel/keembay/kmb_platform.h
@@ -12,6 +12,7 @@
#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/types.h>
+#include <sound/dmaengine_pcm.h>
/* Register values with reference to KMB databook v1.1 */
/* common register for all channel */
@@ -103,7 +104,12 @@
#define DW_I2S_PROVIDER BIT(3)
#define I2S_RXDMA 0x01C0
+#define I2S_RRXDMA 0x01C4
#define I2S_TXDMA 0x01C8
+#define I2S_RTXDMA 0x01CC
+#define I2S_DMACR 0x0200
+#define I2S_DMAEN_RXBLOCK (1 << 16)
+#define I2S_DMAEN_TXBLOCK (1 << 17)
/*
* struct i2s_clk_config_data - represent i2s clk configuration data
@@ -131,6 +137,9 @@ struct kmb_i2s_info {
u32 xfer_resolution;
u32 fifo_th;
bool clock_provider;
+ /* data related to DMA transfers b/w i2s and DMAC */
+ struct snd_dmaengine_dai_dma_data play_dma_data;
+ struct snd_dmaengine_dai_dma_data capture_dma_data;
struct i2s_clk_config_data config;
int (*i2s_clk_cfg)(struct i2s_clk_config_data *config);
@@ -141,6 +150,7 @@ struct kmb_i2s_info {
struct snd_pcm_substream *rx_substream;
unsigned int tx_ptr;
unsigned int rx_ptr;
+ bool iec958_fmt;
};
#endif /* KMB_PLATFORM_H_ */
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c
index 8b993722f74e..5b1a15e39912 100644
--- a/sound/soc/intel/skylake/skl.c
+++ b/sound/soc/intel/skylake/skl.c
@@ -950,12 +950,8 @@ static int skl_first_init(struct hdac_bus *bus)
bus->num_streams = cp_streams + pb_streams;
/* allow 64bit DMA address if supported by H/W */
- if (!dma_set_mask(bus->dev, DMA_BIT_MASK(64))) {
- dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(64));
- } else {
- dma_set_mask(bus->dev, DMA_BIT_MASK(32));
- dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(32));
- }
+ if (dma_set_mask_and_coherent(bus->dev, DMA_BIT_MASK(64)))
+ dma_set_mask_and_coherent(bus->dev, DMA_BIT_MASK(32));
/* initialize streams */
snd_hdac_ext_stream_init_all
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index 0a68f4c3d15a..52ba0e3a9e95 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -455,7 +455,7 @@ static struct snd_soc_dai_driver jz4740_i2s_dai = {
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = JZ4740_I2S_FMTS,
},
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
.ops = &jz4740_i2s_dai_ops,
};
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index e037826b2451..c2a5933bfcfc 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -182,25 +182,6 @@ static int kirkwood_dma_close(struct snd_soc_component *component,
return 0;
}
-static int kirkwood_dma_hw_params(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = params_buffer_bytes(params);
-
- return 0;
-}
-
-static int kirkwood_dma_hw_free(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- snd_pcm_set_runtime_buffer(substream, NULL);
- return 0;
-}
-
static int kirkwood_dma_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
@@ -244,82 +225,28 @@ static snd_pcm_uframes_t kirkwood_dma_pointer(
return count;
}
-static int kirkwood_dma_preallocate_dma_buffer(struct snd_pcm *pcm,
- int stream)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- size_t size = kirkwood_dma_snd_hw.buffer_bytes_max;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->area = dma_alloc_coherent(pcm->card->dev, size,
- &buf->addr, GFP_KERNEL);
- if (!buf->area)
- return -ENOMEM;
- buf->bytes = size;
- buf->private_data = NULL;
-
- return 0;
-}
-
static int kirkwood_dma_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
+ size_t size = kirkwood_dma_snd_hw.buffer_bytes_max;
struct snd_card *card = rtd->card->snd_card;
- struct snd_pcm *pcm = rtd->pcm;
int ret;
ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
- ret = kirkwood_dma_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- return ret;
- }
-
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- ret = kirkwood_dma_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- return ret;
- }
+ snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+ card->dev, size, size);
return 0;
}
-static void kirkwood_dma_free_dma_buffers(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
-
- dma_free_coherent(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
-}
-
const struct snd_soc_component_driver kirkwood_soc_component = {
.name = DRV_NAME,
.open = kirkwood_dma_open,
.close = kirkwood_dma_close,
- .hw_params = kirkwood_dma_hw_params,
- .hw_free = kirkwood_dma_hw_free,
.prepare = kirkwood_dma_prepare,
.pointer = kirkwood_dma_pointer,
.pcm_construct = kirkwood_dma_new,
- .pcm_destruct = kirkwood_dma_free_dma_buffers,
};
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 8d3dcfb6a580..effdb76369e4 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -172,7 +172,7 @@ config SND_SOC_MT8192
config SND_SOC_MT8192_MT6359_RT1015_RT5682
tristate "ASoC Audio driver for MT8192 with MT6359 RT1015 RT5682 codec"
depends on I2C
- depends on SND_SOC_MT8192
+ depends on SND_SOC_MT8192 && MTK_PMIC_WRAP
select SND_SOC_MT6359
select SND_SOC_RT1015
select SND_SOC_RT1015P
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
index df29641c74aa..d5cffe7a7e15 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
@@ -655,7 +655,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
},
.ops = &mt2701_afe_i2s_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "I2S1",
@@ -679,7 +679,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
| SNDRV_PCM_FMTBIT_S32_LE)
},
.ops = &mt2701_afe_i2s_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "I2S2",
@@ -703,7 +703,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
| SNDRV_PCM_FMTBIT_S32_LE)
},
.ops = &mt2701_afe_i2s_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "I2S3",
@@ -727,7 +727,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
| SNDRV_PCM_FMTBIT_S32_LE)
},
.ops = &mt2701_afe_i2s_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "MRG BT",
@@ -749,7 +749,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.ops = &mt2701_btmrg_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
}
};
diff --git a/sound/soc/mediatek/mt6797/mt6797-dai-pcm.c b/sound/soc/mediatek/mt6797/mt6797-dai-pcm.c
index 3136f0bc7827..51f736f319e4 100644
--- a/sound/soc/mediatek/mt6797/mt6797-dai-pcm.c
+++ b/sound/soc/mediatek/mt6797/mt6797-dai-pcm.c
@@ -270,8 +270,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_dai_pcm_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "PCM 2",
@@ -291,8 +291,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_dai_pcm_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
};
diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
index 7e7bda70d12e..685f4074b4e0 100644
--- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
+++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
@@ -571,7 +571,7 @@ static struct snd_soc_dai_driver mt8173_afe_pcm_dais[] = {
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.ops = &mt8173_afe_i2s_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
index cfbd0c65c7a3..a4d26a6fc849 100644
--- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
+++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
@@ -125,12 +125,6 @@ mt8183_da7219_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
for_each_rtd_codec_dais(rtd, i, codec_dai) {
if (!strcmp(codec_dai->component->name, RT1015_DEV0_NAME) ||
!strcmp(codec_dai->component->name, RT1015_DEV1_NAME)) {
- ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
- if (ret) {
- dev_err(rtd->dev, "failed to set bclk ratio\n");
- return ret;
- }
-
ret = snd_soc_dai_set_pll(codec_dai, 0,
RT1015_PLL_S_BCLK,
rate * 64, rate * 256);
diff --git a/sound/soc/mediatek/mt8183/mt8183-dai-pcm.c b/sound/soc/mediatek/mt8183/mt8183-dai-pcm.c
index bc3ba3228f08..38ce0e36cdb4 100644
--- a/sound/soc/mediatek/mt8183/mt8183-dai-pcm.c
+++ b/sound/soc/mediatek/mt8183/mt8183-dai-pcm.c
@@ -270,8 +270,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_dai_pcm_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "PCM 2",
@@ -291,8 +291,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_dai_pcm_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
};
diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
index 1ce3eddbee13..271413e719e3 100644
--- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
+++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
@@ -68,12 +68,6 @@ mt8183_mt6358_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
int ret, i;
for_each_rtd_codec_dais(rtd, i, codec_dai) {
- ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
- if (ret < 0) {
- dev_err(card->dev, "failed to set bclk ratio\n");
- return ret;
- }
-
ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
rate * 64, rate * 256);
if (ret < 0) {
@@ -124,6 +118,45 @@ static int mt8183_rt1015_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
}
static int
+mt8183_mt6358_startup(struct snd_pcm_substream *substream)
+{
+ static const unsigned int rates[] = {
+ 48000,
+ };
+ static const struct snd_pcm_hw_constraint_list constraints_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+ };
+ static const unsigned int channels[] = {
+ 2,
+ };
+ static const struct snd_pcm_hw_constraint_list constraints_channels = {
+ .count = ARRAY_SIZE(channels),
+ .list = channels,
+ .mask = 0,
+ };
+
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
+ runtime->hw.channels_max = 2;
+ snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+ snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
+
+ return 0;
+}
+
+static const struct snd_soc_ops mt8183_mt6358_ops = {
+ .startup = mt8183_mt6358_startup,
+};
+
+static int
mt8183_mt6358_ts3a227_max98357_bt_sco_startup(
struct snd_pcm_substream *substream)
{
@@ -362,6 +395,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
+ .ops = &mt8183_mt6358_ops,
SND_SOC_DAILINK_REG(playback1),
},
{
@@ -409,6 +443,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
+ .ops = &mt8183_mt6358_ops,
SND_SOC_DAILINK_REG(capture3),
},
{
diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
index e7fec2d75e3d..7a1724f5ff4c 100644
--- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
+++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
@@ -42,7 +42,7 @@ static const struct snd_pcm_hardware mt8192_afe_hardware = {
static int mt8192_memif_fs(struct snd_pcm_substream *substream,
unsigned int rate)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
@@ -59,7 +59,7 @@ static int mt8192_get_dai_fs(struct mtk_base_afe *afe,
static int mt8192_irq_fs(struct snd_pcm_substream *substream, unsigned int rate)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-pcm.c b/sound/soc/mediatek/mt8192/mt8192-dai-pcm.c
index 6e94cfdf06fc..239e3f5b53d3 100644
--- a/sound/soc/mediatek/mt8192/mt8192-dai-pcm.c
+++ b/sound/soc/mediatek/mt8192/mt8192-dai-pcm.c
@@ -360,8 +360,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_dai_pcm_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
{
.name = "PCM 2",
@@ -381,8 +381,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
.formats = MTK_PCM_FORMATS,
},
.ops = &mtk_dai_pcm_ops,
- .symmetric_rates = 1,
- .symmetric_samplebits = 1,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
},
};
diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c
index 8383536b7ae0..f5de1d769679 100644
--- a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c
+++ b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c
@@ -738,7 +738,7 @@ static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe)
if (!tdm_priv)
return NULL;
- tdm_priv->mclk_multiple = 128;
+ tdm_priv->mclk_multiple = 512;
tdm_priv->bck_id = MT8192_I2S4_BCK;
tdm_priv->mclk_id = MT8192_I2S4_MCK;
tdm_priv->id = MT8192_DAI_TDM;
diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
index ae2c748eb19c..a606133951b7 100644
--- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
+++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
@@ -31,12 +31,15 @@
#define RT5682_CODEC_DAI "rt5682-aif1"
#define RT5682_DEV0_NAME "rt5682.1-001a"
-static struct snd_soc_jack headset_jack;
+struct mt8192_mt6359_priv {
+ struct snd_soc_jack headset_jack;
+ struct snd_soc_jack hdmi_jack;
+};
static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai;
@@ -46,12 +49,6 @@ static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
int ret, i;
for_each_rtd_codec_dais(rtd, i, codec_dai) {
- ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
- if (ret) {
- dev_err(card->dev, "failed to set bclk ratio\n");
- return ret;
- }
-
ret = snd_soc_dai_set_pll(codec_dai, 0,
RT1015_PLL_S_BCLK,
params_rate(params) * 64,
@@ -77,7 +74,7 @@ static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
static int mt8192_rt5682_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_card *card = rtd->card;
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
@@ -311,7 +308,8 @@ static int mt8192_rt5682_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *cmpnt_codec =
asoc_rtd_to_codec(rtd, 0)->component;
- struct snd_soc_jack *jack = &headset_jack;
+ struct mt8192_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_jack *jack = &priv->headset_jack;
int ret;
ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
@@ -329,14 +327,25 @@ static int mt8192_rt5682_init(struct snd_soc_pcm_runtime *rtd)
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
- ret = snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
+ return snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
+};
+
+static int mt8192_mt6359_hdmi_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_component *cmpnt_codec =
+ asoc_rtd_to_codec(rtd, 0)->component;
+ struct mt8192_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ int ret;
+
+ ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT,
+ &priv->hdmi_jack, NULL, 0);
if (ret) {
- dev_err(rtd->dev, "Headset Jack set failed: %d\n", ret);
+ dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret);
return ret;
}
- return 0;
-};
+ return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL);
+}
static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
@@ -351,14 +360,8 @@ static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
}
static int
-mt8192_mt6359_rt1015_rt5682_cap1_startup(struct snd_pcm_substream *substream)
+mt8192_mt6359_cap1_startup(struct snd_pcm_substream *substream)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_component *component =
- snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
- int ret;
-
static const unsigned int channels[] = {
1, 2, 4
};
@@ -376,13 +379,15 @@ mt8192_mt6359_rt1015_rt5682_cap1_startup(struct snd_pcm_substream *substream)
.mask = 0,
};
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
if (ret < 0) {
- dev_err(afe->dev, "hw_constraint_list channels failed\n");
+ dev_err(rtd->dev, "hw_constraint_list channels failed\n");
return ret;
}
@@ -390,15 +395,15 @@ mt8192_mt6359_rt1015_rt5682_cap1_startup(struct snd_pcm_substream *substream)
SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
if (ret < 0) {
- dev_err(afe->dev, "hw_constraint_list rate failed\n");
+ dev_err(rtd->dev, "hw_constraint_list rate failed\n");
return ret;
}
return 0;
}
-static const struct snd_soc_ops mt8192_mt6359_rt1015_rt5682_capture1_ops = {
- .startup = mt8192_mt6359_rt1015_rt5682_cap1_startup,
+static const struct snd_soc_ops mt8192_mt6359_capture1_ops = {
+ .startup = mt8192_mt6359_cap1_startup,
};
static int
@@ -656,7 +661,7 @@ SND_SOC_DAILINK_DEFS(pcm2,
SND_SOC_DAILINK_DEFS(tdm,
DAILINK_COMP_ARRAY(COMP_CPU("TDM")),
- DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
@@ -759,7 +764,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
- .ops = &mt8192_mt6359_rt1015_rt5682_capture1_ops,
+ .ops = &mt8192_mt6359_capture1_ops,
SND_SOC_DAILINK_REG(capture1),
},
{
@@ -994,8 +999,14 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
{
.name = "TDM",
.no_pcm = 1,
+ .dai_fmt = SND_SOC_DAIFMT_DSP_A |
+ SND_SOC_DAIFMT_IB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.dpcm_playback = 1,
.ignore_suspend = 1,
+ .be_hw_params_fixup = mt8192_i2s_hw_params_fixup,
+ .ignore = 1,
+ .init = mt8192_mt6359_hdmi_init,
SND_SOC_DAILINK_REG(tdm),
},
};
@@ -1006,6 +1017,7 @@ mt8192_mt6359_rt1015_rt5682_widgets[] = {
SND_SOC_DAPM_SPK("Right Spk", NULL),
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_OUTPUT("TDM Out"),
};
static const struct snd_soc_dapm_route mt8192_mt6359_rt1015_rt5682_routes[] = {
@@ -1016,6 +1028,8 @@ static const struct snd_soc_dapm_route mt8192_mt6359_rt1015_rt5682_routes[] = {
{ "Headphone Jack", NULL, "HPOL" },
{ "Headphone Jack", NULL, "HPOR" },
{ "IN1P", NULL, "Headset Mic" },
+ /* TDM */
+ { "TDM Out", NULL, "TDM" },
};
static const struct snd_kcontrol_new mt8192_mt6359_rt1015_rt5682_controls[] = {
@@ -1089,10 +1103,11 @@ static struct snd_soc_card mt8192_mt6359_rt1015p_rt5682_card = {
static int mt8192_mt6359_dev_probe(struct platform_device *pdev)
{
struct snd_soc_card *card;
- struct device_node *platform_node;
+ struct device_node *platform_node, *hdmi_codec;
int ret, i;
struct snd_soc_dai_link *dai_link;
const struct of_device_id *match;
+ struct mt8192_mt6359_priv *priv;
platform_node = of_parse_phandle(pdev->dev.of_node,
"mediatek,platform", 0);
@@ -1108,6 +1123,9 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev)
card = (struct snd_soc_card *)match->data;
card->dev = &pdev->dev;
+ hdmi_codec = of_parse_phandle(pdev->dev.of_node,
+ "mediatek,hdmi-codec", 0);
+
for_each_card_prelinks(card, i, dai_link) {
if (strcmp(dai_link->name, "I2S3") == 0) {
if (card == &mt8192_mt6359_rt1015_rt5682_card) {
@@ -1134,10 +1152,20 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev)
}
}
+ if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) {
+ dai_link->codecs->of_node = hdmi_codec;
+ dai_link->ignore = 0;
+ }
+
if (!dai_link->platforms->name)
dai_link->platforms->of_node = platform_node;
}
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ snd_soc_card_set_drvdata(card, priv);
+
ret = mt8192_afe_gpio_init(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "init gpio error %d\n", ret);
diff --git a/sound/soc/meson/aiu-fifo-i2s.c b/sound/soc/meson/aiu-fifo-i2s.c
index d91b0d874342..2388a2d0b3a6 100644
--- a/sound/soc/meson/aiu-fifo-i2s.c
+++ b/sound/soc/meson/aiu-fifo-i2s.c
@@ -124,7 +124,6 @@ const struct snd_soc_dai_ops aiu_fifo_i2s_dai_ops = {
.trigger = aiu_fifo_i2s_trigger,
.prepare = aiu_fifo_i2s_prepare,
.hw_params = aiu_fifo_i2s_hw_params,
- .hw_free = aiu_fifo_hw_free,
.startup = aiu_fifo_startup,
.shutdown = aiu_fifo_shutdown,
};
diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c
index 44eb6faacf44..2fb30f89bf7a 100644
--- a/sound/soc/meson/aiu-fifo-spdif.c
+++ b/sound/soc/meson/aiu-fifo-spdif.c
@@ -158,7 +158,6 @@ const struct snd_soc_dai_ops aiu_fifo_spdif_dai_ops = {
.trigger = fifo_spdif_trigger,
.prepare = fifo_spdif_prepare,
.hw_params = fifo_spdif_hw_params,
- .hw_free = aiu_fifo_hw_free,
.startup = aiu_fifo_startup,
.shutdown = aiu_fifo_shutdown,
};
diff --git a/sound/soc/meson/aiu-fifo.c b/sound/soc/meson/aiu-fifo.c
index aa88aae8e517..4ad23267cace 100644
--- a/sound/soc/meson/aiu-fifo.c
+++ b/sound/soc/meson/aiu-fifo.c
@@ -99,11 +99,6 @@ int aiu_fifo_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_component *component = dai->component;
struct aiu_fifo *fifo = dai->playback_dma_data;
dma_addr_t end;
- int ret;
-
- ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
- if (ret < 0)
- return ret;
/* Setup the fifo boundaries */
end = runtime->dma_addr + runtime->dma_bytes - fifo->fifo_block;
@@ -124,12 +119,6 @@ int aiu_fifo_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-int aiu_fifo_hw_free(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- return snd_pcm_lib_free_pages(substream);
-}
-
static irqreturn_t aiu_fifo_isr(int irq, void *dev_id)
{
struct snd_pcm_substream *playback = dev_id;
@@ -187,15 +176,12 @@ void aiu_fifo_shutdown(struct snd_pcm_substream *substream,
int aiu_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_dai *dai)
{
- struct snd_pcm_substream *substream =
- rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
struct snd_card *card = rtd->card->snd_card;
struct aiu_fifo *fifo = dai->playback_dma_data;
size_t size = fifo->pcm->buffer_bytes_max;
- snd_pcm_lib_preallocate_pages(substream,
- SNDRV_DMA_TYPE_DEV,
- card->dev, size, size);
+ snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+ card->dev, size, size);
return 0;
}
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 5301859a8453..bcde4a96c168 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -353,7 +353,7 @@ static struct snd_soc_dai_driver pxa_i2s_dai = {
.rates = PXA2XX_I2S_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = &pxa_i2s_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static const struct snd_soc_component_driver pxa_i2s_component = {
diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c
index 8507ef8f6679..3efa133d1c64 100644
--- a/sound/soc/qcom/lpass-apq8016.c
+++ b/sound/soc/qcom/lpass-apq8016.c
@@ -250,7 +250,7 @@ static struct lpass_variant apq8016_data = {
.micmode = REG_FIELD_ID(0x1000, 4, 7, 4, 0x1000),
.micmono = REG_FIELD_ID(0x1000, 3, 3, 4, 0x1000),
.wssrc = REG_FIELD_ID(0x1000, 2, 2, 4, 0x1000),
- .bitwidth = REG_FIELD_ID(0x1000, 0, 0, 4, 0x1000),
+ .bitwidth = REG_FIELD_ID(0x1000, 0, 1, 4, 0x1000),
.rdma_dyncclk = REG_FIELD_ID(0x8400, 12, 12, 2, 0x1000),
.rdma_bursten = REG_FIELD_ID(0x8400, 11, 11, 2, 0x1000),
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c
index 66b834312f33..c642e5f8f28c 100644
--- a/sound/soc/qcom/lpass-cpu.c
+++ b/sound/soc/qcom/lpass-cpu.c
@@ -286,16 +286,12 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
ret);
- if (drvdata->bit_clk_state[id] == LPAIF_BIT_CLK_DISABLE) {
- ret = clk_enable(drvdata->mi2s_bit_clk[id]);
- if (ret) {
- dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret);
- clk_disable(drvdata->mi2s_osr_clk[id]);
- return ret;
- }
- drvdata->bit_clk_state[id] = LPAIF_BIT_CLK_ENABLE;
+ ret = clk_enable(drvdata->mi2s_bit_clk[id]);
+ if (ret) {
+ dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret);
+ clk_disable(drvdata->mi2s_osr_clk[id]);
+ return ret;
}
-
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -310,10 +306,9 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
if (ret)
dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
ret);
- if (drvdata->bit_clk_state[id] == LPAIF_BIT_CLK_ENABLE) {
- clk_disable(drvdata->mi2s_bit_clk[dai->driver->id]);
- drvdata->bit_clk_state[id] = LPAIF_BIT_CLK_DISABLE;
- }
+
+ clk_disable(drvdata->mi2s_bit_clk[dai->driver->id]);
+
break;
}
@@ -480,6 +475,7 @@ static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg)
}
static struct regmap_config lpass_cpu_regmap_config = {
+ .name = "lpass_cpu",
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
@@ -599,7 +595,7 @@ static bool lpass_hdmi_regmap_writeable(struct device *dev, unsigned int reg)
return true;
}
- for (i = 0; i < v->rdma_channels; ++i) {
+ for (i = 0; i < v->hdmi_rdma_channels; ++i) {
if (reg == LPAIF_HDMI_RDMACTL_REG(v, i))
return true;
if (reg == LPAIF_HDMI_RDMABASE_REG(v, i))
@@ -645,7 +641,7 @@ static bool lpass_hdmi_regmap_readable(struct device *dev, unsigned int reg)
if (reg == LPASS_HDMITX_APP_IRQSTAT_REG(v))
return true;
- for (i = 0; i < v->rdma_channels; ++i) {
+ for (i = 0; i < v->hdmi_rdma_channels; ++i) {
if (reg == LPAIF_HDMI_RDMACTL_REG(v, i))
return true;
if (reg == LPAIF_HDMI_RDMABASE_REG(v, i))
@@ -672,7 +668,7 @@ static bool lpass_hdmi_regmap_volatile(struct device *dev, unsigned int reg)
if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v))
return true;
- for (i = 0; i < v->rdma_channels; ++i) {
+ for (i = 0; i < v->hdmi_rdma_channels; ++i) {
if (reg == LPAIF_HDMI_RDMACURR_REG(v, i))
return true;
}
@@ -680,6 +676,7 @@ static bool lpass_hdmi_regmap_volatile(struct device *dev, unsigned int reg)
}
static struct regmap_config lpass_hdmi_regmap_config = {
+ .name = "lpass_hdmi",
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
@@ -748,7 +745,6 @@ static void of_lpass_cpu_parse_dai_data(struct device *dev,
}
if (id == LPASS_DP_RX) {
data->hdmi_port_enable = 1;
- dev_err(dev, "HDMI Port is enabled: %d\n", id);
} else {
data->mi2s_playback_sd_mode[id] =
of_lpass_cpu_parse_sd_lines(dev, node,
@@ -793,11 +789,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif");
drvdata->lpaif = devm_ioremap_resource(dev, res);
- if (IS_ERR((void const __force *)drvdata->lpaif)) {
- dev_err(dev, "error mapping reg resource: %ld\n",
- PTR_ERR((void const __force *)drvdata->lpaif));
- return PTR_ERR((void const __force *)drvdata->lpaif);
- }
+ if (IS_ERR(drvdata->lpaif))
+ return PTR_ERR(drvdata->lpaif);
lpass_cpu_regmap_config.max_register = LPAIF_WRDMAPER_REG(variant,
variant->wrdma_channels +
@@ -815,14 +808,11 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-hdmiif");
drvdata->hdmiif = devm_ioremap_resource(dev, res);
- if (IS_ERR((void const __force *)drvdata->hdmiif)) {
- dev_err(dev, "error mapping reg resource: %ld\n",
- PTR_ERR((void const __force *)drvdata->hdmiif));
- return PTR_ERR((void const __force *)drvdata->hdmiif);
- }
+ if (IS_ERR(drvdata->hdmiif))
+ return PTR_ERR(drvdata->hdmiif);
lpass_hdmi_regmap_config.max_register = LPAIF_HDMI_RDMAPER_REG(variant,
- variant->hdmi_rdma_channels);
+ variant->hdmi_rdma_channels - 1);
drvdata->hdmiif_map = devm_regmap_init_mmio(dev, drvdata->hdmiif,
&lpass_hdmi_regmap_config);
if (IS_ERR(drvdata->hdmiif_map)) {
@@ -866,7 +856,6 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
PTR_ERR(drvdata->mi2s_bit_clk[dai_id]));
return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]);
}
- drvdata->bit_clk_state[dai_id] = LPAIF_BIT_CLK_DISABLE;
}
/* Allocation for i2sctl regmap fields */
diff --git a/sound/soc/qcom/lpass-lpaif-reg.h b/sound/soc/qcom/lpass-lpaif-reg.h
index baf72f124ea9..2eb03ad9b7c7 100644
--- a/sound/soc/qcom/lpass-lpaif-reg.h
+++ b/sound/soc/qcom/lpass-lpaif-reg.h
@@ -60,9 +60,6 @@
#define LPAIF_I2SCTL_BITWIDTH_24 1
#define LPAIF_I2SCTL_BITWIDTH_32 2
-#define LPAIF_BIT_CLK_DISABLE 0
-#define LPAIF_BIT_CLK_ENABLE 1
-
#define LPAIF_I2SCTL_RESET_STATE 0x003C0004
#define LPAIF_DMACTL_RESET_STATE 0x00200000
diff --git a/sound/soc/qcom/lpass-sc7180.c b/sound/soc/qcom/lpass-sc7180.c
index 735c9dac28f2..8c168d3c589e 100644
--- a/sound/soc/qcom/lpass-sc7180.c
+++ b/sound/soc/qcom/lpass-sc7180.c
@@ -171,7 +171,7 @@ static struct lpass_variant sc7180_data = {
.rdma_channels = 5,
.hdmi_rdma_reg_base = 0x64000,
.hdmi_rdma_reg_stride = 0x1000,
- .hdmi_rdma_channels = 3,
+ .hdmi_rdma_channels = 4,
.dmactl_audif_start = 1,
.wrdma_reg_base = 0x18000,
.wrdma_reg_stride = 0x1000,
diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h
index 2d68af0da34d..83b2e08ade06 100644
--- a/sound/soc/qcom/lpass.h
+++ b/sound/soc/qcom/lpass.h
@@ -68,7 +68,6 @@ struct lpass_data {
unsigned int mi2s_playback_sd_mode[LPASS_MAX_MI2S_PORTS];
unsigned int mi2s_capture_sd_mode[LPASS_MAX_MI2S_PORTS];
int hdmi_port_enable;
- int bit_clk_state[LPASS_MAX_MI2S_PORTS];
/* low-power audio interface (LPAIF) registers */
void __iomem *lpaif;
diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c
index daa58b5f941e..cad1cd1bfdf0 100644
--- a/sound/soc/qcom/qdsp6/q6afe.c
+++ b/sound/soc/qcom/qdsp6/q6afe.c
@@ -1707,7 +1707,7 @@ int q6afe_vote_lpass_core_hw(struct device *dev, uint32_t hw_block_id,
pkt->hdr.token = hw_block_id;
pkt->hdr.opcode = AFE_CMD_REMOTE_LPASS_CORE_HW_VOTE_REQUEST;
vote_cfg->hw_block_id = hw_block_id;
- strlcpy(vote_cfg->client_name, client_name,
+ strscpy(vote_cfg->client_name, client_name,
sizeof(vote_cfg->client_name));
ret = afe_apr_send_pkt(afe, pkt, NULL,
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c
index c9ac9c1d26c4..9766725c2916 100644
--- a/sound/soc/qcom/qdsp6/q6asm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
@@ -1233,6 +1233,25 @@ static void q6asm_dai_pcm_free(struct snd_soc_component *component,
}
}
+static const struct snd_soc_dapm_widget q6asm_dapm_widgets[] = {
+ SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, SND_SOC_NOPM, 0, 0),
+};
+
static const struct snd_soc_component_driver q6asm_fe_dai_component = {
.name = DRV_NAME,
.open = q6asm_dai_open,
@@ -1245,6 +1264,8 @@ static const struct snd_soc_component_driver q6asm_fe_dai_component = {
.pcm_construct = q6asm_dai_pcm_new,
.pcm_destruct = q6asm_dai_pcm_free,
.compress_ops = &q6asm_dai_compress_ops,
+ .dapm_widgets = q6asm_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(q6asm_dapm_widgets),
};
static struct snd_soc_dai_driver q6asm_fe_dais_template[] = {
diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c
index a6618efe22f2..36bf8bd4edd7 100644
--- a/sound/soc/qcom/qdsp6/q6asm.c
+++ b/sound/soc/qcom/qdsp6/q6asm.c
@@ -491,7 +491,7 @@ static int __q6asm_memory_map_regions(struct audio_client *ac, int dir,
*
* @dir: direction of audio stream
* @ac: audio client instanace
- * @phys: physcial address that needs mapping.
+ * @phys: physical address that needs mapping.
* @period_sz: audio period size
* @periods: number of periods
*
diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c
index 53185e26fea1..0a6b9433f6ac 100644
--- a/sound/soc/qcom/qdsp6/q6routing.c
+++ b/sound/soc/qcom/qdsp6/q6routing.c
@@ -713,24 +713,6 @@ static const struct snd_kcontrol_new mmul8_mixer_controls[] = {
Q6ROUTING_TX_MIXERS(MSM_FRONTEND_DAI_MULTIMEDIA8) };
static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
- /* Frontend AIF */
- SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, 0, 0, 0),
-
/* Mixer definitions */
SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0,
hdmi_mixer_controls,
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index eae287d905eb..0740764e7f71 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -373,7 +373,7 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
I2S_DMACR_RDL(16));
val = I2S_CKR_TRCM_TXRX;
- if (dai->driver->symmetric_rates && rtd->dai_link->symmetric_rates)
+ if (dai->driver->symmetric_rate && rtd->dai_link->symmetric_rate)
val = I2S_CKR_TRCM_TXONLY;
regmap_update_bits(i2s->regmap, I2S_CKR,
@@ -471,7 +471,7 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = {
SNDRV_PCM_FMTBIT_S32_LE),
},
.ops = &rockchip_i2s_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static const struct snd_soc_component_driver rockchip_i2s_component = {
diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c
index e5f732747f71..9295d648624e 100644
--- a/sound/soc/rockchip/rockchip_pdm.c
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -338,7 +338,7 @@ static struct snd_soc_dai_driver rockchip_pdm_dai = {
.formats = ROCKCHIP_PDM_FORMATS,
},
.ops = &rockchip_pdm_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static const struct snd_soc_component_driver rockchip_pdm_component = {
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 4bdc268fd981..b043183174b2 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -1175,7 +1175,7 @@ static int i2s_alloc_dais(struct samsung_i2s_priv *priv,
dai_drv->probe = samsung_i2s_dai_probe;
dai_drv->remove = samsung_i2s_dai_remove;
- dai_drv->symmetric_rates = 1;
+ dai_drv->symmetric_rate = 1;
dai_drv->ops = &samsung_i2s_dai_ops;
dai_drv->playback.channels_min = 1;
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 6f50c7b47326..bfd76e9cc0ca 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -452,7 +452,7 @@ static int s3c_pcm_dai_probe(struct snd_soc_dai *dai)
#define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000
#define S3C_PCM_DAI_DECLARE \
- .symmetric_rates = 1, \
+ .symmetric_rate = 1, \
.probe = s3c_pcm_dai_probe, \
.ops = &s3c_pcm_dai_ops, \
.playback = { \
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 6e670b3e92a0..1029d8d9d800 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -1320,8 +1320,8 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv,
if (rsnd_ssi_is_pin_sharing(io_capture) ||
rsnd_ssi_is_pin_sharing(io_playback)) {
- /* should have symmetric_rates if pin sharing */
- drv->symmetric_rates = 1;
+ /* should have symmetric_rate if pin sharing */
+ drv->symmetric_rate = 1;
}
dev_dbg(dev, "%s (%s/%s)\n", rdai->name,
@@ -1472,7 +1472,7 @@ static int rsnd_kctrl_info(struct snd_kcontrol *kctrl,
uinfo->value.enumerated.items = cfg->max;
if (uinfo->value.enumerated.item >= cfg->max)
uinfo->value.enumerated.item = cfg->max - 1;
- strlcpy(uinfo->value.enumerated.name,
+ strscpy(uinfo->value.enumerated.name,
cfg->texts[uinfo->value.enumerated.item],
sizeof(uinfo->value.enumerated.name));
} else {
diff --git a/sound/soc/sh/siu.h b/sound/soc/sh/siu.h
index 6201840f1bc0..a675c36fc9d9 100644
--- a/sound/soc/sh/siu.h
+++ b/sound/soc/sh/siu.h
@@ -169,7 +169,7 @@ static inline u32 siu_read32(u32 __iomem *addr)
#define SIU_BRGBSEL (0x108 / sizeof(u32))
#define SIU_BRRB (0x10c / sizeof(u32))
-extern struct snd_soc_component_driver siu_component;
+extern const struct snd_soc_component_driver siu_component;
extern struct siu_info *siu_i2s_data;
int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card);
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
index 45c4320976ab..4785886df4f0 100644
--- a/sound/soc/sh/siu_pcm.c
+++ b/sound/soc/sh/siu_pcm.c
@@ -543,7 +543,7 @@ static void siu_pcm_free(struct snd_soc_component *component,
dev_dbg(pcm->card->dev, "%s\n", __func__);
}
-struct const snd_soc_component_driver siu_component = {
+const struct snd_soc_component_driver siu_component = {
.name = DRV_NAME,
.open = siu_pcm_open,
.close = siu_pcm_close,
diff --git a/sound/soc/sirf/Kconfig b/sound/soc/sirf/Kconfig
deleted file mode 100644
index 094a1c89c59d..000000000000
--- a/sound/soc/sirf/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config SND_SOC_SIRF
- tristate "SoC Audio for the SiRF SoC chips"
- depends on ARCH_SIRF || COMPILE_TEST
- select SND_SOC_GENERIC_DMAENGINE_PCM
-
-config SND_SOC_SIRF_AUDIO
- tristate "SoC Audio support for SiRF internal audio codec"
- depends on SND_SOC_SIRF
- select SND_SOC_SIRF_AUDIO_CODEC
- select SND_SOC_SIRF_AUDIO_PORT
-
-config SND_SOC_SIRF_AUDIO_PORT
- select REGMAP_MMIO
- tristate
-
-config SND_SOC_SIRF_USP
- tristate "SoC Audio (I2S protocol) for SiRF SoC USP interface"
- depends on SND_SOC_SIRF
- select REGMAP_MMIO
- tristate
diff --git a/sound/soc/sirf/Makefile b/sound/soc/sirf/Makefile
deleted file mode 100644
index 16ed11965ff9..000000000000
--- a/sound/soc/sirf/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-snd-soc-sirf-audio-objs := sirf-audio.o
-snd-soc-sirf-audio-port-objs := sirf-audio-port.o
-snd-soc-sirf-usp-objs := sirf-usp.o
-
-obj-$(CONFIG_SND_SOC_SIRF_AUDIO) += snd-soc-sirf-audio.o
-obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o
-obj-$(CONFIG_SND_SOC_SIRF_USP) += snd-soc-sirf-usp.o
diff --git a/sound/soc/sirf/sirf-audio-port.c b/sound/soc/sirf/sirf-audio-port.c
deleted file mode 100644
index 8be2f0bc477b..000000000000
--- a/sound/soc/sirf/sirf-audio-port.c
+++ /dev/null
@@ -1,86 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SiRF Audio port driver
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- */
-#include <linux/module.h>
-#include <sound/soc.h>
-#include <sound/dmaengine_pcm.h>
-
-struct sirf_audio_port {
- struct regmap *regmap;
- struct snd_dmaengine_dai_dma_data playback_dma_data;
- struct snd_dmaengine_dai_dma_data capture_dma_data;
-};
-
-
-static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai)
-{
- struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai);
-
- snd_soc_dai_init_dma_data(dai, &port->playback_dma_data,
- &port->capture_dma_data);
- return 0;
-}
-
-static struct snd_soc_dai_driver sirf_audio_port_dai = {
- .probe = sirf_audio_port_dai_probe,
- .name = "sirf-audio-port",
- .id = 0,
- .playback = {
- .channels_min = 2,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
-};
-
-static const struct snd_soc_component_driver sirf_audio_port_component = {
- .name = "sirf-audio-port",
-};
-
-static int sirf_audio_port_probe(struct platform_device *pdev)
-{
- int ret;
- struct sirf_audio_port *port;
-
- port = devm_kzalloc(&pdev->dev,
- sizeof(struct sirf_audio_port), GFP_KERNEL);
- if (!port)
- return -ENOMEM;
-
- ret = devm_snd_soc_register_component(&pdev->dev,
- &sirf_audio_port_component, &sirf_audio_port_dai, 1);
- if (ret)
- return ret;
-
- platform_set_drvdata(pdev, port);
- return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
-}
-
-static const struct of_device_id sirf_audio_port_of_match[] = {
- { .compatible = "sirf,audio-port", },
- {}
-};
-MODULE_DEVICE_TABLE(of, sirf_audio_port_of_match);
-
-static struct platform_driver sirf_audio_port_driver = {
- .driver = {
- .name = "sirf-audio-port",
- .of_match_table = sirf_audio_port_of_match,
- },
- .probe = sirf_audio_port_probe,
-};
-
-module_platform_driver(sirf_audio_port_driver);
-
-MODULE_DESCRIPTION("SiRF Audio Port driver");
-MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/sirf/sirf-audio.c b/sound/soc/sirf/sirf-audio.c
deleted file mode 100644
index c923b6772b22..000000000000
--- a/sound/soc/sirf/sirf-audio.c
+++ /dev/null
@@ -1,160 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SiRF audio card driver
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-
-struct sirf_audio_card {
- unsigned int gpio_hp_pa;
- unsigned int gpio_spk_pa;
-};
-
-static int sirf_audio_hp_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *ctrl, int event)
-{
- struct snd_soc_dapm_context *dapm = w->dapm;
- struct snd_soc_card *card = dapm->card;
- struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card);
- int on = !SND_SOC_DAPM_EVENT_OFF(event);
-
- if (gpio_is_valid(sirf_audio_card->gpio_hp_pa))
- gpio_set_value(sirf_audio_card->gpio_hp_pa, on);
- return 0;
-}
-
-static int sirf_audio_spk_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *ctrl, int event)
-{
- struct snd_soc_dapm_context *dapm = w->dapm;
- struct snd_soc_card *card = dapm->card;
- struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card);
- int on = !SND_SOC_DAPM_EVENT_OFF(event);
-
- if (gpio_is_valid(sirf_audio_card->gpio_spk_pa))
- gpio_set_value(sirf_audio_card->gpio_spk_pa, on);
-
- return 0;
-}
-static const struct snd_soc_dapm_widget sirf_audio_dapm_widgets[] = {
- SND_SOC_DAPM_HP("Hp", sirf_audio_hp_event),
- SND_SOC_DAPM_SPK("Ext Spk", sirf_audio_spk_event),
- SND_SOC_DAPM_MIC("Ext Mic", NULL),
-};
-
-static const struct snd_soc_dapm_route intercon[] = {
- {"Hp", NULL, "HPOUTL"},
- {"Hp", NULL, "HPOUTR"},
- {"Ext Spk", NULL, "SPKOUT"},
- {"MICIN1", NULL, "Mic Bias"},
- {"Mic Bias", NULL, "Ext Mic"},
-};
-
-/* Digital audio interface glue - connects codec <--> CPU */
-SND_SOC_DAILINK_DEFS(sirf,
- DAILINK_COMP_ARRAY(COMP_EMPTY()),
- DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sirf-audio-codec")),
- DAILINK_COMP_ARRAY(COMP_EMPTY()));
-
-static struct snd_soc_dai_link sirf_audio_dai_link[] = {
- {
- .name = "SiRF audio card",
- .stream_name = "SiRF audio HiFi",
- SND_SOC_DAILINK_REG(sirf),
- },
-};
-
-/* Audio machine driver */
-static struct snd_soc_card snd_soc_sirf_audio_card = {
- .name = "SiRF audio card",
- .owner = THIS_MODULE,
- .dai_link = sirf_audio_dai_link,
- .num_links = ARRAY_SIZE(sirf_audio_dai_link),
- .dapm_widgets = sirf_audio_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(sirf_audio_dapm_widgets),
- .dapm_routes = intercon,
- .num_dapm_routes = ARRAY_SIZE(intercon),
-};
-
-static int sirf_audio_probe(struct platform_device *pdev)
-{
- struct snd_soc_card *card = &snd_soc_sirf_audio_card;
- struct sirf_audio_card *sirf_audio_card;
- int ret;
-
- sirf_audio_card = devm_kzalloc(&pdev->dev, sizeof(struct sirf_audio_card),
- GFP_KERNEL);
- if (sirf_audio_card == NULL)
- return -ENOMEM;
-
- sirf_audio_dai_link[0].cpus->of_node =
- of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0);
- sirf_audio_dai_link[0].platforms->of_node =
- of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0);
- sirf_audio_dai_link[0].codecs->of_node =
- of_parse_phandle(pdev->dev.of_node, "sirf,audio-codec", 0);
- sirf_audio_card->gpio_spk_pa = of_get_named_gpio(pdev->dev.of_node,
- "spk-pa-gpios", 0);
- sirf_audio_card->gpio_hp_pa = of_get_named_gpio(pdev->dev.of_node,
- "hp-pa-gpios", 0);
- if (gpio_is_valid(sirf_audio_card->gpio_spk_pa)) {
- ret = devm_gpio_request_one(&pdev->dev,
- sirf_audio_card->gpio_spk_pa,
- GPIOF_OUT_INIT_LOW, "SPA_PA_SD");
- if (ret) {
- dev_err(&pdev->dev,
- "Failed to request GPIO_%d for reset: %d\n",
- sirf_audio_card->gpio_spk_pa, ret);
- return ret;
- }
- }
- if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) {
- ret = devm_gpio_request_one(&pdev->dev,
- sirf_audio_card->gpio_hp_pa,
- GPIOF_OUT_INIT_LOW, "HP_PA_SD");
- if (ret) {
- dev_err(&pdev->dev,
- "Failed to request GPIO_%d for reset: %d\n",
- sirf_audio_card->gpio_hp_pa, ret);
- return ret;
- }
- }
-
- card->dev = &pdev->dev;
- snd_soc_card_set_drvdata(card, sirf_audio_card);
-
- ret = devm_snd_soc_register_card(&pdev->dev, card);
- if (ret)
- dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret);
-
- return ret;
-}
-
-static const struct of_device_id sirf_audio_of_match[] = {
- {.compatible = "sirf,sirf-audio-card", },
- { },
-};
-MODULE_DEVICE_TABLE(of, sirf_audio_of_match);
-
-static struct platform_driver sirf_audio_driver = {
- .driver = {
- .name = "sirf-audio-card",
- .pm = &snd_soc_pm_ops,
- .of_match_table = sirf_audio_of_match,
- },
- .probe = sirf_audio_probe,
-};
-module_platform_driver(sirf_audio_driver);
-
-MODULE_AUTHOR("RongJun Ying <RongJun.Ying@csr.com>");
-MODULE_DESCRIPTION("ALSA SoC SIRF audio card driver");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/sirf/sirf-usp.c b/sound/soc/sirf/sirf-usp.c
deleted file mode 100644
index 2af0c6f14ee6..000000000000
--- a/sound/soc/sirf/sirf-usp.c
+++ /dev/null
@@ -1,435 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SiRF USP in I2S/DSP mode
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- */
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/clk.h>
-#include <linux/pm_runtime.h>
-#include <sound/soc.h>
-#include <sound/pcm_params.h>
-#include <sound/dmaengine_pcm.h>
-
-#include "sirf-usp.h"
-
-struct sirf_usp {
- struct regmap *regmap;
- struct clk *clk;
- u32 mode1_reg;
- u32 mode2_reg;
- int daifmt_format;
- struct snd_dmaengine_dai_dma_data playback_dma_data;
- struct snd_dmaengine_dai_dma_data capture_dma_data;
-};
-
-static void sirf_usp_tx_enable(struct sirf_usp *usp)
-{
- regmap_update_bits(usp->regmap, USP_TX_FIFO_OP,
- USP_TX_FIFO_RESET, USP_TX_FIFO_RESET);
- regmap_write(usp->regmap, USP_TX_FIFO_OP, 0);
-
- regmap_update_bits(usp->regmap, USP_TX_FIFO_OP,
- USP_TX_FIFO_START, USP_TX_FIFO_START);
-
- regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
- USP_TX_ENA, USP_TX_ENA);
-}
-
-static void sirf_usp_tx_disable(struct sirf_usp *usp)
-{
- regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
- USP_TX_ENA, ~USP_TX_ENA);
- /* FIFO stop */
- regmap_write(usp->regmap, USP_TX_FIFO_OP, 0);
-}
-
-static void sirf_usp_rx_enable(struct sirf_usp *usp)
-{
- regmap_update_bits(usp->regmap, USP_RX_FIFO_OP,
- USP_RX_FIFO_RESET, USP_RX_FIFO_RESET);
- regmap_write(usp->regmap, USP_RX_FIFO_OP, 0);
-
- regmap_update_bits(usp->regmap, USP_RX_FIFO_OP,
- USP_RX_FIFO_START, USP_RX_FIFO_START);
-
- regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
- USP_RX_ENA, USP_RX_ENA);
-}
-
-static void sirf_usp_rx_disable(struct sirf_usp *usp)
-{
- regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
- USP_RX_ENA, ~USP_RX_ENA);
- /* FIFO stop */
- regmap_write(usp->regmap, USP_RX_FIFO_OP, 0);
-}
-
-static int sirf_usp_pcm_dai_probe(struct snd_soc_dai *dai)
-{
- struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
-
- snd_soc_dai_init_dma_data(dai, &usp->playback_dma_data,
- &usp->capture_dma_data);
- return 0;
-}
-
-static int sirf_usp_pcm_set_dai_fmt(struct snd_soc_dai *dai,
- unsigned int fmt)
-{
- struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
-
- /* set master/slave audio interface */
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBM_CFM:
- break;
- default:
- dev_err(dai->dev, "Only CBM and CFM supported\n");
- return -EINVAL;
- }
-
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- case SND_SOC_DAIFMT_DSP_A:
- usp->daifmt_format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK);
- break;
- default:
- dev_err(dai->dev, "Only I2S and DSP_A format supported\n");
- return -EINVAL;
- }
-
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_NF:
- break;
- case SND_SOC_DAIFMT_IB_NF:
- usp->daifmt_format |= (fmt & SND_SOC_DAIFMT_INV_MASK);
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void sirf_usp_i2s_init(struct sirf_usp *usp)
-{
- /* Configure RISC mode */
- regmap_update_bits(usp->regmap, USP_RISC_DSP_MODE,
- USP_RISC_DSP_SEL, ~USP_RISC_DSP_SEL);
-
- /*
- * Configure DMA IO Length register
- * Set no limit, USP can receive data continuously until it is diabled
- */
- regmap_write(usp->regmap, USP_TX_DMA_IO_LEN, 0);
- regmap_write(usp->regmap, USP_RX_DMA_IO_LEN, 0);
-
- /* Configure Mode2 register */
- regmap_write(usp->regmap, USP_MODE2, (1 << USP_RXD_DELAY_LEN_OFFSET) |
- (0 << USP_TXD_DELAY_LEN_OFFSET) |
- USP_TFS_CLK_SLAVE_MODE | USP_RFS_CLK_SLAVE_MODE);
-
- /* Configure Mode1 register */
- regmap_write(usp->regmap, USP_MODE1,
- USP_SYNC_MODE | USP_EN | USP_TXD_ACT_EDGE_FALLING |
- USP_RFS_ACT_LEVEL_LOGIC1 | USP_TFS_ACT_LEVEL_LOGIC1 |
- USP_TX_UFLOW_REPEAT_ZERO | USP_CLOCK_MODE_SLAVE);
-
- /* Configure RX DMA IO Control register */
- regmap_write(usp->regmap, USP_RX_DMA_IO_CTRL, 0);
-
- /* Congiure RX FIFO Control register */
- regmap_write(usp->regmap, USP_RX_FIFO_CTRL,
- (USP_RX_FIFO_THRESHOLD << USP_RX_FIFO_THD_OFFSET) |
- (USP_TX_RX_FIFO_WIDTH_DWORD << USP_RX_FIFO_WIDTH_OFFSET));
-
- /* Congiure RX FIFO Level Check register */
- regmap_write(usp->regmap, USP_RX_FIFO_LEVEL_CHK,
- RX_FIFO_SC(0x04) | RX_FIFO_LC(0x0E) | RX_FIFO_HC(0x1B));
-
- /* Configure TX DMA IO Control register*/
- regmap_write(usp->regmap, USP_TX_DMA_IO_CTRL, 0);
-
- /* Configure TX FIFO Control register */
- regmap_write(usp->regmap, USP_TX_FIFO_CTRL,
- (USP_TX_FIFO_THRESHOLD << USP_TX_FIFO_THD_OFFSET) |
- (USP_TX_RX_FIFO_WIDTH_DWORD << USP_TX_FIFO_WIDTH_OFFSET));
- /* Congiure TX FIFO Level Check register */
- regmap_write(usp->regmap, USP_TX_FIFO_LEVEL_CHK,
- TX_FIFO_SC(0x1B) | TX_FIFO_LC(0x0E) | TX_FIFO_HC(0x04));
-}
-
-static int sirf_usp_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
-{
- struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
- u32 data_len, frame_len, shifter_len;
-
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- data_len = 16;
- frame_len = 16;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- data_len = 24;
- frame_len = 32;
- break;
- case SNDRV_PCM_FORMAT_S24_3LE:
- data_len = 24;
- frame_len = 24;
- break;
- default:
- dev_err(dai->dev, "Format unsupported\n");
- return -EINVAL;
- }
-
- shifter_len = data_len;
-
- switch (usp->daifmt_format & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL,
- USP_I2S_SYNC_CHG, USP_I2S_SYNC_CHG);
- break;
- case SND_SOC_DAIFMT_DSP_A:
- regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL,
- USP_I2S_SYNC_CHG, 0);
- frame_len = data_len * params_channels(params);
- data_len = frame_len;
- break;
- default:
- dev_err(dai->dev, "Only support I2S and DSP_A mode\n");
- return -EINVAL;
- }
-
- switch (usp->daifmt_format & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_NF:
- break;
- case SND_SOC_DAIFMT_IB_NF:
- regmap_update_bits(usp->regmap, USP_MODE1,
- USP_RXD_ACT_EDGE_FALLING | USP_TXD_ACT_EDGE_FALLING,
- USP_RXD_ACT_EDGE_FALLING);
- break;
- default:
- return -EINVAL;
- }
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- regmap_update_bits(usp->regmap, USP_TX_FRAME_CTRL,
- USP_TXC_DATA_LEN_MASK | USP_TXC_FRAME_LEN_MASK
- | USP_TXC_SHIFTER_LEN_MASK | USP_TXC_SLAVE_CLK_SAMPLE,
- ((data_len - 1) << USP_TXC_DATA_LEN_OFFSET)
- | ((frame_len - 1) << USP_TXC_FRAME_LEN_OFFSET)
- | ((shifter_len - 1) << USP_TXC_SHIFTER_LEN_OFFSET)
- | USP_TXC_SLAVE_CLK_SAMPLE);
- else
- regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL,
- USP_RXC_DATA_LEN_MASK | USP_RXC_FRAME_LEN_MASK
- | USP_RXC_SHIFTER_LEN_MASK | USP_SINGLE_SYNC_MODE,
- ((data_len - 1) << USP_RXC_DATA_LEN_OFFSET)
- | ((frame_len - 1) << USP_RXC_FRAME_LEN_OFFSET)
- | ((shifter_len - 1) << USP_RXC_SHIFTER_LEN_OFFSET)
- | USP_SINGLE_SYNC_MODE);
-
- return 0;
-}
-
-static int sirf_usp_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- sirf_usp_tx_enable(usp);
- else
- sirf_usp_rx_enable(usp);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- sirf_usp_tx_disable(usp);
- else
- sirf_usp_rx_disable(usp);
- break;
- }
-
- return 0;
-}
-
-static const struct snd_soc_dai_ops sirf_usp_pcm_dai_ops = {
- .trigger = sirf_usp_pcm_trigger,
- .set_fmt = sirf_usp_pcm_set_dai_fmt,
- .hw_params = sirf_usp_pcm_hw_params,
-};
-
-static struct snd_soc_dai_driver sirf_usp_pcm_dai = {
- .probe = sirf_usp_pcm_dai_probe,
- .name = "sirf-usp-pcm",
- .id = 0,
- .playback = {
- .stream_name = "SiRF USP PCM Playback",
- .channels_min = 1,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_192000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_S24_3LE,
- },
- .capture = {
- .stream_name = "SiRF USP PCM Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_192000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_S24_3LE,
- },
- .ops = &sirf_usp_pcm_dai_ops,
-};
-
-static int sirf_usp_pcm_runtime_suspend(struct device *dev)
-{
- struct sirf_usp *usp = dev_get_drvdata(dev);
-
- clk_disable_unprepare(usp->clk);
- return 0;
-}
-
-static int sirf_usp_pcm_runtime_resume(struct device *dev)
-{
- struct sirf_usp *usp = dev_get_drvdata(dev);
- int ret;
-
- ret = clk_prepare_enable(usp->clk);
- if (ret) {
- dev_err(dev, "clk_enable failed: %d\n", ret);
- return ret;
- }
- sirf_usp_i2s_init(usp);
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int sirf_usp_pcm_suspend(struct device *dev)
-{
- struct sirf_usp *usp = dev_get_drvdata(dev);
-
- if (!pm_runtime_status_suspended(dev)) {
- regmap_read(usp->regmap, USP_MODE1, &usp->mode1_reg);
- regmap_read(usp->regmap, USP_MODE2, &usp->mode2_reg);
- sirf_usp_pcm_runtime_suspend(dev);
- }
- return 0;
-}
-
-static int sirf_usp_pcm_resume(struct device *dev)
-{
- struct sirf_usp *usp = dev_get_drvdata(dev);
- int ret;
-
- if (!pm_runtime_status_suspended(dev)) {
- ret = sirf_usp_pcm_runtime_resume(dev);
- if (ret)
- return ret;
- regmap_write(usp->regmap, USP_MODE1, usp->mode1_reg);
- regmap_write(usp->regmap, USP_MODE2, usp->mode2_reg);
- }
- return 0;
-}
-#endif
-
-static const struct snd_soc_component_driver sirf_usp_component = {
- .name = "sirf-usp",
-};
-
-static const struct regmap_config sirf_usp_regmap_config = {
- .reg_bits = 32,
- .reg_stride = 4,
- .val_bits = 32,
- .max_register = USP_RX_FIFO_DATA,
- .cache_type = REGCACHE_NONE,
-};
-
-static int sirf_usp_pcm_probe(struct platform_device *pdev)
-{
- int ret;
- struct sirf_usp *usp;
- void __iomem *base;
-
- usp = devm_kzalloc(&pdev->dev, sizeof(struct sirf_usp),
- GFP_KERNEL);
- if (!usp)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, usp);
-
- base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(base))
- return PTR_ERR(base);
- usp->regmap = devm_regmap_init_mmio(&pdev->dev, base,
- &sirf_usp_regmap_config);
- if (IS_ERR(usp->regmap))
- return PTR_ERR(usp->regmap);
-
- usp->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(usp->clk)) {
- dev_err(&pdev->dev, "Get clock failed.\n");
- return PTR_ERR(usp->clk);
- }
-
- pm_runtime_enable(&pdev->dev);
- if (!pm_runtime_enabled(&pdev->dev)) {
- ret = sirf_usp_pcm_runtime_resume(&pdev->dev);
- if (ret)
- return ret;
- }
-
- ret = devm_snd_soc_register_component(&pdev->dev, &sirf_usp_component,
- &sirf_usp_pcm_dai, 1);
- if (ret) {
- dev_err(&pdev->dev, "Register Audio SoC dai failed.\n");
- return ret;
- }
- return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
-}
-
-static int sirf_usp_pcm_remove(struct platform_device *pdev)
-{
- if (!pm_runtime_enabled(&pdev->dev))
- sirf_usp_pcm_runtime_suspend(&pdev->dev);
- else
- pm_runtime_disable(&pdev->dev);
- return 0;
-}
-
-static const struct of_device_id sirf_usp_pcm_of_match[] = {
- { .compatible = "sirf,prima2-usp-pcm", },
- {}
-};
-MODULE_DEVICE_TABLE(of, sirf_usp_pcm_of_match);
-
-static const struct dev_pm_ops sirf_usp_pcm_pm_ops = {
- SET_RUNTIME_PM_OPS(sirf_usp_pcm_runtime_suspend,
- sirf_usp_pcm_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(sirf_usp_pcm_suspend, sirf_usp_pcm_resume)
-};
-
-static struct platform_driver sirf_usp_pcm_driver = {
- .driver = {
- .name = "sirf-usp-pcm",
- .of_match_table = sirf_usp_pcm_of_match,
- .pm = &sirf_usp_pcm_pm_ops,
- },
- .probe = sirf_usp_pcm_probe,
- .remove = sirf_usp_pcm_remove,
-};
-
-module_platform_driver(sirf_usp_pcm_driver);
-
-MODULE_DESCRIPTION("SiRF SoC USP PCM bus driver");
-MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/sirf/sirf-usp.h b/sound/soc/sirf/sirf-usp.h
deleted file mode 100644
index 08993b5992c4..000000000000
--- a/sound/soc/sirf/sirf-usp.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/arm/mach-prima2/include/mach/sirfsoc_usp.h
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- */
-
-#ifndef _SIRF_USP_H
-#define _SIRF_USP_H
-
-/* USP Registers */
-#define USP_MODE1 0x00
-#define USP_MODE2 0x04
-#define USP_TX_FRAME_CTRL 0x08
-#define USP_RX_FRAME_CTRL 0x0C
-#define USP_TX_RX_ENABLE 0x10
-#define USP_INT_ENABLE 0x14
-#define USP_INT_STATUS 0x18
-#define USP_PIN_IO_DATA 0x1C
-#define USP_RISC_DSP_MODE 0x20
-#define USP_AYSNC_PARAM_REG 0x24
-#define USP_IRDA_X_MODE_DIV 0x28
-#define USP_SM_CFG 0x2C
-#define USP_TX_DMA_IO_CTRL 0x100
-#define USP_TX_DMA_IO_LEN 0x104
-#define USP_TX_FIFO_CTRL 0x108
-#define USP_TX_FIFO_LEVEL_CHK 0x10C
-#define USP_TX_FIFO_OP 0x110
-#define USP_TX_FIFO_STATUS 0x114
-#define USP_TX_FIFO_DATA 0x118
-#define USP_RX_DMA_IO_CTRL 0x120
-#define USP_RX_DMA_IO_LEN 0x124
-#define USP_RX_FIFO_CTRL 0x128
-#define USP_RX_FIFO_LEVEL_CHK 0x12C
-#define USP_RX_FIFO_OP 0x130
-#define USP_RX_FIFO_STATUS 0x134
-#define USP_RX_FIFO_DATA 0x138
-
-/* USP MODE register-1 */
-#define USP_SYNC_MODE 0x00000001
-#define USP_CLOCK_MODE_SLAVE 0x00000002
-#define USP_LOOP_BACK_EN 0x00000004
-#define USP_HPSIR_EN 0x00000008
-#define USP_ENDIAN_CTRL_LSBF 0x00000010
-#define USP_EN 0x00000020
-#define USP_RXD_ACT_EDGE_FALLING 0x00000040
-#define USP_TXD_ACT_EDGE_FALLING 0x00000080
-#define USP_RFS_ACT_LEVEL_LOGIC1 0x00000100
-#define USP_TFS_ACT_LEVEL_LOGIC1 0x00000200
-#define USP_SCLK_IDLE_MODE_TOGGLE 0x00000400
-#define USP_SCLK_IDLE_LEVEL_LOGIC1 0x00000800
-#define USP_SCLK_PIN_MODE_IO 0x00001000
-#define USP_RFS_PIN_MODE_IO 0x00002000
-#define USP_TFS_PIN_MODE_IO 0x00004000
-#define USP_RXD_PIN_MODE_IO 0x00008000
-#define USP_TXD_PIN_MODE_IO 0x00010000
-#define USP_SCLK_IO_MODE_INPUT 0x00020000
-#define USP_RFS_IO_MODE_INPUT 0x00040000
-#define USP_TFS_IO_MODE_INPUT 0x00080000
-#define USP_RXD_IO_MODE_INPUT 0x00100000
-#define USP_TXD_IO_MODE_INPUT 0x00200000
-#define USP_IRDA_WIDTH_DIV_MASK 0x3FC00000
-#define USP_IRDA_WIDTH_DIV_OFFSET 0
-#define USP_IRDA_IDLE_LEVEL_HIGH 0x40000000
-#define USP_TX_UFLOW_REPEAT_ZERO 0x80000000
-#define USP_TX_ENDIAN_MODE 0x00000020
-#define USP_RX_ENDIAN_MODE 0x00000020
-
-/* USP Mode Register-2 */
-#define USP_RXD_DELAY_LEN_MASK 0x000000FF
-#define USP_RXD_DELAY_LEN_OFFSET 0
-
-#define USP_TXD_DELAY_LEN_MASK 0x0000FF00
-#define USP_TXD_DELAY_LEN_OFFSET 8
-
-#define USP_ENA_CTRL_MODE 0x00010000
-#define USP_FRAME_CTRL_MODE 0x00020000
-#define USP_TFS_SOURCE_MODE 0x00040000
-#define USP_TFS_MS_MODE 0x00080000
-#define USP_CLK_DIVISOR_MASK 0x7FE00000
-#define USP_CLK_DIVISOR_OFFSET 21
-
-#define USP_TFS_CLK_SLAVE_MODE (1<<20)
-#define USP_RFS_CLK_SLAVE_MODE (1<<19)
-
-#define USP_IRDA_DATA_WIDTH 0x80000000
-
-/* USP Transmit Frame Control Register */
-
-#define USP_TXC_DATA_LEN_MASK 0x000000FF
-#define USP_TXC_DATA_LEN_OFFSET 0
-
-#define USP_TXC_SYNC_LEN_MASK 0x0000FF00
-#define USP_TXC_SYNC_LEN_OFFSET 8
-
-#define USP_TXC_FRAME_LEN_MASK 0x00FF0000
-#define USP_TXC_FRAME_LEN_OFFSET 16
-
-#define USP_TXC_SHIFTER_LEN_MASK 0x1F000000
-#define USP_TXC_SHIFTER_LEN_OFFSET 24
-
-#define USP_TXC_SLAVE_CLK_SAMPLE 0x20000000
-
-#define USP_TXC_CLK_DIVISOR_MASK 0xC0000000
-#define USP_TXC_CLK_DIVISOR_OFFSET 30
-
-/* USP Receive Frame Control Register */
-
-#define USP_RXC_DATA_LEN_MASK 0x000000FF
-#define USP_RXC_DATA_LEN_OFFSET 0
-
-#define USP_RXC_FRAME_LEN_MASK 0x0000FF00
-#define USP_RXC_FRAME_LEN_OFFSET 8
-
-#define USP_RXC_SHIFTER_LEN_MASK 0x001F0000
-#define USP_RXC_SHIFTER_LEN_OFFSET 16
-
-#define USP_START_EDGE_MODE 0x00800000
-#define USP_I2S_SYNC_CHG 0x00200000
-
-#define USP_RXC_CLK_DIVISOR_MASK 0x0F000000
-#define USP_RXC_CLK_DIVISOR_OFFSET 24
-#define USP_SINGLE_SYNC_MODE 0x00400000
-
-/* Tx - RX Enable Register */
-
-#define USP_RX_ENA 0x00000001
-#define USP_TX_ENA 0x00000002
-
-/* USP Interrupt Enable and status Register */
-#define USP_RX_DONE_INT 0x00000001
-#define USP_TX_DONE_INT 0x00000002
-#define USP_RX_OFLOW_INT 0x00000004
-#define USP_TX_UFLOW_INT 0x00000008
-#define USP_RX_IO_DMA_INT 0x00000010
-#define USP_TX_IO_DMA_INT 0x00000020
-#define USP_RXFIFO_FULL_INT 0x00000040
-#define USP_TXFIFO_EMPTY_INT 0x00000080
-#define USP_RXFIFO_THD_INT 0x00000100
-#define USP_TXFIFO_THD_INT 0x00000200
-#define USP_UART_FRM_ERR_INT 0x00000400
-#define USP_RX_TIMEOUT_INT 0x00000800
-#define USP_TX_ALLOUT_INT 0x00001000
-#define USP_RXD_BREAK_INT 0x00008000
-
-/* All possible TX interruots */
-#define USP_TX_INTERRUPT (USP_TX_DONE_INT|USP_TX_UFLOW_INT|\
- USP_TX_IO_DMA_INT|\
- USP_TXFIFO_EMPTY_INT|\
- USP_TXFIFO_THD_INT)
-/* All possible RX interruots */
-#define USP_RX_INTERRUPT (USP_RX_DONE_INT|USP_RX_OFLOW_INT|\
- USP_RX_IO_DMA_INT|\
- USP_RXFIFO_FULL_INT|\
- USP_RXFIFO_THD_INT|\
- USP_RX_TIMEOUT_INT)
-
-#define USP_INT_ALL 0x1FFF
-
-/* USP Pin I/O Data Register */
-
-#define USP_RFS_PIN_VALUE_MASK 0x00000001
-#define USP_TFS_PIN_VALUE_MASK 0x00000002
-#define USP_RXD_PIN_VALUE_MASK 0x00000004
-#define USP_TXD_PIN_VALUE_MASK 0x00000008
-#define USP_SCLK_PIN_VALUE_MASK 0x00000010
-
-/* USP RISC/DSP Mode Register */
-#define USP_RISC_DSP_SEL 0x00000001
-
-/* USP ASYNC PARAMETER Register*/
-
-#define USP_ASYNC_TIMEOUT_MASK 0x0000FFFF
-#define USP_ASYNC_TIMEOUT_OFFSET 0
-#define USP_ASYNC_TIMEOUT(x) (((x)&USP_ASYNC_TIMEOUT_MASK) \
- <<USP_ASYNC_TIMEOUT_OFFSET)
-
-#define USP_ASYNC_DIV2_MASK 0x003F0000
-#define USP_ASYNC_DIV2_OFFSET 16
-
-/* USP TX DMA I/O MODE Register */
-#define USP_TX_MODE_IO 0x00000001
-
-/* USP TX DMA I/O Length Register */
-#define USP_TX_DATA_LEN_MASK 0xFFFFFFFF
-#define USP_TX_DATA_LEN_OFFSET 0
-
-/* USP TX FIFO Control Register */
-#define USP_TX_FIFO_WIDTH_MASK 0x00000003
-#define USP_TX_FIFO_WIDTH_OFFSET 0
-
-#define USP_TX_FIFO_THD_MASK 0x000001FC
-#define USP_TX_FIFO_THD_OFFSET 2
-
-/* USP TX FIFO Level Check Register */
-#define USP_TX_FIFO_LEVEL_CHECK_MASK 0x1F
-#define USP_TX_FIFO_SC_OFFSET 0
-#define USP_TX_FIFO_LC_OFFSET 10
-#define USP_TX_FIFO_HC_OFFSET 20
-
-#define TX_FIFO_SC(x) (((x) & USP_TX_FIFO_LEVEL_CHECK_MASK) \
- << USP_TX_FIFO_SC_OFFSET)
-#define TX_FIFO_LC(x) (((x) & USP_TX_FIFO_LEVEL_CHECK_MASK) \
- << USP_TX_FIFO_LC_OFFSET)
-#define TX_FIFO_HC(x) (((x) & USP_TX_FIFO_LEVEL_CHECK_MASK) \
- << USP_TX_FIFO_HC_OFFSET)
-
-/* USP TX FIFO Operation Register */
-#define USP_TX_FIFO_RESET 0x00000001
-#define USP_TX_FIFO_START 0x00000002
-
-/* USP TX FIFO Status Register */
-#define USP_TX_FIFO_LEVEL_MASK 0x0000007F
-#define USP_TX_FIFO_LEVEL_OFFSET 0
-
-#define USP_TX_FIFO_FULL 0x00000080
-#define USP_TX_FIFO_EMPTY 0x00000100
-
-/* USP TX FIFO Data Register */
-#define USP_TX_FIFO_DATA_MASK 0xFFFFFFFF
-#define USP_TX_FIFO_DATA_OFFSET 0
-
-/* USP RX DMA I/O MODE Register */
-#define USP_RX_MODE_IO 0x00000001
-#define USP_RX_DMA_FLUSH 0x00000004
-
-/* USP RX DMA I/O Length Register */
-#define USP_RX_DATA_LEN_MASK 0xFFFFFFFF
-#define USP_RX_DATA_LEN_OFFSET 0
-
-/* USP RX FIFO Control Register */
-#define USP_RX_FIFO_WIDTH_MASK 0x00000003
-#define USP_RX_FIFO_WIDTH_OFFSET 0
-
-#define USP_RX_FIFO_THD_MASK 0x000001FC
-#define USP_RX_FIFO_THD_OFFSET 2
-
-/* USP RX FIFO Level Check Register */
-
-#define USP_RX_FIFO_LEVEL_CHECK_MASK 0x1F
-#define USP_RX_FIFO_SC_OFFSET 0
-#define USP_RX_FIFO_LC_OFFSET 10
-#define USP_RX_FIFO_HC_OFFSET 20
-
-#define RX_FIFO_SC(x) (((x) & USP_RX_FIFO_LEVEL_CHECK_MASK) \
- << USP_RX_FIFO_SC_OFFSET)
-#define RX_FIFO_LC(x) (((x) & USP_RX_FIFO_LEVEL_CHECK_MASK) \
- << USP_RX_FIFO_LC_OFFSET)
-#define RX_FIFO_HC(x) (((x) & USP_RX_FIFO_LEVEL_CHECK_MASK) \
- << USP_RX_FIFO_HC_OFFSET)
-
-/* USP RX FIFO Operation Register */
-#define USP_RX_FIFO_RESET 0x00000001
-#define USP_RX_FIFO_START 0x00000002
-
-/* USP RX FIFO Status Register */
-
-#define USP_RX_FIFO_LEVEL_MASK 0x0000007F
-#define USP_RX_FIFO_LEVEL_OFFSET 0
-
-#define USP_RX_FIFO_FULL 0x00000080
-#define USP_RX_FIFO_EMPTY 0x00000100
-
-/* USP RX FIFO Data Register */
-
-#define USP_RX_FIFO_DATA_MASK 0xFFFFFFFF
-#define USP_RX_FIFO_DATA_OFFSET 0
-
-/*
- * When rx thd irq occur, sender just disable tx empty irq,
- * Remaining data in tx fifo wil also be sent out.
- */
-#define USP_FIFO_SIZE 128
-#define USP_TX_FIFO_THRESHOLD (USP_FIFO_SIZE/2)
-#define USP_RX_FIFO_THRESHOLD (USP_FIFO_SIZE/2)
-
-/* FIFO_WIDTH for the USP_TX_FIFO_CTRL and USP_RX_FIFO_CTRL registers */
-#define USP_FIFO_WIDTH_BYTE 0x00
-#define USP_FIFO_WIDTH_WORD 0x01
-#define USP_FIFO_WIDTH_DWORD 0x02
-
-#define USP_ASYNC_DIV2 16
-
-#define USP_PLUGOUT_RETRY_CNT 2
-
-#define USP_TX_RX_FIFO_WIDTH_DWORD 2
-
-#define SIRF_USP_DIV_MCLK 0
-
-#define SIRF_USP_I2S_TFS_SYNC 0
-#define SIRF_USP_I2S_RFS_SYNC 1
-#endif
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index 760523382f3c..159bf88b9f8c 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <sound/soc.h>
+#include <linux/bitops.h>
#define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret)
static inline int _soc_component_ret(struct snd_soc_component *component,
@@ -34,6 +35,18 @@ static inline int _soc_component_ret(struct snd_soc_component *component,
return ret;
}
+static inline int soc_component_field_shift(struct snd_soc_component *component,
+ unsigned int mask)
+{
+ if (!mask) {
+ dev_err(component->dev, "ASoC: error field mask is zero for %s\n",
+ component->name);
+ return 0;
+ }
+
+ return (ffs(mask) - 1);
+}
+
/*
* We might want to check substream by using list.
* In such case, we can update these macros.
@@ -840,6 +853,47 @@ int snd_soc_component_update_bits_async(struct snd_soc_component *component,
EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async);
/**
+ * snd_soc_component_read_field() - Read register field value
+ * @component: Component to read from
+ * @reg: Register to read
+ * @mask: mask of the register field
+ *
+ * Return: read value of register field.
+ */
+unsigned int snd_soc_component_read_field(struct snd_soc_component *component,
+ unsigned int reg, unsigned int mask)
+{
+ unsigned int val;
+
+ val = snd_soc_component_read(component, reg);
+
+ val = (val & mask) >> soc_component_field_shift(component, mask);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_read_field);
+
+/**
+ * snd_soc_component_write_field() - write to register field
+ * @component: Component to write to
+ * @reg: Register to write
+ * @mask: mask of the register field to update
+ * @val: value of the field to write
+ *
+ * Return: 1 for change, otherwise 0.
+ */
+int snd_soc_component_write_field(struct snd_soc_component *component,
+ unsigned int reg, unsigned int mask,
+ unsigned int val)
+{
+
+ val = (val << soc_component_field_shift(component, mask)) & mask;
+
+ return snd_soc_component_update_bits(component, reg, mask, val);
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_write_field);
+
+/**
* snd_soc_component_async_complete() - Ensure asynchronous I/O has completed
* @component: Component for which to wait
*
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 2b75d0139e47..b005f9eadd71 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2528,9 +2528,20 @@ static struct snd_soc_dapm_widget *dapm_find_widget(
{
struct snd_soc_dapm_widget *w;
struct snd_soc_dapm_widget *fallback = NULL;
+ char prefixed_pin[80];
+ const char *pin_name;
+ const char *prefix = soc_dapm_prefix(dapm);
+
+ if (prefix) {
+ snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s",
+ prefix, pin);
+ pin_name = prefixed_pin;
+ } else {
+ pin_name = pin;
+ }
for_each_card_widgets(dapm->card, w) {
- if (!strcmp(w->name, pin)) {
+ if (!strcmp(w->name, pin_name)) {
if (w->dapm == dapm)
return w;
else
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index ee51dc7fd893..14d85ca1e435 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -203,6 +203,34 @@ static inline void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm)
}
#endif
+/* Set FE's runtime_update state; the state is protected via PCM stream lock
+ * for avoiding the race with trigger callback.
+ * If the state is unset and a trigger is pending while the previous operation,
+ * process the pending trigger action here.
+ */
+static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd);
+static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe,
+ int stream, enum snd_soc_dpcm_update state)
+{
+ struct snd_pcm_substream *substream =
+ snd_soc_dpcm_get_substream(fe, stream);
+
+ snd_pcm_stream_lock_irq(substream);
+ if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) {
+ dpcm_fe_dai_do_trigger(substream,
+ fe->dpcm[stream].trigger_pending - 1);
+ fe->dpcm[stream].trigger_pending = 0;
+ }
+ fe->dpcm[stream].runtime_update = state;
+ snd_pcm_stream_unlock_irq(substream);
+}
+
+static void dpcm_set_be_update_state(struct snd_soc_pcm_runtime *be,
+ int stream, enum snd_soc_dpcm_update state)
+{
+ be->dpcm[stream].runtime_update = state;
+}
+
/**
* snd_soc_runtime_action() - Increment/Decrement active count for
* PCM runtime components
@@ -301,59 +329,46 @@ int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
return 0;
}
+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));
+ } else {
+ dai->rate = 0;
+ dai->channels = 0;
+ dai->sample_bits = 0;
+ }
+}
+
static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
struct snd_soc_dai *soc_dai)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
int ret;
- if (soc_dai->rate && (soc_dai->driver->symmetric_rates ||
- rtd->dai_link->symmetric_rates)) {
- dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n",
- soc_dai->rate);
-
- ret = snd_pcm_hw_constraint_single(substream->runtime,
- SNDRV_PCM_HW_PARAM_RATE,
- soc_dai->rate);
- if (ret < 0) {
- dev_err(soc_dai->dev,
- "ASoC: Unable to apply rate constraint: %d\n",
- ret);
- return ret;
- }
- }
-
- if (soc_dai->channels && (soc_dai->driver->symmetric_channels ||
- rtd->dai_link->symmetric_channels)) {
- dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d channel(s)\n",
- soc_dai->channels);
-
- ret = snd_pcm_hw_constraint_single(substream->runtime,
- SNDRV_PCM_HW_PARAM_CHANNELS,
- soc_dai->channels);
- if (ret < 0) {
- dev_err(soc_dai->dev,
- "ASoC: Unable to apply channel symmetry constraint: %d\n",
- ret);
- return ret;
- }
- }
-
- if (soc_dai->sample_bits && (soc_dai->driver->symmetric_samplebits ||
- rtd->dai_link->symmetric_samplebits)) {
- dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d sample bits\n",
- soc_dai->sample_bits);
-
- ret = snd_pcm_hw_constraint_single(substream->runtime,
- SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
- soc_dai->sample_bits);
- if (ret < 0) {
- dev_err(soc_dai->dev,
- "ASoC: Unable to apply sample bits symmetry constraint: %d\n",
- ret);
- return ret;
- }
- }
+#define __soc_pcm_apply_symmetry(name, NAME) \
+ if (soc_dai->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); \
+ \
+ ret = snd_pcm_hw_constraint_single(substream->runtime, \
+ SNDRV_PCM_HW_PARAM_##NAME,\
+ soc_dai->name); \
+ if (ret < 0) { \
+ dev_err(soc_dai->dev, \
+ "ASoC: Unable to apply %s constraint: %d\n",\
+ #name, ret); \
+ return ret; \
+ } \
+ }
+
+ __soc_pcm_apply_symmetry(rate, RATE);
+ __soc_pcm_apply_symmetry(channels, CHANNELS);
+ __soc_pcm_apply_symmetry(sample_bits, SAMPLE_BITS);
return 0;
}
@@ -362,61 +377,30 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_soc_dai d;
struct snd_soc_dai *dai;
struct snd_soc_dai *cpu_dai;
- unsigned int rate, channels, sample_bits, symmetry, i;
-
- rate = params_rate(params);
- channels = params_channels(params);
- sample_bits = snd_pcm_format_physical_width(params_format(params));
-
- /* reject unmatched parameters when applying symmetry */
- symmetry = rtd->dai_link->symmetric_rates;
-
- for_each_rtd_cpu_dais(rtd, i, dai)
- symmetry |= dai->driver->symmetric_rates;
-
- if (symmetry) {
- for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
- if (cpu_dai->rate && cpu_dai->rate != rate) {
- dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n",
- cpu_dai->rate, rate);
- return -EINVAL;
- }
- }
- }
-
- symmetry = rtd->dai_link->symmetric_channels;
+ unsigned int symmetry, i;
- for_each_rtd_dais(rtd, i, dai)
- symmetry |= dai->driver->symmetric_channels;
-
- if (symmetry) {
- for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
- if (cpu_dai->channels &&
- cpu_dai->channels != channels) {
- dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n",
- cpu_dai->channels, channels);
- return -EINVAL;
+ soc_pcm_set_dai_params(&d, params);
+
+#define __soc_pcm_params_symmetry(name) \
+ symmetry = rtd->dai_link->symmetric_##name; \
+ for_each_rtd_dais(rtd, i, dai) \
+ symmetry |= dai->driver->symmetric_##name; \
+ \
+ if (symmetry) \
+ for_each_rtd_cpu_dais(rtd, i, cpu_dai) \
+ if (cpu_dai->name && cpu_dai->name != d.name) { \
+ dev_err(rtd->dev, "ASoC: unmatched %s symmetry: %d - %d\n", \
+ #name, cpu_dai->name, d.name); \
+ return -EINVAL; \
}
- }
- }
- symmetry = rtd->dai_link->symmetric_samplebits;
-
- for_each_rtd_dais(rtd, i, dai)
- symmetry |= dai->driver->symmetric_samplebits;
-
- if (symmetry) {
- for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
- if (cpu_dai->sample_bits &&
- cpu_dai->sample_bits != sample_bits) {
- dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n",
- cpu_dai->sample_bits, sample_bits);
- return -EINVAL;
- }
- }
- }
+ /* reject unmatched parameters when applying symmetry */
+ __soc_pcm_params_symmetry(rate);
+ __soc_pcm_params_symmetry(channels);
+ __soc_pcm_params_symmetry(sample_bits);
return 0;
}
@@ -428,15 +412,15 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream)
struct snd_soc_dai *dai;
unsigned int symmetry, i;
- symmetry = link->symmetric_rates ||
+ symmetry = link->symmetric_rate ||
link->symmetric_channels ||
- link->symmetric_samplebits;
+ link->symmetric_sample_bits;
for_each_rtd_dais(rtd, i, dai)
symmetry = symmetry ||
- dai->driver->symmetric_rates ||
+ dai->driver->symmetric_rate ||
dai->driver->symmetric_channels ||
- dai->driver->symmetric_samplebits;
+ dai->driver->symmetric_sample_bits;
return symmetry;
}
@@ -489,6 +473,42 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
soc_pcm_set_msb(substream, cpu_bits);
}
+static void soc_pcm_hw_init(struct snd_pcm_hardware *hw)
+{
+ hw->rates = UINT_MAX;
+ hw->rate_min = 0;
+ hw->rate_max = UINT_MAX;
+ hw->channels_min = 0;
+ hw->channels_max = UINT_MAX;
+ hw->formats = ULLONG_MAX;
+}
+
+static void soc_pcm_hw_update_rate(struct snd_pcm_hardware *hw,
+ struct snd_soc_pcm_stream *p)
+{
+ hw->rates = snd_pcm_rate_mask_intersect(hw->rates, p->rates);
+
+ /* setup hw->rate_min/max via hw->rates first */
+ snd_pcm_hw_limit_rates(hw);
+
+ /* update hw->rate_min/max by snd_soc_pcm_stream */
+ hw->rate_min = max(hw->rate_min, p->rate_min);
+ hw->rate_max = min_not_zero(hw->rate_max, p->rate_max);
+}
+
+static void soc_pcm_hw_update_chan(struct snd_pcm_hardware *hw,
+ struct snd_soc_pcm_stream *p)
+{
+ hw->channels_min = max(hw->channels_min, p->channels_min);
+ hw->channels_max = min(hw->channels_max, p->channels_max);
+}
+
+static void soc_pcm_hw_update_format(struct snd_pcm_hardware *hw,
+ struct snd_soc_pcm_stream *p)
+{
+ hw->formats &= p->formats;
+}
+
/**
* snd_soc_runtime_calc_hw() - Calculate hw limits for a PCM stream
* @rtd: ASoC PCM runtime
@@ -505,14 +525,11 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_dai *cpu_dai;
struct snd_soc_pcm_stream *codec_stream;
struct snd_soc_pcm_stream *cpu_stream;
- unsigned int chan_min = 0, chan_max = UINT_MAX;
unsigned int cpu_chan_min = 0, cpu_chan_max = UINT_MAX;
- unsigned int rate_min = 0, rate_max = UINT_MAX;
- unsigned int cpu_rate_min = 0, cpu_rate_max = UINT_MAX;
- unsigned int rates = UINT_MAX, cpu_rates = UINT_MAX;
- u64 formats = ULLONG_MAX;
int i;
+ soc_pcm_hw_init(hw);
+
/* first calculate min/max only for CPUs in the DAI link */
for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
@@ -527,14 +544,12 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
cpu_stream = snd_soc_dai_get_pcm_stream(cpu_dai, stream);
- cpu_chan_min = max(cpu_chan_min, cpu_stream->channels_min);
- cpu_chan_max = min(cpu_chan_max, cpu_stream->channels_max);
- cpu_rate_min = max(cpu_rate_min, cpu_stream->rate_min);
- cpu_rate_max = min_not_zero(cpu_rate_max, cpu_stream->rate_max);
- formats &= cpu_stream->formats;
- cpu_rates = snd_pcm_rate_mask_intersect(cpu_stream->rates,
- cpu_rates);
+ soc_pcm_hw_update_chan(hw, cpu_stream);
+ soc_pcm_hw_update_rate(hw, cpu_stream);
+ soc_pcm_hw_update_format(hw, cpu_stream);
}
+ cpu_chan_min = hw->channels_min;
+ cpu_chan_max = hw->channels_max;
/* second calculate min/max only for CODECs in the DAI link */
for_each_rtd_codec_dais(rtd, i, codec_dai) {
@@ -550,16 +565,13 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
codec_stream = snd_soc_dai_get_pcm_stream(codec_dai, stream);
- chan_min = max(chan_min, codec_stream->channels_min);
- chan_max = min(chan_max, codec_stream->channels_max);
- rate_min = max(rate_min, codec_stream->rate_min);
- rate_max = min_not_zero(rate_max, codec_stream->rate_max);
- formats &= codec_stream->formats;
- rates = snd_pcm_rate_mask_intersect(codec_stream->rates, rates);
+ soc_pcm_hw_update_chan(hw, codec_stream);
+ soc_pcm_hw_update_rate(hw, codec_stream);
+ soc_pcm_hw_update_format(hw, codec_stream);
}
/* Verify both a valid CPU DAI and a valid CODEC DAI were found */
- if (!chan_min || !cpu_chan_min)
+ if (!hw->channels_min)
return -EINVAL;
/*
@@ -568,23 +580,10 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
* channel allocation be fixed up later
*/
if (rtd->num_codecs > 1) {
- chan_min = cpu_chan_min;
- chan_max = cpu_chan_max;
+ hw->channels_min = cpu_chan_min;
+ hw->channels_max = cpu_chan_max;
}
- /* finally find a intersection between CODECs and CPUs */
- hw->channels_min = max(chan_min, cpu_chan_min);
- hw->channels_max = min(chan_max, cpu_chan_max);
- hw->formats = formats;
- hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_rates);
-
- snd_pcm_hw_limit_rates(hw);
-
- hw->rate_min = max(hw->rate_min, cpu_rate_min);
- hw->rate_min = max(hw->rate_min, rate_min);
- hw->rate_max = min_not_zero(hw->rate_max, cpu_rate_max);
- hw->rate_max = min_not_zero(hw->rate_max, rate_max);
-
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_runtime_calc_hw);
@@ -870,11 +869,8 @@ static int soc_pcm_hw_clean(struct snd_pcm_substream *substream, int rollback)
for_each_rtd_dais(rtd, i, dai) {
int active = snd_soc_dai_stream_active(dai, substream->stream);
- if (snd_soc_dai_active(dai) == 1) {
- dai->rate = 0;
- dai->channels = 0;
- dai->sample_bits = 0;
- }
+ if (snd_soc_dai_active(dai) == 1)
+ soc_pcm_set_dai_params(dai, NULL);
if (active == 1)
snd_soc_dai_digital_mute(dai, 1, substream->stream);
@@ -971,11 +967,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if(ret < 0)
goto out;
- codec_dai->rate = params_rate(&codec_params);
- codec_dai->channels = params_channels(&codec_params);
- codec_dai->sample_bits = snd_pcm_format_physical_width(
- params_format(&codec_params));
-
+ soc_pcm_set_dai_params(codec_dai, &codec_params);
snd_soc_dapm_update_dai(substream, &codec_params, codec_dai);
}
@@ -992,11 +984,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
goto out;
/* store the parameters for each DAI */
- cpu_dai->rate = params_rate(params);
- cpu_dai->channels = params_channels(params);
- cpu_dai->sample_bits =
- snd_pcm_format_physical_width(params_format(params));
-
+ soc_pcm_set_dai_params(cpu_dai, params);
snd_soc_dapm_update_dai(substream, params, cpu_dai);
}
@@ -1335,7 +1323,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
stream ? "capture" : "playback",
dpcm->be->dai_link->name, fe->dai_link->name);
dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
- dpcm->be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
+ dpcm_set_be_update_state(dpcm->be, stream, SND_SOC_DPCM_UPDATE_BE);
prune++;
}
@@ -1371,8 +1359,8 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
/* is there a valid BE rtd for this widget */
be = dpcm_get_be(card, widget, stream);
if (!be) {
- dev_err(fe->dev, "ASoC: no BE found for %s\n",
- widget->name);
+ dev_dbg(fe->dev, "ASoC: no BE found for %s\n",
+ widget->name);
continue;
}
@@ -1390,7 +1378,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
continue;
/* new */
- be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
+ dpcm_set_be_update_state(be, stream, SND_SOC_DPCM_UPDATE_BE);
new++;
}
@@ -1418,8 +1406,7 @@ void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream)
spin_lock_irqsave(&fe->card->dpcm_lock, flags);
for_each_dpcm_be(fe, stream, dpcm)
- dpcm->be->dpcm[stream].runtime_update =
- SND_SOC_DPCM_UPDATE_NO;
+ dpcm_set_be_update_state(dpcm->be, stream, SND_SOC_DPCM_UPDATE_NO);
spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
}
@@ -1542,21 +1529,21 @@ unwind:
static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime,
struct snd_soc_pcm_stream *stream)
{
- runtime->hw.rate_min = stream->rate_min;
- runtime->hw.rate_max = min_not_zero(stream->rate_max, UINT_MAX);
- runtime->hw.channels_min = stream->channels_min;
- runtime->hw.channels_max = stream->channels_max;
+ struct snd_pcm_hardware *hw = &runtime->hw;
+
+ soc_pcm_hw_update_rate(hw, stream);
+ soc_pcm_hw_update_chan(hw, stream);
if (runtime->hw.formats)
runtime->hw.formats &= stream->formats;
else
runtime->hw.formats = stream->formats;
- runtime->hw.rates = stream->rates;
}
static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream,
- u64 *formats)
+ struct snd_pcm_runtime *runtime)
{
struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
+ struct snd_pcm_hardware *hw = &runtime->hw;
struct snd_soc_dpcm *dpcm;
struct snd_soc_dai *dai;
int stream = substream->stream;
@@ -1584,16 +1571,16 @@ static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream,
codec_stream = snd_soc_dai_get_pcm_stream(dai, stream);
- *formats &= codec_stream->formats;
+ soc_pcm_hw_update_format(hw, codec_stream);
}
}
}
static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream,
- unsigned int *channels_min,
- unsigned int *channels_max)
+ struct snd_pcm_runtime *runtime)
{
struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
+ struct snd_pcm_hardware *hw = &runtime->hw;
struct snd_soc_dpcm *dpcm;
int stream = substream->stream;
@@ -1622,10 +1609,7 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream,
cpu_stream = snd_soc_dai_get_pcm_stream(dai, stream);
- *channels_min = max(*channels_min,
- cpu_stream->channels_min);
- *channels_max = min(*channels_max,
- cpu_stream->channels_max);
+ soc_pcm_hw_update_chan(hw, cpu_stream);
}
/*
@@ -1635,20 +1619,16 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream,
if (be->num_codecs == 1) {
codec_stream = snd_soc_dai_get_pcm_stream(asoc_rtd_to_codec(be, 0), stream);
- *channels_min = max(*channels_min,
- codec_stream->channels_min);
- *channels_max = min(*channels_max,
- codec_stream->channels_max);
+ soc_pcm_hw_update_chan(hw, codec_stream);
}
}
}
static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream,
- unsigned int *rates,
- unsigned int *rate_min,
- unsigned int *rate_max)
+ struct snd_pcm_runtime *runtime)
{
struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
+ struct snd_pcm_hardware *hw = &runtime->hw;
struct snd_soc_dpcm *dpcm;
int stream = substream->stream;
@@ -1676,9 +1656,7 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream,
pcm = snd_soc_dai_get_pcm_stream(dai, stream);
- *rate_min = max(*rate_min, pcm->rate_min);
- *rate_max = min_not_zero(*rate_max, pcm->rate_max);
- *rates = snd_pcm_rate_mask_intersect(*rates, pcm->rates);
+ soc_pcm_hw_update_rate(hw, pcm);
}
}
}
@@ -1686,10 +1664,13 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream,
static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_pcm_hardware *hw = &runtime->hw;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai;
int i;
+ soc_pcm_hw_init(hw);
+
for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
/*
* Skip CPUs which don't support the current stream
@@ -1703,34 +1684,9 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)
substream->stream));
}
- dpcm_runtime_merge_format(substream, &runtime->hw.formats);
- dpcm_runtime_merge_chan(substream, &runtime->hw.channels_min,
- &runtime->hw.channels_max);
- dpcm_runtime_merge_rate(substream, &runtime->hw.rates,
- &runtime->hw.rate_min, &runtime->hw.rate_max);
-}
-
-static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd);
-
-/* Set FE's runtime_update state; the state is protected via PCM stream lock
- * for avoiding the race with trigger callback.
- * If the state is unset and a trigger is pending while the previous operation,
- * process the pending trigger action here.
- */
-static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe,
- int stream, enum snd_soc_dpcm_update state)
-{
- struct snd_pcm_substream *substream =
- snd_soc_dpcm_get_substream(fe, stream);
-
- snd_pcm_stream_lock_irq(substream);
- if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) {
- dpcm_fe_dai_do_trigger(substream,
- fe->dpcm[stream].trigger_pending - 1);
- fe->dpcm[stream].trigger_pending = 0;
- }
- fe->dpcm[stream].runtime_update = state;
- snd_pcm_stream_unlock_irq(substream);
+ dpcm_runtime_merge_format(substream, runtime);
+ dpcm_runtime_merge_chan(substream, runtime);
+ dpcm_runtime_merge_rate(substream, runtime);
}
static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream,
@@ -1791,7 +1747,6 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream,
static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
{
struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
- struct snd_pcm_runtime *runtime = fe_substream->runtime;
int stream = fe_substream->stream, ret = 0;
dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
@@ -1814,7 +1769,6 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
dpcm_set_fe_runtime(fe_substream);
- snd_pcm_limit_hw_rates(runtime);
ret = dpcm_apply_symmetry(fe_substream, stream);
if (ret < 0)
@@ -2432,7 +2386,7 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
snd_soc_dpcm_get_substream(fe, stream);
struct snd_soc_dpcm *dpcm;
enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
- int ret;
+ int ret = 0;
unsigned long flags;
dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n",
@@ -2440,8 +2394,13 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
/* Only start the BE if the FE is ready */
if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE ||
- fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
- return -EINVAL;
+ fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) {
+ ret = -EINVAL;
+ dev_err(fe->dev, "ASoC: FE %s is not ready %d\n",
+ fe->dai_link->name, fe->dpcm[stream].state);
+ ret = -EINVAL;
+ goto disconnect;
+ }
/* startup must always be called for new BEs */
ret = dpcm_be_dai_startup(fe, stream);
@@ -2502,12 +2461,18 @@ hw_free:
close:
dpcm_be_dai_shutdown(fe, stream);
disconnect:
- /* disconnect any closed BEs */
+ /* disconnect any pending BEs */
spin_lock_irqsave(&fe->card->dpcm_lock, flags);
for_each_dpcm_be(fe, stream, dpcm) {
struct snd_soc_pcm_runtime *be = dpcm->be;
- if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
- dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
+
+ /* is this op for this BE ? */
+ if (!snd_soc_dpcm_be_can_update(fe, be, stream))
+ continue;
+
+ if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE ||
+ be->dpcm[stream].state == SND_SOC_DPCM_STATE_NEW)
+ dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
}
spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
@@ -2671,15 +2636,11 @@ open_end:
return ret;
}
-/* create a new pcm */
-int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
+static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
+ int *playback, int *capture)
{
struct snd_soc_dai *codec_dai;
struct snd_soc_dai *cpu_dai;
- struct snd_soc_component *component;
- struct snd_pcm *pcm;
- char new_name[64];
- int ret = 0, playback = 0, capture = 0;
int stream;
int i;
@@ -2695,12 +2656,11 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
- playback = 1;
+ *playback = 1;
break;
}
}
-
- if (!playback) {
+ if (!*playback) {
dev_err(rtd->card->dev,
"No CPU DAIs support playback for stream %s\n",
rtd->dai_link->stream_name);
@@ -2712,12 +2672,12 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
- capture = 1;
+ *capture = 1;
break;
}
}
- if (!capture) {
+ if (!*capture) {
dev_err(rtd->card->dev,
"No CPU DAIs support capture for stream %s\n",
rtd->dai_link->stream_name);
@@ -2744,36 +2704,46 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
snd_soc_dai_stream_valid(cpu_dai, cpu_playback))
- playback = 1;
+ *playback = 1;
if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
snd_soc_dai_stream_valid(cpu_dai, cpu_capture))
- capture = 1;
+ *capture = 1;
}
}
if (rtd->dai_link->playback_only) {
- playback = 1;
- capture = 0;
+ *playback = 1;
+ *capture = 0;
}
if (rtd->dai_link->capture_only) {
- playback = 0;
- capture = 1;
+ *playback = 0;
+ *capture = 1;
}
+ return 0;
+}
+
+static int soc_create_pcm(struct snd_pcm **pcm,
+ struct snd_soc_pcm_runtime *rtd,
+ int playback, int capture, int num)
+{
+ char new_name[64];
+ int ret;
+
/* create the PCM */
if (rtd->dai_link->params) {
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,
- playback, capture, &pcm);
+ 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,
- playback, capture, &pcm);
+ playback, capture, pcm);
} else {
if (rtd->dai_link->dynamic)
snprintf(new_name, sizeof(new_name), "%s (*)",
@@ -2785,7 +2755,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
"multicodec" : asoc_rtd_to_codec(rtd, 0)->name, num);
ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
- capture, &pcm);
+ capture, pcm);
}
if (ret < 0) {
dev_err(rtd->card->dev, "ASoC: can't create pcm %s for dailink %s: %d\n",
@@ -2794,14 +2764,33 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
}
dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name);
+ return 0;
+}
+
+/* create a new pcm */
+int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
+{
+ struct snd_soc_component *component;
+ struct snd_pcm *pcm;
+ int ret = 0, playback = 0, capture = 0;
+ int i;
+
+ ret = soc_get_playback_capture(rtd, &playback, &capture);
+ if (ret < 0)
+ return ret;
+
+ ret = soc_create_pcm(&pcm, rtd, playback, capture, num);
+ if (ret < 0)
+ return ret;
+
/* DAPM dai link stream work */
if (rtd->dai_link->params)
rtd->close_delayed_work_func = codec2codec_close_delayed_work;
else
rtd->close_delayed_work_func = snd_soc_close_delayed_work;
- pcm->nonatomic = rtd->dai_link->nonatomic;
rtd->pcm = pcm;
+ pcm->nonatomic = rtd->dai_link->nonatomic;
pcm->private_data = rtd;
if (rtd->dai_link->no_pcm || rtd->dai_link->params) {
@@ -2854,8 +2843,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
ret = snd_soc_pcm_component_new(rtd);
if (ret < 0) {
- dev_err(rtd->dev, "ASoC: pcm %s constructor failed for dailink %s: %d\n",
- new_name, rtd->dai_link->name, ret);
+ dev_err(rtd->dev, "ASoC: pcm constructor failed for dailink %s: %d\n",
+ rtd->dai_link->name, ret);
return ret;
}
diff --git a/sound/soc/soc-topology-test.c b/sound/soc/soc-topology-test.c
new file mode 100644
index 000000000000..ae3968161509
--- /dev/null
+++ b/sound/soc/soc-topology-test.c
@@ -0,0 +1,843 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * soc-topology-test.c -- ALSA SoC Topology Kernel Unit Tests
+ *
+ * Copyright(c) 2021 Intel Corporation. All rights reserved.
+ */
+
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-topology.h>
+#include <kunit/test.h>
+
+/* ===== HELPER FUNCTIONS =================================================== */
+
+/*
+ * snd_soc_component needs device to operate on (primarily for prints), create
+ * fake one, as we don't register with PCI or anything else
+ * device_driver name is used in some of the prints (fmt_single_name) so
+ * we also mock up minimal one
+ */
+static struct device *test_dev;
+
+static struct device_driver test_drv = {
+ .name = "sound-soc-topology-test-driver",
+};
+
+static int snd_soc_tplg_test_init(struct kunit *test)
+{
+ test_dev = root_device_register("sound-soc-topology-test");
+ test_dev = get_device(test_dev);
+ if (!test_dev)
+ return -ENODEV;
+
+ test_dev->driver = &test_drv;
+
+ return 0;
+}
+
+static void snd_soc_tplg_test_exit(struct kunit *test)
+{
+ put_device(test_dev);
+ root_device_unregister(test_dev);
+}
+
+/*
+ * helper struct we use when registering component, as we load topology during
+ * component probe, we need to pass struct kunit somehow to probe function, so
+ * we can report test result
+ */
+struct kunit_soc_component {
+ struct kunit *kunit;
+ int expect; /* what result we expect when loading topology */
+ struct snd_soc_component comp;
+ struct snd_soc_card card;
+ struct firmware fw;
+};
+
+static int d_probe(struct snd_soc_component *component)
+{
+ struct kunit_soc_component *kunit_comp =
+ container_of(component, struct kunit_soc_component, comp);
+ int ret;
+
+ ret = snd_soc_tplg_component_load(component, NULL, &kunit_comp->fw);
+ KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret,
+ "Failed topology load");
+
+ return 0;
+}
+
+static void d_remove(struct snd_soc_component *component)
+{
+ struct kunit_soc_component *kunit_comp =
+ container_of(component, struct kunit_soc_component, comp);
+ int ret;
+
+ ret = snd_soc_tplg_component_remove(component);
+ KUNIT_EXPECT_EQ(kunit_comp->kunit, 0, ret);
+}
+
+/*
+ * ASoC minimal boiler plate
+ */
+SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY()));
+
+SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("sound-soc-topology-test")));
+
+static struct snd_soc_dai_link kunit_dai_links[] = {
+ {
+ .name = "KUNIT Audio Port",
+ .id = 0,
+ .stream_name = "Audio Playback/Capture",
+ .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),
+ },
+};
+
+static const struct snd_soc_component_driver test_component = {
+ .name = "sound-soc-topology-test",
+ .probe = d_probe,
+ .remove = d_remove,
+ .non_legacy_dai_naming = 1,
+};
+
+/* ===== TOPOLOGY TEMPLATES ================================================= */
+
+// Structural representation of topology which can be generated with:
+// $ touch empty
+// $ alsatplg -c empty -o empty.tplg
+// $ xxd -i empty.tplg
+
+struct tplg_tmpl_001 {
+ struct snd_soc_tplg_hdr header;
+ struct snd_soc_tplg_manifest manifest;
+} __packed;
+
+static struct tplg_tmpl_001 tplg_tmpl_empty = {
+ .header = {
+ .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC),
+ .abi = cpu_to_le32(5),
+ .version = 0,
+ .type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST),
+ .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)),
+ .vendor_type = 0,
+ .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
+ .index = 0,
+ .count = cpu_to_le32(1),
+ },
+
+ .manifest = {
+ .size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
+ /* rest of fields is 0 */
+ },
+};
+
+// Structural representation of topology containing SectionPCM
+
+struct tplg_tmpl_002 {
+ struct snd_soc_tplg_hdr header;
+ struct snd_soc_tplg_manifest manifest;
+ struct snd_soc_tplg_hdr pcm_header;
+ struct snd_soc_tplg_pcm pcm;
+} __packed;
+
+static struct tplg_tmpl_002 tplg_tmpl_with_pcm = {
+ .header = {
+ .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC),
+ .abi = cpu_to_le32(5),
+ .version = 0,
+ .type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST),
+ .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)),
+ .vendor_type = 0,
+ .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
+ .index = 0,
+ .count = cpu_to_le32(1),
+ },
+ .manifest = {
+ .size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
+ .pcm_elems = cpu_to_le32(1),
+ /* rest of fields is 0 */
+ },
+ .pcm_header = {
+ .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC),
+ .abi = cpu_to_le32(5),
+ .version = 0,
+ .type = cpu_to_le32(SND_SOC_TPLG_TYPE_PCM),
+ .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)),
+ .vendor_type = 0,
+ .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)),
+ .index = 0,
+ .count = cpu_to_le32(1),
+ },
+ .pcm = {
+ .size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)),
+ .pcm_name = "KUNIT Audio",
+ .dai_name = "kunit-audio-dai",
+ .pcm_id = 0,
+ .dai_id = 0,
+ .playback = cpu_to_le32(1),
+ .capture = cpu_to_le32(1),
+ .compress = 0,
+ .stream = {
+ [0] = {
+ .channels = cpu_to_le32(2),
+ },
+ [1] = {
+ .channels = cpu_to_le32(2),
+ },
+ },
+ .num_streams = 0,
+ .caps = {
+ [0] = {
+ .name = "kunit-audio-playback",
+ .channels_min = cpu_to_le32(2),
+ .channels_max = cpu_to_le32(2),
+ },
+ [1] = {
+ .name = "kunit-audio-capture",
+ .channels_min = cpu_to_le32(2),
+ .channels_max = cpu_to_le32(2),
+ },
+ },
+ .flag_mask = 0,
+ .flags = 0,
+ .priv = { 0 },
+ },
+};
+
+/* ===== TEST CASES ========================================================= */
+
+// TEST CASE
+// Test passing NULL component as parameter to snd_soc_tplg_component_load
+
+/*
+ * need to override generic probe function with one using NULL when calling
+ * topology load during component initialization, we don't need .remove
+ * handler as load should fail
+ */
+static int d_probe_null_comp(struct snd_soc_component *component)
+{
+ struct kunit_soc_component *kunit_comp =
+ container_of(component, struct kunit_soc_component, comp);
+ int ret;
+
+ /* instead of passing component pointer as first argument, pass NULL here */
+ ret = snd_soc_tplg_component_load(NULL, NULL, &kunit_comp->fw);
+ KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret,
+ "Failed topology load");
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver test_component_null_comp = {
+ .name = "sound-soc-topology-test",
+ .probe = d_probe_null_comp,
+ .non_legacy_dai_naming = 1,
+};
+
+static void snd_soc_tplg_test_load_with_null_comp(struct kunit *test)
+{
+ struct kunit_soc_component *kunit_comp;
+ int ret;
+
+ /* prepare */
+ kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+ kunit_comp->kunit = test;
+ kunit_comp->expect = -EINVAL; /* expect failure */
+
+ kunit_comp->card.dev = test_dev,
+ kunit_comp->card.name = "kunit-card",
+ kunit_comp->card.owner = THIS_MODULE,
+ kunit_comp->card.dai_link = kunit_dai_links,
+ kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+ kunit_comp->card.fully_routed = true,
+
+ /* run test */
+ ret = snd_soc_register_card(&kunit_comp->card);
+ if (ret != 0 && ret != -EPROBE_DEFER)
+ KUNIT_FAIL(test, "Failed to register card");
+
+ ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component_null_comp, test_dev);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ /* cleanup */
+ ret = snd_soc_unregister_card(&kunit_comp->card);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test passing NULL ops as parameter to snd_soc_tplg_component_load
+
+/*
+ * NULL ops is default case, we pass empty topology (fw), so we don't have
+ * anything to parse and just do nothing, which results in return 0; from
+ * calling soc_tplg_dapm_complete in soc_tplg_process_headers
+ */
+static void snd_soc_tplg_test_load_with_null_ops(struct kunit *test)
+{
+ struct kunit_soc_component *kunit_comp;
+ int ret;
+
+ /* prepare */
+ kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+ kunit_comp->kunit = test;
+ kunit_comp->expect = 0; /* expect success */
+
+ kunit_comp->card.dev = test_dev,
+ kunit_comp->card.name = "kunit-card",
+ kunit_comp->card.owner = THIS_MODULE,
+ kunit_comp->card.dai_link = kunit_dai_links,
+ kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+ kunit_comp->card.fully_routed = true,
+
+ /* run test */
+ ret = snd_soc_register_card(&kunit_comp->card);
+ if (ret != 0 && ret != -EPROBE_DEFER)
+ KUNIT_FAIL(test, "Failed to register card");
+
+ ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ /* cleanup */
+ ret = snd_soc_unregister_card(&kunit_comp->card);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test passing NULL fw as parameter to snd_soc_tplg_component_load
+
+/*
+ * need to override generic probe function with one using NULL pointer to fw
+ * when calling topology load during component initialization, we don't need
+ * .remove handler as load should fail
+ */
+static int d_probe_null_fw(struct snd_soc_component *component)
+{
+ struct kunit_soc_component *kunit_comp =
+ container_of(component, struct kunit_soc_component, comp);
+ int ret;
+
+ /* instead of passing fw pointer as third argument, pass NULL here */
+ ret = snd_soc_tplg_component_load(component, NULL, NULL);
+ KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret,
+ "Failed topology load");
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver test_component_null_fw = {
+ .name = "sound-soc-topology-test",
+ .probe = d_probe_null_fw,
+ .non_legacy_dai_naming = 1,
+};
+
+static void snd_soc_tplg_test_load_with_null_fw(struct kunit *test)
+{
+ struct kunit_soc_component *kunit_comp;
+ int ret;
+
+ /* prepare */
+ kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+ kunit_comp->kunit = test;
+ kunit_comp->expect = -EINVAL; /* expect failure */
+
+ kunit_comp->card.dev = test_dev,
+ kunit_comp->card.name = "kunit-card",
+ kunit_comp->card.owner = THIS_MODULE,
+ kunit_comp->card.dai_link = kunit_dai_links,
+ kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+ kunit_comp->card.fully_routed = true,
+
+ /* run test */
+ ret = snd_soc_register_card(&kunit_comp->card);
+ if (ret != 0 && ret != -EPROBE_DEFER)
+ KUNIT_FAIL(test, "Failed to register card");
+
+ ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component_null_fw, test_dev);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ /* cleanup */
+ ret = snd_soc_unregister_card(&kunit_comp->card);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test passing "empty" topology file
+static void snd_soc_tplg_test_load_empty_tplg(struct kunit *test)
+{
+ struct kunit_soc_component *kunit_comp;
+ struct tplg_tmpl_001 *data;
+ int size;
+ int ret;
+
+ /* prepare */
+ kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+ kunit_comp->kunit = test;
+ kunit_comp->expect = 0; /* expect success */
+
+ size = sizeof(tplg_tmpl_empty);
+ data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+ memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
+
+ kunit_comp->fw.data = (u8 *)data;
+ kunit_comp->fw.size = size;
+
+ kunit_comp->card.dev = test_dev,
+ kunit_comp->card.name = "kunit-card",
+ kunit_comp->card.owner = THIS_MODULE,
+ kunit_comp->card.dai_link = kunit_dai_links,
+ kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+ kunit_comp->card.fully_routed = true,
+
+ /* run test */
+ ret = snd_soc_register_card(&kunit_comp->card);
+ if (ret != 0 && ret != -EPROBE_DEFER)
+ KUNIT_FAIL(test, "Failed to register card");
+
+ ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ /* cleanup */
+ ret = snd_soc_unregister_card(&kunit_comp->card);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test "empty" topology file, but with bad "magic"
+// In theory we could loop through all possible bad values, but it takes too
+// long, so just use SND_SOC_TPLG_MAGIC + 1
+static void snd_soc_tplg_test_load_empty_tplg_bad_magic(struct kunit *test)
+{
+ struct kunit_soc_component *kunit_comp;
+ struct tplg_tmpl_001 *data;
+ int size;
+ int ret;
+
+ /* prepare */
+ kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+ kunit_comp->kunit = test;
+ kunit_comp->expect = -EINVAL; /* expect failure */
+
+ size = sizeof(tplg_tmpl_empty);
+ data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+ memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
+ /*
+ * override abi
+ * any value != magic number is wrong
+ */
+ data->header.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC + 1);
+
+ kunit_comp->fw.data = (u8 *)data;
+ kunit_comp->fw.size = size;
+
+ kunit_comp->card.dev = test_dev,
+ kunit_comp->card.name = "kunit-card",
+ kunit_comp->card.owner = THIS_MODULE,
+ kunit_comp->card.dai_link = kunit_dai_links,
+ kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+ kunit_comp->card.fully_routed = true,
+
+ /* run test */
+ ret = snd_soc_register_card(&kunit_comp->card);
+ if (ret != 0 && ret != -EPROBE_DEFER)
+ KUNIT_FAIL(test, "Failed to register card");
+
+ ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ /* cleanup */
+ ret = snd_soc_unregister_card(&kunit_comp->card);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test "empty" topology file, but with bad "abi"
+// In theory we could loop through all possible bad values, but it takes too
+// long, so just use SND_SOC_TPLG_ABI_VERSION + 1
+static void snd_soc_tplg_test_load_empty_tplg_bad_abi(struct kunit *test)
+{
+ struct kunit_soc_component *kunit_comp;
+ struct tplg_tmpl_001 *data;
+ int size;
+ int ret;
+
+ /* prepare */
+ kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+ kunit_comp->kunit = test;
+ kunit_comp->expect = -EINVAL; /* expect failure */
+
+ size = sizeof(tplg_tmpl_empty);
+ data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+ memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
+ /*
+ * override abi
+ * any value != accepted range is wrong
+ */
+ data->header.abi = cpu_to_le32(SND_SOC_TPLG_ABI_VERSION + 1);
+
+ kunit_comp->fw.data = (u8 *)data;
+ kunit_comp->fw.size = size;
+
+ kunit_comp->card.dev = test_dev,
+ kunit_comp->card.name = "kunit-card",
+ kunit_comp->card.owner = THIS_MODULE,
+ kunit_comp->card.dai_link = kunit_dai_links,
+ kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+ kunit_comp->card.fully_routed = true,
+
+ /* run test */
+ ret = snd_soc_register_card(&kunit_comp->card);
+ if (ret != 0 && ret != -EPROBE_DEFER)
+ KUNIT_FAIL(test, "Failed to register card");
+
+ ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ /* cleanup */
+ ret = snd_soc_unregister_card(&kunit_comp->card);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test "empty" topology file, but with bad "size"
+// In theory we could loop through all possible bad values, but it takes too
+// long, so just use sizeof(struct snd_soc_tplg_hdr) + 1
+static void snd_soc_tplg_test_load_empty_tplg_bad_size(struct kunit *test)
+{
+ struct kunit_soc_component *kunit_comp;
+ struct tplg_tmpl_001 *data;
+ int size;
+ int ret;
+
+ /* prepare */
+ kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+ kunit_comp->kunit = test;
+ kunit_comp->expect = -EINVAL; /* expect failure */
+
+ size = sizeof(tplg_tmpl_empty);
+ data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+ memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
+ /*
+ * override size
+ * any value != struct size is wrong
+ */
+ data->header.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr) + 1);
+
+ kunit_comp->fw.data = (u8 *)data;
+ kunit_comp->fw.size = size;
+
+ kunit_comp->card.dev = test_dev,
+ kunit_comp->card.name = "kunit-card",
+ kunit_comp->card.owner = THIS_MODULE,
+ kunit_comp->card.dai_link = kunit_dai_links,
+ kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+ kunit_comp->card.fully_routed = true,
+
+ /* run test */
+ ret = snd_soc_register_card(&kunit_comp->card);
+ if (ret != 0 && ret != -EPROBE_DEFER)
+ KUNIT_FAIL(test, "Failed to register card");
+
+ ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ /* cleanup */
+ ret = snd_soc_unregister_card(&kunit_comp->card);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ snd_soc_unregister_component(test_dev);
+}
+
+// TEST CASE
+// Test "empty" topology file, but with bad "payload_size"
+// In theory we could loop through all possible bad values, but it takes too
+// long, so just use the known wrong one
+static void snd_soc_tplg_test_load_empty_tplg_bad_payload_size(struct kunit *test)
+{
+ struct kunit_soc_component *kunit_comp;
+ struct tplg_tmpl_001 *data;
+ int size;
+ int ret;
+
+ /* prepare */
+ kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+ kunit_comp->kunit = test;
+ kunit_comp->expect = -EINVAL; /* expect failure */
+
+ size = sizeof(tplg_tmpl_empty);
+ data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+ memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
+ /*
+ * override payload size
+ * there is only explicit check for 0, so check with it, other values
+ * are handled by just not reading behind EOF
+ */
+ data->header.payload_size = 0;
+
+ kunit_comp->fw.data = (u8 *)data;
+ kunit_comp->fw.size = size;
+
+ kunit_comp->card.dev = test_dev,
+ kunit_comp->card.name = "kunit-card",
+ kunit_comp->card.owner = THIS_MODULE,
+ kunit_comp->card.dai_link = kunit_dai_links,
+ kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+ kunit_comp->card.fully_routed = true,
+
+ /* run test */
+ ret = snd_soc_register_card(&kunit_comp->card);
+ if (ret != 0 && ret != -EPROBE_DEFER)
+ KUNIT_FAIL(test, "Failed to register card");
+
+ ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ /* cleanup */
+ snd_soc_unregister_component(test_dev);
+
+ ret = snd_soc_unregister_card(&kunit_comp->card);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+}
+
+// TEST CASE
+// Test passing topology file with PCM definition
+static void snd_soc_tplg_test_load_pcm_tplg(struct kunit *test)
+{
+ struct kunit_soc_component *kunit_comp;
+ u8 *data;
+ int size;
+ int ret;
+
+ /* prepare */
+ kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+ kunit_comp->kunit = test;
+ kunit_comp->expect = 0; /* expect success */
+
+ size = sizeof(tplg_tmpl_with_pcm);
+ data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+ memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm));
+
+ kunit_comp->fw.data = data;
+ kunit_comp->fw.size = size;
+
+ kunit_comp->card.dev = test_dev,
+ kunit_comp->card.name = "kunit-card",
+ kunit_comp->card.owner = THIS_MODULE,
+ kunit_comp->card.dai_link = kunit_dai_links,
+ kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+ kunit_comp->card.fully_routed = true,
+
+ /* run test */
+ ret = snd_soc_register_card(&kunit_comp->card);
+ if (ret != 0 && ret != -EPROBE_DEFER)
+ KUNIT_FAIL(test, "Failed to register card");
+
+ ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ snd_soc_unregister_component(test_dev);
+
+ /* cleanup */
+ ret = snd_soc_unregister_card(&kunit_comp->card);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+}
+
+// TEST CASE
+// Test passing topology file with PCM definition
+// with component reload
+static void snd_soc_tplg_test_load_pcm_tplg_reload_comp(struct kunit *test)
+{
+ struct kunit_soc_component *kunit_comp;
+ u8 *data;
+ int size;
+ int ret;
+ int i;
+
+ /* prepare */
+ kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+ kunit_comp->kunit = test;
+ kunit_comp->expect = 0; /* expect success */
+
+ size = sizeof(tplg_tmpl_with_pcm);
+ data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+ memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm));
+
+ kunit_comp->fw.data = data;
+ kunit_comp->fw.size = size;
+
+ kunit_comp->card.dev = test_dev,
+ kunit_comp->card.name = "kunit-card",
+ kunit_comp->card.owner = THIS_MODULE,
+ kunit_comp->card.dai_link = kunit_dai_links,
+ kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+ kunit_comp->card.fully_routed = true,
+
+ /* run test */
+ ret = snd_soc_register_card(&kunit_comp->card);
+ if (ret != 0 && ret != -EPROBE_DEFER)
+ KUNIT_FAIL(test, "Failed to register card");
+
+ for (i = 0; i < 100; i++) {
+ ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ snd_soc_unregister_component(test_dev);
+ }
+
+ /* cleanup */
+ ret = snd_soc_unregister_card(&kunit_comp->card);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+}
+
+// TEST CASE
+// Test passing topology file with PCM definition
+// with card reload
+static void snd_soc_tplg_test_load_pcm_tplg_reload_card(struct kunit *test)
+{
+ struct kunit_soc_component *kunit_comp;
+ u8 *data;
+ int size;
+ int ret;
+ int i;
+
+ /* prepare */
+ kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
+ kunit_comp->kunit = test;
+ kunit_comp->expect = 0; /* expect success */
+
+ size = sizeof(tplg_tmpl_with_pcm);
+ data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
+
+ memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm));
+
+ kunit_comp->fw.data = data;
+ kunit_comp->fw.size = size;
+
+ kunit_comp->card.dev = test_dev,
+ kunit_comp->card.name = "kunit-card",
+ kunit_comp->card.owner = THIS_MODULE,
+ kunit_comp->card.dai_link = kunit_dai_links,
+ kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
+ kunit_comp->card.fully_routed = true,
+
+ /* run test */
+ ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+
+ for (i = 0; i < 100; i++) {
+ ret = snd_soc_register_card(&kunit_comp->card);
+ if (ret != 0 && ret != -EPROBE_DEFER)
+ KUNIT_FAIL(test, "Failed to register card");
+
+ ret = snd_soc_unregister_card(&kunit_comp->card);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+ }
+
+ /* cleanup */
+ snd_soc_unregister_component(test_dev);
+}
+
+/* ===== KUNIT MODULE DEFINITIONS =========================================== */
+
+static struct kunit_case snd_soc_tplg_test_cases[] = {
+ KUNIT_CASE(snd_soc_tplg_test_load_with_null_comp),
+ KUNIT_CASE(snd_soc_tplg_test_load_with_null_ops),
+ KUNIT_CASE(snd_soc_tplg_test_load_with_null_fw),
+ KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg),
+ KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_magic),
+ KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_abi),
+ KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_size),
+ KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_payload_size),
+ KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg),
+ KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg_reload_comp),
+ KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg_reload_card),
+ {}
+};
+
+static struct kunit_suite snd_soc_tplg_test_suite = {
+ .name = "snd_soc_tplg_test",
+ .init = snd_soc_tplg_test_init,
+ .exit = snd_soc_tplg_test_exit,
+ .test_cases = snd_soc_tplg_test_cases,
+};
+
+kunit_test_suites(&snd_soc_tplg_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 22e7b4c9115b..1b0cd33a1348 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -1672,7 +1672,7 @@ static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,
unsigned int flag_mask, unsigned int flags)
{
if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES)
- dai_drv->symmetric_rates =
+ dai_drv->symmetric_rate =
flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES ? 1 : 0;
if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS)
@@ -1681,7 +1681,7 @@ static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,
1 : 0;
if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS)
- dai_drv->symmetric_samplebits =
+ dai_drv->symmetric_sample_bits =
flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS ?
1 : 0;
}
@@ -1764,7 +1764,7 @@ static void set_link_flags(struct snd_soc_dai_link *link,
unsigned int flag_mask, unsigned int flags)
{
if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES)
- link->symmetric_rates =
+ link->symmetric_rate =
flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES ? 1 : 0;
if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS)
@@ -1773,7 +1773,7 @@ static void set_link_flags(struct snd_soc_dai_link *link,
1 : 0;
if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS)
- link->symmetric_samplebits =
+ link->symmetric_sample_bits =
flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS ?
1 : 0;
@@ -2660,8 +2660,14 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp,
struct soc_tplg tplg;
int ret;
- /* component needs to exist to keep and reference data while parsing */
- if (!comp)
+ /*
+ * check if we have sane parameters:
+ * comp - needs to exist to keep and reference data while parsing
+ * comp->dev - used for resource management and prints
+ * comp->card - used for setting card related parameters
+ * fw - we need it, as it is the very thing we parse
+ */
+ if (!comp || !comp->dev || !comp->card || !fw)
return -EINVAL;
/* setup parsing context */
@@ -2669,11 +2675,13 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp,
tplg.fw = fw;
tplg.dev = comp->dev;
tplg.comp = comp;
- tplg.ops = ops;
- tplg.io_ops = ops->io_ops;
- tplg.io_ops_count = ops->io_ops_count;
- tplg.bytes_ext_ops = ops->bytes_ext_ops;
- tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count;
+ if (ops) {
+ tplg.ops = ops;
+ tplg.io_ops = ops->io_ops;
+ tplg.io_ops_count = ops->io_ops_count;
+ tplg.bytes_ext_ops = ops->bytes_ext_ops;
+ tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count;
+ }
ret = soc_tplg_load(&tplg);
/* free the created components if fail to load topology */
diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c
index adc7c37145d6..6d8f7d9fd192 100644
--- a/sound/soc/sof/core.c
+++ b/sound/soc/sof/core.c
@@ -246,6 +246,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
if (plat_data->sof_probe_complete)
plat_data->sof_probe_complete(sdev->dev);
+ sdev->probe_completed = true;
+
return 0;
fw_trace_err:
@@ -316,6 +318,7 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
INIT_LIST_HEAD(&sdev->route_list);
spin_lock_init(&sdev->ipc_lock);
spin_lock_init(&sdev->hw_lock);
+ mutex_init(&sdev->power_state_access);
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
INIT_WORK(&sdev->probe_work, sof_probe_work);
@@ -339,6 +342,14 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
}
EXPORT_SYMBOL(snd_sof_device_probe);
+bool snd_sof_device_probe_completed(struct device *dev)
+{
+ struct snd_sof_dev *sdev = dev_get_drvdata(dev);
+
+ return sdev->probe_completed;
+}
+EXPORT_SYMBOL(snd_sof_device_probe_completed);
+
int snd_sof_device_remove(struct device *dev)
{
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
@@ -384,6 +395,14 @@ int snd_sof_device_remove(struct device *dev)
}
EXPORT_SYMBOL(snd_sof_device_remove);
+int snd_sof_device_shutdown(struct device *dev)
+{
+ struct snd_sof_dev *sdev = dev_get_drvdata(dev);
+
+ return snd_sof_shutdown(sdev);
+}
+EXPORT_SYMBOL(snd_sof_device_shutdown);
+
MODULE_AUTHOR("Liam Girdwood");
MODULE_DESCRIPTION("Sound Open Firmware (SOF) Core");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c
index 30213a1beaaa..715a374b33cf 100644
--- a/sound/soc/sof/debug.c
+++ b/sound/soc/sof/debug.c
@@ -352,7 +352,7 @@ static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer,
char *string;
int ret;
- string = kzalloc(count, GFP_KERNEL);
+ string = kzalloc(count+1, GFP_KERNEL);
if (!string)
return -ENOMEM;
diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c
index 789148e5584b..30025d3c16b6 100644
--- a/sound/soc/sof/intel/hda-bus.c
+++ b/sound/soc/sof/intel/hda-bus.c
@@ -9,6 +9,7 @@
#include <linux/io.h>
#include <sound/hdaudio.h>
+#include <sound/hda_i915.h>
#include "../sof-priv.h"
#include "hda.h"
@@ -19,13 +20,43 @@
#define sof_hda_ext_ops NULL
#endif
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+static void sof_hda_bus_link_power(struct hdac_device *codec, bool enable)
+{
+ struct hdac_bus *bus = codec->bus;
+ bool oldstate = test_bit(codec->addr, &bus->codec_powered);
+
+ snd_hdac_ext_bus_link_power(codec, enable);
+
+ if (enable == oldstate)
+ return;
+
+ /*
+ * Both codec driver and controller can hold references to
+ * display power. To avoid unnecessary power-up/down cycles,
+ * controller doesn't immediately release its reference.
+ *
+ * If the codec driver powers down the link, release
+ * the controller reference as well.
+ */
+ if (codec->addr == HDA_IDISP_ADDR && !enable)
+ snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
+}
+
+static const struct hdac_bus_ops bus_core_ops = {
+ .command = snd_hdac_bus_send_cmd,
+ .get_response = snd_hdac_bus_get_response,
+ .link_power = sof_hda_bus_link_power,
+};
+#endif
+
/*
* This can be used for both with/without hda link support.
*/
void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev)
{
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
- snd_hdac_ext_bus_init(bus, dev, NULL, sof_hda_ext_ops);
+ snd_hdac_ext_bus_init(bus, dev, &bus_core_ops, sof_hda_ext_ops);
#else /* CONFIG_SND_SOC_SOF_HDA */
memset(bus, 0, sizeof(*bus));
bus->dev = dev;
diff --git a/sound/soc/sof/intel/hda-compress.c b/sound/soc/sof/intel/hda-compress.c
index 53c08034fa22..fe2f3f7d236b 100644
--- a/sound/soc/sof/intel/hda-compress.c
+++ b/sound/soc/sof/intel/hda-compress.c
@@ -25,7 +25,7 @@ int hda_probe_compr_assign(struct snd_sof_dev *sdev,
{
struct hdac_ext_stream *stream;
- stream = hda_dsp_stream_get(sdev, cstream->direction);
+ stream = hda_dsp_stream_get(sdev, cstream->direction, 0);
if (!stream)
return -EBUSY;
@@ -82,7 +82,7 @@ int hda_probe_compr_set_params(struct snd_sof_dev *sdev,
ret = hda_dsp_stream_hw_params(sdev, stream, dmab, NULL);
if (ret < 0) {
- dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret);
+ dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
return ret;
}
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c
index 1c5e05b88a90..5788fe356960 100644
--- a/sound/soc/sof/intel/hda-dsp.c
+++ b/sound/soc/sof/intel/hda-dsp.c
@@ -624,7 +624,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
#endif
/* power down DSP */
- ret = hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask);
+ ret = snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask);
if (ret < 0) {
dev_err(sdev->dev,
"error: failed to power down core during suspend\n");
@@ -732,7 +732,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev)
ret = snd_hdac_ext_bus_link_power_up(hlink);
if (ret < 0) {
dev_dbg(sdev->dev,
- "error %x in %s: failed to power up links",
+ "error %d in %s: failed to power up links",
ret, __func__);
return ret;
}
@@ -802,11 +802,15 @@ int hda_dsp_runtime_idle(struct snd_sof_dev *sdev)
int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev)
{
+ struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
const struct sof_dsp_power_state target_state = {
.state = SOF_DSP_PM_D3,
};
int ret;
+ /* cancel any attempt for DSP D0I3 */
+ cancel_delayed_work_sync(&hda->d0i3_work);
+
/* stop hda controller and power dsp off */
ret = hda_suspend(sdev, true);
if (ret < 0)
@@ -930,19 +934,15 @@ void hda_dsp_d0i3_work(struct work_struct *work)
d0i3_work.work);
struct hdac_bus *bus = &hdev->hbus.core;
struct snd_sof_dev *sdev = dev_get_drvdata(bus->dev);
- struct sof_dsp_power_state target_state;
+ struct sof_dsp_power_state target_state = {
+ .state = SOF_DSP_PM_D0,
+ .substate = SOF_HDA_DSP_PM_D0I3,
+ };
int ret;
- target_state.state = SOF_DSP_PM_D0;
-
/* DSP can enter D0I3 iff only D0I3-compatible streams are active */
- if (snd_sof_dsp_only_d0i3_compatible_stream_active(sdev))
- target_state.substate = SOF_HDA_DSP_PM_D0I3;
- else
- target_state.substate = SOF_HDA_DSP_PM_D0I0;
-
- /* remain in D0I0 */
- if (target_state.substate == SOF_HDA_DSP_PM_D0I0)
+ if (!snd_sof_dsp_only_d0i3_compatible_stream_active(sdev))
+ /* remain in D0I0 */
return;
/* This can fail but error cannot be propagated */
diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c
index ed773696b495..fc25ee8f68dc 100644
--- a/sound/soc/sof/intel/hda-loader.c
+++ b/sound/soc/sof/intel/hda-loader.c
@@ -35,7 +35,7 @@ static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsig
struct pci_dev *pci = to_pci_dev(sdev->dev);
int ret;
- dsp_stream = hda_dsp_stream_get(sdev, direction);
+ dsp_stream = hda_dsp_stream_get(sdev, direction, 0);
if (!dsp_stream) {
dev_err(sdev->dev, "error: no stream available\n");
@@ -47,7 +47,7 @@ static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsig
/* allocate DMA buffer */
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, &pci->dev, size, dmab);
if (ret < 0) {
- dev_err(sdev->dev, "error: memory alloc failed: %x\n", ret);
+ dev_err(sdev->dev, "error: memory alloc failed: %d\n", ret);
goto error;
}
@@ -58,13 +58,13 @@ static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsig
if (direction == SNDRV_PCM_STREAM_CAPTURE) {
ret = hda_dsp_iccmax_stream_hw_params(sdev, dsp_stream, dmab, NULL);
if (ret < 0) {
- dev_err(sdev->dev, "error: iccmax stream prepare failed: %x\n", ret);
+ dev_err(sdev->dev, "error: iccmax stream prepare failed: %d\n", ret);
goto error;
}
} else {
ret = hda_dsp_stream_hw_params(sdev, dsp_stream, dmab, NULL);
if (ret < 0) {
- dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret);
+ dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
goto error;
}
hda_dsp_stream_spib_config(sdev, dsp_stream, HDA_DSP_SPIB_ENABLE, size);
@@ -93,7 +93,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag)
int i;
/* step 1: power up corex */
- ret = hda_dsp_core_power_up(sdev, chip->host_managed_cores_mask);
+ ret = snd_sof_dsp_core_power_up(sdev, chip->host_managed_cores_mask);
if (ret < 0) {
if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
dev_err(sdev->dev, "error: dsp core 0/1 power up failed\n");
@@ -147,8 +147,9 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag)
chip->ipc_ack_mask,
chip->ipc_ack_mask);
- /* step 5: power down corex */
- ret = hda_dsp_core_power_down(sdev, chip->host_managed_cores_mask & ~(BIT(0)));
+ /* step 5: power down cores that are no longer needed */
+ ret = snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask &
+ ~(chip->init_core_mask));
if (ret < 0) {
if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
dev_err(sdev->dev,
@@ -183,7 +184,7 @@ err:
flags |= SOF_DBG_DUMP_FORCE_ERR_LEVEL;
hda_dsp_dump(sdev, flags);
- hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask);
+ snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask);
return ret;
}
diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c
index 5d35bb18660a..df00db8369c7 100644
--- a/sound/soc/sof/intel/hda-pcm.c
+++ b/sound/soc/sof/intel/hda-pcm.c
@@ -111,7 +111,7 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev,
ret = hda_dsp_stream_hw_params(sdev, stream, dmab, params);
if (ret < 0) {
- dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret);
+ dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
return ret;
}
@@ -215,11 +215,25 @@ found:
int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream)
{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_soc_component *scomp = sdev->component;
struct hdac_ext_stream *dsp_stream;
+ struct snd_sof_pcm *spcm;
int direction = substream->stream;
+ u32 flags = 0;
+
+ spcm = snd_sof_find_spcm_dai(scomp, rtd);
+ if (!spcm) {
+ dev_err(sdev->dev, "error: can't find PCM with DAI ID %d\n", rtd->dai_link->id);
+ return -EINVAL;
+ }
- dsp_stream = hda_dsp_stream_get(sdev, direction);
+ /* All playback and D0i3 compatible streams are DMI L1 capable */
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK ||
+ spcm->stream[substream->stream].d0i3_compatible)
+ flags |= SOF_HDA_STREAM_DMI_L1_COMPATIBLE;
+ dsp_stream = hda_dsp_stream_get(sdev, direction, flags);
if (!dsp_stream) {
dev_err(sdev->dev, "error: no stream available\n");
return -ENODEV;
diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
index 0e09ede922c7..40a3993ae2cb 100644
--- a/sound/soc/sof/intel/hda-stream.c
+++ b/sound/soc/sof/intel/hda-stream.c
@@ -155,7 +155,7 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev,
/* get next unused stream */
struct hdac_ext_stream *
-hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction)
+hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags)
{
struct hdac_bus *bus = sof_to_bus(sdev);
struct sof_intel_hda_stream *hda_stream;
@@ -183,18 +183,22 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction)
spin_unlock_irq(&bus->reg_lock);
/* stream found ? */
- if (!stream)
+ if (!stream) {
dev_err(sdev->dev, "error: no free %s streams\n",
direction == SNDRV_PCM_STREAM_PLAYBACK ?
"playback" : "capture");
+ return stream;
+ }
+
+ hda_stream->flags = flags;
/*
- * Disable DMI Link L1 entry when capture stream is opened.
+ * Prevent DMI Link L1 entry for streams that don't support it.
* Workaround to address a known issue with host DMA that results
* in xruns during pause/release in capture scenarios.
*/
if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
- if (stream && direction == SNDRV_PCM_STREAM_CAPTURE)
+ if (stream && !(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE))
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
HDA_VS_INTEL_EM2,
HDA_VS_INTEL_EM2_L1SEN, 0);
@@ -206,37 +210,39 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction)
int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag)
{
struct hdac_bus *bus = sof_to_bus(sdev);
+ struct sof_intel_hda_stream *hda_stream;
+ struct hdac_ext_stream *stream;
struct hdac_stream *s;
- bool active_capture_stream = false;
+ bool dmi_l1_enable = true;
bool found = false;
spin_lock_irq(&bus->reg_lock);
/*
- * close stream matching the stream tag
- * and check if there are any open capture streams.
+ * close stream matching the stream tag and check if there are any open streams
+ * that are DMI L1 incompatible.
*/
list_for_each_entry(s, &bus->stream_list, list) {
+ stream = stream_to_hdac_ext_stream(s);
+ hda_stream = container_of(stream, struct sof_intel_hda_stream, hda_stream);
+
if (!s->opened)
continue;
if (s->direction == direction && s->stream_tag == stream_tag) {
s->opened = false;
found = true;
- } else if (s->direction == SNDRV_PCM_STREAM_CAPTURE) {
- active_capture_stream = true;
+ } else if (!(hda_stream->flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) {
+ dmi_l1_enable = false;
}
}
spin_unlock_irq(&bus->reg_lock);
- /* Enable DMI L1 entry if there are no capture streams open */
- if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
- if (!active_capture_stream)
- snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
- HDA_VS_INTEL_EM2,
- HDA_VS_INTEL_EM2_L1SEN,
- HDA_VS_INTEL_EM2_L1SEN);
+ /* Enable DMI L1 if permitted */
+ if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1) && dmi_l1_enable)
+ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2,
+ HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN);
if (!found) {
dev_dbg(sdev->dev, "stream_tag %d not opened!\n", stream_tag);
diff --git a/sound/soc/sof/intel/hda-trace.c b/sound/soc/sof/intel/hda-trace.c
index 1eb746d5adeb..29e3da3c63db 100644
--- a/sound/soc/sof/intel/hda-trace.c
+++ b/sound/soc/sof/intel/hda-trace.c
@@ -32,7 +32,7 @@ static int hda_dsp_trace_prepare(struct snd_sof_dev *sdev)
ret = hda_dsp_stream_hw_params(sdev, stream, dmab, NULL);
if (ret < 0)
- dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret);
+ dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
return ret;
}
@@ -42,8 +42,8 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, u32 *stream_tag)
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
int ret;
- hda->dtrace_stream = hda_dsp_stream_get(sdev,
- SNDRV_PCM_STREAM_CAPTURE);
+ hda->dtrace_stream = hda_dsp_stream_get(sdev, SNDRV_PCM_STREAM_CAPTURE,
+ SOF_HDA_STREAM_DMI_L1_COMPATIBLE);
if (!hda->dtrace_stream) {
dev_err(sdev->dev,
@@ -59,7 +59,7 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, u32 *stream_tag)
*/
ret = hda_dsp_trace_prepare(sdev);
if (ret < 0) {
- dev_err(sdev->dev, "error: hdac trace init failed: %x\n", ret);
+ dev_err(sdev->dev, "error: hdac trace init failed: %d\n", ret);
hda_dsp_stream_put(sdev, SNDRV_PCM_STREAM_CAPTURE, *stream_tag);
hda->dtrace_stream = NULL;
*stream_tag = 0;
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 509a9b256423..0dc3a8c0f5e3 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -285,11 +285,13 @@ static char *hda_model;
module_param(hda_model, charp, 0444);
MODULE_PARM_DESC(hda_model, "Use the given HDA board model.");
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) || IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
static int hda_dmic_num = -1;
module_param_named(dmic_num, hda_dmic_num, int, 0444);
MODULE_PARM_DESC(dmic_num, "SOF HDA DMIC number");
+#endif
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
static bool hda_codec_use_common_hdmi = IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI);
module_param_named(use_common_hdmi, hda_codec_use_common_hdmi, bool, 0444);
MODULE_PARM_DESC(use_common_hdmi, "SOF HDA use common HDMI codec driver");
@@ -317,26 +319,6 @@ static const struct hda_dsp_msg_code hda_dsp_rom_msg[] = {
{HDA_DSP_ROM_NULL_FW_ENTRY, "error: null FW entry point"},
};
-static void hda_dsp_get_status_skl(struct snd_sof_dev *sdev)
-{
- u32 status;
- int i;
-
- status = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
- HDA_ADSP_FW_STATUS_SKL);
-
- for (i = 0; i < ARRAY_SIZE(hda_dsp_rom_msg); i++) {
- if (status == hda_dsp_rom_msg[i].code) {
- dev_err(sdev->dev, "%s - code %8.8x\n",
- hda_dsp_rom_msg[i].msg, status);
- return;
- }
- }
-
- /* not for us, must be generic sof message */
- dev_dbg(sdev->dev, "unknown ROM status value %8.8x\n", status);
-}
-
static void hda_dsp_get_status(struct snd_sof_dev *sdev)
{
u32 status;
@@ -385,36 +367,6 @@ static void hda_dsp_get_registers(struct snd_sof_dev *sdev,
stack_words * sizeof(u32));
}
-void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags)
-{
- struct sof_ipc_dsp_oops_xtensa xoops;
- struct sof_ipc_panic_info panic_info;
- u32 stack[HDA_DSP_STACK_DUMP_SIZE];
- u32 status, panic;
-
- /* try APL specific status message types first */
- hda_dsp_get_status_skl(sdev);
-
- /* now try generic SOF status messages */
- status = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
- HDA_ADSP_ERROR_CODE_SKL);
-
- /*TODO: Check: there is no define in spec, but it is used in the code*/
- panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
- HDA_ADSP_ERROR_CODE_SKL + 0x4);
-
- if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) {
- hda_dsp_get_registers(sdev, &xoops, &panic_info, stack,
- HDA_DSP_STACK_DUMP_SIZE);
- snd_sof_get_status(sdev, status, panic, &xoops, &panic_info,
- stack, HDA_DSP_STACK_DUMP_SIZE);
- } else {
- dev_err(sdev->dev, "error: status = 0x%8.8x panic = 0x%8.8x\n",
- status, panic);
- hda_dsp_get_status_skl(sdev);
- }
-}
-
/* dump the first 8 dwords representing the extended ROM status */
static void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev, u32 flags)
{
@@ -555,7 +507,7 @@ static int hda_init(struct snd_sof_dev *sdev)
return ret;
}
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) || IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
static int check_nhlt_dmic(struct snd_sof_dev *sdev)
{
@@ -579,25 +531,76 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
const char *dmic_str)
{
const char *tplg_filename = NULL;
- char *filename;
- char *split_ext;
+ char *filename, *tmp;
+ const char *split_ext;
- filename = devm_kstrdup(sdev->dev, sof_tplg_filename, GFP_KERNEL);
+ filename = kstrdup(sof_tplg_filename, GFP_KERNEL);
if (!filename)
return NULL;
/* this assumes a .tplg extension */
- split_ext = strsep(&filename, ".");
- if (split_ext) {
+ tmp = filename;
+ split_ext = strsep(&tmp, ".");
+ if (split_ext)
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
"%s%s%s.tplg",
split_ext, idisp_str, dmic_str);
- if (!tplg_filename)
- return NULL;
- }
+ kfree(filename);
+
return tplg_filename;
}
+static int dmic_topology_fixup(struct snd_sof_dev *sdev,
+ const char **tplg_filename,
+ const char *idisp_str,
+ int *dmic_found)
+{
+ const char *default_tplg_filename = *tplg_filename;
+ const char *fixed_tplg_filename;
+ const char *dmic_str;
+ int dmic_num;
+
+ /* first check NHLT for DMICs */
+ dmic_num = check_nhlt_dmic(sdev);
+
+ /* allow for module parameter override */
+ if (hda_dmic_num != -1) {
+ dev_dbg(sdev->dev,
+ "overriding DMICs detected in NHLT tables %d by kernel param %d\n",
+ dmic_num, hda_dmic_num);
+ dmic_num = hda_dmic_num;
+ }
+
+ switch (dmic_num) {
+ case 1:
+ dmic_str = "-1ch";
+ break;
+ case 2:
+ dmic_str = "-2ch";
+ break;
+ case 3:
+ dmic_str = "-3ch";
+ break;
+ case 4:
+ dmic_str = "-4ch";
+ break;
+ default:
+ dmic_num = 0;
+ dmic_str = "";
+ break;
+ }
+
+ fixed_tplg_filename = fixup_tplg_name(sdev, default_tplg_filename,
+ idisp_str, dmic_str);
+ if (!fixed_tplg_filename)
+ return -ENOMEM;
+
+ dev_info(sdev->dev, "DMICs detected in NHLT tables: %d\n", dmic_num);
+ *dmic_found = dmic_num;
+ *tplg_filename = fixed_tplg_filename;
+
+ return 0;
+}
#endif
static int hda_init_caps(struct snd_sof_dev *sdev)
@@ -809,13 +812,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
sdev->mailbox_bar = HDA_DSP_BAR;
/* allow 64bit DMA address if supported by H/W */
- if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(64))) {
- dev_dbg(sdev->dev, "DMA mask is 64 bit\n");
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(64));
- } else {
+ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(64))) {
dev_dbg(sdev->dev, "DMA mask is 32 bit\n");
- dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
- dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32));
+ dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32));
}
/* init streams */
@@ -932,7 +931,7 @@ int hda_dsp_remove(struct snd_sof_dev *sdev)
/* disable cores */
if (chip)
- hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask);
+ snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask);
/* disable DSP */
snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
@@ -967,9 +966,9 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
struct snd_sof_pdata *pdata = sdev->pdata;
const char *tplg_filename;
const char *idisp_str;
- const char *dmic_str;
int dmic_num = 0;
int codec_num = 0;
+ int ret;
int i;
/* codec detection */
@@ -994,10 +993,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
if (!pdata->machine && codec_num <= 2) {
hda_mach = snd_soc_acpi_intel_hda_machines;
- /* topology: use the info from hda_machines */
- pdata->tplg_filename =
- hda_mach->sof_tplg_filename;
-
dev_info(bus->dev, "using HDA machine driver %s now\n",
hda_mach->drv_name);
@@ -1006,42 +1001,13 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
else
idisp_str = "";
- /* first check NHLT for DMICs */
- dmic_num = check_nhlt_dmic(sdev);
-
- /* allow for module parameter override */
- if (hda_dmic_num != -1)
- dmic_num = hda_dmic_num;
-
- switch (dmic_num) {
- case 1:
- dmic_str = "-1ch";
- break;
- case 2:
- dmic_str = "-2ch";
- break;
- case 3:
- dmic_str = "-3ch";
- break;
- case 4:
- dmic_str = "-4ch";
- break;
- default:
- dmic_num = 0;
- dmic_str = "";
- break;
- }
-
- tplg_filename = pdata->tplg_filename;
- tplg_filename = fixup_tplg_name(sdev, tplg_filename,
- idisp_str, dmic_str);
- if (!tplg_filename)
- return -EINVAL;
-
- dev_info(bus->dev,
- "DMICs detected in NHLT tables: %d\n",
- dmic_num);
+ /* topology: use the info from hda_machines */
+ tplg_filename = hda_mach->sof_tplg_filename;
+ ret = dmic_topology_fixup(sdev, &tplg_filename, idisp_str, &dmic_num);
+ if (ret < 0)
+ return ret;
+ hda_mach->mach_params.dmic_num = dmic_num;
pdata->machine = hda_mach;
pdata->tplg_filename = tplg_filename;
}
@@ -1053,7 +1019,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
&pdata->machine->mach_params;
mach_params->codec_mask = bus->codec_mask;
mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi;
- mach_params->dmic_num = dmic_num;
}
return 0;
@@ -1075,32 +1040,63 @@ static bool link_slaves_found(struct snd_sof_dev *sdev,
struct sdw_intel_slave_id *ids = sdw->ids;
int num_slaves = sdw->num_slaves;
unsigned int part_id, link_id, unique_id, mfg_id;
- int i, j;
+ int i, j, k;
for (i = 0; i < link->num_adr; i++) {
u64 adr = link->adr_d[i].adr;
+ int reported_part_count = 0;
mfg_id = SDW_MFG_ID(adr);
part_id = SDW_PART_ID(adr);
link_id = SDW_DISCO_LINK_ID(adr);
+
+ for (j = 0; j < num_slaves; 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)
+ reported_part_count++;
+ }
+
for (j = 0; j < num_slaves; 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)
continue;
- /*
- * we have to check unique id
- * if there is more than one
- * Slave on the link
- */
- unique_id = SDW_UNIQUE_ID(adr);
- if (link->num_adr == 1 ||
- ids[j].id.unique_id == SDW_IGNORED_UNIQUE_ID ||
- ids[j].id.unique_id == unique_id) {
- dev_dbg(bus->dev,
- "found %x at link %d\n",
- part_id, link_id);
- break;
+
+ /* find out how many identical parts are expected */
+ for (k = 0; k < link->num_adr; k++) {
+ u64 adr2 = link->adr_d[i].adr;
+ unsigned int part_id2, link_id2, mfg_id2;
+
+ mfg_id2 = SDW_MFG_ID(adr2);
+ part_id2 = SDW_PART_ID(adr2);
+ link_id2 = SDW_DISCO_LINK_ID(adr2);
+
+ if (link_id2 == link_id &&
+ part_id2 == part_id &&
+ mfg_id2 == mfg_id)
+ expected_part_count++;
+ }
+
+ if (reported_part_count == expected_part_count) {
+ /*
+ * we have to check unique id
+ * if there is more than one
+ * Slave on the link
+ */
+ unique_id = SDW_UNIQUE_ID(adr);
+ if (reported_part_count == 1 ||
+ ids[j].id.unique_id == unique_id) {
+ dev_dbg(bus->dev, "found %x at link %d\n",
+ part_id, link_id);
+ break;
+ }
+ } else {
+ dev_dbg(bus->dev, "part %x reported %d expected %d on link %d, skipping\n",
+ part_id, reported_part_count, expected_part_count, link_id);
}
}
if (j == num_slaves) {
@@ -1117,7 +1113,6 @@ static int 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 hdac_bus *bus = sof_to_bus(sdev);
struct snd_soc_acpi_mach *mach;
struct sof_intel_hda_dev *hdev;
u32 link_mask;
@@ -1165,16 +1160,42 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
break;
}
if (mach && mach->link_mask) {
- dev_dbg(bus->dev,
- "SoundWire machine driver %s topology %s\n",
- mach->drv_name,
- mach->sof_tplg_filename);
+ int dmic_num = 0;
+
pdata->machine = mach;
mach->mach_params.links = mach->links;
mach->mach_params.link_mask = mach->link_mask;
mach->mach_params.platform = dev_name(sdev->dev);
- pdata->fw_filename = mach->sof_fw_filename;
+ if (mach->sof_fw_filename)
+ pdata->fw_filename = mach->sof_fw_filename;
+ else
+ pdata->fw_filename = pdata->desc->default_fw_filename;
pdata->tplg_filename = mach->sof_tplg_filename;
+
+ /*
+ * DMICs use up to 4 pins and are typically pin-muxed with SoundWire
+ * link 2 and 3, thus we only try to enable dmics if all conditions
+ * are true:
+ * a) link 2 and 3 are not used by SoundWire
+ * b) the NHLT table reports the presence of microphones
+ */
+ if (!(mach->link_mask & GENMASK(3, 2))) {
+ const char *tplg_filename = mach->sof_tplg_filename;
+ int ret;
+
+ ret = dmic_topology_fixup(sdev, &tplg_filename, "", &dmic_num);
+
+ if (ret < 0)
+ return ret;
+
+ pdata->tplg_filename = tplg_filename;
+ }
+ mach->mach_params.dmic_num = dmic_num;
+
+ dev_dbg(sdev->dev,
+ "SoundWire machine driver %s topology %s\n",
+ mach->drv_name,
+ pdata->tplg_filename);
} else {
dev_info(sdev->dev,
"No SoundWire machine driver found\n");
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index a3b6f3e9121c..d1c38c37bc9d 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -388,7 +388,8 @@
#define SSP_SET_SFRM_SLAVE BIT(24)
#define SSP_SET_SLAVE (SSP_SET_SCLK_SLAVE | SSP_SET_SFRM_SLAVE)
-#define HDA_IDISP_CODEC(x) ((x) & BIT(2))
+#define HDA_IDISP_ADDR 2
+#define HDA_IDISP_CODEC(x) ((x) & BIT(HDA_IDISP_ADDR))
struct sof_intel_dsp_bdl {
__le32 addr_l;
@@ -402,6 +403,9 @@ struct sof_intel_dsp_bdl {
#define SOF_HDA_PLAYBACK 0
#define SOF_HDA_CAPTURE 1
+/* stream flags */
+#define SOF_HDA_STREAM_DMI_L1_COMPATIBLE 1
+
/*
* Time in ms for opportunistic D0I3 entry delay.
* This has been deliberately chosen to be long to avoid race conditions.
@@ -471,6 +475,7 @@ struct sof_intel_hda_stream {
struct hdac_ext_stream hda_stream;
struct sof_intel_stream stream;
int host_reserved; /* reserve host DMA channel */
+ u32 flags;
};
#define hstream_to_sof_hda_stream(hstream) \
@@ -513,7 +518,6 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev);
int hda_dsp_runtime_resume(struct snd_sof_dev *sdev);
int hda_dsp_runtime_idle(struct snd_sof_dev *sdev);
int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev);
-void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags);
void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags);
void hda_ipc_dump(struct snd_sof_dev *sdev);
void hda_ipc_irq_dump(struct snd_sof_dev *sdev);
@@ -562,7 +566,7 @@ bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev);
bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev);
struct hdac_ext_stream *
- hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction);
+ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags);
int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag);
int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev,
struct hdac_ext_stream *stream,
diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c
index 2252ca38ff4b..419f05ba1920 100644
--- a/sound/soc/sof/intel/tgl.c
+++ b/sound/soc/sof/intel/tgl.c
@@ -22,9 +22,10 @@ static const struct snd_sof_debugfs_map tgl_dsp_debugfs[] = {
/* Tigerlake ops */
const struct snd_sof_dsp_ops sof_tgl_ops = {
- /* probe and remove */
+ /* probe/remove/shutdown */
.probe = hda_dsp_probe,
.remove = hda_dsp_remove,
+ .shutdown = hda_dsp_remove,
/* Register IO */
.write = sof_io_write,
diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index fc13bb06dbf3..c2d07b783f60 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -106,6 +106,8 @@ static void ipc_log_header(struct device *dev, u8 *text, u32 cmd)
str2 = "CLK_REQ"; break;
case SOF_IPC_PM_CORE_ENABLE:
str2 = "CORE_ENABLE"; break;
+ case SOF_IPC_PM_GATE:
+ str2 = "GATE"; break;
default:
str2 = "unknown type"; break;
}
@@ -796,7 +798,7 @@ int snd_sof_ipc_valid(struct snd_sof_dev *sdev)
return -EINVAL;
}
- if (v->abi_version > SOF_ABI_VERSION) {
+ if (SOF_ABI_VERSION_MINOR(v->abi_version) > SOF_ABI_MINOR) {
if (!IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS)) {
dev_warn(sdev->dev, "warn: FW ABI is more recent than kernel\n");
} else {
diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c
index 08a17abb63ff..6efaf766f2ab 100644
--- a/sound/soc/sof/loader.c
+++ b/sound/soc/sof/loader.c
@@ -731,6 +731,8 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev)
if (ret < 0) {
dev_err(sdev->dev, "error: request firmware %s failed err: %d\n",
fw_filename, ret);
+ dev_err(sdev->dev,
+ "you may need to download the firmware from https://github.com/thesofproject/sof-bin/\n");
goto err;
} else {
dev_dbg(sdev->dev, "request_firmware %s successful\n",
@@ -811,7 +813,6 @@ EXPORT_SYMBOL(snd_sof_load_firmware);
int snd_sof_run_firmware(struct snd_sof_dev *sdev)
{
int ret;
- int init_core_mask;
init_waitqueue_head(&sdev->boot_wait);
@@ -843,8 +844,6 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev)
return ret;
}
- init_core_mask = ret;
-
/*
* now wait for the DSP to boot. There are 3 possible outcomes:
* 1. Boot wait times out indicating FW boot failure.
@@ -874,9 +873,6 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev)
return ret;
}
- /* fw boot is complete. Update the active cores mask */
- sdev->enabled_cores_mask = init_core_mask;
-
return 0;
}
EXPORT_SYMBOL(snd_sof_run_firmware);
diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
index 95e748b36903..5099ad03df72 100644
--- a/sound/soc/sof/ops.h
+++ b/sound/soc/sof/ops.h
@@ -37,6 +37,14 @@ static inline int snd_sof_remove(struct snd_sof_dev *sdev)
return 0;
}
+static inline int snd_sof_shutdown(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->shutdown)
+ return sof_ops(sdev)->shutdown(sdev);
+
+ return 0;
+}
+
/* control */
/*
@@ -68,19 +76,31 @@ static inline int snd_sof_dsp_reset(struct snd_sof_dev *sdev)
static inline int snd_sof_dsp_core_power_up(struct snd_sof_dev *sdev,
unsigned int core_mask)
{
- if (sof_ops(sdev)->core_power_up)
- return sof_ops(sdev)->core_power_up(sdev, core_mask);
+ int ret = 0;
- return 0;
+ core_mask &= ~sdev->enabled_cores_mask;
+ if (sof_ops(sdev)->core_power_up && core_mask) {
+ ret = sof_ops(sdev)->core_power_up(sdev, core_mask);
+ if (!ret)
+ sdev->enabled_cores_mask |= core_mask;
+ }
+
+ return ret;
}
static inline int snd_sof_dsp_core_power_down(struct snd_sof_dev *sdev,
unsigned int core_mask)
{
- if (sof_ops(sdev)->core_power_down)
- return sof_ops(sdev)->core_power_down(sdev, core_mask);
+ int ret = 0;
- return 0;
+ core_mask &= sdev->enabled_cores_mask;
+ if (sof_ops(sdev)->core_power_down && core_mask) {
+ ret = sof_ops(sdev)->core_power_down(sdev, core_mask);
+ if (!ret)
+ sdev->enabled_cores_mask &= ~core_mask;
+ }
+
+ return ret;
}
/* pre/post fw load */
@@ -208,11 +228,16 @@ static inline int
snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev,
const struct sof_dsp_power_state *target_state)
{
+ int ret = 0;
+
+ mutex_lock(&sdev->power_state_access);
+
if (sof_ops(sdev)->set_power_state)
- return sof_ops(sdev)->set_power_state(sdev, target_state);
+ ret = sof_ops(sdev)->set_power_state(sdev, target_state);
- /* D0 substate is not supported, do nothing here. */
- return 0;
+ mutex_unlock(&sdev->power_state_access);
+
+ return ret;
}
/* debug */
diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
index 0dc39fbcd81d..61c3fe17342d 100644
--- a/sound/soc/sof/pcm.c
+++ b/sound/soc/sof/pcm.c
@@ -707,7 +707,12 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
}
break;
case SOF_DAI_INTEL_ALH:
- /* do nothing for ALH dai_link */
+ /*
+ * Dai could run with different channel count compared with
+ * front end, so get dai channel count from topology
+ */
+ channels->min = dai->dai_config->alh.channels;
+ channels->max = dai->dai_config->alh.channels;
break;
case SOF_DAI_IMX_ESAI:
rate->min = dai->dai_config->esai.fsync_rate;
diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c
index c83fb6255961..fd265803f7bc 100644
--- a/sound/soc/sof/pm.c
+++ b/sound/soc/sof/pm.c
@@ -256,7 +256,6 @@ suspend:
/* reset FW state */
sdev->fw_state = SOF_FW_BOOT_NOT_STARTED;
- sdev->enabled_cores_mask = 0;
return ret;
}
diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c
index 215711ac7450..fd1f0d8c2853 100644
--- a/sound/soc/sof/sof-pci-dev.c
+++ b/sound/soc/sof/sof-pci-dev.c
@@ -66,6 +66,13 @@ static const struct dmi_system_id community_key_platforms[] = {
}
},
{
+ .ident = "Up Extreme",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
+ DMI_MATCH(DMI_BOARD_NAME, "UP-WHL01"),
+ }
+ },
+ {
.ident = "Google Chromebooks",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
@@ -213,7 +220,7 @@ static const struct sof_dev_desc icl_desc = {
};
#endif
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE)
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) || IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE)
static const struct sof_dev_desc tgl_desc = {
.machines = snd_soc_acpi_intel_tgl_machines,
.alt_machines = snd_soc_acpi_intel_tgl_sdw_machines,
@@ -230,7 +237,9 @@ static const struct sof_dev_desc tgl_desc = {
.nocodec_tplg_filename = "sof-tgl-nocodec.tplg",
.ops = &sof_tgl_ops,
};
+#endif
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE)
static const struct sof_dev_desc tglh_desc = {
.machines = snd_soc_acpi_intel_tgl_machines,
.alt_machines = snd_soc_acpi_intel_tgl_sdw_machines,
@@ -445,13 +454,19 @@ static void sof_pci_remove(struct pci_dev *pci)
snd_sof_device_remove(&pci->dev);
/* follow recommendation in pci-driver.c to increment usage counter */
- if (!(sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME))
+ if (snd_sof_device_probe_completed(&pci->dev) &&
+ !(sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME))
pm_runtime_get_noresume(&pci->dev);
/* release pci regions and disable device */
pci_release_regions(pci);
}
+static void sof_pci_shutdown(struct pci_dev *pci)
+{
+ snd_sof_device_shutdown(&pci->dev);
+}
+
/* PCI IDs */
static const struct pci_device_id sof_pci_ids[] = {
#if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD)
@@ -514,6 +529,8 @@ static const struct pci_device_id sof_pci_ids[] = {
#if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE)
{ PCI_DEVICE(0x8086, 0x7ad0),
.driver_data = (unsigned long)&adls_desc},
+ { PCI_DEVICE(0x8086, 0x51c8),
+ .driver_data = (unsigned long)&tgl_desc},
#endif
{ 0, }
};
@@ -525,6 +542,7 @@ static struct pci_driver snd_sof_pci_driver = {
.id_table = sof_pci_ids,
.probe = sof_pci_probe,
.remove = sof_pci_remove,
+ .shutdown = sof_pci_shutdown,
.driver = {
.pm = &sof_pci_pm,
},
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index 68da8f797403..ad0d7ba2708c 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -98,9 +98,10 @@ struct snd_sof_pdata;
*/
struct snd_sof_dsp_ops {
- /* probe and remove */
+ /* probe/remove/shutdown */
int (*probe)(struct snd_sof_dev *sof_dev); /* mandatory */
int (*remove)(struct snd_sof_dev *sof_dev); /* optional */
+ int (*shutdown)(struct snd_sof_dev *sof_dev); /* optional */
/* DSP core boot / reset */
int (*run)(struct snd_sof_dev *sof_dev); /* mandatory */
@@ -375,6 +376,8 @@ struct snd_sof_dev {
/* current DSP power state */
struct sof_dsp_power_state dsp_power_state;
+ /* mutex to protect the dsp_power_state access */
+ struct mutex power_state_access;
/* Intended power target of system suspend */
enum sof_system_suspend_state system_suspend_target;
@@ -386,6 +389,7 @@ struct snd_sof_dev {
/* work queue in case the probe is implemented in two steps */
struct work_struct probe_work;
+ bool probe_completed;
/* DSP HW differentiation */
struct snd_sof_pdata *pdata;
@@ -460,6 +464,8 @@ struct snd_sof_dev {
int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data);
int snd_sof_device_remove(struct device *dev);
+int snd_sof_device_shutdown(struct device *dev);
+bool snd_sof_device_probe_completed(struct device *dev);
int snd_sof_runtime_suspend(struct device *dev);
int snd_sof_runtime_resume(struct device *dev);
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index b6b32a7a91f8..10f99620eb31 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -1073,7 +1073,7 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
scontrol->cmd = SOF_CTRL_CMD_VOLUME;
/* extract tlv data */
- if (get_tlv_data(kc->tlv.p, tlv) < 0) {
+ if (!kc->tlv.p || get_tlv_data(kc->tlv.p, tlv) < 0) {
dev_err(scomp->dev, "error: invalid TLV data\n");
ret = -EINVAL;
goto out_free;
@@ -1352,10 +1352,6 @@ static int sof_core_enable(struct snd_sof_dev *sdev, int core)
core, ret);
goto err;
}
-
- /* update enabled cores mask */
- sdev->enabled_cores_mask |= BIT(core);
-
return ret;
err:
/* power down core if it is host managed and return the original error if this fails too */
@@ -2603,10 +2599,6 @@ static int sof_widget_unload(struct snd_soc_component *scomp,
if (ret < 0)
dev_err(scomp->dev, "error: powering down pipeline schedule core %d\n",
pipeline->core);
-
- /* update enabled cores mask */
- sdev->enabled_cores_mask &= ~(1 << pipeline->core);
-
break;
default:
break;
@@ -3666,7 +3658,7 @@ static int sof_manifest(struct snd_soc_component *scomp, int index,
return -EINVAL;
}
- if (abi_version > SOF_ABI_VERSION) {
+ if (SOF_ABI_VERSION_MINOR(abi_version) > SOF_ABI_MINOR) {
if (!IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS)) {
dev_warn(scomp->dev, "warn: topology ABI is more recent than kernel\n");
} else {
@@ -3740,6 +3732,8 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
if (ret < 0) {
dev_err(scomp->dev, "error: tplg request firmware %s failed err: %d\n",
file, ret);
+ dev_err(scomp->dev,
+ "you may need to download the firmware from https://github.com/thesofproject/sof-bin/\n");
return ret;
}
diff --git a/sound/soc/sprd/sprd-mcdt.c b/sound/soc/sprd/sprd-mcdt.c
index f439e5503a3c..34b2ce733b54 100644
--- a/sound/soc/sprd/sprd-mcdt.c
+++ b/sound/soc/sprd/sprd-mcdt.c
@@ -866,23 +866,23 @@ EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_disable);
struct sprd_mcdt_chan *sprd_mcdt_request_chan(u8 channel,
enum sprd_mcdt_channel_type type)
{
- struct sprd_mcdt_chan *temp, *chan = NULL;
+ struct sprd_mcdt_chan *temp;
mutex_lock(&sprd_mcdt_list_mutex);
list_for_each_entry(temp, &sprd_mcdt_chan_list, list) {
if (temp->type == type && temp->id == channel) {
- chan = temp;
+ list_del_init(&temp->list);
break;
}
}
- if (chan)
- list_del(&chan->list);
+ if (list_entry_is_head(temp, &sprd_mcdt_chan_list, list))
+ temp = NULL;
mutex_unlock(&sprd_mcdt_list_mutex);
- return chan;
+ return temp;
}
EXPORT_SYMBOL_GPL(sprd_mcdt_request_chan);
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
index 7c4d63c33f15..7d1672cf78cc 100644
--- a/sound/soc/stm/stm32_i2s.c
+++ b/sound/soc/stm/stm32_i2s.c
@@ -8,6 +8,7 @@
#include <linux/bitfield.h>
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of_irq.h>
@@ -196,6 +197,9 @@ enum i2s_datlen {
#define STM32_I2S_IS_MASTER(x) ((x)->ms_flg == I2S_MS_MASTER)
#define STM32_I2S_IS_SLAVE(x) ((x)->ms_flg == I2S_MS_SLAVE)
+#define STM32_I2S_NAME_LEN 32
+#define STM32_I2S_RATE_11K 11025
+
/**
* struct stm32_i2s_data - private data of I2S
* @regmap_conf: I2S register map configuration pointer
@@ -206,6 +210,7 @@ enum i2s_datlen {
* @dma_data_rx: dma configuration data for tx channel
* @substream: PCM substream data pointer
* @i2sclk: kernel clock feeding the I2S clock generator
+ * @i2smclk: master clock from I2S mclk provider
* @pclk: peripheral clock driving bus interface
* @x8kclk: I2S parent clock for sampling frequencies multiple of 8kHz
* @x11kclk: I2S parent clock for sampling frequencies multiple of 11kHz
@@ -215,6 +220,9 @@ enum i2s_datlen {
* @irq_lock: prevent race condition with IRQ
* @mclk_rate: master clock frequency (Hz)
* @fmt: DAI protocol
+ * @divider: prescaler division ratio
+ * @div: prescaler div field
+ * @odd: prescaler odd field
* @refcount: keep count of opened streams on I2S
* @ms_flg: master mode flag.
*/
@@ -227,6 +235,7 @@ struct stm32_i2s_data {
struct snd_dmaengine_dai_dma_data dma_data_rx;
struct snd_pcm_substream *substream;
struct clk *i2sclk;
+ struct clk *i2smclk;
struct clk *pclk;
struct clk *x8kclk;
struct clk *x11kclk;
@@ -236,10 +245,210 @@ struct stm32_i2s_data {
spinlock_t irq_lock; /* used to prevent race condition with IRQ */
unsigned int mclk_rate;
unsigned int fmt;
+ unsigned int divider;
+ unsigned int div;
+ bool odd;
int refcount;
int ms_flg;
};
+struct stm32_i2smclk_data {
+ struct clk_hw hw;
+ unsigned long freq;
+ struct stm32_i2s_data *i2s_data;
+};
+
+#define to_mclk_data(_hw) container_of(_hw, struct stm32_i2smclk_data, hw)
+
+static int stm32_i2s_calc_clk_div(struct stm32_i2s_data *i2s,
+ unsigned long input_rate,
+ unsigned long output_rate)
+{
+ unsigned int ratio, div, divider = 1;
+ bool odd;
+
+ ratio = DIV_ROUND_CLOSEST(input_rate, output_rate);
+
+ /* Check the parity of the divider */
+ odd = ratio & 0x1;
+
+ /* Compute the div prescaler */
+ div = ratio >> 1;
+
+ /* If div is 0 actual divider is 1 */
+ if (div) {
+ divider = ((2 * div) + odd);
+ dev_dbg(&i2s->pdev->dev, "Divider: 2*%d(div)+%d(odd) = %d\n",
+ div, odd, divider);
+ }
+
+ /* Division by three is not allowed by I2S prescaler */
+ if ((div == 1 && odd) || div > I2S_CGFR_I2SDIV_MAX) {
+ dev_err(&i2s->pdev->dev, "Wrong divider setting\n");
+ return -EINVAL;
+ }
+
+ if (input_rate % divider)
+ dev_dbg(&i2s->pdev->dev,
+ "Rate not accurate. requested (%ld), actual (%ld)\n",
+ output_rate, input_rate / divider);
+
+ i2s->div = div;
+ i2s->odd = odd;
+ i2s->divider = divider;
+
+ return 0;
+}
+
+static int stm32_i2s_set_clk_div(struct stm32_i2s_data *i2s)
+{
+ u32 cgfr, cgfr_mask;
+
+ cgfr = I2S_CGFR_I2SDIV_SET(i2s->div) | (i2s->odd << I2S_CGFR_ODD_SHIFT);
+ cgfr_mask = I2S_CGFR_I2SDIV_MASK | I2S_CGFR_ODD;
+
+ return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
+ cgfr_mask, cgfr);
+}
+
+static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s,
+ unsigned int rate)
+{
+ struct platform_device *pdev = i2s->pdev;
+ struct clk *parent_clk;
+ int ret;
+
+ if (!(rate % STM32_I2S_RATE_11K))
+ parent_clk = i2s->x11kclk;
+ else
+ parent_clk = i2s->x8kclk;
+
+ ret = clk_set_parent(i2s->i2sclk, parent_clk);
+ if (ret)
+ dev_err(&pdev->dev,
+ "Error %d setting i2sclk parent clock\n", ret);
+
+ return ret;
+}
+
+static long stm32_i2smclk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct stm32_i2smclk_data *mclk = to_mclk_data(hw);
+ struct stm32_i2s_data *i2s = mclk->i2s_data;
+ int ret;
+
+ ret = stm32_i2s_calc_clk_div(i2s, *prate, rate);
+ if (ret)
+ return ret;
+
+ mclk->freq = *prate / i2s->divider;
+
+ return mclk->freq;
+}
+
+static unsigned long stm32_i2smclk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct stm32_i2smclk_data *mclk = to_mclk_data(hw);
+
+ return mclk->freq;
+}
+
+static int stm32_i2smclk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct stm32_i2smclk_data *mclk = to_mclk_data(hw);
+ struct stm32_i2s_data *i2s = mclk->i2s_data;
+ int ret;
+
+ ret = stm32_i2s_calc_clk_div(i2s, parent_rate, rate);
+ if (ret)
+ return ret;
+
+ ret = stm32_i2s_set_clk_div(i2s);
+ if (ret)
+ return ret;
+
+ mclk->freq = rate;
+
+ return 0;
+}
+
+static int stm32_i2smclk_enable(struct clk_hw *hw)
+{
+ struct stm32_i2smclk_data *mclk = to_mclk_data(hw);
+ struct stm32_i2s_data *i2s = mclk->i2s_data;
+
+ dev_dbg(&i2s->pdev->dev, "Enable master clock\n");
+
+ return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
+ I2S_CGFR_MCKOE, I2S_CGFR_MCKOE);
+}
+
+static void stm32_i2smclk_disable(struct clk_hw *hw)
+{
+ struct stm32_i2smclk_data *mclk = to_mclk_data(hw);
+ struct stm32_i2s_data *i2s = mclk->i2s_data;
+
+ dev_dbg(&i2s->pdev->dev, "Disable master clock\n");
+
+ regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, I2S_CGFR_MCKOE, 0);
+}
+
+static const struct clk_ops mclk_ops = {
+ .enable = stm32_i2smclk_enable,
+ .disable = stm32_i2smclk_disable,
+ .recalc_rate = stm32_i2smclk_recalc_rate,
+ .round_rate = stm32_i2smclk_round_rate,
+ .set_rate = stm32_i2smclk_set_rate,
+};
+
+static int stm32_i2s_add_mclk_provider(struct stm32_i2s_data *i2s)
+{
+ struct clk_hw *hw;
+ struct stm32_i2smclk_data *mclk;
+ struct device *dev = &i2s->pdev->dev;
+ const char *pname = __clk_get_name(i2s->i2sclk);
+ char *mclk_name, *p, *s = (char *)pname;
+ int ret, i = 0;
+
+ mclk = devm_kzalloc(dev, sizeof(*mclk), GFP_KERNEL);
+ if (!mclk)
+ return -ENOMEM;
+
+ mclk_name = devm_kcalloc(dev, sizeof(char),
+ STM32_I2S_NAME_LEN, GFP_KERNEL);
+ if (!mclk_name)
+ return -ENOMEM;
+
+ /*
+ * Forge mclk clock name from parent clock name and suffix.
+ * String after "_" char is stripped in parent name.
+ */
+ p = mclk_name;
+ while (*s && *s != '_' && (i < (STM32_I2S_NAME_LEN - 7))) {
+ *p++ = *s++;
+ i++;
+ }
+ strcat(p, "_mclk");
+
+ mclk->hw.init = CLK_HW_INIT(mclk_name, pname, &mclk_ops, 0);
+ mclk->i2s_data = i2s;
+ hw = &mclk->hw;
+
+ dev_dbg(dev, "Register master clock %s\n", mclk_name);
+ ret = devm_clk_hw_register(&i2s->pdev->dev, hw);
+ if (ret) {
+ dev_err(dev, "mclk register fails with error %d\n", ret);
+ return ret;
+ }
+ i2s->i2smclk = hw->clk;
+
+ /* register mclk provider */
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
+}
+
static irqreturn_t stm32_i2s_isr(int irq, void *devid)
{
struct stm32_i2s_data *i2s = (struct stm32_i2s_data *)devid;
@@ -405,18 +614,46 @@ static int stm32_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq, int dir)
{
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
+ int ret = 0;
- dev_dbg(cpu_dai->dev, "I2S MCLK frequency is %uHz\n", freq);
+ dev_dbg(cpu_dai->dev, "I2S MCLK frequency is %uHz. mode: %s, dir: %s\n",
+ freq, STM32_I2S_IS_MASTER(i2s) ? "master" : "slave",
+ dir ? "output" : "input");
- if ((dir == SND_SOC_CLOCK_OUT) && STM32_I2S_IS_MASTER(i2s)) {
- i2s->mclk_rate = freq;
+ /* MCLK generation is available only in master mode */
+ if (dir == SND_SOC_CLOCK_OUT && STM32_I2S_IS_MASTER(i2s)) {
+ if (!i2s->i2smclk) {
+ dev_dbg(cpu_dai->dev, "No MCLK registered\n");
+ return 0;
+ }
- /* Enable master clock if master mode and mclk-fs are set */
- return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
- I2S_CGFR_MCKOE, I2S_CGFR_MCKOE);
+ /* Assume shutdown if requested frequency is 0Hz */
+ if (!freq) {
+ /* Release mclk rate only if rate was actually set */
+ if (i2s->mclk_rate) {
+ clk_rate_exclusive_put(i2s->i2smclk);
+ i2s->mclk_rate = 0;
+ }
+ 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);
+ if (ret)
+ return ret;
+ ret = clk_set_rate_exclusive(i2s->i2smclk, freq);
+ if (ret) {
+ dev_err(cpu_dai->dev, "Could not set mclk rate\n");
+ return ret;
+ }
+ ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
+ I2S_CGFR_MCKOE, I2S_CGFR_MCKOE);
+ if (!ret)
+ i2s->mclk_rate = freq;
}
- return 0;
+ return ret;
}
static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai,
@@ -424,11 +661,10 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai,
{
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
unsigned long i2s_clock_rate;
- unsigned int tmp, div, real_div, nb_bits, frame_len;
+ unsigned int nb_bits, frame_len;
unsigned int rate = params_rate(params);
+ u32 cgfr;
int ret;
- u32 cgfr, cgfr_mask;
- bool odd;
if (!(rate % 11025))
clk_set_parent(i2s->i2sclk, i2s->x11kclk);
@@ -449,7 +685,10 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai,
* dsp mode : div = i2s_clk / (nb_bits x ws)
*/
if (i2s->mclk_rate) {
- tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, i2s->mclk_rate);
+ ret = stm32_i2s_calc_clk_div(i2s, i2s_clock_rate,
+ i2s->mclk_rate);
+ if (ret)
+ return ret;
} else {
frame_len = 32;
if ((i2s->fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
@@ -462,34 +701,13 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai,
return ret;
nb_bits = frame_len * ((cgfr & I2S_CGFR_CHLEN) + 1);
- tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, (nb_bits * rate));
- }
-
- /* Check the parity of the divider */
- odd = tmp & 0x1;
-
- /* Compute the div prescaler */
- div = tmp >> 1;
-
- cgfr = I2S_CGFR_I2SDIV_SET(div) | (odd << I2S_CGFR_ODD_SHIFT);
- cgfr_mask = I2S_CGFR_I2SDIV_MASK | I2S_CGFR_ODD;
-
- real_div = ((2 * div) + odd);
- dev_dbg(cpu_dai->dev, "I2S clk: %ld, SCLK: %d\n",
- i2s_clock_rate, rate);
- dev_dbg(cpu_dai->dev, "Divider: 2*%d(div)+%d(odd) = %d\n",
- div, odd, real_div);
-
- if (((div == 1) && odd) || (div > I2S_CGFR_I2SDIV_MAX)) {
- dev_err(cpu_dai->dev, "Wrong divider setting\n");
- return -EINVAL;
+ ret = stm32_i2s_calc_clk_div(i2s, i2s_clock_rate,
+ (nb_bits * rate));
+ if (ret)
+ return ret;
}
- if (!div && !odd)
- dev_warn(cpu_dai->dev, "real divider forced to 1\n");
-
- ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
- cgfr_mask, cgfr);
+ ret = stm32_i2s_set_clk_div(i2s);
if (ret < 0)
return ret;
@@ -694,9 +912,6 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream,
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
unsigned long flags;
- regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
- I2S_CGFR_MCKOE, (unsigned int)~I2S_CGFR_MCKOE);
-
clk_disable_unprepare(i2s->i2sclk);
spin_lock_irqsave(&i2s->irq_lock, flags);
@@ -861,6 +1076,13 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
return PTR_ERR(i2s->x11kclk);
}
+ /* Register mclk provider if requested */
+ if (of_find_property(np, "#clock-cells", NULL)) {
+ ret = stm32_i2s_add_mclk_provider(i2s);
+ if (ret < 0)
+ return ret;
+ }
+
/* Get irqs */
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -906,16 +1128,16 @@ static int stm32_i2s_probe(struct platform_device *pdev)
if (!i2s)
return -ENOMEM;
- ret = stm32_i2s_parse_dt(pdev, i2s);
- if (ret)
- return ret;
-
i2s->pdev = pdev;
i2s->ms_flg = I2S_MS_NOT_SET;
spin_lock_init(&i2s->lock_fd);
spin_lock_init(&i2s->irq_lock);
platform_set_drvdata(pdev, i2s);
+ ret = stm32_i2s_parse_dt(pdev, i2s);
+ if (ret)
+ return ret;
+
ret = stm32_i2s_dais_init(pdev, i2s);
if (ret)
return ret;
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 4b8ca5be0a29..78506c3811dc 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -1105,7 +1105,7 @@ static struct snd_soc_dai_driver sun4i_i2s_dai = {
.formats = SUN4I_FORMATS,
},
.ops = &sun4i_i2s_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static const struct snd_soc_component_driver sun4i_i2s_component = {
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 180442c62be1..460924fc173f 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -640,9 +640,9 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = {
.rates = SUN8I_CODEC_PCM_RATES,
.formats = SUN8I_CODEC_PCM_FORMATS,
},
- .symmetric_rates = true,
+ .symmetric_rate = true,
.symmetric_channels = true,
- .symmetric_samplebits = true,
+ .symmetric_sample_bits = true,
},
{
.name = "sun8i-codec-aif2",
@@ -665,9 +665,9 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = {
.rates = SUN8I_CODEC_PCM_RATES,
.formats = SUN8I_CODEC_PCM_FORMATS,
},
- .symmetric_rates = true,
+ .symmetric_rate = true,
.symmetric_channels = true,
- .symmetric_samplebits = true,
+ .symmetric_sample_bits = true,
},
{
.name = "sun8i-codec-aif3",
@@ -690,9 +690,9 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = {
.rates = SUN8I_CODEC_PCM_RATES,
.formats = SUN8I_CODEC_PCM_FORMATS,
},
- .symmetric_rates = true,
+ .symmetric_rate = true,
.symmetric_channels = true,
- .symmetric_samplebits = true,
+ .symmetric_sample_bits = true,
},
};
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index a62cc87551ac..a4e6760944d0 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -9,9 +9,10 @@ config SND_SOC_TEGRA
help
Say Y or M here if you want support for SoC audio on Tegra.
+if SND_SOC_TEGRA
+
config SND_SOC_TEGRA20_AC97
tristate "Tegra20 AC97 interface"
- depends on SND_SOC_TEGRA
select SND_SOC_AC97_BUS
select SND_SOC_TEGRA20_DAS
help
@@ -21,7 +22,6 @@ config SND_SOC_TEGRA20_AC97
config SND_SOC_TEGRA20_DAS
tristate "Tegra20 DAS module"
- depends on SND_SOC_TEGRA
help
Say Y or M if you want to add support for the Tegra20 DAS module.
You will also need to select the individual machine drivers to
@@ -29,7 +29,6 @@ config SND_SOC_TEGRA20_DAS
config SND_SOC_TEGRA20_I2S
tristate "Tegra20 I2S interface"
- depends on SND_SOC_TEGRA
select SND_SOC_TEGRA20_DAS
help
Say Y or M if you want to add support for codecs attached to the
@@ -38,7 +37,6 @@ config SND_SOC_TEGRA20_I2S
config SND_SOC_TEGRA20_SPDIF
tristate "Tegra20 SPDIF interface"
- depends on SND_SOC_TEGRA
help
Say Y or M if you want to add support for the Tegra20 SPDIF interface.
You will also need to select the individual machine drivers to support
@@ -46,7 +44,6 @@ config SND_SOC_TEGRA20_SPDIF
config SND_SOC_TEGRA30_AHUB
tristate "Tegra30 AHUB module"
- depends on SND_SOC_TEGRA
help
Say Y or M if you want to add support for the Tegra30 AHUB module.
You will also need to select the individual machine drivers to
@@ -54,7 +51,6 @@ config SND_SOC_TEGRA30_AHUB
config SND_SOC_TEGRA30_I2S
tristate "Tegra30 I2S interface"
- depends on SND_SOC_TEGRA
select SND_SOC_TEGRA30_AHUB
help
Say Y or M if you want to add support for codecs attached to the
@@ -63,7 +59,6 @@ config SND_SOC_TEGRA30_I2S
config SND_SOC_TEGRA210_AHUB
tristate "Tegra210 AHUB module"
- depends on SND_SOC_TEGRA
help
Config to enable Audio Hub (AHUB) module, which comprises of a
switch called Audio Crossbar (AXBAR) used to configure or modify
@@ -73,7 +68,6 @@ config SND_SOC_TEGRA210_AHUB
config SND_SOC_TEGRA210_DMIC
tristate "Tegra210 DMIC module"
- depends on SND_SOC_TEGRA
help
Config to enable the Digital MIC (DMIC) controller which is used
to interface with Pulse Density Modulation (PDM) input devices.
@@ -84,7 +78,6 @@ config SND_SOC_TEGRA210_DMIC
config SND_SOC_TEGRA210_I2S
tristate "Tegra210 I2S module"
- depends on SND_SOC_TEGRA
help
Config to enable the Inter-IC Sound (I2S) Controller which
implements full-duplex and bidirectional and single direction
@@ -94,7 +87,6 @@ config SND_SOC_TEGRA210_I2S
config SND_SOC_TEGRA186_DSPK
tristate "Tegra186 DSPK module"
- depends on SND_SOC_TEGRA
help
Config to enable the Digital Speaker Controller (DSPK) which
converts the multi-bit Pulse Code Modulation (PCM) audio input to
@@ -107,7 +99,6 @@ config SND_SOC_TEGRA186_DSPK
config SND_SOC_TEGRA210_ADMAIF
tristate "Tegra210 ADMAIF module"
- depends on SND_SOC_TEGRA
help
Config to enable ADMAIF which is the interface between ADMA and
Audio Hub (AHUB). Each ADMA channel that sends/receives data to/
@@ -117,9 +108,18 @@ config SND_SOC_TEGRA210_ADMAIF
channel. Buffer size is configurable for each ADMAIIF channel.
Say Y or M if you want to add support for Tegra210 ADMAIF module.
+config SND_SOC_TEGRA_AUDIO_GRAPH_CARD
+ tristate "Audio Graph Card based Tegra driver"
+ depends on SND_AUDIO_GRAPH_CARD
+ help
+ Config to enable Tegra audio machine driver based on generic
+ audio graph driver. It is a thin driver written to customize
+ few things for Tegra audio. Most of the code is re-used from
+ audio graph driver and the same DT bindings are used.
+
config SND_SOC_TEGRA_RT5640
tristate "SoC Audio support for Tegra boards using an RT5640 codec"
- depends on SND_SOC_TEGRA && I2C && GPIOLIB
+ depends on I2C && GPIOLIB
select SND_SOC_RT5640
help
Say Y or M here if you want to add support for SoC audio on Tegra
@@ -127,7 +127,7 @@ config SND_SOC_TEGRA_RT5640
config SND_SOC_TEGRA_WM8753
tristate "SoC Audio support for Tegra boards using a WM8753 codec"
- depends on SND_SOC_TEGRA && I2C && GPIOLIB
+ depends on I2C && GPIOLIB
select SND_SOC_WM8753
help
Say Y or M here if you want to add support for SoC audio on Tegra
@@ -135,7 +135,7 @@ config SND_SOC_TEGRA_WM8753
config SND_SOC_TEGRA_WM8903
tristate "SoC Audio support for Tegra boards using a WM8903 codec"
- depends on SND_SOC_TEGRA && I2C && GPIOLIB
+ depends on I2C && GPIOLIB
select SND_SOC_WM8903
help
Say Y or M here if you want to add support for SoC audio on Tegra
@@ -144,7 +144,7 @@ config SND_SOC_TEGRA_WM8903
config SND_SOC_TEGRA_WM9712
tristate "SoC Audio support for Tegra boards using a WM9712 codec"
- depends on SND_SOC_TEGRA && GPIOLIB
+ depends on GPIOLIB
select SND_SOC_TEGRA20_AC97
select SND_SOC_WM9712
help
@@ -153,7 +153,7 @@ config SND_SOC_TEGRA_WM9712
config SND_SOC_TEGRA_TRIMSLICE
tristate "SoC Audio support for TrimSlice board"
- depends on SND_SOC_TEGRA && I2C
+ depends on I2C
select SND_SOC_TLV320AIC23_I2C
help
Say Y or M here if you want to add support for SoC audio on the
@@ -161,7 +161,7 @@ config SND_SOC_TEGRA_TRIMSLICE
config SND_SOC_TEGRA_ALC5632
tristate "SoC Audio support for Tegra boards using an ALC5632 codec"
- depends on SND_SOC_TEGRA && I2C && GPIOLIB
+ depends on I2C && GPIOLIB
select SND_SOC_ALC5632
help
Say Y or M here if you want to add support for SoC audio on the
@@ -169,7 +169,7 @@ config SND_SOC_TEGRA_ALC5632
config SND_SOC_TEGRA_MAX98090
tristate "SoC Audio support for Tegra boards using a MAX98090 codec"
- depends on SND_SOC_TEGRA && I2C && GPIOLIB
+ depends on I2C && GPIOLIB
select SND_SOC_MAX98090
help
Say Y or M here if you want to add support for SoC audio on Tegra
@@ -177,7 +177,7 @@ config SND_SOC_TEGRA_MAX98090
config SND_SOC_TEGRA_RT5677
tristate "SoC Audio support for Tegra boards using a RT5677 codec"
- depends on SND_SOC_TEGRA && I2C && GPIOLIB
+ depends on I2C && GPIOLIB
select SND_SOC_RT5677
help
Say Y or M here if you want to add support for SoC audio on Tegra
@@ -185,9 +185,11 @@ config SND_SOC_TEGRA_RT5677
config SND_SOC_TEGRA_SGTL5000
tristate "SoC Audio support for Tegra boards using a SGTL5000 codec"
- depends on SND_SOC_TEGRA && I2C && GPIOLIB
+ depends on I2C && GPIOLIB
select SND_SOC_SGTL5000
help
Say Y or M here if you want to add support for SoC audio on Tegra
boards using the SGTL5000 codec, such as Apalis T30, Apalis TK1 or
Colibri T30.
+
+endif
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 60040a06b814..b17dd6eef92a 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -38,6 +38,7 @@ snd-soc-tegra-trimslice-objs := trimslice.o
snd-soc-tegra-alc5632-objs := tegra_alc5632.o
snd-soc-tegra-max98090-objs := tegra_max98090.o
snd-soc-tegra-sgtl5000-objs := tegra_sgtl5000.o
+snd-soc-tegra-audio-graph-card-objs := tegra_audio_graph_card.o
obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o
obj-$(CONFIG_SND_SOC_TEGRA_RT5677) += snd-soc-tegra-rt5677.o
@@ -48,3 +49,4 @@ obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
obj-$(CONFIG_SND_SOC_TEGRA_MAX98090) += snd-soc-tegra-max98090.o
obj-$(CONFIG_SND_SOC_TEGRA_SGTL5000) += snd-soc-tegra-sgtl5000.o
+obj-$(CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD) += snd-soc-tegra-audio-graph-card.o
diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c
index 7d9948fb2ca7..8ee9a77bd83d 100644
--- a/sound/soc/tegra/tegra186_dspk.c
+++ b/sound/soc/tegra/tegra186_dspk.c
@@ -217,7 +217,7 @@ static struct snd_soc_dai_driver tegra186_dspk_dais[] = {
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra186_dspk_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index 005fc4e645aa..d7a3d046c8f8 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -260,7 +260,7 @@ static const struct snd_soc_dai_driver tegra20_i2s_dai_template = {
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.ops = &tegra20_i2s_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static const struct snd_soc_component_driver tegra20_i2s_component = {
diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c
index ead2c99bf72e..b096478cd2ef 100644
--- a/sound/soc/tegra/tegra210_dmic.c
+++ b/sound/soc/tegra/tegra210_dmic.c
@@ -228,7 +228,7 @@ static struct snd_soc_dai_driver tegra210_dmic_dais[] = {
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_dmic_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c
index ca31ec92e508..45f31ccb49d8 100644
--- a/sound/soc/tegra/tegra210_i2s.c
+++ b/sound/soc/tegra/tegra210_i2s.c
@@ -577,7 +577,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = {
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_i2s_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
};
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index 156e3b9d613c..9ef05ca4f6c4 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -45,8 +45,7 @@ static int tegra30_ahub_runtime_suspend(struct device *dev)
regcache_cache_only(ahub->regmap_apbif, true);
regcache_cache_only(ahub->regmap_ahub, true);
- clk_disable_unprepare(ahub->clk_apbif);
- clk_disable_unprepare(ahub->clk_d_audio);
+ clk_bulk_disable_unprepare(ahub->nclocks, ahub->clocks);
return 0;
}
@@ -66,22 +65,39 @@ static int tegra30_ahub_runtime_resume(struct device *dev)
{
int ret;
- ret = clk_prepare_enable(ahub->clk_d_audio);
- if (ret) {
- dev_err(dev, "clk_enable d_audio failed: %d\n", ret);
+ ret = reset_control_assert(ahub->reset);
+ if (ret)
return ret;
- }
- ret = clk_prepare_enable(ahub->clk_apbif);
- if (ret) {
- dev_err(dev, "clk_enable apbif failed: %d\n", ret);
- clk_disable(ahub->clk_d_audio);
+
+ ret = clk_bulk_prepare_enable(ahub->nclocks, ahub->clocks);
+ if (ret)
return ret;
- }
+
+ usleep_range(10, 100);
+
+ ret = reset_control_deassert(ahub->reset);
+ if (ret)
+ goto disable_clocks;
regcache_cache_only(ahub->regmap_apbif, false);
regcache_cache_only(ahub->regmap_ahub, false);
+ regcache_mark_dirty(ahub->regmap_apbif);
+ regcache_mark_dirty(ahub->regmap_ahub);
+
+ ret = regcache_sync(ahub->regmap_apbif);
+ if (ret)
+ goto disable_clocks;
+
+ ret = regcache_sync(ahub->regmap_ahub);
+ if (ret)
+ goto disable_clocks;
return 0;
+
+disable_clocks:
+ clk_bulk_disable_unprepare(ahub->nclocks, ahub->clocks);
+
+ return ret;
}
int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
@@ -337,6 +353,8 @@ static const struct {
const char *rst_name;
u32 mod_list_mask;
} configlink_mods[] = {
+ { "d_audio", MOD_LIST_MASK_TEGRA30_OR_LATER },
+ { "apbif", MOD_LIST_MASK_TEGRA30_OR_LATER },
{ "i2s0", MOD_LIST_MASK_TEGRA30_OR_LATER },
{ "i2s1", MOD_LIST_MASK_TEGRA30_OR_LATER },
{ "i2s2", MOD_LIST_MASK_TEGRA30_OR_LATER },
@@ -526,7 +544,6 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
/*
* The AHUB hosts a register bus: the "configlink". For this to
* operate correctly, all devices on this bus must be out of reset.
- * Ensure that here.
*/
for (i = 0; i < ARRAY_SIZE(configlink_mods); i++) {
if (!(configlink_mods[i].mod_list_mask &
@@ -542,10 +559,8 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
return ret;
}
- ret = reset_control_deassert(rst);
+ /* just check presence of the reset control in DT */
reset_control_put(rst);
- if (ret)
- return ret;
}
ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub),
@@ -557,18 +572,17 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
ahub->soc_data = soc_data;
ahub->dev = &pdev->dev;
- ahub->clk_d_audio = devm_clk_get(&pdev->dev, "d_audio");
- if (IS_ERR(ahub->clk_d_audio)) {
- dev_err(&pdev->dev, "Can't retrieve ahub d_audio clock\n");
- ret = PTR_ERR(ahub->clk_d_audio);
- return ret;
- }
+ ahub->clocks[ahub->nclocks++].id = "apbif";
+ ahub->clocks[ahub->nclocks++].id = "d_audio";
- ahub->clk_apbif = devm_clk_get(&pdev->dev, "apbif");
- if (IS_ERR(ahub->clk_apbif)) {
- dev_err(&pdev->dev, "Can't retrieve ahub apbif clock\n");
- ret = PTR_ERR(ahub->clk_apbif);
+ ret = devm_clk_bulk_get(&pdev->dev, ahub->nclocks, ahub->clocks);
+ if (ret)
return ret;
+
+ ahub->reset = devm_reset_control_array_get_exclusive(&pdev->dev);
+ if (IS_ERR(ahub->reset)) {
+ dev_err(&pdev->dev, "Can't get resets: %pe\n", ahub->reset);
+ return PTR_ERR(ahub->reset);
}
res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h
index 6889c5f23d02..3b85244f87f1 100644
--- a/sound/soc/tegra/tegra30_ahub.h
+++ b/sound/soc/tegra/tegra30_ahub.h
@@ -511,8 +511,9 @@ struct tegra30_ahub_soc_data {
struct tegra30_ahub {
const struct tegra30_ahub_soc_data *soc_data;
struct device *dev;
- struct clk *clk_d_audio;
- struct clk *clk_apbif;
+ struct reset_control *reset;
+ struct clk_bulk_data clocks[2];
+ unsigned int nclocks;
resource_size_t apbif_addr;
struct regmap *regmap_apbif;
struct regmap *regmap_ahub;
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index db5a8587bfa4..6740df541508 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -316,7 +316,7 @@ static const struct snd_soc_dai_driver tegra30_i2s_dai_template = {
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.ops = &tegra30_i2s_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
};
static const struct snd_soc_component_driver tegra30_i2s_component = {
diff --git a/sound/soc/tegra/tegra_audio_graph_card.c b/sound/soc/tegra/tegra_audio_graph_card.c
new file mode 100644
index 000000000000..ddedf18adde1
--- /dev/null
+++ b/sound/soc/tegra/tegra_audio_graph_card.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// tegra_audio_graph_card.c - Audio Graph based Tegra Machine Driver
+//
+// Copyright (c) 2020-2021 NVIDIA CORPORATION. All rights reserved.
+
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <sound/graph_card.h>
+#include <sound/pcm_params.h>
+
+#define MAX_PLLA_OUT0_DIV 128
+
+#define simple_to_tegra_priv(simple) \
+ container_of(simple, struct tegra_audio_priv, simple)
+
+enum srate_type {
+ /*
+ * Sample rates multiple of 8000 Hz and below are supported:
+ * ( 8000, 16000, 32000, 48000, 96000, 192000 Hz )
+ */
+ x8_RATE,
+
+ /*
+ * Sample rates multiple of 11025 Hz and below are supported:
+ * ( 11025, 22050, 44100, 88200, 176400 Hz )
+ */
+ x11_RATE,
+
+ NUM_RATE_TYPE,
+};
+
+struct tegra_audio_priv {
+ struct asoc_simple_priv simple;
+ struct clk *clk_plla_out0;
+ struct clk *clk_plla;
+};
+
+/* Tegra audio chip data */
+struct tegra_audio_cdata {
+ unsigned int plla_rates[NUM_RATE_TYPE];
+ unsigned int plla_out0_rates[NUM_RATE_TYPE];
+};
+
+/* Setup PLL clock as per the given sample rate */
+static int tegra_audio_graph_update_pll(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct asoc_simple_priv *simple = snd_soc_card_get_drvdata(rtd->card);
+ struct tegra_audio_priv *priv = simple_to_tegra_priv(simple);
+ struct device *dev = rtd->card->dev;
+ const struct tegra_audio_cdata *data = of_device_get_match_data(dev);
+ unsigned int plla_rate, plla_out0_rate, bclk;
+ unsigned int srate = params_rate(params);
+ int err;
+
+ switch (srate) {
+ case 11025:
+ case 22050:
+ case 44100:
+ case 88200:
+ case 176400:
+ plla_out0_rate = data->plla_out0_rates[x11_RATE];
+ plla_rate = data->plla_rates[x11_RATE];
+ break;
+ case 8000:
+ case 16000:
+ case 32000:
+ case 48000:
+ case 96000:
+ case 192000:
+ plla_out0_rate = data->plla_out0_rates[x8_RATE];
+ plla_rate = data->plla_rates[x8_RATE];
+ break;
+ default:
+ dev_err(rtd->card->dev, "Unsupported sample rate %u\n",
+ srate);
+ return -EINVAL;
+ }
+
+ /*
+ * Below is the clock relation:
+ *
+ * PLLA
+ * |
+ * |--> PLLA_OUT0
+ * |
+ * |---> I2S modules
+ * |
+ * |---> DMIC modules
+ * |
+ * |---> DSPK modules
+ *
+ *
+ * Default PLLA_OUT0 rate might be too high when I/O is running
+ * at minimum PCM configurations. This may result in incorrect
+ * clock rates and glitchy audio. The maximum divider is 128
+ * and any thing higher than that won't work. Thus reduce PLLA_OUT0
+ * to work for lower configurations.
+ *
+ * This problem is seen for I2S only, as DMIC and DSPK minimum
+ * clock requirements are under allowed divider limits.
+ */
+ bclk = srate * params_channels(params) * params_width(params);
+ if (div_u64(plla_out0_rate, bclk) > MAX_PLLA_OUT0_DIV)
+ plla_out0_rate >>= 1;
+
+ dev_dbg(rtd->card->dev,
+ "Update clock rates: PLLA(= %u Hz) and PLLA_OUT0(= %u Hz)\n",
+ plla_rate, plla_out0_rate);
+
+ /* Set PLLA rate */
+ err = clk_set_rate(priv->clk_plla, plla_rate);
+ if (err) {
+ dev_err(rtd->card->dev,
+ "Can't set plla rate for %u, err: %d\n",
+ plla_rate, err);
+ return err;
+ }
+
+ /* Set PLLA_OUT0 rate */
+ err = clk_set_rate(priv->clk_plla_out0, plla_out0_rate);
+ if (err) {
+ dev_err(rtd->card->dev,
+ "Can't set plla_out0 rate %u, err: %d\n",
+ plla_out0_rate, err);
+ return err;
+ }
+
+ return err;
+}
+
+static int tegra_audio_graph_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ int err;
+
+ /*
+ * This gets called for each DAI link (FE or BE) when DPCM is used.
+ * We may not want to update PLLA rate for each call. So PLLA update
+ * must be restricted to external I/O links (I2S, DMIC or DSPK) since
+ * they actually depend on it. I/O modules update their clocks in
+ * hw_param() of their respective component driver and PLLA rate
+ * update here helps them to derive appropriate rates.
+ *
+ * TODO: When more HW accelerators get added (like sample rate
+ * converter, volume gain controller etc., which don't really
+ * depend on PLLA) we need a better way to filter here.
+ */
+ if (cpu_dai->driver->ops && rtd->dai_link->no_pcm) {
+ err = tegra_audio_graph_update_pll(substream, params);
+ if (err)
+ return err;
+ }
+
+ return asoc_simple_hw_params(substream, params);
+}
+
+static const struct snd_soc_ops tegra_audio_graph_ops = {
+ .startup = asoc_simple_startup,
+ .shutdown = asoc_simple_shutdown,
+ .hw_params = tegra_audio_graph_hw_params,
+};
+
+static int tegra_audio_graph_card_probe(struct snd_soc_card *card)
+{
+ struct asoc_simple_priv *simple = snd_soc_card_get_drvdata(card);
+ struct tegra_audio_priv *priv = simple_to_tegra_priv(simple);
+
+ priv->clk_plla = devm_clk_get(card->dev, "pll_a");
+ if (IS_ERR(priv->clk_plla)) {
+ dev_err(card->dev, "Can't retrieve clk pll_a\n");
+ return PTR_ERR(priv->clk_plla);
+ }
+
+ priv->clk_plla_out0 = devm_clk_get(card->dev, "plla_out0");
+ if (IS_ERR(priv->clk_plla_out0)) {
+ dev_err(card->dev, "Can't retrieve clk plla_out0\n");
+ return PTR_ERR(priv->clk_plla_out0);
+ }
+
+ return audio_graph_card_probe(card);
+}
+
+static int tegra_audio_graph_probe(struct platform_device *pdev)
+{
+ struct tegra_audio_priv *priv;
+ struct device *dev = &pdev->dev;
+ struct snd_soc_card *card;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ card = simple_priv_to_card(&priv->simple);
+
+ card->probe = tegra_audio_graph_card_probe;
+
+ /* audio_graph_parse_of() depends on below */
+ card->component_chaining = 1;
+ priv->simple.ops = &tegra_audio_graph_ops;
+ priv->simple.force_dpcm = 1;
+
+ return audio_graph_parse_of(&priv->simple, dev);
+}
+
+static const struct tegra_audio_cdata tegra210_data = {
+ /* PLLA */
+ .plla_rates[x8_RATE] = 368640000,
+ .plla_rates[x11_RATE] = 338688000,
+ /* PLLA_OUT0 */
+ .plla_out0_rates[x8_RATE] = 49152000,
+ .plla_out0_rates[x11_RATE] = 45158400,
+};
+
+static const struct tegra_audio_cdata tegra186_data = {
+ /* PLLA */
+ .plla_rates[x8_RATE] = 245760000,
+ .plla_rates[x11_RATE] = 270950400,
+ /* PLLA_OUT0 */
+ .plla_out0_rates[x8_RATE] = 49152000,
+ .plla_out0_rates[x11_RATE] = 45158400,
+};
+
+static const struct of_device_id graph_of_tegra_match[] = {
+ { .compatible = "nvidia,tegra210-audio-graph-card",
+ .data = &tegra210_data },
+ { .compatible = "nvidia,tegra186-audio-graph-card",
+ .data = &tegra186_data },
+ {},
+};
+MODULE_DEVICE_TABLE(of, graph_of_tegra_match);
+
+static struct platform_driver tegra_audio_graph_card = {
+ .driver = {
+ .name = "tegra-audio-graph-card",
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = graph_of_tegra_match,
+ },
+ .probe = tegra_audio_graph_probe,
+ .remove = audio_graph_remove,
+};
+module_platform_driver(tegra_audio_graph_card);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ASoC Tegra Audio Graph Sound Card");
+MODULE_AUTHOR("Sameer Pujar <spujar@nvidia.com>");
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index b3f36515cbc1..573374b89b10 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -255,11 +255,7 @@ static int tegra_pcm_dma_allocate(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm *pcm = rtd->pcm;
int ret;
- ret = dma_set_mask(card->dev, DMA_BIT_MASK(32));
- if (ret < 0)
- return ret;
-
- ret = dma_set_coherent_mask(card->dev, DMA_BIT_MASK(32));
+ ret = dma_set_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
if (ret < 0)
return ret;
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
index 6247ec3d3a09..b94220306d1a 100644
--- a/sound/soc/ti/davinci-mcasp.c
+++ b/sound/soc/ti/davinci-mcasp.c
@@ -1641,7 +1641,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
},
.ops = &davinci_mcasp_dai_ops,
- .symmetric_rates = 1,
+ .symmetric_rate = 1,
},
{
.name = "davinci-mcasp.1",
diff --git a/sound/soc/txx9/Kconfig b/sound/soc/txx9/Kconfig
deleted file mode 100644
index d928edf9f5a9..000000000000
--- a/sound/soc/txx9/Kconfig
+++ /dev/null
@@ -1,30 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-##
-## TXx9 ACLC
-##
-config SND_SOC_TXX9ACLC
- tristate "SoC Audio for TXx9"
- depends on HAS_TXX9_ACLC && TXX9_DMAC
- help
- This option enables support for the AC Link Controllers in TXx9 SoC.
-
-config HAS_TXX9_ACLC
- bool
-
-config SND_SOC_TXX9ACLC_AC97
- tristate
- select AC97_BUS
- select SND_AC97_CODEC
- select SND_SOC_AC97_BUS
-
-
-##
-## Boards
-##
-config SND_SOC_TXX9ACLC_GENERIC
- tristate "Generic TXx9 ACLC sound machine"
- depends on SND_SOC_TXX9ACLC
- select SND_SOC_TXX9ACLC_AC97
- select SND_SOC_AC97_CODEC
- help
- This is a generic AC97 sound machine for use in TXx9 based systems.
diff --git a/sound/soc/txx9/Makefile b/sound/soc/txx9/Makefile
deleted file mode 100644
index 37ad833eb329..000000000000
--- a/sound/soc/txx9/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# Platform
-snd-soc-txx9aclc-objs := txx9aclc.o
-snd-soc-txx9aclc-ac97-objs := txx9aclc-ac97.o
-
-obj-$(CONFIG_SND_SOC_TXX9ACLC) += snd-soc-txx9aclc.o
-obj-$(CONFIG_SND_SOC_TXX9ACLC_AC97) += snd-soc-txx9aclc-ac97.o
-
-# Machine
-snd-soc-txx9aclc-generic-objs := txx9aclc-generic.o
-
-obj-$(CONFIG_SND_SOC_TXX9ACLC_GENERIC) += snd-soc-txx9aclc-generic.o
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
deleted file mode 100644
index d9e348444bd0..000000000000
--- a/sound/soc/txx9/txx9aclc-ac97.c
+++ /dev/null
@@ -1,230 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * TXx9 ACLC AC97 driver
- *
- * Copyright (C) 2009 Atsushi Nemoto
- *
- * Based on RBTX49xx patch from CELF patch archive.
- * (C) Copyright TOSHIBA CORPORATION 2004-2006
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/gfp.h>
-#include <asm/mach-tx39xx/ioremap.h> /* for TXX9_DIRECTMAP_BASE */
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include "txx9aclc.h"
-
-#define AC97_DIR \
- (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
-
-#define AC97_RATES \
- SNDRV_PCM_RATE_8000_48000
-
-#ifdef __BIG_ENDIAN
-#define AC97_FMTS SNDRV_PCM_FMTBIT_S16_BE
-#else
-#define AC97_FMTS SNDRV_PCM_FMTBIT_S16_LE
-#endif
-
-static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq);
-
-/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */
-static struct txx9aclc_plat_drvdata *txx9aclc_drvdata;
-
-static int txx9aclc_regready(struct txx9aclc_plat_drvdata *drvdata)
-{
- return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY;
-}
-
-/* AC97 controller reads codec register */
-static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97,
- unsigned short reg)
-{
- struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
- void __iomem *base = drvdata->base;
- u32 dat;
-
- if (!(__raw_readl(base + ACINTSTS) & ACINT_CODECRDY(ac97->num)))
- return 0xffff;
- reg |= ac97->num << 7;
- dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ;
- __raw_writel(dat, base + ACREGACC);
- __raw_writel(ACINT_REGACCRDY, base + ACINTEN);
- if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) {
- __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
- printk(KERN_ERR "ac97 read timeout (reg %#x)\n", reg);
- dat = 0xffff;
- goto done;
- }
- dat = __raw_readl(base + ACREGACC);
- if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) {
- printk(KERN_ERR "reg mismatch %x with %x\n",
- dat, reg);
- dat = 0xffff;
- goto done;
- }
- dat = (dat >> ACREGACC_DAT_SHIFT) & 0xffff;
-done:
- __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
- return dat;
-}
-
-/* AC97 controller writes to codec register */
-static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
- unsigned short val)
-{
- struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
- void __iomem *base = drvdata->base;
-
- __raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) |
- (val << ACREGACC_DAT_SHIFT),
- base + ACREGACC);
- __raw_writel(ACINT_REGACCRDY, base + ACINTEN);
- if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) {
- printk(KERN_ERR
- "ac97 write timeout (reg %#x)\n", reg);
- }
- __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
-}
-
-static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97)
-{
- struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
- void __iomem *base = drvdata->base;
- u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY;
-
- __raw_writel(ACCTL_ENLINK, base + ACCTLDIS);
- udelay(1);
- __raw_writel(ACCTL_ENLINK, base + ACCTLEN);
- /* wait for primary codec ready status */
- __raw_writel(ready, base + ACINTEN);
- if (!wait_event_timeout(ac97_waitq,
- (__raw_readl(base + ACINTSTS) & ready) == ready,
- HZ)) {
- dev_err(&ac97->dev, "primary codec is not ready "
- "(status %#x)\n",
- __raw_readl(base + ACINTSTS));
- }
- __raw_writel(ACINT_REGACCRDY, base + ACINTSTS);
- __raw_writel(ready, base + ACINTDIS);
-}
-
-/* AC97 controller operations */
-static struct snd_ac97_bus_ops txx9aclc_ac97_ops = {
- .read = txx9aclc_ac97_read,
- .write = txx9aclc_ac97_write,
- .reset = txx9aclc_ac97_cold_reset,
-};
-
-static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id)
-{
- struct txx9aclc_plat_drvdata *drvdata = dev_id;
- void __iomem *base = drvdata->base;
-
- __raw_writel(__raw_readl(base + ACINTMSTS), base + ACINTDIS);
- wake_up(&ac97_waitq);
- return IRQ_HANDLED;
-}
-
-static int txx9aclc_ac97_probe(struct snd_soc_dai *dai)
-{
- txx9aclc_drvdata = snd_soc_dai_get_drvdata(dai);
- return 0;
-}
-
-static int txx9aclc_ac97_remove(struct snd_soc_dai *dai)
-{
- struct txx9aclc_plat_drvdata *drvdata = snd_soc_dai_get_drvdata(dai);
-
- /* disable AC-link */
- __raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS);
- txx9aclc_drvdata = NULL;
- return 0;
-}
-
-static struct snd_soc_dai_driver txx9aclc_ac97_dai = {
- .probe = txx9aclc_ac97_probe,
- .remove = txx9aclc_ac97_remove,
- .playback = {
- .rates = AC97_RATES,
- .formats = AC97_FMTS,
- .channels_min = 2,
- .channels_max = 2,
- },
- .capture = {
- .rates = AC97_RATES,
- .formats = AC97_FMTS,
- .channels_min = 2,
- .channels_max = 2,
- },
-};
-
-static const struct snd_soc_component_driver txx9aclc_ac97_component = {
- .name = "txx9aclc-ac97",
-};
-
-static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
-{
- struct txx9aclc_plat_drvdata *drvdata;
- struct resource *r;
- int err;
- int irq;
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return irq;
-
- drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
- if (!drvdata)
- return -ENOMEM;
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- drvdata->base = devm_ioremap_resource(&pdev->dev, r);
- if (IS_ERR(drvdata->base))
- return PTR_ERR(drvdata->base);
-
- platform_set_drvdata(pdev, drvdata);
- drvdata->physbase = r->start;
- if (sizeof(drvdata->physbase) > sizeof(r->start) &&
- r->start >= TXX9_DIRECTMAP_BASE &&
- r->start < TXX9_DIRECTMAP_BASE + 0x400000)
- drvdata->physbase |= 0xf00000000ull;
- err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq,
- 0, dev_name(&pdev->dev), drvdata);
- if (err < 0)
- return err;
-
- err = snd_soc_set_ac97_ops(&txx9aclc_ac97_ops);
- if (err < 0)
- return err;
-
- return devm_snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component,
- &txx9aclc_ac97_dai, 1);
-}
-
-static int txx9aclc_ac97_dev_remove(struct platform_device *pdev)
-{
- snd_soc_set_ac97_ops(NULL);
- return 0;
-}
-
-static struct platform_driver txx9aclc_ac97_driver = {
- .probe = txx9aclc_ac97_dev_probe,
- .remove = txx9aclc_ac97_dev_remove,
- .driver = {
- .name = "txx9aclc-ac97",
- },
-};
-
-module_platform_driver(txx9aclc_ac97_driver);
-
-MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
-MODULE_DESCRIPTION("TXx9 ACLC AC97 driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:txx9aclc-ac97");
diff --git a/sound/soc/txx9/txx9aclc-generic.c b/sound/soc/txx9/txx9aclc-generic.c
deleted file mode 100644
index d6893721ba1d..000000000000
--- a/sound/soc/txx9/txx9aclc-generic.c
+++ /dev/null
@@ -1,88 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Generic TXx9 ACLC machine driver
- *
- * Copyright (C) 2009 Atsushi Nemoto
- *
- * Based on RBTX49xx patch from CELF patch archive.
- * (C) Copyright TOSHIBA CORPORATION 2004-2006
- *
- * This is a very generic AC97 sound machine driver for boards which
- * have (AC97) audio at ACLC (e.g. RBTX49XX boards).
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include "txx9aclc.h"
-
-SND_SOC_DAILINK_DEFS(hifi,
- DAILINK_COMP_ARRAY(COMP_CPU("txx9aclc-ac97")),
- DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")),
- DAILINK_COMP_ARRAY(COMP_PLATFORM("txx9aclc-pcm-audio")));
-
-static struct snd_soc_dai_link txx9aclc_generic_dai = {
- .name = "AC97",
- .stream_name = "AC97 HiFi",
- SND_SOC_DAILINK_REG(hifi),
-};
-
-static struct snd_soc_card txx9aclc_generic_card = {
- .name = "Generic TXx9 ACLC Audio",
- .owner = THIS_MODULE,
- .dai_link = &txx9aclc_generic_dai,
- .num_links = 1,
-};
-
-static struct platform_device *soc_pdev;
-
-static int __init txx9aclc_generic_probe(struct platform_device *pdev)
-{
- int ret;
-
- soc_pdev = platform_device_alloc("soc-audio", -1);
- if (!soc_pdev)
- return -ENOMEM;
- platform_set_drvdata(soc_pdev, &txx9aclc_generic_card);
- ret = platform_device_add(soc_pdev);
- if (ret) {
- platform_device_put(soc_pdev);
- return ret;
- }
-
- return 0;
-}
-
-static int __exit txx9aclc_generic_remove(struct platform_device *pdev)
-{
- platform_device_unregister(soc_pdev);
- return 0;
-}
-
-static struct platform_driver txx9aclc_generic_driver = {
- .remove = __exit_p(txx9aclc_generic_remove),
- .driver = {
- .name = "txx9aclc-generic",
- },
-};
-
-static int __init txx9aclc_generic_init(void)
-{
- return platform_driver_probe(&txx9aclc_generic_driver,
- txx9aclc_generic_probe);
-}
-
-static void __exit txx9aclc_generic_exit(void)
-{
- platform_driver_unregister(&txx9aclc_generic_driver);
-}
-
-module_init(txx9aclc_generic_init);
-module_exit(txx9aclc_generic_exit);
-
-MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
-MODULE_DESCRIPTION("Generic TXx9 ACLC ALSA SoC audio driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:txx9aclc-generic");
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
deleted file mode 100644
index 1d2d0d9b57b0..000000000000
--- a/sound/soc/txx9/txx9aclc.c
+++ /dev/null
@@ -1,422 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Generic TXx9 ACLC platform driver
- *
- * Copyright (C) 2009 Atsushi Nemoto
- *
- * Based on RBTX49xx patch from CELF patch archive.
- * (C) Copyright TOSHIBA CORPORATION 2004-2006
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-#include <linux/dmaengine.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include "txx9aclc.h"
-
-#define DRV_NAME "txx9aclc"
-
-static struct txx9aclc_soc_device {
- struct txx9aclc_dmadata dmadata[2];
-} txx9aclc_soc_device;
-
-/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */
-static struct txx9aclc_plat_drvdata *txx9aclc_drvdata;
-
-static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
- struct txx9aclc_dmadata *dmadata);
-
-static const struct snd_pcm_hardware txx9aclc_pcm_hardware = {
- /*
- * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
- * needs more works for noncoherent MIPS.
- */
- .info = SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BATCH |
- SNDRV_PCM_INFO_PAUSE,
- .period_bytes_min = 1024,
- .period_bytes_max = 8 * 1024,
- .periods_min = 2,
- .periods_max = 4096,
- .buffer_bytes_max = 32 * 1024,
-};
-
-static int txx9aclc_pcm_hw_params(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct txx9aclc_dmadata *dmadata = runtime->private_data;
-
- dev_dbg(component->dev,
- "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd "
- "runtime->min_align %ld\n",
- (unsigned long)runtime->dma_area,
- (unsigned long)runtime->dma_addr, runtime->dma_bytes,
- runtime->min_align);
- dev_dbg(component->dev,
- "periods %d period_bytes %d stream %d\n",
- params_periods(params), params_period_bytes(params),
- substream->stream);
-
- dmadata->substream = substream;
- dmadata->pos = 0;
- return 0;
-}
-
-static int txx9aclc_pcm_prepare(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct txx9aclc_dmadata *dmadata = runtime->private_data;
-
- dmadata->dma_addr = runtime->dma_addr;
- dmadata->buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
- dmadata->period_bytes = snd_pcm_lib_period_bytes(substream);
-
- if (dmadata->buffer_bytes == dmadata->period_bytes) {
- dmadata->frag_bytes = dmadata->period_bytes >> 1;
- dmadata->frags = 2;
- } else {
- dmadata->frag_bytes = dmadata->period_bytes;
- dmadata->frags = dmadata->buffer_bytes / dmadata->period_bytes;
- }
- dmadata->frag_count = 0;
- dmadata->pos = 0;
- return 0;
-}
-
-static void txx9aclc_dma_complete(void *arg)
-{
- struct txx9aclc_dmadata *dmadata = arg;
- unsigned long flags;
-
- /* dma completion handler cannot submit new operations */
- spin_lock_irqsave(&dmadata->dma_lock, flags);
- if (dmadata->frag_count >= 0) {
- dmadata->dmacount--;
- if (!WARN_ON(dmadata->dmacount < 0))
- queue_work(system_highpri_wq, &dmadata->work);
- }
- spin_unlock_irqrestore(&dmadata->dma_lock, flags);
-}
-
-static struct dma_async_tx_descriptor *
-txx9aclc_dma_submit(struct txx9aclc_dmadata *dmadata, dma_addr_t buf_dma_addr)
-{
- struct dma_chan *chan = dmadata->dma_chan;
- struct dma_async_tx_descriptor *desc;
- struct scatterlist sg;
-
- sg_init_table(&sg, 1);
- sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf_dma_addr)),
- dmadata->frag_bytes, buf_dma_addr & (PAGE_SIZE - 1));
- sg_dma_address(&sg) = buf_dma_addr;
- desc = dmaengine_prep_slave_sg(chan, &sg, 1,
- dmadata->substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- dev_err(&chan->dev->device, "cannot prepare slave dma\n");
- return NULL;
- }
- desc->callback = txx9aclc_dma_complete;
- desc->callback_param = dmadata;
- dmaengine_submit(desc);
- return desc;
-}
-
-#define NR_DMA_CHAIN 2
-
-static void txx9aclc_dma_work(struct work_struct *work)
-{
- struct txx9aclc_dmadata *dmadata =
- container_of(work, struct txx9aclc_dmadata, work);
- struct dma_chan *chan = dmadata->dma_chan;
- struct dma_async_tx_descriptor *desc;
- struct snd_pcm_substream *substream = dmadata->substream;
- u32 ctlbit = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- ACCTL_AUDODMA : ACCTL_AUDIDMA;
- int i;
- unsigned long flags;
-
- spin_lock_irqsave(&dmadata->dma_lock, flags);
- if (dmadata->frag_count < 0) {
- struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
- void __iomem *base = drvdata->base;
-
- spin_unlock_irqrestore(&dmadata->dma_lock, flags);
- dmaengine_terminate_all(chan);
- /* first time */
- for (i = 0; i < NR_DMA_CHAIN; i++) {
- desc = txx9aclc_dma_submit(dmadata,
- dmadata->dma_addr + i * dmadata->frag_bytes);
- if (!desc)
- return;
- }
- dmadata->dmacount = NR_DMA_CHAIN;
- dma_async_issue_pending(chan);
- spin_lock_irqsave(&dmadata->dma_lock, flags);
- __raw_writel(ctlbit, base + ACCTLEN);
- dmadata->frag_count = NR_DMA_CHAIN % dmadata->frags;
- spin_unlock_irqrestore(&dmadata->dma_lock, flags);
- return;
- }
- if (WARN_ON(dmadata->dmacount >= NR_DMA_CHAIN)) {
- spin_unlock_irqrestore(&dmadata->dma_lock, flags);
- return;
- }
- while (dmadata->dmacount < NR_DMA_CHAIN) {
- dmadata->dmacount++;
- spin_unlock_irqrestore(&dmadata->dma_lock, flags);
- desc = txx9aclc_dma_submit(dmadata,
- dmadata->dma_addr +
- dmadata->frag_count * dmadata->frag_bytes);
- if (!desc)
- return;
- dma_async_issue_pending(chan);
-
- spin_lock_irqsave(&dmadata->dma_lock, flags);
- dmadata->frag_count++;
- dmadata->frag_count %= dmadata->frags;
- dmadata->pos += dmadata->frag_bytes;
- dmadata->pos %= dmadata->buffer_bytes;
- if ((dmadata->frag_count * dmadata->frag_bytes) %
- dmadata->period_bytes == 0)
- snd_pcm_period_elapsed(substream);
- }
- spin_unlock_irqrestore(&dmadata->dma_lock, flags);
-}
-
-static int txx9aclc_pcm_trigger(struct snd_soc_component *component,
- struct snd_pcm_substream *substream, int cmd)
-{
- struct txx9aclc_dmadata *dmadata = substream->runtime->private_data;
- struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
- void __iomem *base = drvdata->base;
- unsigned long flags;
- int ret = 0;
- u32 ctlbit = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- ACCTL_AUDODMA : ACCTL_AUDIDMA;
-
- spin_lock_irqsave(&dmadata->dma_lock, flags);
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- dmadata->frag_count = -1;
- queue_work(system_highpri_wq, &dmadata->work);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- __raw_writel(ctlbit, base + ACCTLDIS);
- break;
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- case SNDRV_PCM_TRIGGER_RESUME:
- __raw_writel(ctlbit, base + ACCTLEN);
- break;
- default:
- ret = -EINVAL;
- }
- spin_unlock_irqrestore(&dmadata->dma_lock, flags);
- return ret;
-}
-
-static snd_pcm_uframes_t
-txx9aclc_pcm_pointer(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct txx9aclc_dmadata *dmadata = substream->runtime->private_data;
-
- return bytes_to_frames(substream->runtime, dmadata->pos);
-}
-
-static int txx9aclc_pcm_open(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct txx9aclc_soc_device *dev = &txx9aclc_soc_device;
- struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream];
- int ret;
-
- ret = snd_soc_set_runtime_hwparams(substream, &txx9aclc_pcm_hardware);
- if (ret)
- return ret;
- /* ensure that buffer size is a multiple of period size */
- ret = snd_pcm_hw_constraint_integer(substream->runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
- return ret;
- substream->runtime->private_data = dmadata;
- return 0;
-}
-
-static int txx9aclc_pcm_close(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct txx9aclc_dmadata *dmadata = substream->runtime->private_data;
- struct dma_chan *chan = dmadata->dma_chan;
-
- dmadata->frag_count = -1;
- dmaengine_terminate_all(chan);
- return 0;
-}
-
-static int txx9aclc_pcm_new(struct snd_soc_component *component,
- struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0);
- struct snd_pcm *pcm = rtd->pcm;
- struct platform_device *pdev = to_platform_device(component->dev);
- struct txx9aclc_soc_device *dev;
- struct resource *r;
- int i;
- int ret;
-
- /* at this point onwards the AC97 component has probed and this will be valid */
- dev = snd_soc_dai_get_drvdata(dai);
-
- dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK;
- dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE;
- for (i = 0; i < 2; i++) {
- r = platform_get_resource(pdev, IORESOURCE_DMA, i);
- if (!r) {
- ret = -EBUSY;
- goto exit;
- }
- dev->dmadata[i].dma_res = r;
- ret = txx9aclc_dma_init(dev, &dev->dmadata[i]);
- if (ret)
- goto exit;
- }
-
- snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
- card->dev, 64 * 1024, 4 * 1024 * 1024);
- return 0;
-
-exit:
- for (i = 0; i < 2; i++) {
- if (dev->dmadata[i].dma_chan)
- dma_release_channel(dev->dmadata[i].dma_chan);
- dev->dmadata[i].dma_chan = NULL;
- }
- return ret;
-}
-
-static bool filter(struct dma_chan *chan, void *param)
-{
- struct txx9aclc_dmadata *dmadata = param;
- char *devname;
- bool found = false;
-
- devname = kasprintf(GFP_KERNEL, "%s.%d", dmadata->dma_res->name,
- (int)dmadata->dma_res->start);
- if (strcmp(dev_name(chan->device->dev), devname) == 0) {
- chan->private = &dmadata->dma_slave;
- found = true;
- }
- kfree(devname);
- return found;
-}
-
-static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
- struct txx9aclc_dmadata *dmadata)
-{
- struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
- struct txx9dmac_slave *ds = &dmadata->dma_slave;
- dma_cap_mask_t mask;
-
- spin_lock_init(&dmadata->dma_lock);
-
- ds->reg_width = sizeof(u32);
- if (dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- ds->tx_reg = drvdata->physbase + ACAUDODAT;
- ds->rx_reg = 0;
- } else {
- ds->tx_reg = 0;
- ds->rx_reg = drvdata->physbase + ACAUDIDAT;
- }
-
- /* Try to grab a DMA channel */
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- dmadata->dma_chan = dma_request_channel(mask, filter, dmadata);
- if (!dmadata->dma_chan) {
- printk(KERN_ERR
- "DMA channel for %s is not available\n",
- dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- "playback" : "capture");
- return -EBUSY;
- }
- INIT_WORK(&dmadata->work, txx9aclc_dma_work);
- return 0;
-}
-
-static int txx9aclc_pcm_probe(struct snd_soc_component *component)
-{
- snd_soc_component_set_drvdata(component, &txx9aclc_soc_device);
- return 0;
-}
-
-static void txx9aclc_pcm_remove(struct snd_soc_component *component)
-{
- struct txx9aclc_soc_device *dev = snd_soc_component_get_drvdata(component);
- struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
- void __iomem *base = drvdata->base;
- int i;
-
- /* disable all FIFO DMAs */
- __raw_writel(ACCTL_AUDODMA | ACCTL_AUDIDMA, base + ACCTLDIS);
- /* dummy R/W to clear pending DMAREQ if any */
- __raw_writel(__raw_readl(base + ACAUDIDAT), base + ACAUDODAT);
-
- for (i = 0; i < 2; i++) {
- struct txx9aclc_dmadata *dmadata = &dev->dmadata[i];
- struct dma_chan *chan = dmadata->dma_chan;
-
- if (chan) {
- dmadata->frag_count = -1;
- dmaengine_terminate_all(chan);
- dma_release_channel(chan);
- }
- dev->dmadata[i].dma_chan = NULL;
- }
-}
-
-static const struct snd_soc_component_driver txx9aclc_soc_component = {
- .name = DRV_NAME,
- .probe = txx9aclc_pcm_probe,
- .remove = txx9aclc_pcm_remove,
- .open = txx9aclc_pcm_open,
- .close = txx9aclc_pcm_close,
- .hw_params = txx9aclc_pcm_hw_params,
- .prepare = txx9aclc_pcm_prepare,
- .trigger = txx9aclc_pcm_trigger,
- .pointer = txx9aclc_pcm_pointer,
- .pcm_construct = txx9aclc_pcm_new,
-};
-
-static int txx9aclc_soc_platform_probe(struct platform_device *pdev)
-{
- return devm_snd_soc_register_component(&pdev->dev,
- &txx9aclc_soc_component, NULL, 0);
-}
-
-static struct platform_driver txx9aclc_pcm_driver = {
- .driver = {
- .name = "txx9aclc-pcm-audio",
- },
-
- .probe = txx9aclc_soc_platform_probe,
-};
-
-module_platform_driver(txx9aclc_pcm_driver);
-
-MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
-MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/txx9/txx9aclc.h b/sound/soc/txx9/txx9aclc.h
deleted file mode 100644
index 37c691ba56ed..000000000000
--- a/sound/soc/txx9/txx9aclc.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * TXx9 SoC AC Link Controller
- */
-
-#ifndef __TXX9ACLC_H
-#define __TXX9ACLC_H
-
-#include <linux/interrupt.h>
-#include <asm/txx9/dmac.h>
-
-#define ACCTLEN 0x00 /* control enable */
-#define ACCTLDIS 0x04 /* control disable */
-#define ACCTL_ENLINK 0x00000001 /* enable/disable AC-link */
-#define ACCTL_AUDODMA 0x00000100 /* AUDODMA enable/disable */
-#define ACCTL_AUDIDMA 0x00001000 /* AUDIDMA enable/disable */
-#define ACCTL_AUDOEHLT 0x00010000 /* AUDO error halt
- enable/disable */
-#define ACCTL_AUDIEHLT 0x00100000 /* AUDI error halt
- enable/disable */
-#define ACREGACC 0x08 /* codec register access */
-#define ACREGACC_DAT_SHIFT 0 /* data field */
-#define ACREGACC_REG_SHIFT 16 /* address field */
-#define ACREGACC_CODECID_SHIFT 24 /* CODEC ID field */
-#define ACREGACC_READ 0x80000000 /* CODEC read */
-#define ACREGACC_WRITE 0x00000000 /* CODEC write */
-#define ACINTSTS 0x10 /* interrupt status */
-#define ACINTMSTS 0x14 /* interrupt masked status */
-#define ACINTEN 0x18 /* interrupt enable */
-#define ACINTDIS 0x1c /* interrupt disable */
-#define ACINT_CODECRDY(n) (0x00000001 << (n)) /* CODECn ready */
-#define ACINT_REGACCRDY 0x00000010 /* ACREGACC ready */
-#define ACINT_AUDOERR 0x00000100 /* AUDO underrun error */
-#define ACINT_AUDIERR 0x00001000 /* AUDI overrun error */
-#define ACDMASTS 0x80 /* DMA request status */
-#define ACDMA_AUDO 0x00000001 /* AUDODMA pending */
-#define ACDMA_AUDI 0x00000010 /* AUDIDMA pending */
-#define ACAUDODAT 0xa0 /* audio out data */
-#define ACAUDIDAT 0xb0 /* audio in data */
-#define ACREVID 0xfc /* revision ID */
-
-struct txx9aclc_dmadata {
- struct resource *dma_res;
- struct txx9dmac_slave dma_slave;
- struct dma_chan *dma_chan;
- struct work_struct work;
- spinlock_t dma_lock;
- int stream; /* SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE */
- struct snd_pcm_substream *substream;
- unsigned long pos;
- dma_addr_t dma_addr;
- unsigned long buffer_bytes;
- unsigned long period_bytes;
- unsigned long frag_bytes;
- int frags;
- int frag_count;
- int dmacount;
-};
-
-struct txx9aclc_plat_drvdata {
- void __iomem *base;
- u64 physbase;
-};
-
-static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata(
- struct snd_soc_dai *dai)
-{
- return dev_get_drvdata(dai->dev);
-}
-
-#endif /* __TXX9ACLC_H */
diff --git a/sound/soc/zte/Kconfig b/sound/soc/zte/Kconfig
deleted file mode 100644
index a23d4f13ca19..000000000000
--- a/sound/soc/zte/Kconfig
+++ /dev/null
@@ -1,26 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config ZX_SPDIF
- tristate "ZTE ZX SPDIF Driver Support"
- depends on ARCH_ZX || COMPILE_TEST
- depends on COMMON_CLK
- select SND_SOC_GENERIC_DMAENGINE_PCM
- help
- Say Y or M if you want to add support for codecs attached to the
- ZTE ZX SPDIF interface
-
-config ZX_I2S
- tristate "ZTE ZX I2S Driver Support"
- depends on ARCH_ZX || COMPILE_TEST
- depends on COMMON_CLK
- select SND_SOC_GENERIC_DMAENGINE_PCM
- help
- Say Y or M if you want to add support for codecs attached to the
- ZTE ZX I2S interface
-
-config ZX_TDM
- tristate "ZTE ZX TDM Driver Support"
- depends on COMMON_CLK
- select SND_SOC_GENERIC_DMAENGINE_PCM
- help
- Say Y or M if you want to add support for codecs attached to the
- ZTE ZX TDM interface
diff --git a/sound/soc/zte/Makefile b/sound/soc/zte/Makefile
deleted file mode 100644
index 2f7cdefa42df..000000000000
--- a/sound/soc/zte/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_ZX_SPDIF) += zx-spdif.o
-obj-$(CONFIG_ZX_I2S) += zx-i2s.o
-obj-$(CONFIG_ZX_TDM) += zx-tdm.o
diff --git a/sound/soc/zte/zx-i2s.c b/sound/soc/zte/zx-i2s.c
deleted file mode 100644
index 1c1a44e08a67..000000000000
--- a/sound/soc/zte/zx-i2s.c
+++ /dev/null
@@ -1,452 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2015 Linaro
- *
- * Author: Jun Nie <jun.nie@linaro.org>
- */
-
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dai.h>
-
-#include <sound/core.h>
-#include <sound/dmaengine_pcm.h>
-#include <sound/initval.h>
-
-#define ZX_I2S_PROCESS_CTRL 0x04
-#define ZX_I2S_TIMING_CTRL 0x08
-#define ZX_I2S_FIFO_CTRL 0x0C
-#define ZX_I2S_FIFO_STATUS 0x10
-#define ZX_I2S_INT_EN 0x14
-#define ZX_I2S_INT_STATUS 0x18
-#define ZX_I2S_DATA 0x1C
-#define ZX_I2S_FRAME_CNTR 0x20
-
-#define I2S_DEAGULT_FIFO_THRES (0x10)
-#define I2S_MAX_FIFO_THRES (0x20)
-
-#define ZX_I2S_PROCESS_TX_EN (1 << 0)
-#define ZX_I2S_PROCESS_TX_DIS (0 << 0)
-#define ZX_I2S_PROCESS_RX_EN (1 << 1)
-#define ZX_I2S_PROCESS_RX_DIS (0 << 1)
-#define ZX_I2S_PROCESS_I2S_EN (1 << 2)
-#define ZX_I2S_PROCESS_I2S_DIS (0 << 2)
-
-#define ZX_I2S_TIMING_MAST (1 << 0)
-#define ZX_I2S_TIMING_SLAVE (0 << 0)
-#define ZX_I2S_TIMING_MS_MASK (1 << 0)
-#define ZX_I2S_TIMING_LOOP (1 << 1)
-#define ZX_I2S_TIMING_NOR (0 << 1)
-#define ZX_I2S_TIMING_LOOP_MASK (1 << 1)
-#define ZX_I2S_TIMING_PTNR (1 << 2)
-#define ZX_I2S_TIMING_NTPR (0 << 2)
-#define ZX_I2S_TIMING_PHASE_MASK (1 << 2)
-#define ZX_I2S_TIMING_TDM (1 << 3)
-#define ZX_I2S_TIMING_I2S (0 << 3)
-#define ZX_I2S_TIMING_TIMING_MASK (1 << 3)
-#define ZX_I2S_TIMING_LONG_SYNC (1 << 4)
-#define ZX_I2S_TIMING_SHORT_SYNC (0 << 4)
-#define ZX_I2S_TIMING_SYNC_MASK (1 << 4)
-#define ZX_I2S_TIMING_TEAK_EN (1 << 5)
-#define ZX_I2S_TIMING_TEAK_DIS (0 << 5)
-#define ZX_I2S_TIMING_TEAK_MASK (1 << 5)
-#define ZX_I2S_TIMING_STD_I2S (0 << 6)
-#define ZX_I2S_TIMING_MSB_JUSTIF (1 << 6)
-#define ZX_I2S_TIMING_LSB_JUSTIF (2 << 6)
-#define ZX_I2S_TIMING_ALIGN_MASK (3 << 6)
-#define ZX_I2S_TIMING_CHN_MASK (7 << 8)
-#define ZX_I2S_TIMING_CHN(x) ((x - 1) << 8)
-#define ZX_I2S_TIMING_LANE_MASK (3 << 11)
-#define ZX_I2S_TIMING_LANE(x) ((x - 1) << 11)
-#define ZX_I2S_TIMING_TSCFG_MASK (7 << 13)
-#define ZX_I2S_TIMING_TSCFG(x) (x << 13)
-#define ZX_I2S_TIMING_TS_WIDTH_MASK (0x1f << 16)
-#define ZX_I2S_TIMING_TS_WIDTH(x) ((x - 1) << 16)
-#define ZX_I2S_TIMING_DATA_SIZE_MASK (0x1f << 21)
-#define ZX_I2S_TIMING_DATA_SIZE(x) ((x - 1) << 21)
-#define ZX_I2S_TIMING_CFG_ERR_MASK (1 << 31)
-
-#define ZX_I2S_FIFO_CTRL_TX_RST (1 << 0)
-#define ZX_I2S_FIFO_CTRL_TX_RST_MASK (1 << 0)
-#define ZX_I2S_FIFO_CTRL_RX_RST (1 << 1)
-#define ZX_I2S_FIFO_CTRL_RX_RST_MASK (1 << 1)
-#define ZX_I2S_FIFO_CTRL_TX_DMA_EN (1 << 4)
-#define ZX_I2S_FIFO_CTRL_TX_DMA_DIS (0 << 4)
-#define ZX_I2S_FIFO_CTRL_TX_DMA_MASK (1 << 4)
-#define ZX_I2S_FIFO_CTRL_RX_DMA_EN (1 << 5)
-#define ZX_I2S_FIFO_CTRL_RX_DMA_DIS (0 << 5)
-#define ZX_I2S_FIFO_CTRL_RX_DMA_MASK (1 << 5)
-#define ZX_I2S_FIFO_CTRL_TX_THRES_MASK (0x1F << 8)
-#define ZX_I2S_FIFO_CTRL_RX_THRES_MASK (0x1F << 16)
-
-#define CLK_RAT (32 * 4)
-
-struct zx_i2s_info {
- struct snd_dmaengine_dai_dma_data dma_playback;
- struct snd_dmaengine_dai_dma_data dma_capture;
- struct clk *dai_wclk;
- struct clk *dai_pclk;
- void __iomem *reg_base;
- int master;
- resource_size_t mapbase;
-};
-
-static void zx_i2s_tx_en(void __iomem *base, bool on)
-{
- unsigned long val;
-
- val = readl_relaxed(base + ZX_I2S_PROCESS_CTRL);
- if (on)
- val |= ZX_I2S_PROCESS_TX_EN | ZX_I2S_PROCESS_I2S_EN;
- else
- val &= ~(ZX_I2S_PROCESS_TX_EN | ZX_I2S_PROCESS_I2S_EN);
- writel_relaxed(val, base + ZX_I2S_PROCESS_CTRL);
-}
-
-static void zx_i2s_rx_en(void __iomem *base, bool on)
-{
- unsigned long val;
-
- val = readl_relaxed(base + ZX_I2S_PROCESS_CTRL);
- if (on)
- val |= ZX_I2S_PROCESS_RX_EN | ZX_I2S_PROCESS_I2S_EN;
- else
- val &= ~(ZX_I2S_PROCESS_RX_EN | ZX_I2S_PROCESS_I2S_EN);
- writel_relaxed(val, base + ZX_I2S_PROCESS_CTRL);
-}
-
-static void zx_i2s_tx_dma_en(void __iomem *base, bool on)
-{
- unsigned long val;
-
- val = readl_relaxed(base + ZX_I2S_FIFO_CTRL);
- val |= ZX_I2S_FIFO_CTRL_TX_RST | (I2S_DEAGULT_FIFO_THRES << 8);
- if (on)
- val |= ZX_I2S_FIFO_CTRL_TX_DMA_EN;
- else
- val &= ~ZX_I2S_FIFO_CTRL_TX_DMA_EN;
- writel_relaxed(val, base + ZX_I2S_FIFO_CTRL);
-}
-
-static void zx_i2s_rx_dma_en(void __iomem *base, bool on)
-{
- unsigned long val;
-
- val = readl_relaxed(base + ZX_I2S_FIFO_CTRL);
- val |= ZX_I2S_FIFO_CTRL_RX_RST | (I2S_DEAGULT_FIFO_THRES << 16);
- if (on)
- val |= ZX_I2S_FIFO_CTRL_RX_DMA_EN;
- else
- val &= ~ZX_I2S_FIFO_CTRL_RX_DMA_EN;
- writel_relaxed(val, base + ZX_I2S_FIFO_CTRL);
-}
-
-#define ZX_I2S_RATES \
- (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
- SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000| \
- SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
-
-#define ZX_I2S_FMTBIT \
- (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
- SNDRV_PCM_FMTBIT_S32_LE)
-
-static int zx_i2s_dai_probe(struct snd_soc_dai *dai)
-{
- struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev);
-
- snd_soc_dai_set_drvdata(dai, zx_i2s);
- zx_i2s->dma_playback.addr = zx_i2s->mapbase + ZX_I2S_DATA;
- zx_i2s->dma_playback.maxburst = 16;
- zx_i2s->dma_capture.addr = zx_i2s->mapbase + ZX_I2S_DATA;
- zx_i2s->dma_capture.maxburst = 16;
- snd_soc_dai_init_dma_data(dai, &zx_i2s->dma_playback,
- &zx_i2s->dma_capture);
- return 0;
-}
-
-static int zx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
-{
- struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(cpu_dai);
- unsigned long val;
-
- val = readl_relaxed(i2s->reg_base + ZX_I2S_TIMING_CTRL);
- val &= ~(ZX_I2S_TIMING_TIMING_MASK | ZX_I2S_TIMING_ALIGN_MASK |
- ZX_I2S_TIMING_TEAK_MASK | ZX_I2S_TIMING_SYNC_MASK |
- ZX_I2S_TIMING_MS_MASK);
-
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_STD_I2S);
- break;
- case SND_SOC_DAIFMT_LEFT_J:
- val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_MSB_JUSTIF);
- break;
- case SND_SOC_DAIFMT_RIGHT_J:
- val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_LSB_JUSTIF);
- break;
- default:
- dev_err(cpu_dai->dev, "Unknown i2s timing\n");
- return -EINVAL;
- }
-
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBM_CFM:
- /* Codec is master, and I2S is slave. */
- i2s->master = 0;
- val |= ZX_I2S_TIMING_SLAVE;
- break;
- case SND_SOC_DAIFMT_CBS_CFS:
- /* Codec is slave, and I2S is master. */
- i2s->master = 1;
- val |= ZX_I2S_TIMING_MAST;
- break;
- default:
- dev_err(cpu_dai->dev, "Unknown master/slave format\n");
- return -EINVAL;
- }
-
- writel_relaxed(val, i2s->reg_base + ZX_I2S_TIMING_CTRL);
- return 0;
-}
-
-static int zx_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *socdai)
-{
- struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(socdai);
- struct snd_dmaengine_dai_dma_data *dma_data;
- unsigned int lane, ch_num, len, ret = 0;
- unsigned int ts_width = 32;
- unsigned long val;
- unsigned long chn_cfg;
-
- dma_data = snd_soc_dai_get_dma_data(socdai, substream);
- dma_data->addr_width = ts_width >> 3;
-
- val = readl_relaxed(i2s->reg_base + ZX_I2S_TIMING_CTRL);
- val &= ~(ZX_I2S_TIMING_TS_WIDTH_MASK | ZX_I2S_TIMING_DATA_SIZE_MASK |
- ZX_I2S_TIMING_LANE_MASK | ZX_I2S_TIMING_CHN_MASK |
- ZX_I2S_TIMING_TSCFG_MASK);
-
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- len = 16;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- len = 24;
- break;
- case SNDRV_PCM_FORMAT_S32_LE:
- len = 32;
- break;
- default:
- dev_err(socdai->dev, "Unknown data format\n");
- return -EINVAL;
- }
- val |= ZX_I2S_TIMING_TS_WIDTH(ts_width) | ZX_I2S_TIMING_DATA_SIZE(len);
-
- ch_num = params_channels(params);
- switch (ch_num) {
- case 1:
- lane = 1;
- chn_cfg = 2;
- break;
- case 2:
- case 4:
- case 6:
- case 8:
- lane = ch_num / 2;
- chn_cfg = 3;
- break;
- default:
- dev_err(socdai->dev, "Not support channel num %d\n", ch_num);
- return -EINVAL;
- }
- val |= ZX_I2S_TIMING_LANE(lane);
- val |= ZX_I2S_TIMING_TSCFG(chn_cfg);
- val |= ZX_I2S_TIMING_CHN(ch_num);
- writel_relaxed(val, i2s->reg_base + ZX_I2S_TIMING_CTRL);
-
- if (i2s->master)
- ret = clk_set_rate(i2s->dai_wclk,
- params_rate(params) * ch_num * CLK_RAT);
-
- return ret;
-}
-
-static int zx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev);
- int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
- int ret = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- if (capture)
- zx_i2s_rx_dma_en(zx_i2s->reg_base, true);
- else
- zx_i2s_tx_dma_en(zx_i2s->reg_base, true);
- fallthrough;
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- if (capture)
- zx_i2s_rx_en(zx_i2s->reg_base, true);
- else
- zx_i2s_tx_en(zx_i2s->reg_base, true);
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- if (capture)
- zx_i2s_rx_dma_en(zx_i2s->reg_base, false);
- else
- zx_i2s_tx_dma_en(zx_i2s->reg_base, false);
- fallthrough;
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- if (capture)
- zx_i2s_rx_en(zx_i2s->reg_base, false);
- else
- zx_i2s_tx_en(zx_i2s->reg_base, false);
- break;
-
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-static int zx_i2s_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev);
- int ret;
-
- ret = clk_prepare_enable(zx_i2s->dai_wclk);
- if (ret)
- return ret;
-
- ret = clk_prepare_enable(zx_i2s->dai_pclk);
- if (ret) {
- clk_disable_unprepare(zx_i2s->dai_wclk);
- return ret;
- }
-
- return ret;
-}
-
-static void zx_i2s_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev);
-
- clk_disable_unprepare(zx_i2s->dai_wclk);
- clk_disable_unprepare(zx_i2s->dai_pclk);
-}
-
-static const struct snd_soc_dai_ops zx_i2s_dai_ops = {
- .trigger = zx_i2s_trigger,
- .hw_params = zx_i2s_hw_params,
- .set_fmt = zx_i2s_set_fmt,
- .startup = zx_i2s_startup,
- .shutdown = zx_i2s_shutdown,
-};
-
-static const struct snd_soc_component_driver zx_i2s_component = {
- .name = "zx-i2s",
-};
-
-static struct snd_soc_dai_driver zx_i2s_dai = {
- .name = "zx-i2s-dai",
- .id = 0,
- .probe = zx_i2s_dai_probe,
- .playback = {
- .channels_min = 1,
- .channels_max = 8,
- .rates = ZX_I2S_RATES,
- .formats = ZX_I2S_FMTBIT,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ZX_I2S_RATES,
- .formats = ZX_I2S_FMTBIT,
- },
- .ops = &zx_i2s_dai_ops,
-};
-
-static int zx_i2s_probe(struct platform_device *pdev)
-{
- struct resource *res;
- struct zx_i2s_info *zx_i2s;
- int ret;
-
- zx_i2s = devm_kzalloc(&pdev->dev, sizeof(*zx_i2s), GFP_KERNEL);
- if (!zx_i2s)
- return -ENOMEM;
-
- zx_i2s->dai_wclk = devm_clk_get(&pdev->dev, "wclk");
- if (IS_ERR(zx_i2s->dai_wclk)) {
- dev_err(&pdev->dev, "Fail to get wclk\n");
- return PTR_ERR(zx_i2s->dai_wclk);
- }
-
- zx_i2s->dai_pclk = devm_clk_get(&pdev->dev, "pclk");
- if (IS_ERR(zx_i2s->dai_pclk)) {
- dev_err(&pdev->dev, "Fail to get pclk\n");
- return PTR_ERR(zx_i2s->dai_pclk);
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- zx_i2s->mapbase = res->start;
- zx_i2s->reg_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(zx_i2s->reg_base)) {
- dev_err(&pdev->dev, "ioremap failed!\n");
- return PTR_ERR(zx_i2s->reg_base);
- }
-
- writel_relaxed(0, zx_i2s->reg_base + ZX_I2S_FIFO_CTRL);
- platform_set_drvdata(pdev, zx_i2s);
-
- ret = devm_snd_soc_register_component(&pdev->dev, &zx_i2s_component,
- &zx_i2s_dai, 1);
- if (ret) {
- dev_err(&pdev->dev, "Register DAI failed: %d\n", ret);
- return ret;
- }
-
- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
- if (ret)
- dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret);
-
- return ret;
-}
-
-static const struct of_device_id zx_i2s_dt_ids[] = {
- { .compatible = "zte,zx296702-i2s", },
- {}
-};
-MODULE_DEVICE_TABLE(of, zx_i2s_dt_ids);
-
-static struct platform_driver i2s_driver = {
- .probe = zx_i2s_probe,
- .driver = {
- .name = "zx-i2s",
- .of_match_table = zx_i2s_dt_ids,
- },
-};
-
-module_platform_driver(i2s_driver);
-
-MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>");
-MODULE_DESCRIPTION("ZTE I2S SoC DAI");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/zte/zx-spdif.c b/sound/soc/zte/zx-spdif.c
deleted file mode 100644
index b4168bd532b7..000000000000
--- a/sound/soc/zte/zx-spdif.c
+++ /dev/null
@@ -1,363 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2015 Linaro
- *
- * Author: Jun Nie <jun.nie@linaro.org>
- */
-
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/dmaengine.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <sound/asoundef.h>
-#include <sound/core.h>
-#include <sound/dmaengine_pcm.h>
-#include <sound/initval.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dai.h>
-
-#define ZX_CTRL 0x04
-#define ZX_FIFOCTRL 0x08
-#define ZX_INT_STATUS 0x10
-#define ZX_INT_MASK 0x14
-#define ZX_DATA 0x18
-#define ZX_VALID_BIT 0x1c
-#define ZX_CH_STA_1 0x20
-#define ZX_CH_STA_2 0x24
-#define ZX_CH_STA_3 0x28
-#define ZX_CH_STA_4 0x2c
-#define ZX_CH_STA_5 0x30
-#define ZX_CH_STA_6 0x34
-
-#define ZX_CTRL_MODA_16 (0 << 6)
-#define ZX_CTRL_MODA_18 BIT(6)
-#define ZX_CTRL_MODA_20 (2 << 6)
-#define ZX_CTRL_MODA_24 (3 << 6)
-#define ZX_CTRL_MODA_MASK (3 << 6)
-
-#define ZX_CTRL_ENB BIT(4)
-#define ZX_CTRL_DNB (0 << 4)
-#define ZX_CTRL_ENB_MASK BIT(4)
-
-#define ZX_CTRL_TX_OPEN BIT(0)
-#define ZX_CTRL_TX_CLOSE (0 << 0)
-#define ZX_CTRL_TX_MASK BIT(0)
-
-#define ZX_CTRL_OPEN (ZX_CTRL_TX_OPEN | ZX_CTRL_ENB)
-#define ZX_CTRL_CLOSE (ZX_CTRL_TX_CLOSE | ZX_CTRL_DNB)
-
-#define ZX_CTRL_DOUBLE_TRACK (0 << 8)
-#define ZX_CTRL_LEFT_TRACK BIT(8)
-#define ZX_CTRL_RIGHT_TRACK (2 << 8)
-#define ZX_CTRL_TRACK_MASK (3 << 8)
-
-#define ZX_FIFOCTRL_TXTH_MASK (0x1f << 8)
-#define ZX_FIFOCTRL_TXTH(x) (x << 8)
-#define ZX_FIFOCTRL_TX_DMA_EN BIT(2)
-#define ZX_FIFOCTRL_TX_DMA_DIS (0 << 2)
-#define ZX_FIFOCTRL_TX_DMA_EN_MASK BIT(2)
-#define ZX_FIFOCTRL_TX_FIFO_RST BIT(0)
-#define ZX_FIFOCTRL_TX_FIFO_RST_MASK BIT(0)
-
-#define ZX_VALID_DOUBLE_TRACK (0 << 0)
-#define ZX_VALID_LEFT_TRACK BIT(1)
-#define ZX_VALID_RIGHT_TRACK (2 << 0)
-#define ZX_VALID_TRACK_MASK (3 << 0)
-
-#define ZX_SPDIF_CLK_RAT (2 * 32)
-
-struct zx_spdif_info {
- struct snd_dmaengine_dai_dma_data dma_data;
- struct clk *dai_clk;
- void __iomem *reg_base;
- resource_size_t mapbase;
-};
-
-static int zx_spdif_dai_probe(struct snd_soc_dai *dai)
-{
- struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
-
- snd_soc_dai_set_drvdata(dai, zx_spdif);
- zx_spdif->dma_data.addr = zx_spdif->mapbase + ZX_DATA;
- zx_spdif->dma_data.maxburst = 8;
- snd_soc_dai_init_dma_data(dai, &zx_spdif->dma_data, NULL);
- return 0;
-}
-
-static int zx_spdif_chanstats(void __iomem *base, unsigned int rate)
-{
- u32 cstas1;
-
- switch (rate) {
- case 22050:
- cstas1 = IEC958_AES3_CON_FS_22050;
- break;
- case 24000:
- cstas1 = IEC958_AES3_CON_FS_24000;
- break;
- case 32000:
- cstas1 = IEC958_AES3_CON_FS_32000;
- break;
- case 44100:
- cstas1 = IEC958_AES3_CON_FS_44100;
- break;
- case 48000:
- cstas1 = IEC958_AES3_CON_FS_48000;
- break;
- case 88200:
- cstas1 = IEC958_AES3_CON_FS_88200;
- break;
- case 96000:
- cstas1 = IEC958_AES3_CON_FS_96000;
- break;
- case 176400:
- cstas1 = IEC958_AES3_CON_FS_176400;
- break;
- case 192000:
- cstas1 = IEC958_AES3_CON_FS_192000;
- break;
- default:
- return -EINVAL;
- }
- cstas1 = cstas1 << 24;
- cstas1 |= IEC958_AES0_CON_NOT_COPYRIGHT;
-
- writel_relaxed(cstas1, base + ZX_CH_STA_1);
- return 0;
-}
-
-static int zx_spdif_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *socdai)
-{
- struct zx_spdif_info *zx_spdif = dev_get_drvdata(socdai->dev);
- struct zx_spdif_info *spdif = snd_soc_dai_get_drvdata(socdai);
- struct snd_dmaengine_dai_dma_data *dma_data =
- snd_soc_dai_get_dma_data(socdai, substream);
- u32 val, ch_num, rate;
- int ret;
-
- dma_data->addr_width = params_width(params) >> 3;
-
- val = readl_relaxed(zx_spdif->reg_base + ZX_CTRL);
- val &= ~ZX_CTRL_MODA_MASK;
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- val |= ZX_CTRL_MODA_16;
- break;
-
- case SNDRV_PCM_FORMAT_S18_3LE:
- val |= ZX_CTRL_MODA_18;
- break;
-
- case SNDRV_PCM_FORMAT_S20_3LE:
- val |= ZX_CTRL_MODA_20;
- break;
-
- case SNDRV_PCM_FORMAT_S24_LE:
- val |= ZX_CTRL_MODA_24;
- break;
- default:
- dev_err(socdai->dev, "Format not support!\n");
- return -EINVAL;
- }
-
- ch_num = params_channels(params);
- if (ch_num == 2)
- val |= ZX_CTRL_DOUBLE_TRACK;
- else
- val |= ZX_CTRL_LEFT_TRACK;
- writel_relaxed(val, zx_spdif->reg_base + ZX_CTRL);
-
- val = readl_relaxed(zx_spdif->reg_base + ZX_VALID_BIT);
- val &= ~ZX_VALID_TRACK_MASK;
- if (ch_num == 2)
- val |= ZX_VALID_DOUBLE_TRACK;
- else
- val |= ZX_VALID_RIGHT_TRACK;
- writel_relaxed(val, zx_spdif->reg_base + ZX_VALID_BIT);
-
- rate = params_rate(params);
- ret = zx_spdif_chanstats(zx_spdif->reg_base, rate);
- if (ret)
- return ret;
- return clk_set_rate(spdif->dai_clk, rate * ch_num * ZX_SPDIF_CLK_RAT);
-}
-
-static void zx_spdif_cfg_tx(void __iomem *base, int on)
-{
- u32 val;
-
- val = readl_relaxed(base + ZX_CTRL);
- val &= ~(ZX_CTRL_ENB_MASK | ZX_CTRL_TX_MASK);
- val |= on ? ZX_CTRL_OPEN : ZX_CTRL_CLOSE;
- writel_relaxed(val, base + ZX_CTRL);
-
- val = readl_relaxed(base + ZX_FIFOCTRL);
- val &= ~ZX_FIFOCTRL_TX_DMA_EN_MASK;
- if (on)
- val |= ZX_FIFOCTRL_TX_DMA_EN;
- writel_relaxed(val, base + ZX_FIFOCTRL);
-}
-
-static int zx_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- u32 val;
- struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
- int ret = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- val = readl_relaxed(zx_spdif->reg_base + ZX_FIFOCTRL);
- val |= ZX_FIFOCTRL_TX_FIFO_RST;
- writel_relaxed(val, zx_spdif->reg_base + ZX_FIFOCTRL);
- fallthrough;
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- zx_spdif_cfg_tx(zx_spdif->reg_base, true);
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- zx_spdif_cfg_tx(zx_spdif->reg_base, false);
- break;
-
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-static int zx_spdif_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
-
- return clk_prepare_enable(zx_spdif->dai_clk);
-}
-
-static void zx_spdif_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
-
- clk_disable_unprepare(zx_spdif->dai_clk);
-}
-
-#define ZX_RATES \
- (SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\
- SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
-
-#define ZX_FORMAT \
- (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE \
- | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
-
-static const struct snd_soc_dai_ops zx_spdif_dai_ops = {
- .trigger = zx_spdif_trigger,
- .startup = zx_spdif_startup,
- .shutdown = zx_spdif_shutdown,
- .hw_params = zx_spdif_hw_params,
-};
-
-static struct snd_soc_dai_driver zx_spdif_dai = {
- .name = "spdif",
- .id = 0,
- .probe = zx_spdif_dai_probe,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ZX_RATES,
- .formats = ZX_FORMAT,
- },
- .ops = &zx_spdif_dai_ops,
-};
-
-static const struct snd_soc_component_driver zx_spdif_component = {
- .name = "spdif",
-};
-
-static void zx_spdif_dev_init(void __iomem *base)
-{
- u32 val;
-
- writel_relaxed(0, base + ZX_CTRL);
- writel_relaxed(0, base + ZX_INT_MASK);
- writel_relaxed(0xf, base + ZX_INT_STATUS);
- writel_relaxed(0x1, base + ZX_FIFOCTRL);
-
- val = readl_relaxed(base + ZX_FIFOCTRL);
- val &= ~(ZX_FIFOCTRL_TXTH_MASK | ZX_FIFOCTRL_TX_FIFO_RST_MASK);
- val |= ZX_FIFOCTRL_TXTH(8);
- writel_relaxed(val, base + ZX_FIFOCTRL);
-}
-
-static int zx_spdif_probe(struct platform_device *pdev)
-{
- struct resource *res;
- struct zx_spdif_info *zx_spdif;
- int ret;
-
- zx_spdif = devm_kzalloc(&pdev->dev, sizeof(*zx_spdif), GFP_KERNEL);
- if (!zx_spdif)
- return -ENOMEM;
-
- zx_spdif->dai_clk = devm_clk_get(&pdev->dev, "tx");
- if (IS_ERR(zx_spdif->dai_clk)) {
- dev_err(&pdev->dev, "Fail to get clk\n");
- return PTR_ERR(zx_spdif->dai_clk);
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- zx_spdif->mapbase = res->start;
- zx_spdif->reg_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(zx_spdif->reg_base)) {
- return PTR_ERR(zx_spdif->reg_base);
- }
-
- zx_spdif_dev_init(zx_spdif->reg_base);
- platform_set_drvdata(pdev, zx_spdif);
-
- ret = devm_snd_soc_register_component(&pdev->dev, &zx_spdif_component,
- &zx_spdif_dai, 1);
- if (ret) {
- dev_err(&pdev->dev, "Register DAI failed: %d\n", ret);
- return ret;
- }
-
- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
- if (ret)
- dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret);
-
- return ret;
-}
-
-static const struct of_device_id zx_spdif_dt_ids[] = {
- { .compatible = "zte,zx296702-spdif", },
- {}
-};
-MODULE_DEVICE_TABLE(of, zx_spdif_dt_ids);
-
-static struct platform_driver spdif_driver = {
- .probe = zx_spdif_probe,
- .driver = {
- .name = "zx-spdif",
- .of_match_table = zx_spdif_dt_ids,
- },
-};
-
-module_platform_driver(spdif_driver);
-
-MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>");
-MODULE_DESCRIPTION("ZTE SPDIF SoC DAI");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/zte/zx-tdm.c b/sound/soc/zte/zx-tdm.c
deleted file mode 100644
index 4f787185d630..000000000000
--- a/sound/soc/zte/zx-tdm.c
+++ /dev/null
@@ -1,458 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * ZTE's TDM driver
- *
- * Copyright (C) 2017 ZTE Ltd
- *
- * Author: Baoyou Xie <baoyou.xie@linaro.org>
- */
-
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <sound/dmaengine_pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dai.h>
-
-#define REG_TIMING_CTRL 0x04
-#define REG_TX_FIFO_CTRL 0x0C
-#define REG_RX_FIFO_CTRL 0x10
-#define REG_INT_EN 0x1C
-#define REG_INT_STATUS 0x20
-#define REG_DATABUF 0x24
-#define REG_TS_MASK0 0x44
-#define REG_PROCESS_CTRL 0x54
-
-#define FIFO_CTRL_TX_RST BIT(0)
-#define FIFO_CTRL_RX_RST BIT(0)
-#define DEAGULT_FIFO_THRES GENMASK(4, 2)
-
-#define FIFO_CTRL_TX_DMA_EN BIT(1)
-#define FIFO_CTRL_RX_DMA_EN BIT(1)
-
-#define TX_FIFO_RST_MASK BIT(0)
-#define RX_FIFO_RST_MASK BIT(0)
-
-#define FIFOCTRL_TX_FIFO_RST BIT(0)
-#define FIFOCTRL_RX_FIFO_RST BIT(0)
-
-#define TXTH_MASK GENMASK(5, 2)
-#define RXTH_MASK GENMASK(5, 2)
-
-#define FIFOCTRL_THRESHOLD(x) ((x) << 2)
-
-#define TIMING_MS_MASK BIT(1)
-/*
- * 00: 8 clk cycles every timeslot
- * 01: 16 clk cycles every timeslot
- * 10: 32 clk cycles every timeslot
- */
-#define TIMING_SYNC_WIDTH_MASK GENMASK(6, 5)
-#define TIMING_WIDTH_SHIFT 5
-#define TIMING_DEFAULT_WIDTH 0
-#define TIMING_TS_WIDTH(x) ((x) << TIMING_WIDTH_SHIFT)
-#define TIMING_WIDTH_FACTOR 8
-
-#define TIMING_MASTER_MODE BIT(21)
-#define TIMING_LSB_FIRST BIT(20)
-#define TIMING_TS_NUM(x) (((x) - 1) << 7)
-#define TIMING_CLK_SEL_MASK GENMASK(2, 0)
-#define TIMING_CLK_SEL_DEF BIT(2)
-
-#define PROCESS_TX_EN BIT(0)
-#define PROCESS_RX_EN BIT(1)
-#define PROCESS_TDM_EN BIT(2)
-#define PROCESS_DISABLE_ALL 0
-
-#define INT_DISABLE_ALL 0
-#define INT_STATUS_MASK GENMASK(6, 0)
-
-struct zx_tdm_info {
- struct snd_dmaengine_dai_dma_data dma_playback;
- struct snd_dmaengine_dai_dma_data dma_capture;
- resource_size_t phy_addr;
- void __iomem *regbase;
- struct clk *dai_wclk;
- struct clk *dai_pclk;
- int master;
- struct device *dev;
-};
-
-static inline u32 zx_tdm_readl(struct zx_tdm_info *tdm, u16 reg)
-{
- return readl_relaxed(tdm->regbase + reg);
-}
-
-static inline void zx_tdm_writel(struct zx_tdm_info *tdm, u16 reg, u32 val)
-{
- writel_relaxed(val, tdm->regbase + reg);
-}
-
-static void zx_tdm_tx_en(struct zx_tdm_info *tdm, bool on)
-{
- unsigned long val;
-
- val = zx_tdm_readl(tdm, REG_PROCESS_CTRL);
- if (on)
- val |= PROCESS_TX_EN | PROCESS_TDM_EN;
- else
- val &= ~(PROCESS_TX_EN | PROCESS_TDM_EN);
- zx_tdm_writel(tdm, REG_PROCESS_CTRL, val);
-}
-
-static void zx_tdm_rx_en(struct zx_tdm_info *tdm, bool on)
-{
- unsigned long val;
-
- val = zx_tdm_readl(tdm, REG_PROCESS_CTRL);
- if (on)
- val |= PROCESS_RX_EN | PROCESS_TDM_EN;
- else
- val &= ~(PROCESS_RX_EN | PROCESS_TDM_EN);
- zx_tdm_writel(tdm, REG_PROCESS_CTRL, val);
-}
-
-static void zx_tdm_tx_dma_en(struct zx_tdm_info *tdm, bool on)
-{
- unsigned long val;
-
- val = zx_tdm_readl(tdm, REG_TX_FIFO_CTRL);
- val |= FIFO_CTRL_TX_RST | DEAGULT_FIFO_THRES;
- if (on)
- val |= FIFO_CTRL_TX_DMA_EN;
- else
- val &= ~FIFO_CTRL_TX_DMA_EN;
- zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, val);
-}
-
-static void zx_tdm_rx_dma_en(struct zx_tdm_info *tdm, bool on)
-{
- unsigned long val;
-
- val = zx_tdm_readl(tdm, REG_RX_FIFO_CTRL);
- val |= FIFO_CTRL_RX_RST | DEAGULT_FIFO_THRES;
- if (on)
- val |= FIFO_CTRL_RX_DMA_EN;
- else
- val &= ~FIFO_CTRL_RX_DMA_EN;
- zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, val);
-}
-
-#define ZX_TDM_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
-
-#define ZX_TDM_FMTBIT \
- (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_MU_LAW | \
- SNDRV_PCM_FMTBIT_A_LAW)
-
-static int zx_tdm_dai_probe(struct snd_soc_dai *dai)
-{
- struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
-
- snd_soc_dai_set_drvdata(dai, zx_tdm);
- zx_tdm->dma_playback.addr = zx_tdm->phy_addr + REG_DATABUF;
- zx_tdm->dma_playback.maxburst = 16;
- zx_tdm->dma_capture.addr = zx_tdm->phy_addr + REG_DATABUF;
- zx_tdm->dma_capture.maxburst = 16;
- snd_soc_dai_init_dma_data(dai, &zx_tdm->dma_playback,
- &zx_tdm->dma_capture);
- return 0;
-}
-
-static int zx_tdm_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
-{
- struct zx_tdm_info *tdm = snd_soc_dai_get_drvdata(cpu_dai);
- unsigned long val;
-
- val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
- val &= ~(TIMING_SYNC_WIDTH_MASK | TIMING_MS_MASK);
- val |= TIMING_DEFAULT_WIDTH << TIMING_WIDTH_SHIFT;
-
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBM_CFM:
- tdm->master = 1;
- val |= TIMING_MASTER_MODE;
- break;
- case SND_SOC_DAIFMT_CBS_CFS:
- tdm->master = 0;
- val &= ~TIMING_MASTER_MODE;
- break;
- default:
- dev_err(cpu_dai->dev, "Unknown master/slave format\n");
- return -EINVAL;
- }
-
-
- zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
-
- return 0;
-}
-
-static int zx_tdm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *socdai)
-{
- struct zx_tdm_info *tdm = snd_soc_dai_get_drvdata(socdai);
- struct snd_dmaengine_dai_dma_data *dma_data;
- unsigned int ts_width = TIMING_DEFAULT_WIDTH;
- unsigned int ch_num = 32;
- unsigned int mask = 0;
- unsigned int ret = 0;
- unsigned long val;
-
- dma_data = snd_soc_dai_get_dma_data(socdai, substream);
- dma_data->addr_width = ch_num >> 3;
-
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_MU_LAW:
- case SNDRV_PCM_FORMAT_A_LAW:
- case SNDRV_PCM_FORMAT_S16_LE:
- ts_width = 1;
- break;
- default:
- dev_err(socdai->dev, "Unknown data format\n");
- return -EINVAL;
- }
-
- val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
- val |= TIMING_TS_WIDTH(ts_width) | TIMING_TS_NUM(1);
- zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
- zx_tdm_writel(tdm, REG_TS_MASK0, mask);
-
- if (tdm->master)
- ret = clk_set_rate(tdm->dai_wclk,
- params_rate(params) * TIMING_WIDTH_FACTOR * ch_num);
-
- return ret;
-}
-
-static int zx_tdm_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
- struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
- unsigned int val;
- int ret = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- if (capture) {
- val = zx_tdm_readl(zx_tdm, REG_RX_FIFO_CTRL);
- val |= FIFOCTRL_RX_FIFO_RST;
- zx_tdm_writel(zx_tdm, REG_RX_FIFO_CTRL, val);
-
- zx_tdm_rx_dma_en(zx_tdm, true);
- } else {
- val = zx_tdm_readl(zx_tdm, REG_TX_FIFO_CTRL);
- val |= FIFOCTRL_TX_FIFO_RST;
- zx_tdm_writel(zx_tdm, REG_TX_FIFO_CTRL, val);
-
- zx_tdm_tx_dma_en(zx_tdm, true);
- }
- break;
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- if (capture)
- zx_tdm_rx_en(zx_tdm, true);
- else
- zx_tdm_tx_en(zx_tdm, true);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- if (capture)
- zx_tdm_rx_dma_en(zx_tdm, false);
- else
- zx_tdm_tx_dma_en(zx_tdm, false);
- break;
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- if (capture)
- zx_tdm_rx_en(zx_tdm, false);
- else
- zx_tdm_tx_en(zx_tdm, false);
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-static int zx_tdm_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
- int ret;
-
- ret = clk_prepare_enable(zx_tdm->dai_wclk);
- if (ret)
- return ret;
-
- ret = clk_prepare_enable(zx_tdm->dai_pclk);
- if (ret) {
- clk_disable_unprepare(zx_tdm->dai_wclk);
- return ret;
- }
-
- return 0;
-}
-
-static void zx_tdm_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
-
- clk_disable_unprepare(zx_tdm->dai_pclk);
- clk_disable_unprepare(zx_tdm->dai_wclk);
-}
-
-static const struct snd_soc_dai_ops zx_tdm_dai_ops = {
- .trigger = zx_tdm_trigger,
- .hw_params = zx_tdm_hw_params,
- .set_fmt = zx_tdm_set_fmt,
- .startup = zx_tdm_startup,
- .shutdown = zx_tdm_shutdown,
-};
-
-static const struct snd_soc_component_driver zx_tdm_component = {
- .name = "zx-tdm",
-};
-
-static void zx_tdm_init_state(struct zx_tdm_info *tdm)
-{
- unsigned int val;
-
- zx_tdm_writel(tdm, REG_PROCESS_CTRL, PROCESS_DISABLE_ALL);
-
- val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
- val |= TIMING_LSB_FIRST;
- val &= ~TIMING_CLK_SEL_MASK;
- val |= TIMING_CLK_SEL_DEF;
- zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
-
- zx_tdm_writel(tdm, REG_INT_EN, INT_DISABLE_ALL);
- /*
- * write INT_STATUS register to clear it.
- */
- zx_tdm_writel(tdm, REG_INT_STATUS, INT_STATUS_MASK);
- zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, FIFOCTRL_RX_FIFO_RST);
- zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, FIFOCTRL_TX_FIFO_RST);
-
- val = zx_tdm_readl(tdm, REG_RX_FIFO_CTRL);
- val &= ~(RXTH_MASK | RX_FIFO_RST_MASK);
- val |= FIFOCTRL_THRESHOLD(8);
- zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, val);
-
- val = zx_tdm_readl(tdm, REG_TX_FIFO_CTRL);
- val &= ~(TXTH_MASK | TX_FIFO_RST_MASK);
- val |= FIFOCTRL_THRESHOLD(8);
- zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, val);
-}
-
-static struct snd_soc_dai_driver zx_tdm_dai = {
- .name = "zx-tdm-dai",
- .id = 0,
- .probe = zx_tdm_dai_probe,
- .playback = {
- .channels_min = 1,
- .channels_max = 4,
- .rates = ZX_TDM_RATES,
- .formats = ZX_TDM_FMTBIT,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 4,
- .rates = ZX_TDM_RATES,
- .formats = ZX_TDM_FMTBIT,
- },
- .ops = &zx_tdm_dai_ops,
-};
-
-static int zx_tdm_probe(struct platform_device *pdev)
-{
- struct of_phandle_args out_args;
- unsigned int dma_reg_offset;
- struct zx_tdm_info *zx_tdm;
- unsigned int dma_mask;
- struct resource *res;
- struct regmap *regmap_sysctrl;
- int ret;
-
- zx_tdm = devm_kzalloc(&pdev->dev, sizeof(*zx_tdm), GFP_KERNEL);
- if (!zx_tdm)
- return -ENOMEM;
-
- zx_tdm->dev = &pdev->dev;
-
- zx_tdm->dai_wclk = devm_clk_get(&pdev->dev, "wclk");
- if (IS_ERR(zx_tdm->dai_wclk)) {
- dev_err(&pdev->dev, "Fail to get wclk\n");
- return PTR_ERR(zx_tdm->dai_wclk);
- }
-
- zx_tdm->dai_pclk = devm_clk_get(&pdev->dev, "pclk");
- if (IS_ERR(zx_tdm->dai_pclk)) {
- dev_err(&pdev->dev, "Fail to get pclk\n");
- return PTR_ERR(zx_tdm->dai_pclk);
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- zx_tdm->phy_addr = res->start;
- zx_tdm->regbase = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(zx_tdm->regbase))
- return PTR_ERR(zx_tdm->regbase);
-
- ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
- "zte,tdm-dma-sysctrl", 2, 0, &out_args);
- if (ret) {
- dev_err(&pdev->dev, "Fail to get zte,tdm-dma-sysctrl\n");
- return ret;
- }
-
- dma_reg_offset = out_args.args[0];
- dma_mask = out_args.args[1];
- regmap_sysctrl = syscon_node_to_regmap(out_args.np);
- if (IS_ERR(regmap_sysctrl)) {
- of_node_put(out_args.np);
- return PTR_ERR(regmap_sysctrl);
- }
-
- regmap_update_bits(regmap_sysctrl, dma_reg_offset, dma_mask, dma_mask);
- of_node_put(out_args.np);
-
- zx_tdm_init_state(zx_tdm);
- platform_set_drvdata(pdev, zx_tdm);
-
- ret = devm_snd_soc_register_component(&pdev->dev, &zx_tdm_component,
- &zx_tdm_dai, 1);
- if (ret) {
- dev_err(&pdev->dev, "Register DAI failed: %d\n", ret);
- return ret;
- }
-
- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
- if (ret)
- dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret);
-
- return ret;
-}
-
-static const struct of_device_id zx_tdm_dt_ids[] = {
- { .compatible = "zte,zx296718-tdm", },
- {}
-};
-MODULE_DEVICE_TABLE(of, zx_tdm_dt_ids);
-
-static struct platform_driver tdm_driver = {
- .probe = zx_tdm_probe,
- .driver = {
- .name = "zx-tdm",
- .of_match_table = zx_tdm_dt_ids,
- },
-};
-module_platform_driver(tdm_driver);
-
-MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
-MODULE_DESCRIPTION("ZTE TDM DAI driver");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c
index 010976d9ceb2..cd4a0bc6d278 100644
--- a/sound/usb/bcd2000/bcd2000.c
+++ b/sound/usb/bcd2000/bcd2000.c
@@ -300,7 +300,7 @@ static int bcd2000_init_midi(struct bcd2000 *bcd2k)
if (ret < 0)
return ret;
- strlcpy(rmidi->name, bcd2k->card->shortname, sizeof(rmidi->name));
+ strscpy(rmidi->name, bcd2k->card->shortname, sizeof(rmidi->name));
rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;
rmidi->private_data = bcd2k;
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
index 3b6bb2cbe886..4981753652a7 100644
--- a/sound/usb/caiaq/audio.c
+++ b/sound/usb/caiaq/audio.c
@@ -804,7 +804,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev)
}
cdev->pcm->private_data = cdev;
- strlcpy(cdev->pcm->name, cdev->product_name, sizeof(cdev->pcm->name));
+ strscpy(cdev->pcm->name, cdev->product_name, sizeof(cdev->pcm->name));
memset(cdev->sub_playback, 0, sizeof(cdev->sub_playback));
memset(cdev->sub_capture, 0, sizeof(cdev->sub_capture));
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index 2af3b7eb0a88..e03481caf7f6 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -477,9 +477,9 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
usb_string(usb_dev, usb_dev->descriptor.iProduct,
cdev->product_name, CAIAQ_USB_STR_LEN);
- strlcpy(card->driver, MODNAME, sizeof(card->driver));
- strlcpy(card->shortname, cdev->product_name, sizeof(card->shortname));
- strlcpy(card->mixername, cdev->product_name, sizeof(card->mixername));
+ strscpy(card->driver, MODNAME, sizeof(card->driver));
+ strscpy(card->shortname, cdev->product_name, sizeof(card->shortname));
+ strscpy(card->mixername, cdev->product_name, sizeof(card->mixername));
/* if the id was not passed as module option, fill it with a shortened
* version of the product string which does not contain any
diff --git a/sound/usb/caiaq/midi.c b/sound/usb/caiaq/midi.c
index 512fbb3ee604..c656d0162432 100644
--- a/sound/usb/caiaq/midi.c
+++ b/sound/usb/caiaq/midi.c
@@ -125,7 +125,7 @@ int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device)
if (ret < 0)
return ret;
- strlcpy(rmidi->name, device->product_name, sizeof(rmidi->name));
+ strscpy(rmidi->name, device->product_name, sizeof(rmidi->name));
rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;
rmidi->private_data = device;
diff --git a/sound/usb/card.c b/sound/usb/card.c
index e08fbf8e3ee0..85ed8507e41a 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -472,7 +472,7 @@ static void usb_audio_make_shortname(struct usb_device *dev,
else if (quirk && quirk->product_name)
s = quirk->product_name;
if (s && *s) {
- strlcpy(card->shortname, s, sizeof(card->shortname));
+ strscpy(card->shortname, s, sizeof(card->shortname));
return;
}
@@ -504,7 +504,7 @@ static void usb_audio_make_longname(struct usb_device *dev,
if (preset && preset->profile_name)
s = preset->profile_name;
if (s && *s) {
- strlcpy(card->longname, s, sizeof(card->longname));
+ strscpy(card->longname, s, sizeof(card->longname));
return;
}
@@ -512,18 +512,17 @@ static void usb_audio_make_longname(struct usb_device *dev,
s = preset->vendor_name;
else if (quirk && quirk->vendor_name)
s = quirk->vendor_name;
+ *card->longname = 0;
if (s && *s) {
- len = strlcpy(card->longname, s, sizeof(card->longname));
+ strscpy(card->longname, s, sizeof(card->longname));
} else {
/* retrieve the vendor and device strings as longname */
if (dev->descriptor.iManufacturer)
- len = usb_string(dev, dev->descriptor.iManufacturer,
- card->longname, sizeof(card->longname));
- else
- len = 0;
+ usb_string(dev, dev->descriptor.iManufacturer,
+ card->longname, sizeof(card->longname));
/* we don't really care if there isn't any vendor string */
}
- if (len > 0) {
+ if (*card->longname) {
strim(card->longname);
if (*card->longname)
strlcat(card->longname, " ", sizeof(card->longname));
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 37091b117614..a741e7da83a2 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -71,7 +71,7 @@ struct snd_usb_endpoint {
unsigned char altsetting; /* corresponding alternate setting */
unsigned char ep_idx; /* endpoint array index */
- unsigned long flags; /* running bit flags */
+ atomic_t state; /* running state */
void (*prepare_data_urb) (struct snd_usb_substream *subs,
struct urb *urb);
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index dc68ed65e478..8243652d5604 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -298,6 +298,11 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
if (selector) {
int ret, i, cur;
+ if (selector->bNrInPins == 1) {
+ ret = 1;
+ goto find_source;
+ }
+
/* the entity ID we are looking for is a selector.
* find out what it currently selects */
ret = uac_clock_selector_get_val(chip, selector->bClockID);
@@ -314,6 +319,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
return -EINVAL;
}
+ find_source:
cur = ret;
ret = __uac_clock_find_source(chip, fmt,
selector->baCSourceID[ret - 1],
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 8e568823c992..102d53515a76 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -21,8 +21,11 @@
#include "clock.h"
#include "quirks.h"
-#define EP_FLAG_RUNNING 1
-#define EP_FLAG_STOPPING 2
+enum {
+ EP_STATE_STOPPED,
+ EP_STATE_RUNNING,
+ EP_STATE_STOPPING,
+};
/* interface refcounting */
struct snd_usb_iface_ref {
@@ -115,6 +118,16 @@ static const char *usb_error_string(int err)
}
}
+static inline bool ep_state_running(struct snd_usb_endpoint *ep)
+{
+ return atomic_read(&ep->state) == EP_STATE_RUNNING;
+}
+
+static inline bool ep_state_update(struct snd_usb_endpoint *ep, int old, int new)
+{
+ return atomic_cmpxchg(&ep->state, old, new) == old;
+}
+
/**
* snd_usb_endpoint_implicit_feedback_sink: Report endpoint usage type
*
@@ -393,7 +406,7 @@ next_packet_fifo_dequeue(struct snd_usb_endpoint *ep)
*/
static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
{
- while (test_bit(EP_FLAG_RUNNING, &ep->flags)) {
+ while (ep_state_running(ep)) {
unsigned long flags;
struct snd_usb_packet_info *packet;
@@ -454,13 +467,13 @@ static void snd_complete_urb(struct urb *urb)
if (unlikely(atomic_read(&ep->chip->shutdown)))
goto exit_clear;
- if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+ if (unlikely(!ep_state_running(ep)))
goto exit_clear;
if (usb_pipeout(ep->pipe)) {
retire_outbound_urb(ep, ctx);
/* can be stopped during retire callback */
- if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+ if (unlikely(!ep_state_running(ep)))
goto exit_clear;
if (snd_usb_endpoint_implicit_feedback_sink(ep)) {
@@ -474,12 +487,12 @@ static void snd_complete_urb(struct urb *urb)
prepare_outbound_urb(ep, ctx);
/* can be stopped during prepare callback */
- if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+ if (unlikely(!ep_state_running(ep)))
goto exit_clear;
} else {
retire_inbound_urb(ep, ctx);
/* can be stopped during retire callback */
- if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+ if (unlikely(!ep_state_running(ep)))
goto exit_clear;
prepare_inbound_urb(ep, ctx);
@@ -835,7 +848,7 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
unsigned long end_time = jiffies + msecs_to_jiffies(1000);
int alive;
- if (!test_bit(EP_FLAG_STOPPING, &ep->flags))
+ if (atomic_read(&ep->state) != EP_STATE_STOPPING)
return 0;
do {
@@ -850,10 +863,11 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
usb_audio_err(ep->chip,
"timeout: still %d active urbs on EP #%x\n",
alive, ep->ep_num);
- clear_bit(EP_FLAG_STOPPING, &ep->flags);
- ep->sync_sink = NULL;
- snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL);
+ if (ep_state_update(ep, EP_STATE_STOPPING, EP_STATE_STOPPED)) {
+ ep->sync_sink = NULL;
+ snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL);
+ }
return 0;
}
@@ -868,26 +882,20 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
}
/*
- * Stop and unlink active urbs.
+ * Stop active urbs
*
- * This function checks and clears EP_FLAG_RUNNING state.
- * When @wait_sync is set, it waits until all pending URBs are killed.
+ * This function moves the EP to STOPPING state if it's being RUNNING.
*/
-static int stop_and_unlink_urbs(struct snd_usb_endpoint *ep, bool force,
- bool wait_sync)
+static int stop_urbs(struct snd_usb_endpoint *ep, bool force)
{
unsigned int i;
- if (!force && atomic_read(&ep->chip->shutdown)) /* to be sure... */
- return -EBADFD;
-
- if (atomic_read(&ep->running))
+ if (!force && atomic_read(&ep->running))
return -EBUSY;
- if (!test_and_clear_bit(EP_FLAG_RUNNING, &ep->flags))
- goto out;
+ if (!ep_state_update(ep, EP_STATE_RUNNING, EP_STATE_STOPPING))
+ return 0;
- set_bit(EP_FLAG_STOPPING, &ep->flags);
INIT_LIST_HEAD(&ep->ready_playback_urbs);
ep->next_packet_head = 0;
ep->next_packet_queued = 0;
@@ -901,24 +909,25 @@ static int stop_and_unlink_urbs(struct snd_usb_endpoint *ep, bool force,
}
}
- out:
- if (wait_sync)
- return wait_clear_urbs(ep);
return 0;
}
/*
* release an endpoint's urbs
*/
-static void release_urbs(struct snd_usb_endpoint *ep, int force)
+static int release_urbs(struct snd_usb_endpoint *ep, bool force)
{
- int i;
+ int i, err;
/* route incoming urbs to nirvana */
snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL);
- /* stop urbs */
- stop_and_unlink_urbs(ep, force, true);
+ /* stop and unlink urbs */
+ err = stop_urbs(ep, force);
+ if (err)
+ return err;
+
+ wait_clear_urbs(ep);
for (i = 0; i < ep->nurbs; i++)
release_urb_ctx(&ep->urb[i]);
@@ -928,6 +937,7 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
ep->syncbuf = NULL;
ep->nurbs = 0;
+ return 0;
}
/*
@@ -1118,7 +1128,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
return 0;
out_of_memory:
- release_urbs(ep, 0);
+ release_urbs(ep, false);
return -ENOMEM;
}
@@ -1162,7 +1172,7 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep)
return 0;
out_of_memory:
- release_urbs(ep, 0);
+ release_urbs(ep, false);
return -ENOMEM;
}
@@ -1180,7 +1190,9 @@ static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
int err;
/* release old buffers, if any */
- release_urbs(ep, 0);
+ err = release_urbs(ep, false);
+ if (err < 0)
+ return err;
ep->datainterval = fmt->datainterval;
ep->maxpacksize = fmt->maxpacksize;
@@ -1360,7 +1372,8 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
* from that context.
*/
- set_bit(EP_FLAG_RUNNING, &ep->flags);
+ if (!ep_state_update(ep, EP_STATE_STOPPED, EP_STATE_RUNNING))
+ goto __error;
if (snd_usb_endpoint_implicit_feedback_sink(ep)) {
for (i = 0; i < ep->nurbs; i++) {
@@ -1433,7 +1446,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
WRITE_ONCE(ep->sync_source->sync_sink, NULL);
if (!atomic_dec_return(&ep->running))
- stop_and_unlink_urbs(ep, false, false);
+ stop_urbs(ep, false);
}
/**
@@ -1446,12 +1459,12 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
*/
void snd_usb_endpoint_release(struct snd_usb_endpoint *ep)
{
- release_urbs(ep, 1);
+ release_urbs(ep, true);
}
/**
* snd_usb_endpoint_free_all: Free the resources of an snd_usb_endpoint
- * @card: The chip
+ * @chip: The chip
*
* This free all endpoints and those resources
*/
diff --git a/sound/usb/hiface/chip.c b/sound/usb/hiface/chip.c
index b2d9623e9934..c2824188d142 100644
--- a/sound/usb/hiface/chip.c
+++ b/sound/usb/hiface/chip.c
@@ -80,12 +80,12 @@ static int hiface_chip_create(struct usb_interface *intf,
return ret;
}
- strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
+ strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));
if (quirk && quirk->device_name)
- strlcpy(card->shortname, quirk->device_name, sizeof(card->shortname));
+ strscpy(card->shortname, quirk->device_name, sizeof(card->shortname));
else
- strlcpy(card->shortname, "M2Tech generic audio", sizeof(card->shortname));
+ strscpy(card->shortname, "M2Tech generic audio", sizeof(card->shortname));
strlcat(card->longname, card->shortname, sizeof(card->longname));
len = strlcat(card->longname, " at ", sizeof(card->longname));
diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c
index d942179ca095..71f17f02f341 100644
--- a/sound/usb/hiface/pcm.c
+++ b/sound/usb/hiface/pcm.c
@@ -594,7 +594,7 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
pcm->private_data = rt;
pcm->private_free = hiface_pcm_free;
- strlcpy(pcm->name, "USB-SPDIF Audio", sizeof(pcm->name));
+ strscpy(pcm->name, "USB-SPDIF Audio", sizeof(pcm->name));
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops);
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
NULL, 0, 0);
diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c
index 521cc846d9d9..11a85e66aa96 100644
--- a/sound/usb/implicit.c
+++ b/sound/usb/implicit.c
@@ -73,6 +73,7 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
/* No quirk for playback but with capture quirk (see below) */
IMPLICIT_FB_SKIP_DEV(0x0582, 0x0130), /* BOSS BR-80 */
IMPLICIT_FB_SKIP_DEV(0x0582, 0x0171), /* BOSS RC-505 */
+ IMPLICIT_FB_SKIP_DEV(0x0582, 0x0185), /* BOSS GP-10 */
IMPLICIT_FB_SKIP_DEV(0x0582, 0x0189), /* BOSS GT-100v2 */
IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d6), /* BOSS GT-1 */
IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d8), /* BOSS Katana */
@@ -86,6 +87,7 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = {
IMPLICIT_FB_FIXED_DEV(0x0582, 0x0130, 0x0d, 0x01), /* BOSS BR-80 */
IMPLICIT_FB_FIXED_DEV(0x0582, 0x0171, 0x0d, 0x01), /* BOSS RC-505 */
+ IMPLICIT_FB_FIXED_DEV(0x0582, 0x0185, 0x0d, 0x01), /* BOSS GP-10 */
IMPLICIT_FB_FIXED_DEV(0x0582, 0x0189, 0x0d, 0x01), /* BOSS GT-100v2 */
IMPLICIT_FB_FIXED_DEV(0x0582, 0x01d6, 0x0d, 0x01), /* BOSS GT-1 */
IMPLICIT_FB_FIXED_DEV(0x0582, 0x01d8, 0x0d, 0x01), /* BOSS Katana */
@@ -302,7 +304,8 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
/* Pioneer devices with vendor spec class */
if (attr == USB_ENDPOINT_SYNC_ASYNC &&
alts->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
- USB_ID_VENDOR(chip->usb_id) == 0x2b73 /* Pioneer */) {
+ (USB_ID_VENDOR(chip->usb_id) == 0x2b73 || /* Pioneer */
+ USB_ID_VENDOR(chip->usb_id) == 0x08e4 /* Pioneer */)) {
if (skip_pioneer_sync_ep(chip, fmt, alts))
return 1;
}
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 12b15ed59eaa..b1c78db0d470 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -115,11 +115,14 @@ find_map(const struct usbmix_name_map *p, int unitid, int control)
static int
check_mapped_name(const struct usbmix_name_map *p, char *buf, int buflen)
{
+ int len;
+
if (!p || !p->name)
return 0;
buflen--;
- return strlcpy(buf, p->name, buflen);
+ len = strscpy(buf, p->name, buflen);
+ return len < 0 ? buflen : len;
}
/* ignore the error value if ignore_ctl_error flag is set */
@@ -151,12 +154,15 @@ static int check_mapped_selector_name(struct mixer_build *state, int unitid,
int index, char *buf, int buflen)
{
const struct usbmix_selector_map *p;
+ int len;
if (!state->selector_map)
return 0;
for (p = state->selector_map; p->id; p++) {
- if (p->id == unitid && index < p->count)
- return strlcpy(buf, p->names[index], buflen);
+ if (p->id == unitid && index < p->count) {
+ len = strscpy(buf, p->names[index], buflen);
+ return len < 0 ? buflen : len;
+ }
}
return 0;
}
@@ -254,7 +260,7 @@ static int get_relative_value(struct usb_mixer_elem_info *cval, int val)
if (val < cval->min)
return 0;
else if (val >= cval->max)
- return (cval->max - cval->min + cval->res - 1) / cval->res;
+ return DIV_ROUND_UP(cval->max - cval->min, cval->res);
else
return (val - cval->min) / cval->res;
}
@@ -1232,7 +1238,7 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
(cval->control << 8) | minchn,
&cval->res) < 0) {
cval->res = 1;
- } else {
+ } else if (cval->head.mixer->protocol == UAC_VERSION_1) {
int last_valid_res = cval->res;
while (cval->res > 1) {
@@ -1338,7 +1344,7 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol,
}
uinfo->value.integer.min = 0;
uinfo->value.integer.max =
- (cval->max - cval->min + cval->res - 1) / cval->res;
+ DIV_ROUND_UP(cval->max - cval->min, cval->res);
}
return 0;
}
@@ -1556,7 +1562,7 @@ static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
if (!found)
return;
- strlcpy(kctl->id.name, "Headphone", sizeof(kctl->id.name));
+ strscpy(kctl->id.name, "Headphone", sizeof(kctl->id.name));
}
static const struct usb_feature_control_info *get_feature_control_info(int control)
@@ -1691,7 +1697,7 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer,
break;
default:
if (!len)
- strlcpy(kctl->id.name, audio_feature_info[control-1].name,
+ strscpy(kctl->id.name, audio_feature_info[control-1].name,
sizeof(kctl->id.name));
break;
}
@@ -1770,7 +1776,7 @@ static void get_connector_control_name(struct usb_mixer_interface *mixer,
int name_len = get_term_name(mixer->chip, term, name, name_size, 0);
if (name_len == 0)
- strlcpy(name, "Unknown", name_size);
+ strscpy(name, "Unknown", name_size);
/*
* sound/core/ctljack.c has a convention of naming jack controls
@@ -2490,7 +2496,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
if (check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name))) {
/* nothing */ ;
} else if (info->name) {
- strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name));
+ strscpy(kctl->id.name, info->name, sizeof(kctl->id.name));
} else {
if (extension_unit)
nameid = uac_extension_unit_iExtension(desc, state->mixer->protocol);
@@ -2503,7 +2509,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
kctl->id.name,
sizeof(kctl->id.name));
if (!len)
- strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
+ strscpy(kctl->id.name, name, sizeof(kctl->id.name));
}
append_ctl_name(kctl, " ");
append_ctl_name(kctl, valinfo->suffix);
@@ -2743,7 +2749,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
kctl->id.name, sizeof(kctl->id.name), 0);
/* ... or use the fixed string "USB" as the last resort */
if (!len)
- strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
+ strscpy(kctl->id.name, "USB", sizeof(kctl->id.name));
/* and add the proper suffix */
if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR ||
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index df036a359f2f..08873d2afe4d 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -2603,141 +2603,251 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer)
}
/*
- * Pioneer DJ DJM-250MK2 and maybe other DJM models
+ * Pioneer DJ DJM Mixers
*
- * For playback, no duplicate mapping should be set.
- * There are three mixer stereo channels (CH1, CH2, AUX)
- * and three stereo sources (Playback 1-2, Playback 3-4, Playback 5-6).
- * Each channel should be mapped just once to one source.
- * If mapped multiple times, only one source will play on given channel
- * (sources are not mixed together).
+ * These devices generally have options for soft-switching the playback and
+ * capture sources in addition to the recording level. Although different
+ * devices have different configurations, there seems to be canonical values
+ * for specific capture/playback types: See the definitions of these below.
*
- * For recording, duplicate mapping is OK. We will get the same signal multiple times.
- *
- * Channels 7-8 are in both directions fixed to FX SEND / FX RETURN.
- *
- * See also notes in the quirks-table.h file.
+ * The wValue is masked with the stereo channel number. e.g. Setting Ch2 to
+ * capture phono would be 0x0203. Capture, playback and capture level have
+ * different wIndexes.
*/
-struct snd_pioneer_djm_option {
- const u16 wIndex;
- const u16 wValue;
+// Capture types
+#define SND_DJM_CAP_LINE 0x00
+#define SND_DJM_CAP_CDLINE 0x01
+#define SND_DJM_CAP_DIGITAL 0x02
+#define SND_DJM_CAP_PHONO 0x03
+#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_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
+
+// Playback types
+#define SND_DJM_PB_CH1 0x00
+#define SND_DJM_PB_CH2 0x01
+#define SND_DJM_PB_AUX 0x04
+
+#define SND_DJM_WINDEX_CAP 0x8002
+#define SND_DJM_WINDEX_CAPLVL 0x8003
+#define SND_DJM_WINDEX_PB 0x8016
+
+// kcontrol->private_value layout
+#define SND_DJM_VALUE_MASK 0x0000ffff
+#define SND_DJM_GROUP_MASK 0x00ff0000
+#define SND_DJM_DEVICE_MASK 0xff000000
+#define SND_DJM_GROUP_SHIFT 16
+#define SND_DJM_DEVICE_SHIFT 24
+
+// device table index
+#define SND_DJM_250MK2_IDX 0x0
+#define SND_DJM_750_IDX 0x1
+#define SND_DJM_900NXS2_IDX 0x2
+
+
+#define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \
+ .name = _name, \
+ .options = snd_djm_opts_##suffix, \
+ .noptions = ARRAY_SIZE(snd_djm_opts_##suffix), \
+ .default_value = _default_value, \
+ .wIndex = _windex }
+
+#define SND_DJM_DEVICE(suffix) { \
+ .controls = snd_djm_ctls_##suffix, \
+ .ncontrols = ARRAY_SIZE(snd_djm_ctls_##suffix) }
+
+
+struct snd_djm_device {
const char *name;
+ const struct snd_djm_ctl *controls;
+ size_t ncontrols;
};
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_level[] = {
- { .name = "-5 dB", .wValue = 0x0300, .wIndex = 0x8003 },
- { .name = "-10 dB", .wValue = 0x0200, .wIndex = 0x8003 },
- { .name = "-15 dB", .wValue = 0x0100, .wIndex = 0x8003 },
- { .name = "-19 dB", .wValue = 0x0000, .wIndex = 0x8003 }
+struct snd_djm_ctl {
+ const char *name;
+ const u16 *options;
+ size_t noptions;
+ u16 default_value;
+ u16 wIndex;
};
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch12[] = {
- { .name = "CH1 Control Tone PHONO", .wValue = 0x0103, .wIndex = 0x8002 },
- { .name = "CH1 Control Tone LINE", .wValue = 0x0100, .wIndex = 0x8002 },
- { .name = "Post CH1 Fader", .wValue = 0x0106, .wIndex = 0x8002 },
- { .name = "Cross Fader A", .wValue = 0x0107, .wIndex = 0x8002 },
- { .name = "Cross Fader B", .wValue = 0x0108, .wIndex = 0x8002 },
- { .name = "MIC", .wValue = 0x0109, .wIndex = 0x8002 },
- { .name = "AUX", .wValue = 0x010d, .wIndex = 0x8002 },
- { .name = "REC OUT", .wValue = 0x010a, .wIndex = 0x8002 }
+static const char *snd_djm_get_label_caplevel(u16 wvalue)
+{
+ switch (wvalue) {
+ case 0x0000: return "-19dB";
+ case 0x0100: return "-15dB";
+ case 0x0200: return "-10dB";
+ case 0x0300: return "-5dB";
+ default: return NULL;
+ }
};
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch34[] = {
- { .name = "CH2 Control Tone PHONO", .wValue = 0x0203, .wIndex = 0x8002 },
- { .name = "CH2 Control Tone LINE", .wValue = 0x0200, .wIndex = 0x8002 },
- { .name = "Post CH2 Fader", .wValue = 0x0206, .wIndex = 0x8002 },
- { .name = "Cross Fader A", .wValue = 0x0207, .wIndex = 0x8002 },
- { .name = "Cross Fader B", .wValue = 0x0208, .wIndex = 0x8002 },
- { .name = "MIC", .wValue = 0x0209, .wIndex = 0x8002 },
- { .name = "AUX", .wValue = 0x020d, .wIndex = 0x8002 },
- { .name = "REC OUT", .wValue = 0x020a, .wIndex = 0x8002 }
+static const char *snd_djm_get_label_cap(u16 wvalue)
+{
+ switch (wvalue & 0x00ff) {
+ case SND_DJM_CAP_LINE: return "Control Tone LINE";
+ case SND_DJM_CAP_CDLINE: return "Control Tone CD/LINE";
+ case SND_DJM_CAP_DIGITAL: return "Control Tone DIGITAL";
+ case SND_DJM_CAP_PHONO: return "Control Tone PHONO";
+ case SND_DJM_CAP_PFADER: return "Post Fader";
+ case SND_DJM_CAP_XFADERA: return "Cross Fader A";
+ 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_AUX: return "Aux";
+ case SND_DJM_CAP_NONE: return "None";
+ 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";
+ case SND_DJM_CAP_CH4PFADER: return "Post Fader Ch4";
+ default: return NULL;
+ }
};
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch56[] = {
- { .name = "REC OUT", .wValue = 0x030a, .wIndex = 0x8002 },
- { .name = "Post CH1 Fader", .wValue = 0x0311, .wIndex = 0x8002 },
- { .name = "Post CH2 Fader", .wValue = 0x0312, .wIndex = 0x8002 },
- { .name = "Cross Fader A", .wValue = 0x0307, .wIndex = 0x8002 },
- { .name = "Cross Fader B", .wValue = 0x0308, .wIndex = 0x8002 },
- { .name = "MIC", .wValue = 0x0309, .wIndex = 0x8002 },
- { .name = "AUX", .wValue = 0x030d, .wIndex = 0x8002 }
+static const char *snd_djm_get_label_pb(u16 wvalue)
+{
+ switch (wvalue & 0x00ff) {
+ case SND_DJM_PB_CH1: return "Ch1";
+ case SND_DJM_PB_CH2: return "Ch2";
+ case SND_DJM_PB_AUX: return "Aux";
+ default: return NULL;
+ }
};
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_12[] = {
- { .name = "CH1", .wValue = 0x0100, .wIndex = 0x8016 },
- { .name = "CH2", .wValue = 0x0101, .wIndex = 0x8016 },
- { .name = "AUX", .wValue = 0x0104, .wIndex = 0x8016 }
+static const char *snd_djm_get_label(u16 wvalue, u16 windex)
+{
+ switch (windex) {
+ case SND_DJM_WINDEX_CAPLVL: return snd_djm_get_label_caplevel(wvalue);
+ case SND_DJM_WINDEX_CAP: return snd_djm_get_label_cap(wvalue);
+ case SND_DJM_WINDEX_PB: return snd_djm_get_label_pb(wvalue);
+ default: return NULL;
+ }
};
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_34[] = {
- { .name = "CH1", .wValue = 0x0200, .wIndex = 0x8016 },
- { .name = "CH2", .wValue = 0x0201, .wIndex = 0x8016 },
- { .name = "AUX", .wValue = 0x0204, .wIndex = 0x8016 }
+
+// DJM-250MK2
+static const u16 snd_djm_opts_cap_level[] = {
+ 0x0000, 0x0100, 0x0200, 0x0300 };
+
+static const u16 snd_djm_opts_250mk2_cap1[] = {
+ 0x0103, 0x0100, 0x0106, 0x0107, 0x0108, 0x0109, 0x010d, 0x010a };
+
+static const u16 snd_djm_opts_250mk2_cap2[] = {
+ 0x0203, 0x0200, 0x0206, 0x0207, 0x0208, 0x0209, 0x020d, 0x020a };
+
+static const u16 snd_djm_opts_250mk2_cap3[] = {
+ 0x030a, 0x0311, 0x0312, 0x0307, 0x0308, 0x0309, 0x030d };
+
+static const u16 snd_djm_opts_250mk2_pb1[] = { 0x0100, 0x0101, 0x0104 };
+static const u16 snd_djm_opts_250mk2_pb2[] = { 0x0200, 0x0201, 0x0204 };
+static const u16 snd_djm_opts_250mk2_pb3[] = { 0x0300, 0x0301, 0x0304 };
+
+static const struct snd_djm_ctl snd_djm_ctls_250mk2[] = {
+ SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Ch1 Input", 250mk2_cap1, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch2 Input", 250mk2_cap2, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch3 Input", 250mk2_cap3, 0, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch1 Output", 250mk2_pb1, 0, SND_DJM_WINDEX_PB),
+ SND_DJM_CTL("Ch2 Output", 250mk2_pb2, 1, SND_DJM_WINDEX_PB),
+ SND_DJM_CTL("Ch3 Output", 250mk2_pb3, 2, SND_DJM_WINDEX_PB)
};
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_56[] = {
- { .name = "CH1", .wValue = 0x0300, .wIndex = 0x8016 },
- { .name = "CH2", .wValue = 0x0301, .wIndex = 0x8016 },
- { .name = "AUX", .wValue = 0x0304, .wIndex = 0x8016 }
+
+// DJM-750
+static const u16 snd_djm_opts_750_cap1[] = {
+ 0x0101, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a, 0x010f };
+static const u16 snd_djm_opts_750_cap2[] = {
+ 0x0200, 0x0201, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a, 0x020f };
+static const u16 snd_djm_opts_750_cap3[] = {
+ 0x0300, 0x0301, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a, 0x030f };
+static const u16 snd_djm_opts_750_cap4[] = {
+ 0x0401, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040f };
+
+static const struct snd_djm_ctl snd_djm_ctls_750[] = {
+ SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Ch1 Input", 750_cap1, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch2 Input", 750_cap2, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch3 Input", 750_cap3, 0, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch4 Input", 750_cap4, 0, SND_DJM_WINDEX_CAP)
};
-struct snd_pioneer_djm_option_group {
- const char *name;
- const struct snd_pioneer_djm_option *options;
- const size_t count;
- const u16 default_value;
+
+// DJM-900NXS2
+static const u16 snd_djm_opts_900nxs2_cap1[] = {
+ 0x0100, 0x0102, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a };
+static const u16 snd_djm_opts_900nxs2_cap2[] = {
+ 0x0200, 0x0202, 0x0203, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a };
+static const u16 snd_djm_opts_900nxs2_cap3[] = {
+ 0x0300, 0x0302, 0x0303, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a };
+static const u16 snd_djm_opts_900nxs2_cap4[] = {
+ 0x0400, 0x0402, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a };
+static const u16 snd_djm_opts_900nxs2_cap5[] = {
+ 0x0507, 0x0508, 0x0509, 0x050a, 0x0511, 0x0512, 0x0513, 0x0514 };
+
+static const struct snd_djm_ctl snd_djm_ctls_900nxs2[] = {
+ SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Ch1 Input", 900nxs2_cap1, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch2 Input", 900nxs2_cap2, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch3 Input", 900nxs2_cap3, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch4 Input", 900nxs2_cap4, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Ch5 Input", 900nxs2_cap5, 3, SND_DJM_WINDEX_CAP)
};
-#define snd_pioneer_djm_option_group_item(_name, suffix, _default_value) { \
- .name = _name, \
- .options = snd_pioneer_djm_options_##suffix, \
- .count = ARRAY_SIZE(snd_pioneer_djm_options_##suffix), \
- .default_value = _default_value }
-
-static const struct snd_pioneer_djm_option_group snd_pioneer_djm_option_groups[] = {
- snd_pioneer_djm_option_group_item("Master Capture Level Capture Switch", capture_level, 0),
- snd_pioneer_djm_option_group_item("Capture 1-2 Capture Switch", capture_ch12, 2),
- snd_pioneer_djm_option_group_item("Capture 3-4 Capture Switch", capture_ch34, 2),
- snd_pioneer_djm_option_group_item("Capture 5-6 Capture Switch", capture_ch56, 0),
- snd_pioneer_djm_option_group_item("Playback 1-2 Playback Switch", playback_12, 0),
- snd_pioneer_djm_option_group_item("Playback 3-4 Playback Switch", playback_34, 1),
- snd_pioneer_djm_option_group_item("Playback 5-6 Playback Switch", playback_56, 2)
+
+static const struct snd_djm_device snd_djm_devices[] = {
+ SND_DJM_DEVICE(250mk2),
+ SND_DJM_DEVICE(750),
+ SND_DJM_DEVICE(900nxs2)
};
-// layout of the kcontrol->private_value:
-#define SND_PIONEER_DJM_VALUE_MASK 0x0000ffff
-#define SND_PIONEER_DJM_GROUP_MASK 0xffff0000
-#define SND_PIONEER_DJM_GROUP_SHIFT 16
-static int snd_pioneer_djm_controls_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *info)
+static int snd_djm_controls_info(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_info *info)
{
- u16 group_index = kctl->private_value >> SND_PIONEER_DJM_GROUP_SHIFT;
- size_t count;
+ unsigned long private_value = kctl->private_value;
+ u8 device_idx = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT;
+ u8 ctl_idx = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT;
+ const struct snd_djm_device *device = &snd_djm_devices[device_idx];
const char *name;
- const struct snd_pioneer_djm_option_group *group;
+ const struct snd_djm_ctl *ctl;
+ size_t noptions;
- if (group_index >= ARRAY_SIZE(snd_pioneer_djm_option_groups))
+ if (ctl_idx >= device->ncontrols)
return -EINVAL;
- group = &snd_pioneer_djm_option_groups[group_index];
- count = group->count;
- if (info->value.enumerated.item >= count)
- info->value.enumerated.item = count - 1;
- name = group->options[info->value.enumerated.item].name;
- strlcpy(info->value.enumerated.name, name, sizeof(info->value.enumerated.name));
+ ctl = &device->controls[ctl_idx];
+ noptions = ctl->noptions;
+ if (info->value.enumerated.item >= noptions)
+ info->value.enumerated.item = noptions - 1;
+
+ name = snd_djm_get_label(ctl->options[info->value.enumerated.item],
+ ctl->wIndex);
+ if (!name)
+ return -EINVAL;
+
+ strscpy(info->value.enumerated.name, name, sizeof(info->value.enumerated.name));
info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
info->count = 1;
- info->value.enumerated.items = count;
+ info->value.enumerated.items = noptions;
return 0;
}
-static int snd_pioneer_djm_controls_update(struct usb_mixer_interface *mixer, u16 group, u16 value)
+static int snd_djm_controls_update(struct usb_mixer_interface *mixer,
+ u8 device_idx, u8 group, u16 value)
{
int err;
+ const struct snd_djm_device *device = &snd_djm_devices[device_idx];
- if (group >= ARRAY_SIZE(snd_pioneer_djm_option_groups)
- || value >= snd_pioneer_djm_option_groups[group].count)
+ if ((group >= device->ncontrols) || value >= device->controls[group].noptions)
return -EINVAL;
err = snd_usb_lock_shutdown(mixer->chip);
@@ -2748,63 +2858,76 @@ static int snd_pioneer_djm_controls_update(struct usb_mixer_interface *mixer, u1
mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0),
USB_REQ_SET_FEATURE,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- snd_pioneer_djm_option_groups[group].options[value].wValue,
- snd_pioneer_djm_option_groups[group].options[value].wIndex,
+ device->controls[group].options[value],
+ device->controls[group].wIndex,
NULL, 0);
snd_usb_unlock_shutdown(mixer->chip);
return err;
}
-static int snd_pioneer_djm_controls_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem)
+static int snd_djm_controls_get(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *elem)
{
- elem->value.enumerated.item[0] = kctl->private_value & SND_PIONEER_DJM_VALUE_MASK;
+ elem->value.enumerated.item[0] = kctl->private_value & SND_DJM_VALUE_MASK;
return 0;
}
-static int snd_pioneer_djm_controls_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem)
+static int snd_djm_controls_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem)
{
struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
struct usb_mixer_interface *mixer = list->mixer;
unsigned long private_value = kctl->private_value;
- u16 group = (private_value & SND_PIONEER_DJM_GROUP_MASK) >> SND_PIONEER_DJM_GROUP_SHIFT;
+
+ u8 device = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT;
+ u8 group = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT;
u16 value = elem->value.enumerated.item[0];
- kctl->private_value = (group << SND_PIONEER_DJM_GROUP_SHIFT) | value;
+ kctl->private_value = ((device << SND_DJM_DEVICE_SHIFT) |
+ (group << SND_DJM_GROUP_SHIFT) |
+ value);
- return snd_pioneer_djm_controls_update(mixer, group, value);
+ return snd_djm_controls_update(mixer, device, group, value);
}
-static int snd_pioneer_djm_controls_resume(struct usb_mixer_elem_list *list)
+static int snd_djm_controls_resume(struct usb_mixer_elem_list *list)
{
unsigned long private_value = list->kctl->private_value;
- u16 group = (private_value & SND_PIONEER_DJM_GROUP_MASK) >> SND_PIONEER_DJM_GROUP_SHIFT;
- u16 value = (private_value & SND_PIONEER_DJM_VALUE_MASK);
+ u8 device = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT;
+ u8 group = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT;
+ u16 value = (private_value & SND_DJM_VALUE_MASK);
- return snd_pioneer_djm_controls_update(list->mixer, group, value);
+ return snd_djm_controls_update(list->mixer, device, group, value);
}
-static int snd_pioneer_djm_controls_create(struct usb_mixer_interface *mixer)
+static int snd_djm_controls_create(struct usb_mixer_interface *mixer,
+ const u8 device_idx)
{
int err, i;
- const struct snd_pioneer_djm_option_group *group;
+ u16 value;
+
+ const struct snd_djm_device *device = &snd_djm_devices[device_idx];
+
struct snd_kcontrol_new knew = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.index = 0,
- .info = snd_pioneer_djm_controls_info,
- .get = snd_pioneer_djm_controls_get,
- .put = snd_pioneer_djm_controls_put
+ .info = snd_djm_controls_info,
+ .get = snd_djm_controls_get,
+ .put = snd_djm_controls_put
};
- for (i = 0; i < ARRAY_SIZE(snd_pioneer_djm_option_groups); i++) {
- group = &snd_pioneer_djm_option_groups[i];
- knew.name = group->name;
- knew.private_value = (i << SND_PIONEER_DJM_GROUP_SHIFT) | group->default_value;
- err = snd_pioneer_djm_controls_update(mixer, i, group->default_value);
+ for (i = 0; i < device->ncontrols; i++) {
+ value = device->controls[i].default_value;
+ knew.name = device->controls[i].name;
+ knew.private_value = (
+ (device_idx << SND_DJM_DEVICE_SHIFT) |
+ (i << SND_DJM_GROUP_SHIFT) |
+ value);
+ err = snd_djm_controls_update(mixer, device_idx, i, value);
if (err)
return err;
- err = add_single_ctl_with_resume(mixer, 0, snd_pioneer_djm_controls_resume,
+ err = add_single_ctl_with_resume(mixer, 0, snd_djm_controls_resume,
&knew, NULL);
if (err)
return err;
@@ -2917,7 +3040,13 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
err = snd_bbfpro_controls_create(mixer);
break;
case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */
- err = snd_pioneer_djm_controls_create(mixer);
+ err = snd_djm_controls_create(mixer, SND_DJM_250MK2_IDX);
+ break;
+ case USB_ID(0x08e4, 0x017f): /* Pioneer DJ DJM-750 */
+ err = snd_djm_controls_create(mixer, SND_DJM_750_IDX);
+ break;
+ case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */
+ err = snd_djm_controls_create(mixer, SND_DJM_900NXS2_IDX);
break;
}
diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c
index 49fcd2505443..691b95466d0f 100644
--- a/sound/usb/mixer_scarlett.c
+++ b/sound/usb/mixer_scarlett.c
@@ -569,7 +569,7 @@ static int add_new_ctl(struct usb_mixer_interface *mixer,
}
kctl->private_free = snd_usb_mixer_elem_free;
- strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
+ strscpy(kctl->id.name, name, sizeof(kctl->id.name));
err = snd_usb_mixer_add_control(&elem->head, kctl);
if (err < 0)
diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
index 4bbec56c7df3..560c2ade829d 100644
--- a/sound/usb/mixer_scarlett_gen2.c
+++ b/sound/usb/mixer_scarlett_gen2.c
@@ -961,7 +961,7 @@ static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer,
}
kctl->private_free = snd_usb_mixer_elem_free;
- strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
+ strscpy(kctl->id.name, name, sizeof(kctl->id.name));
err = snd_usb_mixer_add_control(&elem->head, kctl);
if (err < 0)
diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c
index bd63a9ce6a70..b7b6f3834ed5 100644
--- a/sound/usb/mixer_us16x08.c
+++ b/sound/usb/mixer_us16x08.c
@@ -1076,7 +1076,7 @@ static int add_new_ctl(struct usb_mixer_interface *mixer,
else
kctl->private_free = snd_usb_mixer_elem_free;
- strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
+ strscpy(kctl->id.name, name, sizeof(kctl->id.name));
err = snd_usb_mixer_add_control(&elem->head, kctl);
if (err < 0)
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 078bb4c94033..bf5a0f3c1fad 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -270,10 +270,7 @@ static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream)
{
struct snd_usb_substream *subs = substream->runtime->private_data;
- if (!snd_usb_lock_shutdown(subs->stream->chip)) {
- sync_pending_stops(subs);
- snd_usb_unlock_shutdown(subs->stream->chip);
- }
+ sync_pending_stops(subs);
return 0;
}
@@ -1558,7 +1555,7 @@ void snd_usb_preallocate_buffer(struct snd_usb_substream *subs)
{
struct snd_pcm *pcm = subs->stream->pcm;
struct snd_pcm_substream *s = pcm->streams[subs->direction].substream;
- struct device *dev = subs->dev->bus->controller;
+ struct device *dev = subs->dev->bus->sysdev;
if (snd_usb_use_vmalloc)
snd_pcm_set_managed_buffer(s, SNDRV_DMA_TYPE_VMALLOC,
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index c8a4bdf18207..1165a5ac60f2 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3757,6 +3757,123 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
}
}
},
+{
+ /*
+ * Pioneer DJ DJM-750
+ * 8 channels playback & 8 channels capture @ 44.1/48/96kHz S24LE
+ */
+ USB_DEVICE_VENDOR_SPEC(0x08e4, 0x017f),
+ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 8,
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .endpoint = 0x05,
+ .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 }
+ }
+ },
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 8,
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .endpoint = 0x86,
+ .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 }
+ }
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
+{
+ /*
+ * Pioneer DJ DJM-450
+ * PCM is 8 channels out @ 48 fixed (endpoint 0x01)
+ * and 8 channels in @ 48 fixed (endpoint 0x82).
+ */
+ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0013),
+ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 8, // outputs
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .endpoint = 0x01,
+ .ep_attr = USB_ENDPOINT_XFER_ISOC|
+ USB_ENDPOINT_SYNC_ASYNC,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .nr_rates = 1,
+ .rate_table = (unsigned int[]) { 48000 }
+ }
+ },
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 8, // inputs
+ .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_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .nr_rates = 1,
+ .rate_table = (unsigned int[]) { 48000 }
+ }
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
#undef USB_DEVICE_VENDOR_SPEC
#undef USB_AUDIO_DEVICE
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index e196e364cef1..9ba4682ebc48 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1470,6 +1470,23 @@ static void set_format_emu_quirk(struct snd_usb_substream *subs,
subs->pkt_offset_adj = (emu_samplerate_id >= EMU_QUIRK_SR_176400HZ) ? 4 : 0;
}
+static int pioneer_djm_set_format_quirk(struct snd_usb_substream *subs,
+ u16 windex)
+{
+ unsigned int cur_rate = subs->data_endpoint->cur_rate;
+ u8 sr[3];
+ // Convert to little endian
+ sr[0] = cur_rate & 0xff;
+ sr[1] = (cur_rate >> 8) & 0xff;
+ sr[2] = (cur_rate >> 16) & 0xff;
+ usb_set_interface(subs->dev, 0, 1);
+ // we should derive windex from fmt-sync_ep but it's not set
+ snd_usb_ctl_msg(subs->stream->chip->dev,
+ usb_rcvctrlpipe(subs->stream->chip->dev, 0),
+ 0x01, 0x22, 0x0100, windex, &sr, 0x0003);
+ return 0;
+}
+
void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
const struct audioformat *fmt)
{
@@ -1483,6 +1500,9 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
case USB_ID(0x534d, 0x2109): /* MacroSilicon MS2109 */
subs->stream_offset_adj = 2;
break;
+ case USB_ID(0x2b73, 0x0013): /* Pioneer DJM-450 */
+ pioneer_djm_set_format_quirk(subs, 0x0082);
+ break;
}
}
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c
index 9f9fcd2749f2..1d66c3a4fb10 100644
--- a/sound/x86/intel_hdmi_audio.c
+++ b/sound/x86/intel_hdmi_audio.c
@@ -1770,8 +1770,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
card_ctx->irq = irq;
/* only 32bit addressable */
- dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
- dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+ dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
init_channel_allocations();
@@ -1790,7 +1789,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
/* setup private data which can be retrieved when required */
pcm->private_data = ctx;
pcm->info_flags = 0;
- strlcpy(pcm->name, card->shortname, strlen(card->shortname));
+ strscpy(pcm->name, card->shortname, strlen(card->shortname));
/* setup the ops for playabck */
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &had_pcm_ops);
diff --git a/sound/xen/xen_snd_front_cfg.c b/sound/xen/xen_snd_front_cfg.c
index eda077c8087a..63b0398c3276 100644
--- a/sound/xen/xen_snd_front_cfg.c
+++ b/sound/xen/xen_snd_front_cfg.c
@@ -398,7 +398,7 @@ static int cfg_device(struct xen_snd_front_info *front_info,
str = xenbus_read(XBT_NIL, device_path, XENSND_FIELD_DEVICE_NAME, NULL);
if (!IS_ERR(str)) {
- strlcpy(pcm_instance->name, str, sizeof(pcm_instance->name));
+ strscpy(pcm_instance->name, str, sizeof(pcm_instance->name));
kfree(str);
}